From 0f00dc4c8eb47e67bc0f148c2dd109f73a451e0a Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sun, 2 Jun 2013 12:54:11 +0100 Subject: [PATCH] Rearrange the file tree. It's actually, like, a tree now. Testing is a bit wobbly: you really do have to make the library before the tests will build. I don't like this, but the pieces of the library are all rather intertwined. One small piece of unintertwining: `strongprime.c' no longer includes `rand.h', which detaches the mathematical code from the symmetric-crypto build system disaster. Test files have been moved into `t/' directories as is now established practice. Also take the opportunity to eradicate the CVS `$Id...$' droppings. --- .gitignore | 16 +- .links | 4 +- Makefile.am | 1070 +----------- arena.c | 65 - arena.h | 79 - base/Makefile.am | 54 + base/arena.c | 63 + base/arena.h | 77 + ct.c => base/ct.c | 0 ct.h => base/ct.h | 0 keysz-conv.c => base/keysz-conv.c | 0 base/keysz.c | 81 + keysz.h => base/keysz.h | 0 base/lmem.c | 344 ++++ base/lmem.h | 164 ++ base/paranoia.h | 49 + bbs-fetch.c | 75 - bbs-gen.c | 126 -- bbs-jump.c | 296 ---- bbs-rand.c | 423 ----- bbs.h | 296 ---- bin-gentab.awk | 102 -- bintab.h | 57 - bintab.in | 37 - bitops.h | 62 - bittest.c | 58 - blkc.h | 347 ---- blowfish-mktab.c | 192 --- blowfish.c | 208 --- blowfish.h | 107 -- buf.c | 129 -- buf.h | 106 -- build-setup | 2 +- calc/ec2.cal | 2 - calc/ecp.cal | 2 - calc/gfx-test.cal | 2 - calc/gfx.cal | 2 - cast-base.h | 67 - cast-s.c | 41 - cast-sk.c | 41 - cast-tab.h | 569 ------- cast128.c | 302 ---- cast128.h | 116 -- cast256.c | 205 --- cast256.h | 111 -- catcrypt.c | 771 --------- catsign.c | 1276 --------------- cbc-def.h | 549 ------- cbc.h | 173 -- cc-enc.c | 530 ------ cc-kem.c | 629 ------- cc-list.c | 75 - cc-sig.c | 806 --------- cc-subcmd.c | 111 -- cc.h | 659 -------- cfb-def.h | 508 ------ cfb.h | 186 --- configure.ac | 13 +- cookie.c | 694 -------- counter-def.h | 535 ------ counter.h | 189 --- crc32.c | 91 -- crc32.h | 55 - daftstory.h | 78 - des-base.c | 41 - des-base.h | 158 -- des-mktab.c | 287 ---- des.c | 281 ---- des.h | 126 -- des3.c | 119 -- des3.h | 110 -- desx-tab.h | 80 - desx.c | 151 -- desx.h | 111 -- dh-check.c | 172 -- dh-fetch.c | 100 -- dh-gen.c | 163 -- dh-kcdsa.c | 125 -- dh-limlee.c | 140 -- dh-param.c | 172 -- dh.h | 242 --- dsa-check.c | 89 - dsa-gen.c | 301 ---- dsa-sign.c | 200 --- dsa-verify.c | 207 --- dsa.h | 279 ---- dsarand.c | 337 ---- dsarand.h | 153 -- dsig.c | 1126 ------------- ec-bin.c | 447 ----- ec-exp.c | 143 -- ec-exp.h | 69 - ec-fetch.c | 91 -- ec-gentab.awk | 116 -- ec-guts.h | 60 - ec-info.c | 781 --------- ec-keys.h | 98 -- ec-prime.c | 451 ------ ec-raw.c | 96 -- ec-raw.h | 85 - ec-test.c | 347 ---- ec-test.h | 55 - ec.c | 424 ----- ec.h | 618 ------- ecb-def.h | 473 ------ ecb.h | 140 -- ectab.h | 74 - ectab.in | 636 -------- exp.c | 71 - exp.h | 422 ----- f-binpoly.c | 184 --- f-niceprime.c | 164 -- f-prime.c | 178 -- factorial.c | 152 -- fibrand.c | 249 --- fibrand.h | 139 -- field-exp.c | 73 - field-exp.h | 59 - field-guts.h | 99 -- field-parse.c | 87 - field.c | 78 - field.h | 267 --- fipstest.c | 191 --- fipstest.h | 71 - g-bin.c | 179 -- g-ec.c | 218 --- g-prime.c | 190 --- gcipher.h | 98 -- gdsa.c | 257 --- gdsa.h | 132 -- genlimits.c | 282 ---- genprimes.c | 193 --- gf-arith.c | 309 ---- gf-exp.c | 67 - gf-exp.h | 69 - gf-gcd.c | 263 --- gf.h | 151 -- gfn.c | 274 ---- gfn.h | 132 -- gfreduce-exp.h | 76 - gfreduce.c | 652 -------- gfreduce.h | 178 -- gfshare-mktab.c | 108 -- gfshare.c | 341 ---- gfshare.h | 182 --- gfx-kmul.c | 249 --- gfx-sqr-mktab.c | 91 -- gfx-sqr.c | 214 --- gfx.c | 389 ----- gfx.h | 175 -- ghash-def.h | 121 -- ghash.h | 156 -- gkcdsa.c | 311 ---- gkcdsa.h | 132 -- gmac.h | 92 -- grand.c | 157 -- grand.h | 163 -- group-dstr.c | 85 - group-exp.c | 109 -- group-exp.h | 68 - group-file.c | 64 - group-guts.h | 86 - group-parse.c | 97 -- group-stdops.c | 168 -- group-string.c | 84 - group-test.c | 563 ------- group.h | 411 ----- has160.c | 248 --- has160.h | 159 -- hash.h | 279 ---- hashsum.c | 412 ----- hmac-def.h | 444 ----- hmac.h | 191 --- idea.c | 275 ---- idea.h | 113 -- karatsuba.h | 144 -- key-attr.c | 308 ---- key-binary.c | 316 ---- key-data.c | 469 ------ key-data.h | 594 ------- key-error.c | 62 - key-error.h | 83 - key-fetch.c | 208 --- key-file.c | 338 ---- key-flags.c | 204 --- key-io.c | 571 ------- key-misc.c | 407 ----- key-moan.c | 55 - key-pack.c | 249 --- key-pass.c | 264 --- key-text.c | 346 ---- key.h | 702 -------- key/Makefile.am | 65 + key/key-attr.c | 306 ++++ key/key-binary.c | 314 ++++ key/key-data.c | 467 ++++++ key/key-data.h | 592 +++++++ key/key-error.c | 60 + key/key-error.h | 81 + key/key-fetch.c | 206 +++ key/key-file.c | 336 ++++ key/key-flags.c | 202 +++ key/key-io.c | 569 +++++++ key/key-misc.c | 405 +++++ key/key-moan.c | 53 + key/key-pack.c | 247 +++ key/key-pass.c | 262 +++ key/key-text.c | 344 ++++ key/key.h | 700 ++++++++ key/passphrase.c | 164 ++ key/passphrase.h | 103 ++ key/pixie-common.c | 374 +++++ key/pixie.h | 216 +++ keycheck-mp.c | 88 - keycheck-report.c | 61 - keycheck.c | 110 -- keycheck.h | 148 -- keysz.c | 83 - keyutil.c | 2308 -------------------------- lcrand.c | 306 ---- lcrand.h | 121 -- limlee.c | 398 ----- limlee.h | 140 -- lmem.c | 346 ---- lmem.h | 166 -- manual/catacomb.tex | 2 - mars-mktab.c | 317 ---- mars.c | 266 --- mars.h | 106 -- math/Makefile.am | 392 +++++ math/bin-gentab.awk | 100 ++ math/bintab.h | 55 + math/bintab.in | 35 + math/bitops.h | 60 + math/bittest.c | 56 + math/buf.c | 127 ++ math/buf.h | 104 ++ math/ec-bin.c | 445 +++++ math/ec-exp.c | 141 ++ math/ec-exp.h | 67 + math/ec-fetch.c | 89 + math/ec-gentab.awk | 114 ++ math/ec-guts.h | 58 + math/ec-info.c | 779 +++++++++ math/ec-keys.h | 96 ++ math/ec-prime.c | 449 +++++ math/ec-raw.c | 94 ++ math/ec-raw.h | 83 + math/ec-test.c | 345 ++++ math/ec-test.h | 53 + math/ec.c | 422 +++++ math/ec.h | 616 +++++++ math/ectab.h | 72 + math/ectab.in | 634 ++++++++ math/exp.c | 69 + math/exp.h | 420 +++++ math/f-binpoly.c | 182 +++ math/f-niceprime.c | 162 ++ math/f-prime.c | 176 ++ math/field-exp.c | 71 + math/field-exp.h | 57 + math/field-guts.h | 97 ++ math/field-parse.c | 85 + math/field.c | 76 + math/field.h | 265 +++ math/g-bin.c | 177 ++ math/g-ec.c | 216 +++ math/g-prime.c | 188 +++ math/genlimits.c | 280 ++++ math/genprimes.c | 191 +++ genwheel.c => math/genwheel.c | 0 math/gf-arith.c | 307 ++++ math/gf-exp.c | 65 + math/gf-exp.h | 67 + math/gf-gcd.c | 261 +++ math/gf.h | 149 ++ math/gfn.c | 272 ++++ math/gfn.h | 130 ++ math/gfreduce-exp.h | 74 + math/gfreduce.c | 650 ++++++++ math/gfreduce.h | 176 ++ math/gfx-kmul.c | 247 +++ math/gfx-sqr-mktab.c | 89 + math/gfx-sqr.c | 212 +++ math/gfx.c | 387 +++++ math/gfx.h | 173 ++ math/group-dstr.c | 83 + math/group-exp.c | 107 ++ math/group-exp.h | 66 + math/group-file.c | 62 + math/group-guts.h | 84 + math/group-parse.c | 95 ++ math/group-stdops.c | 166 ++ math/group-string.c | 82 + math/group-test.c | 561 +++++++ math/group.h | 409 +++++ math/karatsuba.h | 142 ++ math/limlee.c | 396 +++++ math/limlee.h | 138 ++ math/mp-arith.c | 929 +++++++++++ math/mp-const.c | 49 + math/mp-exp.c | 65 + math/mp-exp.h | 67 + math/mp-fibonacci.c | 271 ++++ mp-fibonacci.h => math/mp-fibonacci.h | 0 math/mp-gcd.c | 345 ++++ math/mp-io.c | 279 ++++ math/mp-jacobi.c | 201 +++ math/mp-mem.c | 334 ++++ math/mp-misc.c | 94 ++ math/mp-modexp.c | 111 ++ math/mp-modsqrt.c | 207 +++ math/mp-sqrt.c | 153 ++ math/mp-test.c | 62 + math/mp.h | 1024 ++++++++++++ math/mparena.c | 338 ++++ math/mparena.h | 160 ++ math/mpbarrett-exp.c | 122 ++ math/mpbarrett-exp.h | 74 + math/mpbarrett-mexp.c | 175 ++ math/mpbarrett.c | 211 +++ math/mpbarrett.h | 141 ++ math/mpcrt.c | 291 ++++ math/mpcrt.h | 123 ++ math/mpdump.c | 72 + math/mpint.c | 177 ++ math/mpint.h | 190 +++ math/mpmont-exp.c | 145 ++ math/mpmont-exp.h | 71 + math/mpmont-mexp.c | 211 +++ math/mpmont.c | 427 +++++ math/mpmont.h | 201 +++ math/mpmul.c | 179 ++ math/mpmul.h | 139 ++ math/mprand.c | 138 ++ math/mprand.h | 87 + math/mpreduce-exp.h | 74 + math/mpreduce.c | 438 +++++ math/mpreduce.h | 126 ++ math/mpscan.c | 120 ++ math/mpscan.h | 170 ++ math/mptext-dstr.c | 86 + math/mptext-file.c | 62 + math/mptext-len.c | 97 ++ math/mptext-string.c | 96 ++ math/mptext.c | 849 ++++++++++ math/mptext.h | 184 +++ math/mptypes.c | 212 +++ math/mpw.h | 83 + math/mpx-kmul.c | 247 +++ math/mpx-ksqr.c | 211 +++ math/mpx.c | 1737 ++++++++++++++++++++ math/mpx.h | 789 +++++++++ math/p-gentab.awk | 100 ++ math/pfilt.c | 327 ++++ math/pfilt.h | 155 ++ math/pgen-gcd.c | 101 ++ math/pgen-simul.c | 168 ++ math/pgen-stdev.c | 129 ++ math/pgen.c | 420 +++++ math/pgen.h | 289 ++++ math/prim.c | 107 ++ math/prim.h | 89 + math/primeiter.c | 254 +++ primeiter.h => math/primeiter.h | 0 math/ptab.h | 62 + math/ptab.in | 217 +++ math/qdparse.c | 141 ++ math/qdparse.h | 113 ++ math/rabin.c | 197 +++ math/rabin.h | 119 ++ math/rho.c | 298 ++++ math/rho.h | 129 ++ math/strongprime.c | 203 +++ math/strongprime.h | 103 ++ math/t/ec | 451 ++++++ math/t/gf | 89 + math/t/gfn | 32 + math/t/gfreduce | 79 + math/t/gfx | 527 ++++++ math/t/group | 318 ++++ math/t/mp | 326 ++++ math/t/mpbarrett | 133 ++ math/t/mpcrt | 19 + math/t/mpint | 50 + math/t/mpmont | 113 ++ math/t/mpreduce | 31 + math/t/mptext | 88 + math/t/mpx | 888 ++++++++++ math/t/mpx-gen | 118 ++ math/t/pgen | 38 + maurer.c | 235 --- maurer.h | 119 -- md2-tab.h | 80 - md2.c | 223 --- md2.h | 158 -- md4.c | 259 --- md4.h | 159 -- md5.c | 278 ---- md5.h | 160 -- mgf-def.h | 460 ------ mgf.h | 164 -- misc/Makefile.am | 51 + misc/gfshare-mktab.c | 106 ++ misc/gfshare.c | 339 ++++ misc/gfshare.h | 180 ++ misc/share.c | 380 +++++ misc/share.h | 177 ++ mkpgroups | 42 - mkphrase.c | 458 ------ modes.am.in | 67 - mp-arith.c | 931 ----------- mp-const.c | 51 - mp-exp.c | 67 - mp-exp.h | 69 - mp-fibonacci.c | 271 ---- mp-gcd.c | 347 ---- mp-io.c | 281 ---- mp-jacobi.c | 203 --- mp-mem.c | 336 ---- mp-misc.c | 96 -- mp-modexp.c | 113 -- mp-modsqrt.c | 209 --- mp-sqrt.c | 155 -- mp-test.c | 64 - mp.h | 1026 ------------ mparena.c | 340 ---- mparena.h | 162 -- mpbarrett-exp.c | 124 -- mpbarrett-exp.h | 76 - mpbarrett-mexp.c | 177 -- mpbarrett.c | 213 --- mpbarrett.h | 143 -- mpcrt.c | 293 ---- mpcrt.h | 125 -- mpdump.c | 74 - mpint.c | 179 -- mpint.h | 192 --- mpmont-exp.c | 147 -- mpmont-exp.h | 73 - mpmont-mexp.c | 213 --- mpmont.c | 429 ----- mpmont.h | 203 --- mpmul.c | 181 --- mpmul.h | 141 -- mprand.c | 140 -- mprand.h | 89 - mpreduce-exp.h | 76 - mpreduce.c | 440 ----- mpreduce.h | 128 -- mpscan.c | 122 -- mpscan.h | 172 -- mptext-dstr.c | 88 - mptext-file.c | 64 - mptext-len.c | 99 -- mptext-string.c | 98 -- mptext.c | 851 ---------- mptext.h | 186 --- mptypes.c | 214 --- mpw.h | 85 - mpx-kmul.c | 249 --- mpx-ksqr.c | 213 --- mpx.c | 1739 -------------------- mpx.h | 791 --------- noekeon.c | 195 --- noekeon.h | 105 -- noise.c | 461 ------ noise.h | 165 -- oaep.c | 184 --- ofb-def.h | 547 ------- ofb.h | 187 --- p-gentab.awk | 102 -- papers/rand.tex | 2 - paranoia.h | 51 - passphrase.c | 166 -- passphrase.h | 105 -- pcheck.pl | 43 - perftest.c | 616 ------- pfilt.c | 329 ---- pfilt.h | 157 -- pgen-gcd.c | 103 -- pgen-simul.c | 170 -- pgen-stdev.c | 131 -- pgen.c | 422 ----- pgen.h | 291 ---- pixie-common.c | 376 ----- pixie.c | 1462 ----------------- pixie.h | 218 --- pkcs1.c | 261 --- prim.c | 109 -- prim.h | 91 -- primeiter.c | 254 --- progs/Makefile.am | 109 ++ catcrypt.1 => progs/catcrypt.1 | 0 progs/catcrypt.c | 769 +++++++++ catsign.1 => progs/catsign.1 | 0 progs/catsign.c | 1274 +++++++++++++++ progs/cc-enc.c | 528 ++++++ cc-hash.c => progs/cc-hash.c | 0 progs/cc-kem.c | 627 +++++++ progs/cc-list.c | 73 + cc-progress.c => progs/cc-progress.c | 0 progs/cc-sig.c | 804 +++++++++ progs/cc-subcmd.c | 109 ++ progs/cc.h | 657 ++++++++ cookie.1 => progs/cookie.1 | 0 progs/cookie.c | 692 ++++++++ dsig.1 => progs/dsig.1 | 0 progs/dsig.c | 1124 +++++++++++++ progs/factorial.c | 150 ++ fibonacci.c => progs/fibonacci.c | 0 hashsum.1 => progs/hashsum.1 | 0 progs/hashsum.c | 410 +++++ key.1 => progs/key.1 | 0 progs/key.c | 2306 ++++++++++++++++++++++++++ keyring.5 => progs/keyring.5 | 0 mkphrase.1 => progs/mkphrase.1 | 0 progs/mkphrase.c | 456 ++++++ progs/perftest.c | 614 +++++++ pixie.1 => progs/pixie.1 | 0 progs/pixie.c | 1460 +++++++++++++++++ progs/rspit.c | 1400 ++++++++++++++++ xpixie => progs/xpixie | 0 pss.c | 188 --- ptab.h | 64 - ptab.in | 219 --- pub/Makefile.am | 101 ++ pub/bbs-fetch.c | 73 + pub/bbs-gen.c | 124 ++ pub/bbs-jump.c | 294 ++++ pub/bbs-rand.c | 421 +++++ pub/bbs.h | 294 ++++ pub/dh-check.c | 170 ++ pub/dh-fetch.c | 98 ++ pub/dh-gen.c | 161 ++ pub/dh-kcdsa.c | 123 ++ pub/dh-limlee.c | 138 ++ pub/dh-param.c | 170 ++ pub/dh.h | 240 +++ pub/dsa-check.c | 87 + pub/dsa-gen.c | 299 ++++ dsa-misc.c => pub/dsa-misc.c | 0 pub/dsa-sign.c | 198 +++ pub/dsa-verify.c | 205 +++ pub/dsa.h | 277 ++++ pub/gdsa.c | 255 +++ pub/gdsa.h | 130 ++ pub/gkcdsa.c | 309 ++++ pub/gkcdsa.h | 130 ++ pub/keycheck-mp.c | 86 + pub/keycheck-report.c | 59 + pub/keycheck.c | 108 ++ pub/keycheck.h | 146 ++ pub/oaep.c | 182 +++ pub/pkcs1.c | 259 +++ pub/pss.c | 186 +++ pub/rsa-fetch.c | 85 + pub/rsa-gen.c | 189 +++ pub/rsa-priv.c | 260 +++ pub/rsa-pub.c | 190 +++ pub/rsa-recover.c | 240 +++ pub/rsa-test.c | 512 ++++++ pub/rsa.h | 402 +++++ pub/t/bbs | 14 + pub/t/dsa | 119 ++ pub/t/gdsa | 240 +++ pub/t/gkcdsa | 57 + pub/t/rsa | 391 +++++ qdparse.c | 143 -- qdparse.h | 115 -- rabin.c | 199 --- rabin.h | 121 -- rand.c | 586 ------- rand.h | 315 ---- rand/Makefile.am | 83 + rand/dsarand.c | 335 ++++ rand/dsarand.h | 151 ++ rand/fibrand.c | 247 +++ rand/fibrand.h | 137 ++ rand/fipstest.c | 189 +++ rand/fipstest.h | 69 + rand/grand.c | 155 ++ rand/grand.h | 161 ++ rand/lcrand.c | 304 ++++ rand/lcrand.h | 119 ++ rand/maurer.c | 233 +++ rand/maurer.h | 117 ++ rand/noise.c | 459 ++++++ rand/noise.h | 163 ++ rand/rand.c | 584 +++++++ rand/rand.h | 313 ++++ rand/sslprf.c | 356 ++++ rand/sslprf.h | 135 ++ rand/t/lcrand | 32 + rand/t/sslprf | 9 + rand/t/tlsprf | 9 + rand/tlsprf.c | 540 ++++++ rand/tlsprf.h | 203 +++ rc2-tab.h | 80 - rc2.c | 329 ---- rc2.h | 130 -- rc4.c | 369 ----- rc4.h | 197 --- rc5.c | 232 --- rc5.h | 103 -- rho.c | 300 ---- rho.h | 131 -- rijndael-base.c | 135 -- rijndael-base.h | 73 - rijndael-mktab.c | 370 ----- rijndael.c | 160 -- rijndael.h | 128 -- rijndael192.c | 161 -- rijndael192.h | 96 -- rijndael256.c | 161 -- rijndael256.h | 96 -- rmd128.c | 358 ---- rmd128.h | 158 -- rmd160.c | 401 ----- rmd160.h | 161 -- rmd256.c | 376 ----- rmd256.h | 162 -- rmd320.c | 426 ----- rmd320.h | 162 -- rsa-fetch.c | 87 - rsa-gen.c | 191 --- rsa-priv.c | 262 --- rsa-pub.c | 192 --- rsa-recover.c | 242 --- rsa-test.c | 514 ------ rsa.h | 404 ----- rspit.c | 1402 ---------------- safer-mktab.c | 104 -- safer.c | 325 ---- safer.h | 141 -- safersk.c | 16 - safersk.h | 17 - seal.c | 616 ------- seal.h | 165 -- serpent-check.c | 101 -- serpent-sbox.h | 230 --- serpent.c | 215 --- serpent.h | 106 -- sha.c | 306 ---- sha.h | 159 -- sha224.c | 14 - sha224.h | 13 - sha256.c | 335 ---- sha256.h | 171 -- sha384.c | 14 - sha384.h | 13 - sha512.c | 342 ---- sha512.h | 173 -- share.c | 382 ----- share.h | 179 -- skipjack-tab.h | 80 - skipjack.c | 178 -- skipjack.h | 112 -- square-mktab.c | 368 ----- square.c | 196 --- square.h | 114 -- sslprf.c | 358 ---- sslprf.h | 137 -- strongprime.c | 206 --- strongprime.h | 105 -- symm/Makefile.am | 401 +++++ {tests => symm}/aes-trans | 0 symm/blkc.h | 345 ++++ symm/blowfish-mktab.c | 190 +++ symm/blowfish.c | 206 +++ symm/blowfish.h | 105 ++ symm/cast-base.h | 65 + symm/cast-s.c | 39 + symm/cast-sk.c | 39 + symm/cast-tab.h | 567 +++++++ symm/cast128.c | 300 ++++ symm/cast128.h | 114 ++ symm/cast256.c | 203 +++ symm/cast256.h | 109 ++ symm/cbc-def.h | 547 +++++++ symm/cbc.h | 171 ++ symm/cfb-def.h | 506 ++++++ symm/cfb.h | 184 +++ symm/counter-def.h | 533 ++++++ symm/counter.h | 187 +++ symm/crc32.c | 89 + symm/crc32.h | 53 + symm/daftstory.h | 76 + symm/des-base.c | 39 + symm/des-base.h | 156 ++ symm/des-mktab.c | 285 ++++ symm/des.c | 279 ++++ symm/des.h | 124 ++ symm/des3.c | 117 ++ symm/des3.h | 108 ++ symm/desx-tab.h | 78 + symm/desx.c | 149 ++ symm/desx.h | 109 ++ symm/ecb-def.h | 471 ++++++ symm/ecb.h | 138 ++ symm/gcipher.h | 96 ++ symm/ghash-def.h | 119 ++ symm/ghash.h | 154 ++ symm/gmac.h | 90 + gthingtab.c.in => symm/gthingtab.c.in | 0 symm/has160.c | 246 +++ symm/has160.h | 157 ++ symm/hash.h | 277 ++++ symm/hmac-def.h | 442 +++++ symm/hmac.h | 189 +++ symm/idea.c | 273 ++++ symm/idea.h | 111 ++ symm/mars-mktab.c | 315 ++++ symm/mars.c | 264 +++ symm/mars.h | 104 ++ symm/md2-tab.h | 78 + symm/md2.c | 221 +++ symm/md2.h | 156 ++ symm/md4.c | 257 +++ symm/md4.h | 157 ++ symm/md5.c | 276 ++++ symm/md5.h | 158 ++ symm/mgf-def.h | 458 ++++++ symm/mgf.h | 162 ++ mode.c.in => symm/mode.c.in | 0 mode.h.in => symm/mode.h.in | 0 symm/modes.am.in | 77 + multigen => symm/multigen | 0 symm/noekeon.c | 193 +++ symm/noekeon.h | 103 ++ symm/ofb-def.h | 545 +++++++ symm/ofb.h | 185 +++ symm/rc2-tab.h | 78 + symm/rc2.c | 327 ++++ symm/rc2.h | 128 ++ symm/rc4.c | 367 +++++ symm/rc4.h | 195 +++ symm/rc5.c | 230 +++ symm/rc5.h | 101 ++ symm/rijndael-base.c | 133 ++ symm/rijndael-base.h | 71 + symm/rijndael-mktab.c | 368 +++++ symm/rijndael.c | 158 ++ symm/rijndael.h | 126 ++ symm/rijndael192.c | 159 ++ symm/rijndael192.h | 94 ++ symm/rijndael256.c | 159 ++ symm/rijndael256.h | 94 ++ symm/rmd128.c | 356 ++++ symm/rmd128.h | 156 ++ symm/rmd160.c | 399 +++++ symm/rmd160.h | 159 ++ symm/rmd256.c | 374 +++++ symm/rmd256.h | 160 ++ symm/rmd320.c | 424 +++++ symm/rmd320.h | 160 ++ symm/safer-mktab.c | 102 ++ symm/safer.c | 323 ++++ symm/safer.h | 139 ++ symm/safersk.c | 14 + symm/safersk.h | 15 + symm/seal.c | 614 +++++++ symm/seal.h | 163 ++ symm/serpent-check.c | 99 ++ symm/serpent-sbox.h | 228 +++ symm/serpent.c | 213 +++ symm/serpent.h | 104 ++ symm/sha.c | 304 ++++ symm/sha.h | 157 ++ symm/sha224.c | 12 + symm/sha224.h | 11 + symm/sha256.c | 333 ++++ symm/sha256.h | 169 ++ symm/sha384.c | 12 + symm/sha384.h | 11 + symm/sha512.c | 340 ++++ symm/sha512.h | 171 ++ symm/skipjack-tab.h | 78 + symm/skipjack.c | 176 ++ symm/skipjack.h | 110 ++ symm/square-mktab.c | 366 +++++ symm/square.c | 194 +++ symm/square.h | 112 ++ symm/t/.gitignore | 5 + symm/t/blowfish | 119 ++ symm/t/cast128 | 15 + {tests => symm/t}/cast256.aes | 0 symm/t/des | 62 + symm/t/des3 | 41 + symm/t/desx | 22 + symm/t/has160 | 51 + symm/t/idea | 26 + {tests => symm/t}/mars.aes | 0 symm/t/md2 | 77 + symm/t/md4 | 57 + symm/t/md5 | 78 + symm/t/noekeon | 10 + symm/t/rc2 | 13 + symm/t/rc4 | 25 + symm/t/rc5 | 15 + {tests => symm/t}/rijndael.aes | 0 symm/t/rijndael192 | 2884 ++++++++++++++++++++++++++++++++ symm/t/rijndael256 | 2884 ++++++++++++++++++++++++++++++++ symm/t/rmd128 | 108 ++ symm/t/rmd160 | 109 ++ symm/t/rmd256 | 59 + symm/t/rmd320 | 59 + symm/t/safer | 8 + symm/t/safersk | 8 + symm/t/seal | 6 + {tests => symm/t}/serpent.aes | 0 symm/t/sha | 61 + symm/t/sha224 | 72 + symm/t/sha256 | 71 + symm/t/sha384 | 72 + symm/t/sha512 | 73 + symm/t/skipjack | 101 ++ symm/t/square | 523 ++++++ symm/t/tea | 74 + {tests => symm/t}/tea-test.c | 0 symm/t/tiger | 62 + {tests => symm/t}/twofish.aes | 0 symm/t/whirlpool | 64 + symm/t/whirlpool256 | 64 + symm/t/xtea | 70 + {tests => symm/t}/xtea-test.c | 0 symm/tea.c | 122 ++ symm/tea.h | 104 ++ symm/tiger-base.h | 118 ++ symm/tiger-mktab.c | 151 ++ symm/tiger.c | 173 ++ symm/tiger.h | 158 ++ symm/twofish-mktab.c | 411 +++++ symm/twofish.c | 427 +++++ symm/twofish.h | 143 ++ symm/whirlpool-mktab.c | 231 +++ symm/whirlpool.c | 304 ++++ symm/whirlpool.h | 175 ++ symm/whirlpool256.c | 12 + symm/whirlpool256.h | 11 + symm/xtea.c | 120 ++ symm/xtea.h | 104 ++ tea.c | 124 -- tea.h | 106 -- tests/.gitignore | 7 - tests/bbs | 16 - tests/blowfish | 121 -- tests/cast128 | 17 - tests/des | 64 - tests/des3 | 43 - tests/desx | 24 - tests/dsa | 121 -- tests/ec | 453 ------ tests/gdsa | 242 --- tests/gf | 91 -- tests/gfn | 34 - tests/gfreduce | 81 - tests/gfx | 529 ------ tests/gkcdsa | 59 - tests/group | 320 ---- tests/has160 | 53 - tests/idea | 28 - tests/lcrand | 34 - tests/md2 | 79 - tests/md4 | 59 - tests/md5 | 80 - tests/mp | 328 ---- tests/mpbarrett | 135 -- tests/mpcrt | 21 - tests/mpint | 52 - tests/mpmont | 115 -- tests/mpreduce | 33 - tests/mptext | 90 - tests/mpx | 890 ---------- tests/mpx-gen | 120 -- tests/noekeon | 12 - tests/pgen | 40 - tests/rc2 | 15 - tests/rc4 | 28 - tests/rc5 | 17 - tests/rijndael192 | 2886 --------------------------------- tests/rijndael256 | 2886 --------------------------------- tests/rmd128 | 111 -- tests/rmd160 | 111 -- tests/rmd256 | 61 - tests/rmd320 | 61 - tests/rsa | 393 ----- tests/safer | 10 - tests/safersk | 10 - tests/seal | 8 - tests/sha | 63 - tests/sha224 | 74 - tests/sha256 | 73 - tests/sha384 | 74 - tests/sha512 | 75 - tests/skipjack | 103 -- tests/square | 525 ------ tests/sslprf | 11 - tests/tea | 76 - tests/tiger | 64 - tests/tlsprf | 11 - tests/whirlpool | 66 - tests/whirlpool256 | 66 - tests/xtea | 72 - tiger-base.h | 120 -- tiger-mktab.c | 153 -- tiger.c | 175 -- tiger.h | 160 -- tlsprf.c | 542 ------- tlsprf.h | 205 --- twofish-mktab.c | 413 ----- twofish.c | 429 ----- twofish.h | 145 -- vars.am | 102 ++ whirlpool-mktab.c | 233 --- whirlpool.c | 306 ---- whirlpool.h | 177 -- whirlpool256.c | 14 - whirlpool256.h | 13 - xtea.c | 122 -- xtea.h | 106 -- 921 files changed, 102585 insertions(+), 103184 deletions(-) delete mode 100644 arena.c delete mode 100644 arena.h create mode 100644 base/Makefile.am create mode 100644 base/arena.c create mode 100644 base/arena.h rename ct.c => base/ct.c (100%) rename ct.h => base/ct.h (100%) rename keysz-conv.c => base/keysz-conv.c (100%) create mode 100644 base/keysz.c rename keysz.h => base/keysz.h (100%) create mode 100644 base/lmem.c create mode 100644 base/lmem.h create mode 100644 base/paranoia.h delete mode 100644 bbs-fetch.c delete mode 100644 bbs-gen.c delete mode 100644 bbs-jump.c delete mode 100644 bbs-rand.c delete mode 100644 bbs.h delete mode 100755 bin-gentab.awk delete mode 100644 bintab.h delete mode 100644 bintab.in delete mode 100644 bitops.h delete mode 100644 bittest.c delete mode 100644 blkc.h delete mode 100644 blowfish-mktab.c delete mode 100644 blowfish.c delete mode 100644 blowfish.h delete mode 100644 buf.c delete mode 100644 buf.h delete mode 100644 cast-base.h delete mode 100644 cast-s.c delete mode 100644 cast-sk.c delete mode 100644 cast-tab.h delete mode 100644 cast128.c delete mode 100644 cast128.h delete mode 100644 cast256.c delete mode 100644 cast256.h delete mode 100644 catcrypt.c delete mode 100644 catsign.c delete mode 100644 cbc-def.h delete mode 100644 cbc.h delete mode 100644 cc-enc.c delete mode 100644 cc-kem.c delete mode 100644 cc-list.c delete mode 100644 cc-sig.c delete mode 100644 cc-subcmd.c delete mode 100644 cc.h delete mode 100644 cfb-def.h delete mode 100644 cfb.h delete mode 100644 cookie.c delete mode 100644 counter-def.h delete mode 100644 counter.h delete mode 100644 crc32.c delete mode 100644 crc32.h delete mode 100644 daftstory.h delete mode 100644 des-base.c delete mode 100644 des-base.h delete mode 100644 des-mktab.c delete mode 100644 des.c delete mode 100644 des.h delete mode 100644 des3.c delete mode 100644 des3.h delete mode 100644 desx-tab.h delete mode 100644 desx.c delete mode 100644 desx.h delete mode 100644 dh-check.c delete mode 100644 dh-fetch.c delete mode 100644 dh-gen.c delete mode 100644 dh-kcdsa.c delete mode 100644 dh-limlee.c delete mode 100644 dh-param.c delete mode 100644 dh.h delete mode 100644 dsa-check.c delete mode 100644 dsa-gen.c delete mode 100644 dsa-sign.c delete mode 100644 dsa-verify.c delete mode 100644 dsa.h delete mode 100644 dsarand.c delete mode 100644 dsarand.h delete mode 100644 dsig.c delete mode 100644 ec-bin.c delete mode 100644 ec-exp.c delete mode 100644 ec-exp.h delete mode 100644 ec-fetch.c delete mode 100755 ec-gentab.awk delete mode 100644 ec-guts.h delete mode 100644 ec-info.c delete mode 100644 ec-keys.h delete mode 100644 ec-prime.c delete mode 100644 ec-raw.c delete mode 100644 ec-raw.h delete mode 100644 ec-test.c delete mode 100644 ec-test.h delete mode 100644 ec.c delete mode 100644 ec.h delete mode 100644 ecb-def.h delete mode 100644 ecb.h delete mode 100644 ectab.h delete mode 100644 ectab.in delete mode 100644 exp.c delete mode 100644 exp.h delete mode 100644 f-binpoly.c delete mode 100644 f-niceprime.c delete mode 100644 f-prime.c delete mode 100644 factorial.c delete mode 100644 fibrand.c delete mode 100644 fibrand.h delete mode 100644 field-exp.c delete mode 100644 field-exp.h delete mode 100644 field-guts.h delete mode 100644 field-parse.c delete mode 100644 field.c delete mode 100644 field.h delete mode 100644 fipstest.c delete mode 100644 fipstest.h delete mode 100644 g-bin.c delete mode 100644 g-ec.c delete mode 100644 g-prime.c delete mode 100644 gcipher.h delete mode 100644 gdsa.c delete mode 100644 gdsa.h delete mode 100644 genlimits.c delete mode 100644 genprimes.c delete mode 100644 gf-arith.c delete mode 100644 gf-exp.c delete mode 100644 gf-exp.h delete mode 100644 gf-gcd.c delete mode 100644 gf.h delete mode 100644 gfn.c delete mode 100644 gfn.h delete mode 100644 gfreduce-exp.h delete mode 100644 gfreduce.c delete mode 100644 gfreduce.h delete mode 100644 gfshare-mktab.c delete mode 100644 gfshare.c delete mode 100644 gfshare.h delete mode 100644 gfx-kmul.c delete mode 100644 gfx-sqr-mktab.c delete mode 100644 gfx-sqr.c delete mode 100644 gfx.c delete mode 100644 gfx.h delete mode 100644 ghash-def.h delete mode 100644 ghash.h delete mode 100644 gkcdsa.c delete mode 100644 gkcdsa.h delete mode 100644 gmac.h delete mode 100644 grand.c delete mode 100644 grand.h delete mode 100644 group-dstr.c delete mode 100644 group-exp.c delete mode 100644 group-exp.h delete mode 100644 group-file.c delete mode 100644 group-guts.h delete mode 100644 group-parse.c delete mode 100644 group-stdops.c delete mode 100644 group-string.c delete mode 100644 group-test.c delete mode 100644 group.h delete mode 100644 has160.c delete mode 100644 has160.h delete mode 100644 hash.h delete mode 100644 hashsum.c delete mode 100644 hmac-def.h delete mode 100644 hmac.h delete mode 100644 idea.c delete mode 100644 idea.h delete mode 100644 karatsuba.h delete mode 100644 key-attr.c delete mode 100644 key-binary.c delete mode 100644 key-data.c delete mode 100644 key-data.h delete mode 100644 key-error.c delete mode 100644 key-error.h delete mode 100644 key-fetch.c delete mode 100644 key-file.c delete mode 100644 key-flags.c delete mode 100644 key-io.c delete mode 100644 key-misc.c delete mode 100644 key-moan.c delete mode 100644 key-pack.c delete mode 100644 key-pass.c delete mode 100644 key-text.c delete mode 100644 key.h create mode 100644 key/Makefile.am create mode 100644 key/key-attr.c create mode 100644 key/key-binary.c create mode 100644 key/key-data.c create mode 100644 key/key-data.h create mode 100644 key/key-error.c create mode 100644 key/key-error.h create mode 100644 key/key-fetch.c create mode 100644 key/key-file.c create mode 100644 key/key-flags.c create mode 100644 key/key-io.c create mode 100644 key/key-misc.c create mode 100644 key/key-moan.c create mode 100644 key/key-pack.c create mode 100644 key/key-pass.c create mode 100644 key/key-text.c create mode 100644 key/key.h create mode 100644 key/passphrase.c create mode 100644 key/passphrase.h create mode 100644 key/pixie-common.c create mode 100644 key/pixie.h delete mode 100644 keycheck-mp.c delete mode 100644 keycheck-report.c delete mode 100644 keycheck.c delete mode 100644 keycheck.h delete mode 100644 keysz.c delete mode 100644 keyutil.c delete mode 100644 lcrand.c delete mode 100644 lcrand.h delete mode 100644 limlee.c delete mode 100644 limlee.h delete mode 100644 lmem.c delete mode 100644 lmem.h delete mode 100644 mars-mktab.c delete mode 100644 mars.c delete mode 100644 mars.h create mode 100644 math/Makefile.am create mode 100755 math/bin-gentab.awk create mode 100644 math/bintab.h create mode 100644 math/bintab.in create mode 100644 math/bitops.h create mode 100644 math/bittest.c create mode 100644 math/buf.c create mode 100644 math/buf.h create mode 100644 math/ec-bin.c create mode 100644 math/ec-exp.c create mode 100644 math/ec-exp.h create mode 100644 math/ec-fetch.c create mode 100755 math/ec-gentab.awk create mode 100644 math/ec-guts.h create mode 100644 math/ec-info.c create mode 100644 math/ec-keys.h create mode 100644 math/ec-prime.c create mode 100644 math/ec-raw.c create mode 100644 math/ec-raw.h create mode 100644 math/ec-test.c create mode 100644 math/ec-test.h create mode 100644 math/ec.c create mode 100644 math/ec.h create mode 100644 math/ectab.h create mode 100644 math/ectab.in create mode 100644 math/exp.c create mode 100644 math/exp.h create mode 100644 math/f-binpoly.c create mode 100644 math/f-niceprime.c create mode 100644 math/f-prime.c create mode 100644 math/field-exp.c create mode 100644 math/field-exp.h create mode 100644 math/field-guts.h create mode 100644 math/field-parse.c create mode 100644 math/field.c create mode 100644 math/field.h create mode 100644 math/g-bin.c create mode 100644 math/g-ec.c create mode 100644 math/g-prime.c create mode 100644 math/genlimits.c create mode 100644 math/genprimes.c rename genwheel.c => math/genwheel.c (100%) create mode 100644 math/gf-arith.c create mode 100644 math/gf-exp.c create mode 100644 math/gf-exp.h create mode 100644 math/gf-gcd.c create mode 100644 math/gf.h create mode 100644 math/gfn.c create mode 100644 math/gfn.h create mode 100644 math/gfreduce-exp.h create mode 100644 math/gfreduce.c create mode 100644 math/gfreduce.h create mode 100644 math/gfx-kmul.c create mode 100644 math/gfx-sqr-mktab.c create mode 100644 math/gfx-sqr.c create mode 100644 math/gfx.c create mode 100644 math/gfx.h create mode 100644 math/group-dstr.c create mode 100644 math/group-exp.c create mode 100644 math/group-exp.h create mode 100644 math/group-file.c create mode 100644 math/group-guts.h create mode 100644 math/group-parse.c create mode 100644 math/group-stdops.c create mode 100644 math/group-string.c create mode 100644 math/group-test.c create mode 100644 math/group.h create mode 100644 math/karatsuba.h create mode 100644 math/limlee.c create mode 100644 math/limlee.h create mode 100644 math/mp-arith.c create mode 100644 math/mp-const.c create mode 100644 math/mp-exp.c create mode 100644 math/mp-exp.h create mode 100644 math/mp-fibonacci.c rename mp-fibonacci.h => math/mp-fibonacci.h (100%) create mode 100644 math/mp-gcd.c create mode 100644 math/mp-io.c create mode 100644 math/mp-jacobi.c create mode 100644 math/mp-mem.c create mode 100644 math/mp-misc.c create mode 100644 math/mp-modexp.c create mode 100644 math/mp-modsqrt.c create mode 100644 math/mp-sqrt.c create mode 100644 math/mp-test.c create mode 100644 math/mp.h create mode 100644 math/mparena.c create mode 100644 math/mparena.h create mode 100644 math/mpbarrett-exp.c create mode 100644 math/mpbarrett-exp.h create mode 100644 math/mpbarrett-mexp.c create mode 100644 math/mpbarrett.c create mode 100644 math/mpbarrett.h create mode 100644 math/mpcrt.c create mode 100644 math/mpcrt.h create mode 100644 math/mpdump.c create mode 100644 math/mpint.c create mode 100644 math/mpint.h create mode 100644 math/mpmont-exp.c create mode 100644 math/mpmont-exp.h create mode 100644 math/mpmont-mexp.c create mode 100644 math/mpmont.c create mode 100644 math/mpmont.h create mode 100644 math/mpmul.c create mode 100644 math/mpmul.h create mode 100644 math/mprand.c create mode 100644 math/mprand.h create mode 100644 math/mpreduce-exp.h create mode 100644 math/mpreduce.c create mode 100644 math/mpreduce.h create mode 100644 math/mpscan.c create mode 100644 math/mpscan.h create mode 100644 math/mptext-dstr.c create mode 100644 math/mptext-file.c create mode 100644 math/mptext-len.c create mode 100644 math/mptext-string.c create mode 100644 math/mptext.c create mode 100644 math/mptext.h create mode 100644 math/mptypes.c create mode 100644 math/mpw.h create mode 100644 math/mpx-kmul.c create mode 100644 math/mpx-ksqr.c create mode 100644 math/mpx.c create mode 100644 math/mpx.h create mode 100755 math/p-gentab.awk create mode 100644 math/pfilt.c create mode 100644 math/pfilt.h create mode 100644 math/pgen-gcd.c create mode 100644 math/pgen-simul.c create mode 100644 math/pgen-stdev.c create mode 100644 math/pgen.c create mode 100644 math/pgen.h create mode 100644 math/prim.c create mode 100644 math/prim.h create mode 100644 math/primeiter.c rename primeiter.h => math/primeiter.h (100%) create mode 100644 math/ptab.h create mode 100644 math/ptab.in create mode 100644 math/qdparse.c create mode 100644 math/qdparse.h create mode 100644 math/rabin.c create mode 100644 math/rabin.h create mode 100644 math/rho.c create mode 100644 math/rho.h create mode 100644 math/strongprime.c create mode 100644 math/strongprime.h create mode 100644 math/t/ec create mode 100644 math/t/gf create mode 100644 math/t/gfn create mode 100644 math/t/gfreduce create mode 100644 math/t/gfx create mode 100644 math/t/group create mode 100644 math/t/mp create mode 100644 math/t/mpbarrett create mode 100644 math/t/mpcrt create mode 100644 math/t/mpint create mode 100644 math/t/mpmont create mode 100644 math/t/mpreduce create mode 100644 math/t/mptext create mode 100644 math/t/mpx create mode 100755 math/t/mpx-gen create mode 100644 math/t/pgen delete mode 100644 maurer.c delete mode 100644 maurer.h delete mode 100644 md2-tab.h delete mode 100644 md2.c delete mode 100644 md2.h delete mode 100644 md4.c delete mode 100644 md4.h delete mode 100644 md5.c delete mode 100644 md5.h delete mode 100644 mgf-def.h delete mode 100644 mgf.h create mode 100644 misc/Makefile.am create mode 100644 misc/gfshare-mktab.c create mode 100644 misc/gfshare.c create mode 100644 misc/gfshare.h create mode 100644 misc/share.c create mode 100644 misc/share.h delete mode 100755 mkpgroups delete mode 100644 mkphrase.c delete mode 100644 modes.am.in delete mode 100644 mp-arith.c delete mode 100644 mp-const.c delete mode 100644 mp-exp.c delete mode 100644 mp-exp.h delete mode 100644 mp-fibonacci.c delete mode 100644 mp-gcd.c delete mode 100644 mp-io.c delete mode 100644 mp-jacobi.c delete mode 100644 mp-mem.c delete mode 100644 mp-misc.c delete mode 100644 mp-modexp.c delete mode 100644 mp-modsqrt.c delete mode 100644 mp-sqrt.c delete mode 100644 mp-test.c delete mode 100644 mp.h delete mode 100644 mparena.c delete mode 100644 mparena.h delete mode 100644 mpbarrett-exp.c delete mode 100644 mpbarrett-exp.h delete mode 100644 mpbarrett-mexp.c delete mode 100644 mpbarrett.c delete mode 100644 mpbarrett.h delete mode 100644 mpcrt.c delete mode 100644 mpcrt.h delete mode 100644 mpdump.c delete mode 100644 mpint.c delete mode 100644 mpint.h delete mode 100644 mpmont-exp.c delete mode 100644 mpmont-exp.h delete mode 100644 mpmont-mexp.c delete mode 100644 mpmont.c delete mode 100644 mpmont.h delete mode 100644 mpmul.c delete mode 100644 mpmul.h delete mode 100644 mprand.c delete mode 100644 mprand.h delete mode 100644 mpreduce-exp.h delete mode 100644 mpreduce.c delete mode 100644 mpreduce.h delete mode 100644 mpscan.c delete mode 100644 mpscan.h delete mode 100644 mptext-dstr.c delete mode 100644 mptext-file.c delete mode 100644 mptext-len.c delete mode 100644 mptext-string.c delete mode 100644 mptext.c delete mode 100644 mptext.h delete mode 100644 mptypes.c delete mode 100644 mpw.h delete mode 100644 mpx-kmul.c delete mode 100644 mpx-ksqr.c delete mode 100644 mpx.c delete mode 100644 mpx.h delete mode 100644 noekeon.c delete mode 100644 noekeon.h delete mode 100644 noise.c delete mode 100644 noise.h delete mode 100644 oaep.c delete mode 100644 ofb-def.h delete mode 100644 ofb.h delete mode 100755 p-gentab.awk delete mode 100644 paranoia.h delete mode 100644 passphrase.c delete mode 100644 passphrase.h delete mode 100644 pcheck.pl delete mode 100644 perftest.c delete mode 100644 pfilt.c delete mode 100644 pfilt.h delete mode 100644 pgen-gcd.c delete mode 100644 pgen-simul.c delete mode 100644 pgen-stdev.c delete mode 100644 pgen.c delete mode 100644 pgen.h delete mode 100644 pixie-common.c delete mode 100644 pixie.c delete mode 100644 pixie.h delete mode 100644 pkcs1.c delete mode 100644 prim.c delete mode 100644 prim.h delete mode 100644 primeiter.c create mode 100644 progs/Makefile.am rename catcrypt.1 => progs/catcrypt.1 (100%) create mode 100644 progs/catcrypt.c rename catsign.1 => progs/catsign.1 (100%) create mode 100644 progs/catsign.c create mode 100644 progs/cc-enc.c rename cc-hash.c => progs/cc-hash.c (100%) create mode 100644 progs/cc-kem.c create mode 100644 progs/cc-list.c rename cc-progress.c => progs/cc-progress.c (100%) create mode 100644 progs/cc-sig.c create mode 100644 progs/cc-subcmd.c create mode 100644 progs/cc.h rename cookie.1 => progs/cookie.1 (100%) create mode 100644 progs/cookie.c rename dsig.1 => progs/dsig.1 (100%) create mode 100644 progs/dsig.c create mode 100644 progs/factorial.c rename fibonacci.c => progs/fibonacci.c (100%) rename hashsum.1 => progs/hashsum.1 (100%) create mode 100644 progs/hashsum.c rename key.1 => progs/key.1 (100%) create mode 100644 progs/key.c rename keyring.5 => progs/keyring.5 (100%) rename mkphrase.1 => progs/mkphrase.1 (100%) create mode 100644 progs/mkphrase.c create mode 100644 progs/perftest.c rename pixie.1 => progs/pixie.1 (100%) create mode 100644 progs/pixie.c create mode 100644 progs/rspit.c rename xpixie => progs/xpixie (100%) delete mode 100644 pss.c delete mode 100644 ptab.h delete mode 100644 ptab.in create mode 100644 pub/Makefile.am create mode 100644 pub/bbs-fetch.c create mode 100644 pub/bbs-gen.c create mode 100644 pub/bbs-jump.c create mode 100644 pub/bbs-rand.c create mode 100644 pub/bbs.h create mode 100644 pub/dh-check.c create mode 100644 pub/dh-fetch.c create mode 100644 pub/dh-gen.c create mode 100644 pub/dh-kcdsa.c create mode 100644 pub/dh-limlee.c create mode 100644 pub/dh-param.c create mode 100644 pub/dh.h create mode 100644 pub/dsa-check.c create mode 100644 pub/dsa-gen.c rename dsa-misc.c => pub/dsa-misc.c (100%) create mode 100644 pub/dsa-sign.c create mode 100644 pub/dsa-verify.c create mode 100644 pub/dsa.h create mode 100644 pub/gdsa.c create mode 100644 pub/gdsa.h create mode 100644 pub/gkcdsa.c create mode 100644 pub/gkcdsa.h create mode 100644 pub/keycheck-mp.c create mode 100644 pub/keycheck-report.c create mode 100644 pub/keycheck.c create mode 100644 pub/keycheck.h create mode 100644 pub/oaep.c create mode 100644 pub/pkcs1.c create mode 100644 pub/pss.c create mode 100644 pub/rsa-fetch.c create mode 100644 pub/rsa-gen.c create mode 100644 pub/rsa-priv.c create mode 100644 pub/rsa-pub.c create mode 100644 pub/rsa-recover.c create mode 100644 pub/rsa-test.c create mode 100644 pub/rsa.h create mode 100644 pub/t/bbs create mode 100644 pub/t/dsa create mode 100644 pub/t/gdsa create mode 100644 pub/t/gkcdsa create mode 100644 pub/t/rsa delete mode 100644 qdparse.c delete mode 100644 qdparse.h delete mode 100644 rabin.c delete mode 100644 rabin.h delete mode 100644 rand.c delete mode 100644 rand.h create mode 100644 rand/Makefile.am create mode 100644 rand/dsarand.c create mode 100644 rand/dsarand.h create mode 100644 rand/fibrand.c create mode 100644 rand/fibrand.h create mode 100644 rand/fipstest.c create mode 100644 rand/fipstest.h create mode 100644 rand/grand.c create mode 100644 rand/grand.h create mode 100644 rand/lcrand.c create mode 100644 rand/lcrand.h create mode 100644 rand/maurer.c create mode 100644 rand/maurer.h create mode 100644 rand/noise.c create mode 100644 rand/noise.h create mode 100644 rand/rand.c create mode 100644 rand/rand.h create mode 100644 rand/sslprf.c create mode 100644 rand/sslprf.h create mode 100644 rand/t/lcrand create mode 100644 rand/t/sslprf create mode 100644 rand/t/tlsprf create mode 100644 rand/tlsprf.c create mode 100644 rand/tlsprf.h delete mode 100644 rc2-tab.h delete mode 100644 rc2.c delete mode 100644 rc2.h delete mode 100644 rc4.c delete mode 100644 rc4.h delete mode 100644 rc5.c delete mode 100644 rc5.h delete mode 100644 rho.c delete mode 100644 rho.h delete mode 100644 rijndael-base.c delete mode 100644 rijndael-base.h delete mode 100644 rijndael-mktab.c delete mode 100644 rijndael.c delete mode 100644 rijndael.h delete mode 100644 rijndael192.c delete mode 100644 rijndael192.h delete mode 100644 rijndael256.c delete mode 100644 rijndael256.h delete mode 100644 rmd128.c delete mode 100644 rmd128.h delete mode 100644 rmd160.c delete mode 100644 rmd160.h delete mode 100644 rmd256.c delete mode 100644 rmd256.h delete mode 100644 rmd320.c delete mode 100644 rmd320.h delete mode 100644 rsa-fetch.c delete mode 100644 rsa-gen.c delete mode 100644 rsa-priv.c delete mode 100644 rsa-pub.c delete mode 100644 rsa-recover.c delete mode 100644 rsa-test.c delete mode 100644 rsa.h delete mode 100644 rspit.c delete mode 100644 safer-mktab.c delete mode 100644 safer.c delete mode 100644 safer.h delete mode 100644 safersk.c delete mode 100644 safersk.h delete mode 100644 seal.c delete mode 100644 seal.h delete mode 100644 serpent-check.c delete mode 100644 serpent-sbox.h delete mode 100644 serpent.c delete mode 100644 serpent.h delete mode 100644 sha.c delete mode 100644 sha.h delete mode 100644 sha224.c delete mode 100644 sha224.h delete mode 100644 sha256.c delete mode 100644 sha256.h delete mode 100644 sha384.c delete mode 100644 sha384.h delete mode 100644 sha512.c delete mode 100644 sha512.h delete mode 100644 share.c delete mode 100644 share.h delete mode 100644 skipjack-tab.h delete mode 100644 skipjack.c delete mode 100644 skipjack.h delete mode 100644 square-mktab.c delete mode 100644 square.c delete mode 100644 square.h delete mode 100644 sslprf.c delete mode 100644 sslprf.h delete mode 100644 strongprime.c delete mode 100644 strongprime.h create mode 100644 symm/Makefile.am rename {tests => symm}/aes-trans (100%) create mode 100644 symm/blkc.h create mode 100644 symm/blowfish-mktab.c create mode 100644 symm/blowfish.c create mode 100644 symm/blowfish.h create mode 100644 symm/cast-base.h create mode 100644 symm/cast-s.c create mode 100644 symm/cast-sk.c create mode 100644 symm/cast-tab.h create mode 100644 symm/cast128.c create mode 100644 symm/cast128.h create mode 100644 symm/cast256.c create mode 100644 symm/cast256.h create mode 100644 symm/cbc-def.h create mode 100644 symm/cbc.h create mode 100644 symm/cfb-def.h create mode 100644 symm/cfb.h create mode 100644 symm/counter-def.h create mode 100644 symm/counter.h create mode 100644 symm/crc32.c create mode 100644 symm/crc32.h create mode 100644 symm/daftstory.h create mode 100644 symm/des-base.c create mode 100644 symm/des-base.h create mode 100644 symm/des-mktab.c create mode 100644 symm/des.c create mode 100644 symm/des.h create mode 100644 symm/des3.c create mode 100644 symm/des3.h create mode 100644 symm/desx-tab.h create mode 100644 symm/desx.c create mode 100644 symm/desx.h create mode 100644 symm/ecb-def.h create mode 100644 symm/ecb.h create mode 100644 symm/gcipher.h create mode 100644 symm/ghash-def.h create mode 100644 symm/ghash.h create mode 100644 symm/gmac.h rename gthingtab.c.in => symm/gthingtab.c.in (100%) create mode 100644 symm/has160.c create mode 100644 symm/has160.h create mode 100644 symm/hash.h create mode 100644 symm/hmac-def.h create mode 100644 symm/hmac.h create mode 100644 symm/idea.c create mode 100644 symm/idea.h create mode 100644 symm/mars-mktab.c create mode 100644 symm/mars.c create mode 100644 symm/mars.h create mode 100644 symm/md2-tab.h create mode 100644 symm/md2.c create mode 100644 symm/md2.h create mode 100644 symm/md4.c create mode 100644 symm/md4.h create mode 100644 symm/md5.c create mode 100644 symm/md5.h create mode 100644 symm/mgf-def.h create mode 100644 symm/mgf.h rename mode.c.in => symm/mode.c.in (100%) rename mode.h.in => symm/mode.h.in (100%) create mode 100644 symm/modes.am.in rename multigen => symm/multigen (100%) create mode 100644 symm/noekeon.c create mode 100644 symm/noekeon.h create mode 100644 symm/ofb-def.h create mode 100644 symm/ofb.h create mode 100644 symm/rc2-tab.h create mode 100644 symm/rc2.c create mode 100644 symm/rc2.h create mode 100644 symm/rc4.c create mode 100644 symm/rc4.h create mode 100644 symm/rc5.c create mode 100644 symm/rc5.h create mode 100644 symm/rijndael-base.c create mode 100644 symm/rijndael-base.h create mode 100644 symm/rijndael-mktab.c create mode 100644 symm/rijndael.c create mode 100644 symm/rijndael.h create mode 100644 symm/rijndael192.c create mode 100644 symm/rijndael192.h create mode 100644 symm/rijndael256.c create mode 100644 symm/rijndael256.h create mode 100644 symm/rmd128.c create mode 100644 symm/rmd128.h create mode 100644 symm/rmd160.c create mode 100644 symm/rmd160.h create mode 100644 symm/rmd256.c create mode 100644 symm/rmd256.h create mode 100644 symm/rmd320.c create mode 100644 symm/rmd320.h create mode 100644 symm/safer-mktab.c create mode 100644 symm/safer.c create mode 100644 symm/safer.h create mode 100644 symm/safersk.c create mode 100644 symm/safersk.h create mode 100644 symm/seal.c create mode 100644 symm/seal.h create mode 100644 symm/serpent-check.c create mode 100644 symm/serpent-sbox.h create mode 100644 symm/serpent.c create mode 100644 symm/serpent.h create mode 100644 symm/sha.c create mode 100644 symm/sha.h create mode 100644 symm/sha224.c create mode 100644 symm/sha224.h create mode 100644 symm/sha256.c create mode 100644 symm/sha256.h create mode 100644 symm/sha384.c create mode 100644 symm/sha384.h create mode 100644 symm/sha512.c create mode 100644 symm/sha512.h create mode 100644 symm/skipjack-tab.h create mode 100644 symm/skipjack.c create mode 100644 symm/skipjack.h create mode 100644 symm/square-mktab.c create mode 100644 symm/square.c create mode 100644 symm/square.h create mode 100644 symm/t/.gitignore create mode 100644 symm/t/blowfish create mode 100644 symm/t/cast128 rename {tests => symm/t}/cast256.aes (100%) create mode 100644 symm/t/des create mode 100644 symm/t/des3 create mode 100644 symm/t/desx create mode 100644 symm/t/has160 create mode 100644 symm/t/idea rename {tests => symm/t}/mars.aes (100%) create mode 100644 symm/t/md2 create mode 100644 symm/t/md4 create mode 100644 symm/t/md5 create mode 100644 symm/t/noekeon create mode 100644 symm/t/rc2 create mode 100644 symm/t/rc4 create mode 100644 symm/t/rc5 rename {tests => symm/t}/rijndael.aes (100%) create mode 100644 symm/t/rijndael192 create mode 100644 symm/t/rijndael256 create mode 100644 symm/t/rmd128 create mode 100644 symm/t/rmd160 create mode 100644 symm/t/rmd256 create mode 100644 symm/t/rmd320 create mode 100644 symm/t/safer create mode 100644 symm/t/safersk create mode 100644 symm/t/seal rename {tests => symm/t}/serpent.aes (100%) create mode 100644 symm/t/sha create mode 100644 symm/t/sha224 create mode 100644 symm/t/sha256 create mode 100644 symm/t/sha384 create mode 100644 symm/t/sha512 create mode 100644 symm/t/skipjack create mode 100644 symm/t/square create mode 100644 symm/t/tea rename {tests => symm/t}/tea-test.c (100%) create mode 100644 symm/t/tiger rename {tests => symm/t}/twofish.aes (100%) create mode 100644 symm/t/whirlpool create mode 100644 symm/t/whirlpool256 create mode 100644 symm/t/xtea rename {tests => symm/t}/xtea-test.c (100%) create mode 100644 symm/tea.c create mode 100644 symm/tea.h create mode 100644 symm/tiger-base.h create mode 100644 symm/tiger-mktab.c create mode 100644 symm/tiger.c create mode 100644 symm/tiger.h create mode 100644 symm/twofish-mktab.c create mode 100644 symm/twofish.c create mode 100644 symm/twofish.h create mode 100644 symm/whirlpool-mktab.c create mode 100644 symm/whirlpool.c create mode 100644 symm/whirlpool.h create mode 100644 symm/whirlpool256.c create mode 100644 symm/whirlpool256.h create mode 100644 symm/xtea.c create mode 100644 symm/xtea.h delete mode 100644 tea.c delete mode 100644 tea.h delete mode 100644 tests/.gitignore delete mode 100644 tests/bbs delete mode 100644 tests/blowfish delete mode 100644 tests/cast128 delete mode 100644 tests/des delete mode 100644 tests/des3 delete mode 100644 tests/desx delete mode 100644 tests/dsa delete mode 100644 tests/ec delete mode 100644 tests/gdsa delete mode 100644 tests/gf delete mode 100644 tests/gfn delete mode 100644 tests/gfreduce delete mode 100644 tests/gfx delete mode 100644 tests/gkcdsa delete mode 100644 tests/group delete mode 100644 tests/has160 delete mode 100644 tests/idea delete mode 100644 tests/lcrand delete mode 100644 tests/md2 delete mode 100644 tests/md4 delete mode 100644 tests/md5 delete mode 100644 tests/mp delete mode 100644 tests/mpbarrett delete mode 100644 tests/mpcrt delete mode 100644 tests/mpint delete mode 100644 tests/mpmont delete mode 100644 tests/mpreduce delete mode 100644 tests/mptext delete mode 100644 tests/mpx delete mode 100755 tests/mpx-gen delete mode 100644 tests/noekeon delete mode 100644 tests/pgen delete mode 100644 tests/rc2 delete mode 100644 tests/rc4 delete mode 100644 tests/rc5 delete mode 100644 tests/rijndael192 delete mode 100644 tests/rijndael256 delete mode 100644 tests/rmd128 delete mode 100644 tests/rmd160 delete mode 100644 tests/rmd256 delete mode 100644 tests/rmd320 delete mode 100644 tests/rsa delete mode 100644 tests/safer delete mode 100644 tests/safersk delete mode 100644 tests/seal delete mode 100644 tests/sha delete mode 100644 tests/sha224 delete mode 100644 tests/sha256 delete mode 100644 tests/sha384 delete mode 100644 tests/sha512 delete mode 100644 tests/skipjack delete mode 100644 tests/square delete mode 100644 tests/sslprf delete mode 100644 tests/tea delete mode 100644 tests/tiger delete mode 100644 tests/tlsprf delete mode 100644 tests/whirlpool delete mode 100644 tests/whirlpool256 delete mode 100644 tests/xtea delete mode 100644 tiger-base.h delete mode 100644 tiger-mktab.c delete mode 100644 tiger.c delete mode 100644 tiger.h delete mode 100644 tlsprf.c delete mode 100644 tlsprf.h delete mode 100644 twofish-mktab.c delete mode 100644 twofish.c delete mode 100644 twofish.h create mode 100644 vars.am delete mode 100644 whirlpool-mktab.c delete mode 100644 whirlpool.c delete mode 100644 whirlpool.h delete mode 100644 whirlpool256.c delete mode 100644 whirlpool256.h delete mode 100644 xtea.c delete mode 100644 xtea.h diff --git a/.gitignore b/.gitignore index 41bc25f..e849112 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,11 @@ -KEYRING Makefile.in aclocal.m4 configure COPYING.LIB autom4te.cache config -getdate.h -getdate.y -prof -tinymp -*.kr -*.kr.old -ylwrap -modes.am -auto-version -confsubst +progs/getdate.h +progs/getdate.y +symm/modes.am +*.t +*.to diff --git a/.links b/.links index 161dfb0..a6772a4 100644 --- a/.links +++ b/.links @@ -1,5 +1,5 @@ COPYING.LIB -getdate.y -getdate.h config/auto-version config/confsubst +progs/getdate.h +progs/getdate.y diff --git a/Makefile.am b/Makefile.am index 11251fa..4cacfbe 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,1066 +24,53 @@ ### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, ### MA 02111-1307, USA. -###-------------------------------------------------------------------------- -### Miscellaneous useful definitions. - -## Some convenient abbreviations for file suffixes. -e = $(EXEEXT) -o = $(OBJEXT) -t = t$e - -## Installation directories. -archincludedir = $(pkglibdir)/include - -###-------------------------------------------------------------------------- -### Initial values of common variables. +include $(top_srcdir)/vars.am SUBDIRS = -EXTRA_DIST = -CLEANFILES = -DISTCLEANFILES = -MAINTAINERCLEANFILES = -SUFFIXES = -TESTS = -BUILT_SOURCES = - -bin_PROGRAMS = -noinst_PROGRAMS = -lib_LTLIBRARIES = -noinst_LTLIBRARIES = -pkginclude_HEADERS = -nodist_pkginclude_HEADERS = -archinclude_HEADERS = -nodist_archinclude_HEADERS = -dist_man_MANS = - -###-------------------------------------------------------------------------- -### Standard configuration substitutions. - -## Substitute tags in files. -confsubst = $(top_srcdir)/config/confsubst -EXTRA_DIST += config/confsubst - -SUBSTITUTIONS = \ - prefix=$(prefix) exec_prefix=$(exec_prefix) \ - libdir=$(libdir) includedir=$(includedir) \ - PACKAGE=$(PACKAGE) VERSION=$(VERSION) \ - CATACOMB_LIBS="$(CATACOMB_LIBS)" - -V_SUBST = $(V_SUBST_$(V)) -V_SUBST_ = $(V_SUBST_$(AM_DEFAULT_VERBOSITY)) -V_SUBST_0 = @echo " SUBST $@"; -SUBST = $(V_SUBST)$(confsubst) - ###-------------------------------------------------------------------------- ### The main library. -lib_LTLIBRARIES += libcatacomb.la -libcatacomb_la_LIBADD = $(CATACOMB_LIBS) $(mLib_LIBS) +lib_LTLIBRARIES = libcatacomb.la libcatacomb_la_LDFLAGS = -version-info $(LIBTOOL_VERSION_INFO) +libcatacomb_la_LIBADD = $(CATACOMB_LIBS) $(mLib_LIBS) libcatacomb_la_SOURCES = -nodist_libcatacomb_la_SOURCES = - -###-------------------------------------------------------------------------- -### Basic utilities. - -## The locked-memory arena. -pkginclude_HEADERS += arena.h -libcatacomb_la_SOURCES += arena.c - -## Constant-type operations. -pkginclude_HEADERS += ct.h -libcatacomb_la_SOURCES += ct.c - -## Acceptable key-size descriptions. -pkginclude_HEADERS += keysz.h -libcatacomb_la_SOURCES += keysz.c keysz-conv.c - -## System-level memory locking. -pkginclude_HEADERS += lmem.h -libcatacomb_la_SOURCES += lmem.c - -## Clearing secrets from memory. -pkginclude_HEADERS += paranoia.h - -###-------------------------------------------------------------------------- -### Main multiprecision integer library. - -## This library is unfortunately intertwined with some of the code generation -## programs, so we must be rather careful. The important bits of the maths -## library needed by these programs is separated out into `libmpbase'. There -## is work going on to fix this unpleasant situation by generating the -## relevant files from Python scripts rather than C programs, using -## information gathered by `configure'. -noinst_LTLIBRARIES += libmpbase.la -libcatacomb_la_LIBADD += libmpbase.la -libmpbase_la_LIBADD = $(mLib_LIBS) -libmpbase_la_SOURCES = -$(libmpbase_la_OBJECTS): mptypes.h - -## Additional buffer I/O functions for mathematical objects. -pkginclude_HEADERS += buf.h -libcatacomb_la_SOURCES += buf.c - -## Infrastructure for fast exponentiation. -pkginclude_HEADERS += exp.h -libcatacomb_la_SOURCES += exp.c - -## Main user-visible multiprecision arithmetic. -pkginclude_HEADERS += mp.h -libmpbase_la_SOURCES += mp-arith.c -TESTS += mp-arith.$t -libmpbase_la_SOURCES += mp-const.c -libcatacomb_la_SOURCES += mp-exp.c mp-exp.h -libcatacomb_la_SOURCES += mp-gcd.c -TESTS += mp-gcd.$t -libmpbase_la_SOURCES += mp-io.c -libcatacomb_la_SOURCES += mp-jacobi.c -TESTS += mp-jacobi.$t -libmpbase_la_SOURCES += mp-mem.c -libmpbase_la_SOURCES += mp-misc.c -libcatacomb_la_SOURCES += mp-modexp.c -TESTS += mp-modexp.$t -libcatacomb_la_SOURCES += mp-modsqrt.c -TESTS += mp-modsqrt.$t -libcatacomb_la_SOURCES += mp-sqrt.c -TESTS += mp-sqrt.$t -libcatacomb_la_SOURCES += mp-test.c -EXTRA_DIST += tests/mp - -## Computing Fibonacci numbers. -pkginclude_HEADERS += mp-fibonacci.h -libcatacomb_la_SOURCES += mp-fibonacci.c -TESTS += mp-fibonacci.$t - -## Special memory allocation for multiprecision integers. -pkginclude_HEADERS += mparena.h -libmpbase_la_SOURCES += mparena.c - -## Barrett reduction, an efficient method for modular reduction. -pkginclude_HEADERS += mpbarrett.h -libcatacomb_la_SOURCES += mpbarrett.c -TESTS += mpbarrett.$t -libcatacomb_la_SOURCES += mpbarrett-exp.c mpbarrett-mexp.c mpbarrett-exp.h -TESTS += mpbarrett-exp.$t mpbarrett-mexp.$t -EXTRA_DIST += tests/mpbarrett - -## Solving congruences using the Chinese Remainder Theorem. -pkginclude_HEADERS += mpcrt.h -libcatacomb_la_SOURCES += mpcrt.c -TESTS += mpcrt.$t -EXTRA_DIST += tests/mpcrt - -## Conversions between machine-native and multiprecision integers. -pkginclude_HEADERS += mpint.h -libcatacomb_la_SOURCES += mpint.c -TESTS += mpint.$t -EXTRA_DIST += tests/mpint - -## Table of upper and lower limits of various types of machine integers, as -## multiprecision integers. -nodist_archinclude_HEADERS += mplimits.h -nodist_libcatacomb_la_SOURCES += mplimits.c -CLEANFILES += mplimits.h mplimits.c -noinst_PROGRAMS += genlimits -genlimits_LDADD = libmpbase.la -mplimits.c: genlimits$e - $(AM_V_GEN)./genlimits c >mplimits.c.new && \ - mv mplimits.c.new mplimits.c -mplimits.h: genlimits$e - $(AM_V_GEN)./genlimits h >mplimits.h.new && \ - mv mplimits.h.new mplimits.h -$(genlimits_OBJECTS): mptypes.h -mplimits.lo: mplimits.h - -## Montgomery reduction, a clever method for modular arithmetic. -pkginclude_HEADERS += mpmont.h -libcatacomb_la_SOURCES += mpmont.c -TESTS += mpmont.$t -libcatacomb_la_SOURCES += mpmont-exp.c mpmont-mexp.c mpmont-exp.h -TESTS += mpmont-exp.$t mpmont-mexp.$t -EXTRA_DIST += tests/mpmont - -## Efficient multiplication of many small numbers. -pkginclude_HEADERS += mpmul.h -libcatacomb_la_SOURCES += mpmul.c -TESTS += mpmul.$t - -## Generating random numbers. -pkginclude_HEADERS += mprand.h -libcatacomb_la_SOURCES += mprand.c - -## Efficient reduction modulo numbers with conveninent binary -## representations. -pkginclude_HEADERS += mpreduce.h -libcatacomb_la_SOURCES += mpreduce.c mpreduce-exp.h -TESTS += mpreduce.$t -EXTRA_DIST += tests/mpreduce - -## Iteratiion over the bianry representation of multiprecision integers. -pkginclude_HEADERS += mpscan.h -libmpbase_la_SOURCES += mpscan.c - -## Conversion between multiprecision integers and their textual -## representations. -pkginclude_HEADERS += mptext.h -libmpbase_la_SOURCES += mptext.c -TESTS += mptext.$t -libcatacomb_la_SOURCES += mptext-dstr.c -libcatacomb_la_SOURCES += mptext-file.c -libcatacomb_la_SOURCES += mptext-len.c -libmpbase_la_SOURCES += mptext-string.c -EXTRA_DIST += tests/mptext - -## Basic types used in the representation of multiprecision integers. -nodist_archinclude_HEADERS += mptypes.h -BUILT_SOURCES += mptypes.h -CLEANFILES += mptypes.h -noinst_PROGRAMS += mptypes -mptypes.h: mptypes$e - $(AM_V_GEN)./mptypes >mptypes.h.new && mv mptypes.h.new mptypes.h - -## Low-level multiprecision arithmetic. -pkginclude_HEADERS += mpx.h bitops.h mpw.h -libmpbase_la_SOURCES += mpx.c -TESTS += mpx.$t -libmpbase_la_SOURCES += karatsuba.h mpx-kmul.c mpx-ksqr.c -TESTS += mpx-kmul.$t mpx-ksqr.$t -noinst_PROGRAMS += bittest -TESTS += bittest -EXTRA_DIST += tests/mpx - -## A quick-and-dirty parser, used for parsing descriptions of groups, fields, -## etc. -pkginclude_HEADERS += rho.h -libcatacomb_la_SOURCES += rho.c -TESTS += rho.$t - -## Pollard's `rho' algorithm for determining discrete logarithms. -pkginclude_HEADERS += qdparse.h -libcatacomb_la_SOURCES += qdparse.c - -###-------------------------------------------------------------------------- -### Prime number checking, searching, and related jobs. - -## Generating Lim--Lee groups, i.e., unit groups of finite fields without -## small subgroups (except for the obvious ones). -pkginclude_HEADERS += limlee.h -libcatacomb_la_SOURCES += limlee.c - -## A table of small prime numbers. -nodist_pkginclude_HEADERS += primetab.h -nodist_libcatacomb_la_SOURCES += primetab.c -CLEANFILES += primetab.h primetab.c -BUILT_SOURCES += primetab.h primetab.c -noinst_PROGRAMS += genprimes -genprimes_LDADD = $(mLib_LIBS) -primetab.h: primetab.c -primetab.c: genprimes$e - $(AM_V_GEN)./genprimes -hprimetab.h -cprimetab.c \ - -sCATACOMB_PRIMETAB_H \ - -n256 -t"unsigned short" -iprimetab - -## Filtering candidate prime numbers by checking for small factors -## efficiently. -pkginclude_HEADERS += pfilt.h -libcatacomb_la_SOURCES += pfilt.c - -## Generating prime numbers (and other kinds of numbers which need searching -## for). -pkginclude_HEADERS += pgen.h -libcatacomb_la_SOURCES += pgen.c -libcatacomb_la_SOURCES += pgen-gcd.c -libcatacomb_la_SOURCES += pgen-simul.c -libcatacomb_la_SOURCES += pgen-stdev.c -TESTS += pgen.$t -EXTRA_DIST += tests/pgen - -## Finding primitive elements in finite fields. -pkginclude_HEADERS += prim.h -libcatacomb_la_SOURCES += prim.c - -## Iterating over all prime numbers from a given starting point. -pkginclude_HEADERS += primeiter.h -libcatacomb_la_SOURCES += primeiter.c -TESTS += primeiter.$t -primeiter.lo: wheel.h - -## The Miller--Rabin primality test. -pkginclude_HEADERS += rabin.h -libcatacomb_la_SOURCES += rabin.c - -## Finding `strong' primes, using Gordon's algorithm. Once upon a time, -## products of these kinds of numbers were harder to factor. -pkginclude_HEADERS += strongprime.h -libcatacomb_la_SOURCES += strongprime.c - -## A `wheel', used by the prime iteration machinery. -nodist_pkginclude_HEADERS += wheel.h -nodist_libcatacomb_la_SOURCES += wheel.c -CLEANFILES += wheel.h wheel.c -noinst_PROGRAMS += genwheel -genwheel_LDADD = $(mLib_LIBS) -wheel.h: wheel.c -wheel.c: genwheel$e - $(AM_V_GEN)./genwheel -hwheel.h -cwheel.c \ - -sCATACOMB_WHEEL_H \ - -n5 -t"unsigned char" -iwheel - -###-------------------------------------------------------------------------- -### Binary polynomial arithmetic. - -## User-visible binary polynomial arithmetic. -pkginclude_HEADERS += gf.h -libcatacomb_la_SOURCES += gf-arith.c -TESTS += gf-arith.$t -libcatacomb_la_SOURCES += gf-exp.c gf-exp.h -libcatacomb_la_SOURCES += gf-gcd.c -TESTS += gf-gcd.$t -EXTRA_DIST += tests/gf - -## Low-level binary polynomial arithmetic. -pkginclude_HEADERS += gfx.h -libcatacomb_la_SOURCES += gfx.c -TESTS += gfx.$t -libcatacomb_la_SOURCES += gfx-kmul.c -TESTS += gfx-kmul.$t -libcatacomb_la_SOURCES += gfx-sqr.c -gfx-sqr.lo: gfx-sqr-tab.h -TESTS += gfx-sqr.$t -CLEANFILES += gfx-sqr-tab.h -noinst_PROGRAMS += gfx-sqr-mktab -gfx-sqr-tab.h: gfx-sqr-mktab$e - $(AM_V_GEN)./gfx-sqr-mktab >gfx-sqr-tab.h.in && \ - mv gfx-sqr-tab.h.in gfx-sqr-tab.h -EXTRA_DIST += tests/gfx - -## Conversions between normal and polynomial basis representations for binary -## fields. -pkginclude_HEADERS += gfn.h -libcatacomb_la_SOURCES += gfn.c -TESTS += gfn.$t -EXTRA_DIST += tests/gfn - -## Efficient reduction modulo sparse polynomials. -pkginclude_HEADERS += gfreduce.h -libcatacomb_la_SOURCES += gfreduce.c gfreduce-exp.h -TESTS += gfreduce.$t -EXTRA_DIST += tests/gfreduce - -###-------------------------------------------------------------------------- -### Abstractions for various kinds of algebraic objects. - -## Abstract cyclic groups. -pkginclude_HEADERS += group.h group-guts.h -libcatacomb_la_SOURCES += group-dstr.c -libcatacomb_la_SOURCES += group-exp.c group-exp.h -libcatacomb_la_SOURCES += group-file.c -libcatacomb_la_SOURCES += group-parse.c -libcatacomb_la_SOURCES += group-stdops.c -libcatacomb_la_SOURCES += group-string.c -libcatacomb_la_SOURCES += g-bin.c -libcatacomb_la_SOURCES += g-prime.c -libcatacomb_la_SOURCES += g-ec.c -EXTRA_DIST += group-test.c -TESTS += group-test.$t -EXTRA_DIST += tests/group - -## Abstract finite fields. -pkginclude_HEADERS += field.h field-guts.h -libcatacomb_la_SOURCES += field.c -libcatacomb_la_SOURCES += field-exp.c field-exp.h -libcatacomb_la_SOURCES += field-parse.c -libcatacomb_la_SOURCES += f-binpoly.c -libcatacomb_la_SOURCES += f-niceprime.c -libcatacomb_la_SOURCES += f-prime.c - -## Table of built-in binary fields. -pkginclude_HEADERS += bintab.h -libcatacomb_la_SOURCES += bintab.c -CLEANFILES += bintab.c -EXTRA_DIST += bintab.in bin-gentab.awk -bintab.c: bintab.in bin-gentab.awk mpdump$e - $(AM_V_GEN)awk -f $(srcdir)/bin-gentab.awk \ - <$(srcdir)/bintab.in >bintab.c.new && \ - mv bintab.c.new bintab.c - -## Table of built-in prime fields. -pkginclude_HEADERS += ptab.h -libcatacomb_la_SOURCES += ptab.c -CLEANFILES += ptab.c -EXTRA_DIST += ptab.in p-gentab.awk -ptab.c: ptab.in p-gentab.awk mpdump$e - $(AM_V_GEN)awk -f $(srcdir)/p-gentab.awk \ - <$(srcdir)/ptab.in >ptab.c.new && \ - mv ptab.c.new ptab.c - -## A utility for building multiprecision integer constants. -noinst_PROGRAMS += mpdump -mpdump_LDADD = libmpbase.la -$(mpdump_OBJECTS): mptypes.h - -###-------------------------------------------------------------------------- -### Elliptic curve arithmetic. - -## Basic elliptic curve arithmetic. -pkginclude_HEADERS += ec.h ec-guts.h -libcatacomb_la_SOURCES += ec.c -libcatacomb_la_SOURCES += ec-exp.c ec-exp.h -libcatacomb_la_SOURCES += ec-info.c -TESTS += ec-info.$t -libcatacomb_la_SOURCES += ec-bin.c -TESTS += ec-bin.$t -libcatacomb_la_SOURCES += ec-prime.c -TESTS += ec-prime.$t -EXTRA_DIST += tests/ec - -## The standard `raw' encoding (`EC2OSP') of elliptic curve points. -pkginclude_HEADERS += ec-raw.h -libcatacomb_la_SOURCES += ec-raw.c - -## Test infrastructure for elliptic curves. -pkginclude_HEADERS += ec-test.h -libcatacomb_la_SOURCES += ec-test.c -TESTS += ec-test.$t - -## A table of built-in elliptic curves. -pkginclude_HEADERS += ectab.h -libcatacomb_la_SOURCES += ectab.c -CLEANFILES += ectab.c -EXTRA_DIST += ectab.in ec-gentab.awk -ectab.c: ectab.in ec-gentab.awk mpdump$e - $(AM_V_GEN)awk -f $(srcdir)/ec-gentab.awk \ - <$(srcdir)/ectab.in >ectab.c.new && \ - mv ectab.c.new ectab.c - -###-------------------------------------------------------------------------- -### Autogenerated lists. - -## Fancy template substitutions. -multigen = python $(srcdir)/multigen -EXTRA_DIST += multigen - -## The heart of this is an enormous cross-product of crypto primitives and -## the corresponding modes of operation. Rather than write it out longhand, -## we generate it using `multigen'. Unfortunately, this needs to be done -## at the Automake level, which causes some interesting bootstrapping -## problems. -include modes.am - -EXTRA_DIST += modes.am.in modes.am -MAINTAINERCLEANFILES += $(srcdir)/modes.am - -## Generate the lists. -$(srcdir)/modes.am: modes.am.in - $(AM_V_GEN)$(multigen) -g $(srcdir)/modes.am.in $(srcdir)/modes.am \ - blkc="$(BLKCS)" \ - blkcmode="$(BLKCMODES)" \ - blkcciphermode="$(BLKCCIPHERMODES)" \ - hash="$(HASHES)" \ - hashmode="$(HASHMODES)" \ - hashciphermode="$(HASHCIPHERMODES)" \ - hashmacmode="$(HASHMACMODES)" - -## Initialize lists of known classes. -ALL_CIPHERS = $(CIPHER_MODES) -ALL_HASHES = $(HASHES) -ALL_MACS = $(MAC_MODES) - -###-------------------------------------------------------------------------- -### Block ciphers. - -BLKCS = -BLKCMODES = - -BLKCCIPHERMODES = -BLKCMODES += $(BLKCCIPHERMODES) - -## A tool for translating the AES-contest test vectors into a form our test -## rigs understand. -EXTRA_DIST += tests/aes-trans - -## Block cipher utility macros, mainly used in mode implementations. -pkginclude_HEADERS += blkc.h - -## Source code and headers for the block ciphers. -libcatacomb_la_SOURCES += $(BLKC_C) -pkginclude_HEADERS += $(BLKC_H) - -## Schneier's `Blowfish' block cipher. -BLKCS += blowfish -blowfish.lo: blowfish-tab.h -CLEANFILES += blowfish-tab.h -noinst_PROGRAMS += blowfish-mktab -blowfish_mktab_CPPFLAGS = $(AM_CPPFLAGS) -DQUIET -blowfish-tab.h: blowfish-mktab$e - $(AM_V_GEN)./blowfish-mktab >blowfish-tab.h.new && \ - mv blowfish-tab.h.new blowfish-tab.h - -## Adams and Tavares' `CAST' block ciphers. -BLKCS += cast128 cast256 -libcatacomb_la_SOURCES += cast-s.c cast-sk.c cast-base.h cast-tab.h -cast256.$t: tests/cast256 -EXTRA_DIST += tests/cast256.aes -MAINTAINERCLEANFILES += $(srcdir)/tests/cast256 -tests/cast256: tests/cast256.aes - $(AM_V_GEN)$(srcdir)/tests/aes-trans CAST256 \ - <$(srcdir)/tests/cast256.aes \ - >$(srcdir)/tests/cast256.new && \ - mv $(srcdir)/tests/cast256.new $(srcdir)/tests/cast256 - -## IBM's `DES' block cipher, by Feistel, Coppersmith, and others. -BLKCS += des des3 -libcatacomb_la_SOURCES += des-base.h des-base.c desx-tab.h -des-base.lo: des-tab.h -CLEANFILES += des-tab.h -noinst_PROGRAMS += des-mktab -des-tab.h: des-mktab$e - $(AM_V_GEN)./des-mktab >des-tab.h.new && \ - mv des-tab.h.new des-tab.h - -## Rivest's `DESX' variant, with pre- and post-whitening. -BLKCS += desx -libcatacomb_la_SOURCES += desx-tab.h - -## Lai and Massey's IDEA. -BLKCS += idea - -## IBM's `MARS' block cipher. -BLKCS += mars -mars.lo: mars-tab.h -CLEANFILES += mars-tab.h -noinst_PROGRAMS += mars-mktab -mars-tab.h: mars-mktab$e - $(AM_V_GEN)./mars-mktab >mars-tab.h.new && \ - mv mars-tab.h.new mars-tab.h -mars.$t: tests/mars -EXTRA_DIST += tests/mars.aes -MAINTAINERCLEANFILES += $(srcdir)/tests/mars -tests/mars: tests/mars.aes - $(AM_V_GEN)$(srcdir)/tests/aes-trans Mars \ - <$(srcdir)/tests/mars.aes \ - >$(srcdir)/tests/mars.new && \ - mv $(srcdir)/tests/mars.new $(srcdir)/tests/mars -## Daemen, Peeters, Van Assche and Rijmen's `Noekeon'. -BLKCS += noekeon +## Basic utilities. +SUBDIRS += base +libcatacomb_la_LIBADD += base/libbase.la -## Rivest's `RC2' block cipher. -BLKCS += rc2 -libcatacomb_la_SOURCES += rc2-tab.h +## Mathematical infrastructure. +SUBDIRS += math +libcatacomb_la_LIBADD += math/libmath.la -## Rivest's `RC5'. -BLKCS += rc5 +## Symmetric cryptography. +SUBDIRS += symm +libcatacomb_la_LIBADD += symm/libsymm.la -## Daemen and Rijmen's `Rijndael' block cipher, selected as AES. -BLKCS += rijndael rijndael192 rijndael256 -libcatacomb_la_SOURCES += rijndael-base.h rijndael-base.c -rijndael-base.lo: rijndael-tab.h -CLEANFILES += rijndael-tab.h -noinst_PROGRAMS += rijndael-mktab -rijndael-tab.h: rijndael-mktab$e - $(AM_V_GEN)./rijndael-mktab >rijndael-tab.h.new && \ - mv rijndael-tab.h.new rijndael-tab.h -rijndael.$t: tests/rijndael -EXTRA_DIST += tests/rijndael.aes -MAINTAINERCLEANFILES += $(srcdir)/tests/rijndael -tests/rijndael: tests/rijndael.aes - $(AM_V_GEN)$(srcdir)/tests/aes-trans Rijndael \ - <$(srcdir)/tests/rijndael.aes \ - >$(srcdir)/tests/rijndael.new && \ - mv $(srcdir)/tests/rijndael.new $(srcdir)/tests/rijndael +## Key management. +SUBDIRS += key +libcatacomb_la_LIBADD += key/libkey.la -## Massey's `SAFER' block ciphers. -BLKCS += safer safersk -safer.lo: safer-tab.h -CLEANFILES += safer-tab.h -noinst_PROGRAMS += safer-mktab -safer-tab.h: safer-mktab$e - $(AM_V_GEN)./safer-mktab >safer-tab.h.new && \ - mv safer-tab.h.new safer-tab.h +## Miscellaneous cryptography. +SUBDIRS += misc +libcatacomb_la_LIBADD += misc/libmisc.la -## Anderson, Biham and Knudsen's `Serpent' block cipher. -BLKCS += serpent -libcatacomb_la_SOURCES += serpent-sbox.h -noinst_PROGRAMS += serpent-check -TESTS += serpent-check -serpent.$t: tests/serpent -EXTRA_DIST += tests/serpent.aes -MAINTAINERCLEANFILES += $(srcdir)/tests/serpent -tests/serpent: tests/serpent.aes - $(AM_V_GEN)$(srcdir)/tests/aes-trans Serpent -v rev=1 \ - <$(srcdir)/tests/serpent.aes \ - >$(srcdir)/tests/serpent.new && \ - mv $(srcdir)/tests/serpent.new $(srcdir)/tests/serpent +## Public-key cryptography. +SUBDIRS += pub +libcatacomb_la_LIBADD += pub/libpub.la -## The National Security Agency's `Skipjack' block cipher. You don't want to -## use this. -BLKCS += skipjack -libcatacomb_la_SOURCES += skipjack-tab.h +## Random number generators and related functionality. +SUBDIRS += rand +libcatacomb_la_LIBADD += rand/librand.la -## Daemen and Rijmen's `Square' block cipher. -BLKCS += square -square.lo: square-tab.h -CLEANFILES += square-tab.h -noinst_PROGRAMS += square-mktab -square-tab.h: square-mktab$e - $(AM_V_GEN)./square-mktab >square-tab.h.new && \ - mv square-tab.h.new square-tab.h - -## Wheeler and Needham's `TEA' and `XTEA' block ciphers. -BLKCS += tea xtea - -## Schneier, Kelsey, Whiting, Wagner, Hall and Ferguson's `Twofish' block -## cipher. -BLKCS += twofish -twofish.lo: twofish-tab.h -CLEANFILES += twofish-tab.h -noinst_PROGRAMS += twofish-mktab -twofish-tab.h: twofish-mktab$e - $(AM_V_GEN)./twofish-mktab >twofish-tab.h.new && \ - mv twofish-tab.h.new twofish-tab.h -twofish.$t: tests/twofish -EXTRA_DIST += tests/twofish.aes -MAINTAINERCLEANFILES += $(srcdir)/tests/twofish -tests/twofish: tests/twofish.aes - $(AM_V_GEN)$(srcdir)/tests/aes-trans Twofish \ - <$(srcdir)/tests/twofish.aes \ - >$(srcdir)/tests/twofish.new && \ - mv $(srcdir)/tests/twofish.new $(srcdir)/tests/twofish - -## The old NIST modes for DES. -BLKCCIPHERMODES += cbc cfb ecb ofb - -## Counter mode. -BLKCCIPHERMODES += counter - -###-------------------------------------------------------------------------- -### Hash functions. - -HASHES = -HASHMODES = - -HASHCIPHERMODES = -HASHMODES += $(HASHCIPHERMODES) - -HASHMACMODES = -HASHMODES += $(HASHMACMODES) - -## Common definitions for hash functions. -pkginclude_HEADERS += hash.h - -## Source code and headers for the hash functions. -libcatacomb_la_SOURCES += $(HASH_C) -pkginclude_HEADERS += $(HASH_H) - -## Lim and KISA's `HAS-160', recommended for use with KCDSA. -HASHES += has160 - -## Rivest's `MD' series of hash functions -HASHES += md2 md4 md5 -libcatacomb_la_SOURCES += md2-tab.h - -## Dobbertin, Bosselaers and Preneel's `RIPEMD' suite. -HASHES += rmd128 rmd160 rmd256 rmd320 - -## The National Security Agency's `SHA-1' hash function. -HASHES += sha - -## The National Security Agency's `SHA-2' suite. -HASHES += sha224 sha256 -HASHES += sha384 sha512 - -## Anderson and Biham's `Tiger' hash function. -HASHES += tiger -libcatacomb_la_SOURCES += tiger-base.h -tiger.lo: tiger-tab.h -CLEANFILES += tiger-tab.h -noinst_PROGRAMS += tiger-mktab -tiger-tab.h: tiger-mktab$e - $(AM_V_GEN)./tiger-mktab >tiger-tab.h.new && \ - mv tiger-tab.h.new tiger-tab.h - -## Barreto and Rijmen's `Whirlpool' hash function. -HASHES += whirlpool whirlpool256 -whirlpool.lo: whirlpool-tab.h -CLEANFILES += whirlpool-tab.h -noinst_PROGRAMS += whirlpool-mktab -whirlpool-tab.h: whirlpool-mktab$e - $(AM_V_GEN)./whirlpool-mktab >whirlpool-tab.h.new && \ - mv whirlpool-tab.h.new whirlpool-tab.h - -## Bellare, Canetti and Krawczyk's `HMAC' mode for message authentication. -HASHMACMODES += hmac - -## MGF1, used in OAEP and PSS. -HASHCIPHERMODES += mgf - -###-------------------------------------------------------------------------- -### Other symmetric primitives. - -## The CRC32 algorithm, which is useful, but has no worthwhile security. -pkginclude_HEADERS += crc32.h -libcatacomb_la_SOURCES += crc32.c -ALL_HASHES += crc32=gcrc32 - -## Rivest's `RC4' stream cipher. -pkginclude_HEADERS += rc4.h -libcatacomb_la_SOURCES += rc4.c -TESTS += rc4.$t -EXTRA_DIST += tests/rc4 -ALL_CIPHERS += rc4 - -## Coppersmith and Rogaway's `SEAL' pseudorandom function. -pkginclude_HEADERS += seal.h -libcatacomb_la_SOURCES += seal.c -TESTS += seal.$t -EXTRA_DIST += tests/seal -ALL_CIPHERS += seal -###-------------------------------------------------------------------------- -### Autogenerated mode implementations. - -## The master stamp file, indicating that we generated all of the sources. -CLEANFILES += modes-gen-stamp -EXTRA_DIST += mode.h.in mode.c.in -modes-gen-stamp: - $(AM_V_at)touch modes-gen-stamp - $(AM_V_GEN)$(multigen) -g $(srcdir)/mode.c.in \ - @base-@mode.c \ - base="$(BLKCS)" mode="$(BLKCMODES)" - $(AM_V_at)$(multigen) -g $(srcdir)/mode.c.in \ - @base-@mode.c \ - base="$(HASHES)" mode="$(HASHMODES)" - $(AM_V_at)$(multigen) -g $(srcdir)/mode.h.in \ - @base-@mode.h \ - base="$(BLKCS)" mode="$(BLKCMODES)" - $(AM_V_at)$(multigen) -g $(srcdir)/mode.h.in \ - @base-@mode.h \ - base="$(HASHES)" mode="$(HASHMODES)" - $(AM_V_at)touch modes-gen-stamp - -## The individual mode interfaces and implementations. -pkginclude_HEADERS += $(MODE_H) - -## Generated implementations. -BUILT_SOURCES += $(GENMODES_C) -CLEANFILES += $(GENMODES_C) -nodist_libcatacomb_la_SOURCES += $(GENMODES_C) -$(GENMODES_C): modes-gen-stamp - -## Generated interfaces. -BUILT_SOURCES += $(GENMODES_H) -CLEANFILES += $(GENMODES_H) -nodist_pkginclude_HEADERS += $(GENMODES_H) -$(GENMODES_H): modes-gen-stamp - -###-------------------------------------------------------------------------- -### Tables of classes for encryption, hashing, and message authentication. - -## The skeleton for the class tables. -EXTRA_DIST += gthingtab.c.in - -## Table of cipher classes. -pkginclude_HEADERS += gcipher.h -CLEANFILES += gciphertab.c -nodist_libcatacomb_la_SOURCES += gciphertab.c -gciphertab.c: gthingtab.c.in - $(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in gciphertab.c \ - what=gcipher cls=gccipher thing="$(ALL_CIPHERS)" - -## Table of hash classes. -pkginclude_HEADERS += ghash.h ghash-def.h -CLEANFILES += ghashtab.c -nodist_libcatacomb_la_SOURCES += ghashtab.c -ghashtab.c: gthingtab.c.in - $(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in ghashtab.c \ - what=ghash cls=gchash thing="$(ALL_HASHES)" - -## Table of MAC classes. -pkginclude_HEADERS += gmac.h -CLEANFILES += gmactab.c -nodist_libcatacomb_la_SOURCES += gmactab.c -gmactab.c: gthingtab.c.in - $(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in gmactab.c \ - what=gmac cls=gcmac thing="$(ALL_MACS)" - -###-------------------------------------------------------------------------- -### Testing for symmetric crypto things. - -## Run the test programs. -TESTS += $(SYMM_TESTS) -EXTRA_DIST += $(SYMM_TEST_FILES) - -## A piece of sample text for round-trip testing encryption modes. -EXTRA_DIST += daftstory.h - -###-------------------------------------------------------------------------- -### Key management. - -## Assistance for elliptic-curve keys. -pkginclude_HEADERS += ec-keys.h -libcatacomb_la_SOURCES += ec-fetch.c - -## Managing keys and keyring files. -pkginclude_HEADERS += key.h -libcatacomb_la_SOURCES += key-attr.c -libcatacomb_la_SOURCES += key-fetch.c -libcatacomb_la_SOURCES += key-file.c -libcatacomb_la_SOURCES += key-io.c -libcatacomb_la_SOURCES += key-misc.c -libcatacomb_la_SOURCES += key-moan.c - -## Managing key data. -pkginclude_HEADERS += key-data.h -libcatacomb_la_SOURCES += key-binary.c -libcatacomb_la_SOURCES += key-data.c -libcatacomb_la_SOURCES += key-flags.c -libcatacomb_la_SOURCES += key-pack.c -libcatacomb_la_SOURCES += key-pass.c -libcatacomb_la_SOURCES += key-text.c - -## Error reporting. -pkginclude_HEADERS += key-error.h -libcatacomb_la_SOURCES += key-error.c - -## Reading passphrases. -pkginclude_HEADERS += passphrase.h -libcatacomb_la_SOURCES += passphrase.c - -## Interfacing with the passphrase pixie. -pkginclude_HEADERS += pixie.h -libcatacomb_la_SOURCES += pixie-common.c - -###-------------------------------------------------------------------------- -### Secret sharing. - -## Efficient sharing over GF(2^8). -pkginclude_HEADERS += gfshare.h -libcatacomb_la_SOURCES += gfshare.c -gfshare.lo: gfshare-tab.h -CLEANFILES += gfshare-tab.h -noinst_PROGRAMS += gfshare-mktab -gfshare-tab.h: gfshare-mktab$e - $(AM_V_GEN)./gfshare-mktab >gfshare-tab.h.new && \ - mv gfshare-tab.h.new gfshare-tab.h -TESTS += gfshare.$t - -## Number-theoretic sharing over GF(p). -pkginclude_HEADERS += share.h -libcatacomb_la_SOURCES += share.c -TESTS += share.$t - -###-------------------------------------------------------------------------- -### Public-key cryptography. - -## The Blum--Blum--Shub random-bit generator. -pkginclude_HEADERS += bbs.h -libcatacomb_la_SOURCES += bbs-fetch.c -libcatacomb_la_SOURCES += bbs-gen.c -libcatacomb_la_SOURCES += bbs-jump.c -TESTS += bbs-jump.$t -libcatacomb_la_SOURCES += bbs-rand.c -TESTS += bbs-rand.$t -EXTRA_DIST += tests/bbs - -## Plain Diffie--Hellman, in Schorr groups. -pkginclude_HEADERS += dh.h -libcatacomb_la_SOURCES += dh-check.c -libcatacomb_la_SOURCES += dh-fetch.c -libcatacomb_la_SOURCES += dh-gen.c -libcatacomb_la_SOURCES += dh-kcdsa.c -libcatacomb_la_SOURCES += dh-limlee.c -libcatacomb_la_SOURCES += dh-param.c -TESTS += dh-param.$t - -## The National Security Agency's Digital Signature Algorithm. -pkginclude_HEADERS += dsa.h -libcatacomb_la_SOURCES += dsa-gen.c -TESTS += dsa-gen.$t -libcatacomb_la_SOURCES += dsa-misc.c -libcatacomb_la_SOURCES += dsa-sign.c -TESTS += dsa-sign.$t -libcatacomb_la_SOURCES += dsa-verify.c -TESTS += dsa-verify.$t -libcatacomb_la_SOURCES += dsa-check.c -EXTRA_DIST += tests/dsa - -## Generalization of DSA to arbitrary cyclic groups. -pkginclude_HEADERS += gdsa.h -libcatacomb_la_SOURCES += gdsa.c -TESTS += gdsa.$t -EXTRA_DIST += tests/gdsa - -## KISA `KCDSA', generalized to arbitrary cyclic groups. -pkginclude_HEADERS += gkcdsa.h -libcatacomb_la_SOURCES += gkcdsa.c -TESTS += gkcdsa.$t -EXTRA_DIST += tests/gkcdsa - -## General key validity checking machinery. -pkginclude_HEADERS += keycheck.h -libcatacomb_la_SOURCES += keycheck.c -libcatacomb_la_SOURCES += keycheck-mp.c -libcatacomb_la_SOURCES += keycheck-report.c - -## The Rivest--Shamir--Adleman trapdoor one-way function. -pkginclude_HEADERS += rsa.h -libcatacomb_la_SOURCES += rsa-fetch.c -libcatacomb_la_SOURCES += rsa-gen.c -libcatacomb_la_SOURCES += rsa-priv.c -libcatacomb_la_SOURCES += rsa-pub.c -libcatacomb_la_SOURCES += rsa-recover.c -libcatacomb_la_SOURCES += oaep.c -libcatacomb_la_SOURCES += pkcs1.c -libcatacomb_la_SOURCES += pss.c -EXTRA_DIST += rsa-test.c -TESTS += rsa-test.$t -EXTRA_DIST += tests/rsa +## At this point, we should construct the library. +SUBDIRS += . ###-------------------------------------------------------------------------- -### Random number generators. - -## The FIPS186 generator used to generate DSA domain parameters. -pkginclude_HEADERS += dsarand.h -libcatacomb_la_SOURCES += dsarand.c - -## Knuth's lagged-Fibonacci generator. -pkginclude_HEADERS += fibrand.h -libcatacomb_la_SOURCES += fibrand.c - -## The FIPS 140--2 random number generator tests. -pkginclude_HEADERS += fipstest.h -libcatacomb_la_SOURCES += fipstest.c - -## Interface for generic random number sources. -pkginclude_HEADERS += grand.h -libcatacomb_la_SOURCES += grand.c +### Ancillary programs. -## A simple linear-congruential generator. -pkginclude_HEADERS += lcrand.h -libcatacomb_la_SOURCES += lcrand.c -TESTS += lcrand.$t -EXTRA_DIST += tests/lcrand - -## Maurer's universal statistical test. -pkginclude_HEADERS += maurer.h -libcatacomb_la_SOURCES += maurer.c - -## System-specific noise acquisition. -pkginclude_HEADERS += noise.h -libcatacomb_la_SOURCES += noise.c - -## Cryptographic laundering for true random data generation. -pkginclude_HEADERS += rand.h -libcatacomb_la_SOURCES += rand.c - -## The SSL v3 pseudorandom function. -pkginclude_HEADERS += sslprf.h -libcatacomb_la_SOURCES += sslprf.c -TESTS += sslprf.$t -EXTRA_DIST += tests/sslprf - -## The TLS v1 pseudorandom function. -pkginclude_HEADERS += tlsprf.h -libcatacomb_la_SOURCES += tlsprf.c -TESTS += tlsprf.$t -EXTRA_DIST += tests/tlsprf - -###-------------------------------------------------------------------------- -### The `catcrypt' library. - -noinst_LTLIBRARIES += libcatcrypt.la -libcatcrypt_la_SOURCES = - -## The main library. -libcatcrypt_la_SOURCES += cc.h -libcatcrypt_la_SOURCES += cc-enc.c -libcatcrypt_la_SOURCES += cc-hash.c -libcatcrypt_la_SOURCES += cc-kem.c -libcatcrypt_la_SOURCES += cc-list.c -libcatcrypt_la_SOURCES += cc-progress.c -libcatcrypt_la_SOURCES += cc-sig.c -libcatcrypt_la_SOURCES += cc-subcmd.c - -## Date parsing. -libcatcrypt_la_SOURCES += getdate.h -libcatcrypt_la_SOURCES += getdate.y - -###-------------------------------------------------------------------------- -### Utility programs. - -UTILS_LIBS = libcatcrypt.la libcatacomb.la $(mLib_LIBS) $(LIBS) - -## Generate and verify datestamped cookies. -bin_PROGRAMS += cookie -cookie_LDADD = $(UTILS_LIBS) -dist_man_MANS += cookie.1 - -## Asymmetric message encryption and decryption with deniable authentication. -bin_PROGRAMS += catcrypt -catcrypt_LDADD = $(UTILS_LIBS) -dist_man_MANS += catcrypt.1 - -## Signing and verifying files. -bin_PROGRAMS += catsign -catsign_LDADD = $(UTILS_LIBS) -dist_man_MANS += catsign.1 - -## Issue and verify signatures on directory trees. -bin_PROGRAMS += dsig -dsig_LDADD = $(UTILS_LIBS) -dist_man_MANS += dsig.1 - -## Compute factorials to arbitrary precision. -bin_PROGRAMS += factorial -factorial_LDADD = $(UTILS_LIBS) - -## Compute Fibonacci numbers to arbitrary precision. -bin_PROGRAMS += fibonacci -fibonacci_LDADD = $(UTILS_LIBS) - -## Compute hashes of files. -bin_PROGRAMS += hashsum -hashsum_LDADD = $(UTILS_LIBS) -dist_man_MANS += hashsum.1 - -## Key management utility. -bin_PROGRAMS += key -key_SOURCES = keyutil.c -key_LDADD = $(UTILS_LIBS) -dist_man_MANS += key.1 keyring.5 - -## Generate passphrases with given entropy using wordlists and Markov models. -bin_PROGRAMS += mkphrase -mkphrase_LDADD = $(UTILS_LIBS) -dist_man_MANS += mkphrase.1 - -## Performance testing. -bin_PROGRAMS += perftest -perftest_LDADD = $(UTILS_LIBS) - -## Remember passphrases for limited periods of time. -bin_PROGRAMS += pixie -pixie_SOURCES = pixie.c -pixie_LDADD = libcatacomb.la $(mLib_LIBS) $(PIXIE_LIBS) -dist_man_MANS += pixie.1 -EXTRA_DIST += xpixie - -## Generate random data. -bin_PROGRAMS += rspit -rspit_LDADD = $(UTILS_LIBS) - -###-------------------------------------------------------------------------- -### Testing. - -SUFFIXES += .c .$t .to -.c.to: - $(AM_V_CC)$(COMPILE) -c -DTEST_RIG -DSRCDIR=\"$(srcdir)\" $< -o $@ -.to.$t: libcatacomb.la - $(AM_V_CCLD)$(LINK) $< libcatacomb.la $(mLib_LIBS) $(LIBS) -.PRECIOUS: %.to -CLEANFILES += *.to *.$t +SUBDIRS += progs ###-------------------------------------------------------------------------- ### The pkg-config file. @@ -1106,6 +93,7 @@ dist-hook:: ## Additional build tools. EXTRA_DIST += config/auto-version +EXTRA_DIST += config/confsubst ###-------------------------------------------------------------------------- ### Debian. diff --git a/arena.c b/arena.c deleted file mode 100644 index dde8e84..0000000 --- a/arena.c +++ /dev/null @@ -1,65 +0,0 @@ -/* -*-c-*- - * - * $Id: arena.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Abstraction for memory allocation arenas - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include "arena.h" - -/*----- Global variables --------------------------------------------------*/ - -arena *arena_secure = &arena_stdlib; -subarena *arena_subsecure = &sub_global; - -/*----- Static variables --------------------------------------------------*/ - -static subarena sub; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @arena_setsecure@ --- * - * - * Arguments: @arena *a@ = arena to use for secure allocation - * - * Returns: --- - * - * Use: Call at the beginning of the program to set the arena for - * secure allocations. - */ - -void arena_setsecure(arena *a) -{ - arena_secure = a; - subarena_create(&sub, a); - arena_subsecure = ⊂ -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/arena.h b/arena.h deleted file mode 100644 index acae679..0000000 --- a/arena.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*-c-*- - * - * $Id: arena.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Abstraction for memory allocation arenas - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_ARENA_H -#define CATACOMB_ARENA_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -/*----- Global variables --------------------------------------------------*/ - -extern arena *arena_secure; -extern subarena *arena_subsecure; - -/*----- Handy macros ------------------------------------------------------*/ - -#define S_ALLOC(sz) A_ALLOC(arena_secure, sz) -#define S_FREE(sz) A_FREE(arena_secure, sz) - -#define XS_ALLOC(sz) x_alloc(arena_secure, sz) -#define XS_REALLOC(p, sz) x_realloc(arena_secure, p, sz) -#define XS_FREE(p) x_free(arena_secure, p) - -#define S_CREATE(type) A_CREATE(arena_subsecure, type) -#define S_DESTROY(p) A_DESTROY(arena_subsecure, p) - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @arena_setsecure@ --- * - * - * Arguments: @arena *a@ = arena to use for secure allocation - * - * Returns: --- - * - * Use: Call at the beginning of the program to set the arena for - * secure allocations. - */ - -extern void arena_setsecure(arena */*a*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/base/Makefile.am b/base/Makefile.am new file mode 100644 index 0000000..35c86ff --- /dev/null +++ b/base/Makefile.am @@ -0,0 +1,54 @@ +### -*-makefile-*- +### +### Build script for basic utilities +### +### (c) 2013 Straylight/Edgeware +### + +###----- Licensing notice --------------------------------------------------- +### +### This file is part of Catacomb. +### +### Catacomb is free software; you can redistribute it and/or modify +### it under the terms of the GNU Library General Public License as +### published by the Free Software Foundation; either version 2 of the +### License, or (at your option) any later version. +### +### Catacomb is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU Library General Public License for more details. +### +### You should have received a copy of the GNU Library General Public +### License along with Catacomb; if not, write to the Free +### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +### MA 02111-1307, USA. + +include $(top_srcdir)/vars.am + +noinst_LTLIBRARIES = libbase.la +libbase_la_SOURCES = + +###-------------------------------------------------------------------------- +### Component files. + +## The locked-memory arena. +pkginclude_HEADERS += arena.h +libbase_la_SOURCES += arena.c + +## Constant-type operations. +pkginclude_HEADERS += ct.h +libbase_la_SOURCES += ct.c + +## Acceptable key-size descriptions. +pkginclude_HEADERS += keysz.h +libbase_la_SOURCES += keysz.c keysz-conv.c + +## System-level memory locking. +pkginclude_HEADERS += lmem.h +libbase_la_SOURCES += lmem.c + +## Clearing secrets from memory. +pkginclude_HEADERS += paranoia.h + +###----- That's all, folks -------------------------------------------------- diff --git a/base/arena.c b/base/arena.c new file mode 100644 index 0000000..93cbfa5 --- /dev/null +++ b/base/arena.c @@ -0,0 +1,63 @@ +/* -*-c-*- + * + * Abstraction for memory allocation arenas + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include "arena.h" + +/*----- Global variables --------------------------------------------------*/ + +arena *arena_secure = &arena_stdlib; +subarena *arena_subsecure = &sub_global; + +/*----- Static variables --------------------------------------------------*/ + +static subarena sub; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @arena_setsecure@ --- * + * + * Arguments: @arena *a@ = arena to use for secure allocation + * + * Returns: --- + * + * Use: Call at the beginning of the program to set the arena for + * secure allocations. + */ + +void arena_setsecure(arena *a) +{ + arena_secure = a; + subarena_create(&sub, a); + arena_subsecure = ⊂ +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/base/arena.h b/base/arena.h new file mode 100644 index 0000000..70952da --- /dev/null +++ b/base/arena.h @@ -0,0 +1,77 @@ +/* -*-c-*- + * + * Abstraction for memory allocation arenas + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_ARENA_H +#define CATACOMB_ARENA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +/*----- Global variables --------------------------------------------------*/ + +extern arena *arena_secure; +extern subarena *arena_subsecure; + +/*----- Handy macros ------------------------------------------------------*/ + +#define S_ALLOC(sz) A_ALLOC(arena_secure, sz) +#define S_FREE(sz) A_FREE(arena_secure, sz) + +#define XS_ALLOC(sz) x_alloc(arena_secure, sz) +#define XS_REALLOC(p, sz) x_realloc(arena_secure, p, sz) +#define XS_FREE(p) x_free(arena_secure, p) + +#define S_CREATE(type) A_CREATE(arena_subsecure, type) +#define S_DESTROY(p) A_DESTROY(arena_subsecure, p) + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @arena_setsecure@ --- * + * + * Arguments: @arena *a@ = arena to use for secure allocation + * + * Returns: --- + * + * Use: Call at the beginning of the program to set the arena for + * secure allocations. + */ + +extern void arena_setsecure(arena */*a*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/ct.c b/base/ct.c similarity index 100% rename from ct.c rename to base/ct.c diff --git a/ct.h b/base/ct.h similarity index 100% rename from ct.h rename to base/ct.h diff --git a/keysz-conv.c b/base/keysz-conv.c similarity index 100% rename from keysz-conv.c rename to base/keysz-conv.c diff --git a/base/keysz.c b/base/keysz.c new file mode 100644 index 0000000..8291928 --- /dev/null +++ b/base/keysz.c @@ -0,0 +1,81 @@ +/* -*-c-*- + * + * General block cipher utilities + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "gcipher.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @keysz@ --- * + * + * Arguments: @size_t sz@ = a proposed key size, or zero + * @const octet *ksz@ = pointer to key size table + * + * Returns: See below. + * + * Use: Returns a sensible key size. If @sz@ is nonzero, it is + * interpreted as an amount (in bytes) of key material which the + * caller has available, and the return value is either the + * largest allowable key size less than or equal to the caller's + * size, or zero if there is no valid key length small enough. + * If @sz@ is zero, the function returns a `recommended' key + * size. + */ + +size_t keysz(size_t sz, const octet *ksz) +{ + if (sz == 0) + return (ksz[1]); + else switch (ksz[0]) { + case KSZ_ANY: + return (sz); + case KSZ_RANGE: + if (ksz[4]) + sz -= sz % ksz[4]; + if (sz < ksz[2]) + return (0); + if (ksz[3] && sz > ksz[3]) + return (ksz[3]); + return (sz); + case KSZ_SET: { + unsigned q = 0; + for (ksz++; *ksz; ksz++) { + if (sz >= *ksz && q < *ksz) + q = *ksz; + } + return (q); + } + } + + assert(((void)"bad key size table", 0)); + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/keysz.h b/base/keysz.h similarity index 100% rename from keysz.h rename to base/keysz.h diff --git a/base/lmem.c b/base/lmem.c new file mode 100644 index 0000000..a613a54 --- /dev/null +++ b/base/lmem.c @@ -0,0 +1,344 @@ +/* -*-c-*- + * + * Locked memory allocation (Unix-specific) + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef HAVE_MLOCK +# include +#endif + +#include +#include +#include + +#include "lmem.h" + +/*----- Arena operations --------------------------------------------------*/ + +static void *aalloc(arena *a, size_t sz) { return l_alloc((lmem *)a, sz); } +static void afree(arena *a, void *p) { l_free((lmem *)a, p); } +static void apurge(arena *a) { l_purge((lmem *)a); } + +static const arena_ops l_ops = { aalloc, arena_fakerealloc, afree, apurge }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @l_init@ --- * + * + * Arguments: @lmem *lm@ = pointer to locked memory descriptor + * @size_t sz@ = size of locked memory area requested + * + * Returns: Zero if everything is fine, @+1@ if some insecure memory was + * allocated, and @-1@ if everything went horribly wrong. + * + * Use: Initializes the locked memory manager. This function is safe + * to call in a privileged program; privileges should usually be + * dropped after allocating the locked memory block. + * + * You must call @sub_init@ before allocating locked memory + * buffers. + */ + +int l_init(lmem *lm, size_t sz) +{ + char *p; + int rc = 0; + l_node *l; + + /* --- Preliminaries --- */ + + lm->a.ops = &l_ops; + lm->err = 0; + lm->f = 0; + + /* --- Try making a secure locked passphrase buffer --- * + * + * Drop privileges before emitting diagnostic messages. + */ + +#ifdef HAVE_MLOCK + + /* --- Memory-map a page from somewhere --- */ + +# ifdef MAP_ANON + p = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); +# else + { + int fd; + if ((fd = open("/dev/zero", O_RDWR)) >= 0) { + p = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + close(fd); + } + } +# endif + + /* --- Lock the page in memory --- * + * + * Why does @mmap@ return such a stupid result if it fails? + */ + + if (p == 0 || p == MAP_FAILED) { + lm->emsg = "couldn't map locked memory area: %s"; + lm->err = errno; + p = 0; + } else if (mlock(p, sz)) { + lm->emsg = "error locking memory area: %s"; + lm->err = errno; + munmap(p, sz); + p = 0; + } else + lm->f |= LF_LOCKED; + +#endif + + /* --- Make a standard passphrase buffer --- */ + +#ifdef HAVE_MLOCK + if (!p) +#else + lm->err = 0; + lm->emsg = "locked memory not available on this system"; +#endif + { + if ((p = malloc(sz)) == 0) { + lm->emsg = "not enough standard memory!"; + lm->err = ENOMEM; + return (-1); + } + rc = +1; + } + + /* --- Initialize the buffer --- */ + + lm->sz = lm->free = sz; + lm->p = p; + + /* --- Initialize the free list --- */ + + l = CREATE(l_node); + l->next = 0; + l->p = p; + l->sz = sz; + l->f = 0; + lm->l = l; + + /* --- Done --- */ + + return (rc); +} + +/* --- @l_alloc@ --- * + * + * Arguments: @lmem *lm@ = pointer to locked memory descriptor + * @size_t sz@ = size requested + * + * Returns: Pointer to allocated memory. + * + * Use: Allocates @sz@ bytes of locked memory. + */ + +void *l_alloc(lmem *lm, size_t sz) +{ + l_node *l; + + sz = (sz + 3u) & ~3u; + for (l = lm->l; l; l = l->next) { + if (l->f & LF_ALLOC) + continue; + if (l->sz < sz) + continue; + l->f |= LF_ALLOC; + if (l->sz > sz) { + l_node *n = CREATE(l_node); + n->next = l->next; + n->p = l->p + sz; + n->sz = l->sz - sz; + l->sz = sz; + n->f = 0; + l->next = n; + } + assert(((void)"Locked buffer space has vanished", lm->free >= sz)); + lm->free -= sz; + return (l->p); + } + return (0); +} + +/* --- @l_free@ --- * + * + * Arguments: @lmem *lm@ = pointer to locked memory descriptor + * @void *p@ = pointer to block + * + * Returns: --- + * + * Use: Releases a block of locked memory. + */ + +void l_free(lmem *lm, void *p) +{ + l_node *l; + l_node *ll = 0; + + for (l = lm->l; l; l = l->next) { + size_t sz; + + /* --- If this isn't the block, skip it --- */ + + if (l->p != p) { + ll = l; + continue; + } + assert(((void)"Block is already free", l->f & LF_ALLOC)); + + /* --- Coalesce with adjacent free blocks --- */ + + l->f &= ~LF_ALLOC; + sz = l->sz; + memset(p, 0, sz); + + if (ll && !(ll->f & LF_ALLOC)) { + assert(((void)"Previous block doesn't fit", ll->p + ll->sz == p)); + ll->sz += sz; + ll->next = l->next; + DESTROY(l); + l = ll; + } + + ll = l->next; + if (ll && !(ll->f & LF_ALLOC)) { + assert(((void)"Next block doesn't fit", ll->p == l->p + l->sz)); + l->sz += ll->sz; + l->next = ll->next; + DESTROY(ll); + } + + lm->free += sz; + assert(((void)"Free lunch", lm->free <= lm->sz)); + return; + } + assert(((void)"Not a locked block", 0)); +} + +/* --- @l_purge@ --- * + * + * Arguments: @lmem *lm@ = pointer to locked memory descriptor + * + * Returns: --- + * + * Use: Purges all the free blocks in the buffer, and clears all of + * the locked memory. Memory is not freed back to the system. + */ + +void l_purge(lmem *lm) +{ + l_node *l; + + l = lm->l; + while (l) { + l_node *ll = l->next; + DESTROY(l); + l = ll; + } + memset(lm->p, 0, lm->sz); + l = CREATE(l_node); + l->next = 0; + l->p = lm->p; + l->sz = lm->sz; + l->f = 0; + lm->l = l; + lm->free = l->sz; +} + +/* --- @l_destroy@ --- * + * + * Arguments: @lmem *lm@ = pointer to locked memory descriptor + * + * Returns: --- + * + * Use: Disposes of a locked memory arena permanently. + */ + +void l_destroy(lmem *lm) +{ + l_node *l; + + l = lm->l; + while (l) { + l_node *ll = l->next; + DESTROY(l); + l = ll; + } + memset(lm->p, 0, lm->sz); + +#ifdef HAVE_MLOCK + if (lm->f & LF_LOCKED) + munmap(lm->p, lm->sz); + else +#endif + free(lm->p); /*sic*/ +} + +/* --- @l_report@ --- * + * + * Arguments: @lmem *lm@ = pointer to locked memory descriptor + * @dstr *d@ = string to write the error message on + * + * Returns: Zero if the buffer is fine, @+1@ if there was a problem + * getting locked memory but insecure stuff could be allocated, + * and @-1@ if not even insecure memory could be found. + * + * Use: Returns a user-digestable explanation for the state of a + * locked memory buffer. If the return code is zero, no message + * is emitted to the string @d@. + */ + +int l_report(lmem *lm, dstr *d) +{ + int rc; + if (lm->err) + dstr_putf(d, lm->emsg, strerror(lm->err)); + if (!lm->p) + rc = -1; + else if (lm->err) + rc = +1; + else + rc = 0; + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/base/lmem.h b/base/lmem.h new file mode 100644 index 0000000..88b0062 --- /dev/null +++ b/base/lmem.h @@ -0,0 +1,164 @@ +/* -*-c-*- + * + * Locked memory allocation + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_LMEM_H +#define CATACOMB_LMEM_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include +#include + +/*----- Data structures ---------------------------------------------------*/ + +/* --- Block list --- * + * + * The block list is kept in normal memory, to avoid wasting precious locked + * memory. Entries are sorted into ascending address order to make + * coalescing free blocks easier. All blocks, free or not, are included in + * the list. + */ + +typedef struct l_node { + struct l_node *next; /* Next free block in chain */ + char *p; /* Pointer to the block */ + size_t sz; /* Size of the block */ + unsigned f; /* Various flags */ +} l_node; + +#define LF_ALLOC 1u + +/* --- Locked memory buffer state --- */ + +typedef struct lmem { + arena a; /* Arena header block */ + unsigned f; /* Various flags */ + char *p; /* Pointer to locked buffer */ + l_node *l; /* Pointer to block list */ + size_t sz; /* Size of locked buffer */ + size_t free; /* Size of free area */ + int err; char *emsg; /* Error indicators */ +} lmem; + +#define LF_LOCKED 1u + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @l_init@ --- * + * + * Arguments: @lmem *lm@ = pointer to locked memory descriptor + * @size_t sz@ = size of locked memory area requested + * + * Returns: Zero if everything is fine, @+1@ if some insecure memory was + * allocated, and @-1@ if everything went horribly wrong. + * + * Use: Initializes the locked memory manager. This function is safe + * to call in a privileged program; privileges should usually be + * dropped after allocating the locked memory block. + * + * You must call @sub_init@ before allocating locked memory + * buffers. + */ + +extern int l_init(lmem */*lm*/, size_t /*sz*/); + +/* --- @l_alloc@ --- * + * + * Arguments: @lmem *lm@ = pointer to locked memory descriptor + * @size_t sz@ = size requested + * + * Returns: Pointer to allocated memory. + * + * Use: Allocates @sz@ bytes of locked memory. + */ + +extern void *l_alloc(lmem */*lm*/, size_t /*sz*/); + +/* --- @l_free@ --- * + * + * Arguments: @lmem *lm@ = pointer to locked memory descriptor + * @void *p@ = pointer to block + * + * Returns: --- + * + * Use: Releases a block of locked memory. + */ + +extern void l_free(lmem */*lm*/, void */*p*/); + +/* --- @l_purge@ --- * + * + * Arguments: @lmem *lm@ = pointer to locked memory descriptor + * + * Returns: --- + * + * Use: Purges all the free blocks in the buffer, and clears all of + * the locked memory. Memory is not freed back to the system. + */ + +extern void l_purge(lmem */*lm*/); + +/* --- @l_destroy@ --- * + * + * Arguments: @lmem *lm@ = pointer to locked memory descriptor + * + * Returns: --- + * + * Use: Disposes of a locked memory arena permanently. + */ + +extern void l_destroy(lmem */*lm*/); + +/* --- @l_report@ --- * + * + * Arguments: @lmem *lm@ = pointer to locked memory descriptor + * @dstr *d@ = string to write the error message on + * + * Returns: Zero if the buffer is fine, @+1@ if there was a problem + * getting locked memory but insecure stuff could be allocated, + * and @-1@ if not even insecure memory could be found. + * + * Use: Returns a user-digestable explanation for the state of a + * locked memory buffer. If the return code is zero, no message + * is emitted to the string @d@. + */ + +extern int l_report(lmem */*lm*/, dstr */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/base/paranoia.h b/base/paranoia.h new file mode 100644 index 0000000..368667c --- /dev/null +++ b/base/paranoia.h @@ -0,0 +1,49 @@ +/* -*-c-*- + * + * Macros and functions for cryptographic paranoia + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_PARANOIA_H +#define CATACOMB_PARANOIA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +/*----- Macros ------------------------------------------------------------*/ + +#define BURN(x) (memset(&(x), 0, sizeof(x))) + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/bbs-fetch.c b/bbs-fetch.c deleted file mode 100644 index 96c21d0..0000000 --- a/bbs-fetch.c +++ /dev/null @@ -1,75 +0,0 @@ -/* -*-c-*- - * - * $Id: bbs-fetch.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Key fetching for BBS public and private keys - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "bbs.h" -#include "key.h" - -/*----- Key fetching ------------------------------------------------------*/ - -const key_fetchdef bbs_pubfetch[] = { - { "n", offsetof(bbs_pub, n), KENC_MP, 0 }, - { 0, 0, 0, 0 } -}; - -static const key_fetchdef priv[] = { - { "p", offsetof(bbs_priv, p), KENC_MP, 0 }, - { "q", offsetof(bbs_priv, q), KENC_MP, 0 }, - { 0, 0, 0, 0 } -}; - -const key_fetchdef bbs_privfetch[] = { - { "n", offsetof(bbs_priv, n), KENC_MP, 0 }, - { "private", 0, KENC_STRUCT, priv }, - { 0, 0, 0, 0 } -}; - -/* --- @bbs_pubfree@, @bbs_privfree@ --- * - * - * Arguments: @bbs_pub *bp@, @bbs_priv *bp@ = pointer to key block - * - * Returns: --- - * - * Use: Frees an RSA key block. - */ - -void bbs_pubfree(bbs_pub *bp) -{ - mp_drop(bp->n); -} - -void bbs_privfree(bbs_priv *bp) -{ - mp_drop(bp->n); - mp_drop(bp->p); - mp_drop(bp->q); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/bbs-gen.c b/bbs-gen.c deleted file mode 100644 index c668b21..0000000 --- a/bbs-gen.c +++ /dev/null @@ -1,126 +0,0 @@ -/* -*-c-*- - * - * $Id: bbs-gen.c,v 1.6 2004/04/08 01:36:15 mdw Exp $ - * - * Generate Blum integers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include "bbs.h" -#include "mp.h" -#include "mprand.h" -#include "pgen.h" -#include "strongprime.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @bbs_gen@ --- * - * - * Arguments: @bbs_priv *bp@ = pointer to parameter block - * @unsigned nbits@ = number of bits in the modulus - * @grand *r@ = pointer to random number source - * @unsigned n@ = number of attempts to make - * @pgen_proc *event@ = event handler function - * @void *ectx@ = argument for event handler - * - * Returns: If it worked OK, @PGEN_DONE@, otherwise @PGEN_ABORT@. - * - * Use: Finds two prime numbers %$p'$% and %$q'$% such that both are - * congruent to %$3 \bmod 4$%, and $(p - 1)/2$% and - * %$(q - 1)/2$% have no common factors. The product %$n = pq$% - * is eminently suitable for use as a modulus in a Blum-Blum- - * Shub pseudorandom bit generator. - */ - -int bbs_gen(bbs_priv *bp, unsigned nbits, grand *r, unsigned n, - pgen_proc *event, void *ectx) -{ - rabin rb; - pfilt jp; - pgen_jumpctx j; - pgen_gcdstepctx g; - unsigned nb = nbits/2; - mp *x = MP_NEW; - - /* --- Generate @p@ --- */ - -again: - if ((x = strongprime_setup("p", x, &jp, nb, r, n, event, ectx)) == 0) - goto fail_x; - j.j = &jp; - bp->p = pgen("p", MP_NEW, x, event, ectx, n, pgen_jump, &j, - rabin_iters(nb), pgen_test, &rb); - pfilt_destroy(&jp); - if (!bp->p) { - if (n) - goto fail_p; - goto again; - } - - /* --- Generate @q@ --- */ - - nb = nbits - nb; - if ((x = strongprime_setup("q", x, &g.jp, nb, r, n, event, ectx)) == 0) - goto fail_q; - if ((x->v[0] & 3) != 3) - x = mp_add(x, x, g.jp.m); - pfilt_muladd(&g.jp, &g.jp, 2, 0); - g.r = mp_lsr(MP_NEW, bp->p, 1); - g.g = MP_NEW; - g.max = MP_ONE; - bp->q = pgen("q", MP_NEW, x, event, ectx, n, pgen_gcdstep, &g, - rabin_iters(nb), pgen_test, &rb); - pfilt_destroy(&g.jp); - mp_drop(g.r); - mp_drop(g.g); - if (!bp->q) { - if (n) - goto fail_q; - mp_drop(bp->p); - goto again; - } - - /* --- Compute @n@ --- */ - - bp->n = mp_mul(MP_NEW, bp->p, bp->q); - mp_drop(x); - return (PGEN_DONE); - - /* --- Tidy up if things went wrong --- */ - -fail_q: - mp_drop(bp->p); -fail_p: - mp_drop(x); -fail_x: - return (PGEN_ABORT); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/bbs-jump.c b/bbs-jump.c deleted file mode 100644 index 7275bd9..0000000 --- a/bbs-jump.c +++ /dev/null @@ -1,296 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Jumping around a BBS sequence - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "bbs.h" -#include "mp.h" -#include "mpbarrett.h" -#include "mpcrt.h" -#include "mpint.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @jump@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator context - * @const bbs_priv *bp@ = pointer to BBS modulus factors - * @mp *n@ = number of steps to move - * @mp *px@ = exponent mod @p@ for a one-step jump - * @mp *qx@ = exponent mod @q@ for a one-step jump - * - * Returns: --- - * - * Use: Jumps a BBS context a certain number of places (assuming the - * arguments are right). - * - * Let the BBS modulus be %$n = pq$% and the current residue be - * %$x$%. Then the computations performed are: - * - * * Calculate %$x_p = x \bmod p$% and %$x_q = x \bmod q$%. - * - * * Determine %$e_p = px^n \bmod (p - 1)$% and similarly - * %$e_q = qx^n \bmod (p - 1)$%. - * - * * Calculate %$x_p' = x_p^{e_p} \bmod p$% and - * %$x_q' = x_q^{e_q} \bmod q$%. - * - * * Combine %$x_p'$% and %$x_q'$% using the Chinese Remainder - * Theorem. - * - * If you want to step the generator forwards, simply set - * %$px = qx = 2$%. If you want to step backwards, make - * %$px = (p + 1)/4$% and %$qx = (q + 1)/4$%. Note that, if - * %$x$% is a quadratic residue mod $%p$%, then - * - * %$(x^2) ^ {(p + 1)/4}$% - * %${} = x^{(p + 1)/2}$% - * %${} = x \cdot x^{(p - 1)/2}$% - * %${} = x$% - * - * Simple, no? (Note that the division works because - * %$p \equiv 3 \pmod 4$%.) - */ - -static void jump(bbs *b, const bbs_priv *bp, mp *n, - mp *px, mp *qx) -{ - mp *ep, *eq; - mp *v[2] = { MP_NEW, MP_NEW }; - - /* --- First work out the exponents --- */ - - { - mpbarrett mb; - mp *m; - - m = mp_sub(MP_NEW, bp->p, MP_ONE); - mpbarrett_create(&mb, m); - ep = mpbarrett_exp(&mb, MP_NEW, px, n); - mpbarrett_destroy(&mb); - if (qx == px) - eq = MP_COPY(ep); - else { - m = mp_sub(m, bp->q, MP_ONE); - mpbarrett_create(&mb, m); - eq = mpbarrett_exp(&mb, MP_NEW, qx, n); - mpbarrett_destroy(&mb); - } - - mp_drop(m); - } - - /* --- Now calculate the residues of @x@ --- */ - - mp_div(0, &v[0], b->x, bp->p); - mp_div(0, &v[1], b->x, bp->q); - - /* --- Exponentiate --- */ - - { - mpbarrett mb; - - mpbarrett_create(&mb, bp->p); - v[0] = mpbarrett_exp(&mb, v[0], v[0], ep); - mpbarrett_destroy(&mb); - - mpbarrett_create(&mb, bp->q); - v[1] = mpbarrett_exp(&mb, v[1], v[1], eq); - mpbarrett_destroy(&mb); - - mp_drop(ep); - mp_drop(eq); - } - - /* --- Sort out the result using the Chinese Remainder Theorem --- */ - - { - mpcrt_mod mv[2]; - mpcrt c; - int i; - - mv[0].m = MP_COPY(bp->p); - mv[1].m = MP_COPY(bp->q); - for (i = 0; i < 2; i++) - mv[i].n = mv[i].ni = mv[i].nni = MP_NEW; - mpcrt_create(&c, mv, 2, b->mb.m); - b->x = mpcrt_solve(&c, b->x, v); - mpcrt_destroy(&c); - } - - /* --- Tidy away --- */ - - mp_drop(v[0]); - mp_drop(v[1]); - b->r = b->x->v[0]; - b->b = b->k; -} - -/* --- @bbs_{ff,rew}{,n}@ --- * - * - * Arguments: @bbs *b@ = pointer to a BBS generator state - * @const bbs_priv *bp@ = pointer to BBS modulus factors - * @mp *n@, @unsigned long n@ = number of steps to make - * - * Returns: --- - * - * Use: `Fast-forwards' or rewinds a Blum-Blum-Shub generator by @n@ - * steps. The @...n@ versions take an @unsigned long@ argument; - * the non-@...n@ versions a multiprecision integer. If @n@ is - * negative then the generator is stepped in the reverse - * direction. - */ - -static void ff(bbs *b, const bbs_priv *bp, mp *n) - { jump(b, bp, n, MP_TWO, MP_TWO); } - -static void rew(bbs *b, const bbs_priv *bp, mp *n) -{ - mp *px = mp_lsr(MP_NEW, bp->p, 2); - mp *qx = mp_lsr(MP_NEW, bp->q, 2); - px = mp_add(px, px, MP_ONE); - qx = mp_add(qx, qx, MP_ONE); - jump(b, bp, n, px, qx); - mp_drop(px); - mp_drop(qx); -} - -void bbs_ff(bbs *b, const bbs_priv *bp, mp *n) -{ - if (!MP_NEGP(n)) - ff(b, bp, n); - else { - n = mp_neg(MP_NEW, n); - rew(b, bp, n); - mp_drop(n); - } -} - -void bbs_ffn(bbs *b, const bbs_priv *bp, unsigned long n) - { mp *nn = mp_fromulong(MP_NEW, n); ff(b, bp, nn); mp_drop(nn); } - -void bbs_rew(bbs *b, const bbs_priv *bp, mp *n) -{ - if (!MP_NEGP(n)) - rew(b, bp, n); - else { - n = mp_neg(MP_NEW, n); - ff(b, bp, n); - mp_drop(n); - } -} - -void bbs_rewn(bbs *b, const bbs_priv *bp, unsigned long n) - { mp *nn = mp_fromulong(MP_NEW, n); bbs_rew(b, bp, nn); mp_drop(nn); } - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int verify(dstr *v) -{ - bbs_priv bp; - bbs b; - mp *x; - unsigned long n; - int ok = 1; - uint32 p, q, r; - int i; - - bp.p = *(mp **)v[0].buf; - bp.q = *(mp **)v[1].buf; - bp.n = mp_mul(MP_NEW, bp.p, bp.q); - x = *(mp **)v[2].buf; - n = *(unsigned long *)v[3].buf; - - bbs_create(&b, bp.n, x); - p = bbs_bits(&b, 32); - - bbs_seed(&b, x); - for (i = 0; i < n; i++) - bbs_step(&b); - q = bbs_bits(&b, 32); - bbs_wrap(&b); - - bbs_rewn(&b, &bp, n + (32 + b.k - 1) / b.k); - r = bbs_bits(&b, 32); - - if (r != p) { - fputs("\n*** bbs rewind failure\n", stderr); - fputs("p = ", stderr); mp_writefile(bp.p, stderr, 10); fputc('\n', stderr); - fputs("q = ", stderr); mp_writefile(bp.q, stderr, 10); fputc('\n', stderr); - fputs("n = ", stderr); mp_writefile(bp.n, stderr, 10); fputc('\n', stderr); - fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr); - fprintf(stderr, "stepped %lu back\n", n + (32 + b.k - 1) / b.k); - fprintf(stderr, "expected output = %08lx, found %08lx\n", - (unsigned long)p, (unsigned long)r); - ok = 0; - } - - bbs_seed(&b, x); - bbs_ffn(&b, &bp, n); - r = bbs_bits(&b, 32); - - if (q != r) { - fputs("\n*** bbs fastforward failure\n", stderr); - fputs("p = ", stderr); mp_writefile(bp.p, stderr, 10); fputc('\n', stderr); - fputs("q = ", stderr); mp_writefile(bp.q, stderr, 10); fputc('\n', stderr); - fputs("n = ", stderr); mp_writefile(bp.n, stderr, 10); fputc('\n', stderr); - fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr); - fprintf(stderr, "stepped %lu back\n", n + (32 + b.k - 1) / b.k); - fprintf(stderr, "expected output = %08lx, found %08lx\n", - (unsigned long)q, (unsigned long)r); - ok = 0; - } - - bbs_destroy(&b); - mp_drop(bp.p); - mp_drop(bp.q); - mp_drop(bp.n); - mp_drop(x); - - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "bbs-jump", verify, { &type_mp, &type_mp, &type_mp, &type_ulong, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/bbs"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/bbs-rand.c b/bbs-rand.c deleted file mode 100644 index 20d9c7a..0000000 --- a/bbs-rand.c +++ /dev/null @@ -1,423 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Blum-Blum-Shub secure random number generator - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include -#include - -#include "arena.h" -#include "bbs.h" -#include "grand.h" -#include "mp.h" -#include "mpbarrett.h" -#include "mpint.h" -#include "mprand.h" -#include "paranoia.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @bbs_create@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state to initialize - * @mp *m@ = modulus (must be a Blum integer) - * @mp *x@ = initial seed for generator - * - * Returns: --- - * - * Use: Initializes a BBS generator. The generator is stepped once - * after initialization, as for @bbs_seed@. - */ - -void bbs_create(bbs *b, mp *m, mp *x) -{ - mpw kw; - mp k; - - mpbarrett_create(&b->mb, m); - kw = mp_bits(m) - 1; - mp_build(&k, &kw, &kw + 1); - b->k = mp_bits(&k) - 1; - b->x = 0; - bbs_seed(b, x); -} - -/* --- @bbs_destroy@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state - * - * Returns: --- - * - * Use: Destroys a generator state when it's no longer wanted. - */ - -void bbs_destroy(bbs *b) -{ - mp_drop(b->x); - mpbarrett_destroy(&b->mb); -} - -/* --- @bbs_step@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state - * - * Returns: --- - * - * Use: Steps the generator once. This isn't too useful in client - * code. - */ - -void bbs_step(bbs *b) -{ - mp *x = b->x; - x = mp_sqr(x, x); - x = mpbarrett_reduce(&b->mb, x, x); - b->x = x; - b->b = b->k; - b->r = b->x->v[0]; -} - -/* --- @bbs_set@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state - * @mp *x@ = new residue to set - * - * Returns: --- - * - * Use: Sets a new quadratic residue. The generator is stepped once. - */ - -void bbs_set(bbs *b, mp *x) -{ - mp_drop(b->x); - b->x = MP_COPY(x); - bbs_step(b); -} - -/* --- @bbs_seed@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state - * @mp *x@ = new seed to set - * - * Returns --- - * - * Use: Sets a new seed. The generator is stepped until the residue - * has clearly wrapped around. - */ - -void bbs_seed(bbs *b, mp *x) -{ - mp *y; - x = MP_COPY(x); - for (;;) { - y = mp_sqr(MP_NEW, x); - y = mpbarrett_reduce(&b->mb, y, y); - if (MP_CMP(y, <, x)) - break; - mp_drop(x); - x = y; - } - mp_drop(x); - bbs_set(b, y); - mp_drop(y); -} - -/* --- @bbs_bits@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state - * @unsigned bits@ = number of bits wanted - * - * Returns: Bits extracted from the BBS generator. - * - * Use: Extracts a requested number of bits from the BBS generator. - */ - -uint32 bbs_bits(bbs *b, unsigned bits) -{ - uint32 x = 0; - mpw m; - - /* --- Keep turning the handle until there's enough in the reservoir --- */ - - while (bits >= b->b) { - bits -= b->b; - m = (1 << b->b) - 1; - x |= (b->r & m) << bits; - bbs_step(b); - } - - /* --- Extract the last few bits needed --- */ - - if (bits) { - m = (1 << bits) - 1; - b->b -= bits; - x |= (b->r >> b->b) & m; - } - - /* --- Done --- */ - - return (x); -} - -/* --- @bbs_wrap@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state - * - * Returns: --- - * - * Use: Steps the generator if any of the reservoir bits are used. - * This can be used to `wrap up' after a Blum-Goldwasser - * encryption, for example, producing the final value to be sent - * along with the ciphertext. - * - * If a generator is seeded, %$b$% bits are extracted, and then - * @bbs_wrap@ is called, the generator will have been stepped - * %$\lceil b/k \rceil$% times. - */ - -void bbs_wrap(bbs *b) -{ - if (b->b < b->k) - bbs_step(b); -} - -/*----- Generic random number generator interface -------------------------*/ - -typedef struct gctx { - grand r; - bbs b; -} gctx; - -static void gdestroy(grand *r) -{ - gctx *g = (gctx *)r; - bbs_destroy(&g->b); - BURN(*g); - S_DESTROY(g); -} - -static int gmisc(grand *r, unsigned op, ...) -{ - gctx *g = (gctx *)r; - va_list ap; - int rc = 0; - va_start(ap, op); - - switch (op) { - case GRAND_CHECK: - switch (va_arg(ap, unsigned)) { - case GRAND_CHECK: - case GRAND_SEEDINT: - case GRAND_SEEDUINT32: - case GRAND_SEEDMP: - case GRAND_SEEDRAND: - case BBS_SET: - case BBS_STEP: - case BBS_STEPSZ: - case BBS_BITS: - case BBS_WRAP: - case BBS_FF: - case BBS_FFN: - case BBS_REW: - case BBS_REWN: - case BBS_MOD: - case BBS_STATE: - rc = 1; - break; - default: - rc = 0; - break; - } - break; - case GRAND_SEEDINT: { - mp *x = mp_fromuint(MP_NEW, va_arg(ap, unsigned)); - bbs_seed(&g->b, x); - mp_drop(x); - } break; - case GRAND_SEEDUINT32: { - mp *x = mp_fromuint32(MP_NEW, va_arg(ap, uint32)); - bbs_seed(&g->b, x); - mp_drop(x); - } break; - case GRAND_SEEDMP: - bbs_seed(&g->b, va_arg(ap, mp *)); - break; - case GRAND_SEEDRAND: { - grand *rr = va_arg(ap, grand *); - mp *m = mprand(MP_NEW, mp_bits(g->b.mb.m) - 1, rr, 0); - bbs_seed(&g->b, m); - mp_drop(m); - } break; - case BBS_SET: - bbs_set(&g->b, va_arg(ap, mp *)); - break; - case BBS_STEP: - bbs_step(&g->b); - break; - case BBS_STEPSZ: - rc = g->b.k; - break; - case BBS_BITS: { - unsigned nb = va_arg(ap, unsigned); - uint32 *w = va_arg(ap, uint32 *); - *w = bbs_bits(&g->b, nb); - } break; - case BBS_WRAP: - bbs_wrap(&g->b); - break; - case BBS_FF: { - const bbs_priv *bp = va_arg(ap, const bbs_priv *); - mp *n = va_arg(ap, mp *); - bbs_ff(&g->b, bp, n); - } break; - case BBS_FFN: { - const bbs_priv *bp = va_arg(ap, const bbs_priv *); - unsigned long n = va_arg(ap, unsigned long); - bbs_ffn(&g->b, bp, n); - } break; - case BBS_REW: { - const bbs_priv *bp = va_arg(ap, const bbs_priv *); - mp *n = va_arg(ap, mp *); - bbs_rew(&g->b, bp, n); - } break; - case BBS_REWN: { - const bbs_priv *bp = va_arg(ap, const bbs_priv *); - unsigned long n = va_arg(ap, unsigned long); - bbs_rewn(&g->b, bp, n); - } break; - case BBS_MOD: { - mp **n = va_arg(ap, mp **); - if (*n) MP_DROP(*n); - *n = MP_COPY(g->b.mb.m); - } break; - case BBS_STATE: { - mp **n = va_arg(ap, mp **); - if (*n) MP_DROP(*n); - *n = MP_COPY(g->b.x); - } break; - default: - GRAND_BADOP; - break; - } - - va_end(ap); - return (rc); -} - -static octet gbyte(grand *r) -{ - gctx *g = (gctx *)r; - return (bbs_bits(&g->b, 8)); -} - -static uint32 gword(grand *r) -{ - gctx *g = (gctx *)r; - return (bbs_bits(&g->b, 32)); -} - -static const grand_ops gops = { - "bbs", - GRAND_CRYPTO, 0, - gmisc, gdestroy, - gword, gbyte, gword, grand_range, grand_fill -}; - -/* --- @bbs_rand@ --- * - * - * Arguments: @mp *m@ = modulus - * @mp *x@ = initial seed - * - * Returns: Pointer to a generic generator. - * - * Use: Constructs a generic generator interface over a - * Blum-Blum-Shub generator. - */ - -grand *bbs_rand(mp *m, mp *x) -{ - gctx *g = S_CREATE(gctx); - g->r.ops = &gops; - bbs_create(&g->b, m, x); - return (&g->r); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int verify(dstr *v) -{ - mp *n = *(mp **)v[0].buf; - mp *x = *(mp **)v[1].buf; - grand *b = bbs_rand(n, x); - dstr d = DSTR_INIT; - int ok = 1; - - dstr_ensure(&d, v[2].len); - b->ops->fill(b, d.buf, v[2].len); - d.len = v[2].len; - if (memcmp(d.buf, v[2].buf, v[2].len) != 0) { - fputs("\n*** bbs failure\n", stderr); - fputs("n = ", stderr); mp_writefile(n, stderr, 10); fputc('\n', stderr); - fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr); - fputs("expected = ", stderr); type_hex.dump(&v[2], stderr); - fputc('\n', stderr); - fputs(" found = ", stderr); type_hex.dump(&d, stderr); - fputc('\n', stderr); - fprintf(stderr, "k = %u\n", ((gctx *)b)->b.k); - ok = 0; - } - b->ops->destroy(b); - mp_drop(x); - mp_drop(n); - dstr_destroy(&d); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "bbs", verify, { &type_mp, &type_mp, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/bbs"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/bbs.h b/bbs.h deleted file mode 100644 index 30fb474..0000000 --- a/bbs.h +++ /dev/null @@ -1,296 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * The Blum-Blum-Shub random bit generator - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the BBS generator ----------------------------------------* - * - * The Blum-Blum-Shub generator takes the least significant bits from the - * sequence %$x_i = x_{i - 1}^2 \bmod n$%, where %$n = pq$% is the product of - * two primes %$p$% and %$q$%, each of which are congruent to %$3 \bmod 4$%. - * For maximum period of the generator, %$(p - 1)/2$% and %$(q - 1)/1$% - * should be coprime. It is safe to use the least significant - * %$\log \log n$% bits of each step in the sequence -- an adversary must - * factor the modulus before being able to work forwards or backwards. The - * output of the generator cannot be distinguished from a (uniform, - * independent) random sequence of bits using any polynomial-time test. This - * is by far the strongest pseudorandom number generator provided in - * Catacomb, and by far the slowest too. For normal use, the standard - * Catacomb @rand@ generator should be more than adequate. - */ - -#ifndef CATACOMB_BBS_H -#define CATACOMB_BBS_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -#ifndef CATACOMB_KEY_H -# include "key.h" -#endif - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_MPBARRETT_H -# include "mpbarrett.h" -#endif - -#ifndef CATACOMB_PGEN_H -# include "pgen.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- Basic generator state --- */ - -typedef struct bbs { - mpbarrett mb; /* Barrett reduction context */ - mp *x; /* Current quadratic residue */ - unsigned k; /* Number of bits from each step */ - unsigned b; /* Number of bits in reservoir */ - mpw r; /* Reservoir of output bits */ -} bbs; - -/* --- Parameters --- */ - -typedef struct bbs_pub { - mp *n; -} bbs_pub; - -typedef struct bbs_priv { - mp *p, *q; /* Prime factors (3 mod 4) */ - mp *n; /* Product @pq@ -- a Blum integer */ -} bbs_priv; - -/*----- Key fetching ------------------------------------------------------*/ - -extern const key_fetchdef bbs_pubfetch[]; -#define BBS_PUBFETCHSZ 3 - -extern const key_fetchdef bbs_privfetch[]; -#define BBS_PRIVFETCHSZ 7 - -/* --- @bbs_pubfree@, @bbs_privfree@ --- * - * - * Arguments: @bbs_pub *bp@, @bbs_priv *bp@ = pointer to key block - * - * Returns: --- - * - * Use: Frees a BBS key block. - */ - -extern void bbs_pubfree(bbs_pub */*bp*/); -extern void bbs_privfree(bbs_priv */*bp*/); - -/*----- The basic generator -----------------------------------------------*/ - -/* --- @bbs_create@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state to initialize - * @mp *m@ = modulus (must be a Blum integer) - * @mp *x@ = initial seed for generator - * - * Returns: --- - * - * Use: Initializes a BBS generator. The generator is stepped once - * after initialization, as for @bbs_seed@. - */ - -extern void bbs_create(bbs */*b*/, mp */*m*/, mp */*x*/); - -/* --- @bbs_destroy@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state - * - * Returns: --- - * - * Use: Destroys a generator state when it's no longer wanted. - */ - -extern void bbs_destroy(bbs */*b*/); - -/* --- @bbs_step@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state - * - * Returns: --- - * - * Use: Steps the generator once. This isn't too useful in client - * code. - */ - -extern void bbs_step(bbs */*b*/); - -/* --- @bbs_set@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state - * @mp *x@ = new residue to set - * - * Returns: --- - * - * Use: Sets a new quadratic residue. The generator is stepped once. - */ - -extern void bbs_set(bbs */*b*/, mp */*x*/); - -/* --- @bbs_seed@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state - * @mp *x@ = new seed to set - * - * Returns --- - * - * Use: Sets a new seed. The generator is stepped until the residue - * has clearly wrapped around. - */ - -extern void bbs_seed(bbs */*b*/, mp */*x*/); - -/* --- @bbs_bits@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state - * @unsigned bits@ = number of bits wanted - * - * Returns: Bits extracted from the BBS generator. - * - * Use: Extracts a requested number of bits from the BBS generator. - */ - -extern uint32 bbs_bits(bbs */*b*/, unsigned /*bits*/); - -/* --- @bbs_wrap@ --- * - * - * Arguments: @bbs *b@ = pointer to BBS generator state - * - * Returns: --- - * - * Use: Steps the generator if any of the reservoir bits are used. - * This can be used to `wrap up' after a Blum-Goldwasser - * encryption, for example, producing the final value to be sent - * along with the ciphertext. - * - * If a generator is seeded, %$b$% bits are extracted, and then - * @bbs_wrap@ is called, the generator will have been stepped - * %$\lceil b/k \rceil$% times. - */ - -extern void bbs_wrap(bbs */*b*/); - -/*----- Large forwards and backwards jumps --------------------------------*/ - -/* --- @bbs_{ff,rew}{,n}@ --- * - * - * Arguments: @bbs *b@ = pointer to a BBS generator state - * @const bbs_priv *bp@ = pointer to BBS modulus factors - * @mp *n@, @unsigned long n@ = number of steps to make - * - * Returns: --- - * - * Use: `Fast-forwards' or rewinds a Blum-Blum-Shub generator by @n@ - * steps. The @...n@ versions take an @unsigned long@ argument; - * the non-@...n@ versions a multiprecision integer. If @n@ is - * negative then the generator is stepped in the reverse - * direction. - */ - -extern void bbs_ff(bbs */*b*/, const bbs_priv */*bp*/, mp */*n*/); -extern void bbs_ffn(bbs */*b*/, const bbs_priv */*bp*/, unsigned long /*n*/); -extern void bbs_rew(bbs */*b*/, const bbs_priv */*bp*/, mp */*n*/); -extern void bbs_rewn(bbs */*b*/, const bbs_priv */*bp*/, unsigned long /*n*/); - -/*----- Parameter generation ----------------------------------------------*/ - -/* --- @bbs_gen@ --- * - * - * Arguments: @bbs_priv *bp@ = pointer to parameter block - * @unsigned nbits@ = number of bits in the modulus - * @grand *r@ = pointer to random number source - * @unsigned n@ = number of attempts to make - * @pgen_proc *event@ = event handler function - * @void *ectx@ = argument for event handler - * - * Returns: If it worked OK, @PGEN_DONE@, otherwise @PGEN_ABORT@. - * - * Use: Finds two prime numbers %$p'$% and %$q'$% such that both are - * congruent to %$3 \bmod 4$%, and $(p - 1)/2$% and - * %$(q - 1)/2$% have no common factors. The product %$n = pq$% - * is eminently suitable for use as a modulus in a Blum-Blum- - * Shub pseudorandom bit generator. - */ - -extern int bbs_gen(bbs_priv */*bp*/, unsigned /*nbits*/, grand */*r*/, - unsigned /*n*/, pgen_proc */*event*/, void */*ectx*/); - -/*----- Generic random number generator interface -------------------------*/ - -/* --- @bbs_rand@ --- * - * - * Arguments: @mp *m@ = modulus - * @mp *x@ = initial seed - * - * Returns: Pointer to a generic generator. - * - * Use: Constructs a generic generator interface over a - * Blum-Blum-Shub generator. - */ - -extern grand *bbs_rand(mp */*m*/, mp */*x*/); - -/* --- Blum-Blum-Shub-specific misc op codes --- */ - -enum { - BBS_SET = GRAND_SPECIFIC('B'), /* @mp *x@ */ - BBS_STEP, /* @void@ */ - BBS_STEPSZ, /* @void@ */ - BBS_BITS, /* @unsigned bits, uint32 *w@ */ - BBS_WRAP, /* @void@ */ - BBS_FF, /* @bbs_priv *p, mp *n@ */ - BBS_FFN, /* @bbs_priv *p, unsigned long n@ */ - BBS_REW, /* @bbs_priv *p, mp *n@ */ - BBS_REWN, /* @bbs_priv *p, unsigned long n@ */ - BBS_MOD, /* @mp **n@ */ - BBS_STATE /* @mp **x@ */ -}; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/bin-gentab.awk b/bin-gentab.awk deleted file mode 100755 index fb8630e..0000000 --- a/bin-gentab.awk +++ /dev/null @@ -1,102 +0,0 @@ -#! /usr/bin/awk -f -# -# $Id: p-gentab.awk 2187 2004-09-04 07:50:08Z mdw $ - -function banner(name, s, i) -{ - s = "/*----- " name " "; - while (length(s) < 75) s = s "-"; - return (s "*/"); -} - -function fix(name) -{ - gsub(/[^0-9A-Za-z_]+/, "_", name); - return (name); -} - -BEGIN { - print "/* -*-c-*-"; - print " *"; - print " * Table of binary groups [generated]"; - print " */"; - print ""; - print "#include \"bintab.h\""; - print ""; - print "#define N(x) (sizeof(x)/sizeof(*x))"; - print "#define MP(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }"; - print "#define NOMP { 0, 0, 0, 0, 0 }"; - print ""; - print banner("Binary group data"); - print ""; - - d_i = 0; - name = ""; -} - -function putmp(x, d) -{ - if (!(x in data)) { - print "group " name ": missing " x >"/dev/stderr"; - exit 1; - } - d = data[x]; - if (!(d in cache)) { - n = "p_" fix(name) "_" x; - print "static mpw " n "[] = {"; - system("./mpdump " d); - print "};"; - print ""; - cache[d] = n; - } - mp[x] = cache[d]; -} - -function flush() -{ - if (name == "") return; - print "/* --- Group " name " --- */"; - delete mp; - print ""; - putmp("p"); - putmp("q"); - putmp("g"); - print "static bindata bin_" fix(name) " = {"; - print " MP(" mp["p"] ")," - print " MP(" mp["q"] ")," - print " MP(" mp["g"] ")" - print "};"; - print ""; - dname[d_i++] = name; - d[name] = name; - r[name] = "bin_" fix(name); - name = ""; -} - -/^[ \t]*(#|$)/ { next; } - -$1 == "alias" { flush(); dname[d_i++] = $2; d[$2] = $3; next; } - -$1 == "group" { flush(); delete data; name = $2; next; } - -{ data[$1] = $2; next; } - -END { - flush(); - print banner("Main table"); - print ""; - print "const binentry bintab[] = {"; - for (i = 0; i < d_i; i++) { - name = dname[i]; - rname = d[name]; - if (!rname in r) { - print "group " rname " not found (alias from " name ")" >"/dev/stderr"; - exit 1; - } - print " { \"" name "\", &" r[rname] " },"; - } - print " { 0, 0 }"; - print "};" - print ""; - print banner("That's all, folks"); -} diff --git a/bintab.h b/bintab.h deleted file mode 100644 index 221d749..0000000 --- a/bintab.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Table of standard (ish) binary groups - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_BINTAB_H -#define CATACOMB_BINTAB_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "ptab.h" - -/*----- Data structures ---------------------------------------------------*/ - -typedef pdata bindata; -typedef pentry binentry; - -/*----- Global variables --------------------------------------------------*/ - -extern const binentry bintab[]; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/bintab.in b/bintab.in deleted file mode 100644 index debe112..0000000 --- a/bintab.in +++ /dev/null @@ -1,37 +0,0 @@ -# $Id$ -# -# Standard binary groups - -#----- From P1363 annex A --------------------------------------------------- - -group p1363-40 - p 0x200000000000000000000000000000000000000000000065 - q 0xabbcb671934086d21ff5f7 - g 0x66704fca38d7962439e5f9bdab4d9ac6f0dd745c72f822e - -group p1363-56 - p 0x100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100d - q 0x5538ed0653399777d80d50e508fd01 - g 0x44e2fd3317b4a1968ce65b7e72f8d64262987d0a818a5a5189a6d588b67317c9ee05a38e3e5691e34933e3e050543d8b - -group p1363-64 - p 0x4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800001 - q 0x84b73a6a902299c1aeeb8b537f1ea87c1 - g 0xce10e3ae38cacb7c1076723b80be855c629c03abef26d2a5ca898f75d2bd794daa9e21781f063ab2785a8c402f976d73e5c8d66072cd950dee1ea722bb8f3d - -group p1363-80 - p 0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080043 - q 0x519f0cb14cf36cfcda7d08fab2b578314c9542801 - g 0xd0f0d0046d995f82b1599c7bceb20010b2ec0d27748d113c532657584c9ea11ab6be6b7236cfafc2a087503e1ad108e559206d559e7c30f4a516da71fa3e08fc50e03084f18af4a59e9c6835beb67dfd2b47ef8d0ea30d8f65e378e9ba82819ffc0ade685fa6cb346dcecca7134893db0a6950c2beab89ee38508f03f2f1f186 - -group p1363-112 - p 0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040481 - q 0x399ac734bd00a6f622bdd00c5f930dcf2ae5d7c521755f7b664f104e423bddd - g 0x40154611e5cd5d4826382b23d4ba28fa9d050bb4db5e81b90816fa2823b62328798b70c061734b327e7e3221002a08554e4902f26c476a152380f49e7e2624066de81ef26ddabf4b2c4cc9374f60189e4e5446e04c39d1de05947c54eb6d8c63e498a83d5025ea9fcf2ff3195fb76d76cc2df73918268b72f693a28a01c14622351cc53546bdaacfc95ad19aee16d3d88fbb5fe8143a8a3dcf3d48525be95bef28921edcee081b5269d0b5307ed97f55e5d0218dd17a39f393e017fcfe999626f1fc6ae9a485395a62a3e969d2e0cce55755cc0e22c4356741313d762505c9a2594af3e94d8f913798d92ccf6a73d2447c474ed2924a29856c5c2feeb178a35b15545 - -group p1363-128 - p 0x1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002441 - q 0xa5c52c0d53fc1f43b2cbfd7447d53d55c37004338502dfda0f31b7df76bde74081 - g 0x9447bb7ca087a37a5268c9e4cd3b9c3eb752272af39657d616181d28f18634368ba972a26b93b2980b391e23d7a9313785a5a17adfd9f810a3677cc20342965e09afc81b8413c5b3054c3adffec6411f088942d5877eef220b2a01cd7c48e8bae8f394b2a0893eb293f6355fc3ea962e503ae1d6fd0c3d718de374100cf89cb9c72e125fac9f930abb9959d03ef18354dd16f3a51e42e2c43ef100a8c3ca9523e6decbdf1f67db454df5781d16d55e94663f9633985d2f76b71a9bb10a985a8c6e8cb4190bef038798e9f402ea8027698e9d28a4ee14f0a6724f38dab82578a0e9600fa5717f40d8f107cb148c896c3061945318b25436c04f84a1b0fa043417bf7904915fa6afaed5fd24c73a5a1328973f39e8bc930ccc3099d7f715f8738b13d0b113899200b2293cdba34a46d22c0fab4d8ed33a71c691ba90687000030ad2fe05b5668520e24edb37edcf43827d9cf0b96ff776f88a2041eadd6902e12428716b46533d765d - -#----- That's all, folks ---------------------------------------------------- diff --git a/bitops.h b/bitops.h deleted file mode 100644 index 02f9a34..0000000 --- a/bitops.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*-c-*- - * - * $Id: bitops.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Bit operations by truth table - * - * (c) 2002 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_BITOPS_H -#define CATACOMB_BITOPS_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Macros ------------------------------------------------------------*/ - -#define B0000(x, y) (0u) -#define B0001(x, y) ((x) & (y)) -#define B0010(x, y) ((x) & ~(y)) -#define B0011(x, y) (x) -#define B0100(x, y) (~(x) & (y)) -#define B0101(x, y) (y) -#define B0110(x, y) ((x) ^ (y)) -#define B0111(x, y) ((x) | (y)) -#define B1000(x, y) (~((x) | (y))) -#define B1001(x, y) (~((x) ^ (y))) -#define B1010(x, y) (~(y)) -#define B1011(x, y) ((x) | ~(y)) -#define B1100(x, y) (~(x)) -#define B1101(x, y) (~(x) | (y)) -#define B1110(x, y) (~((x) & (y))) -#define B1111(x, y) (~0u) - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/bittest.c b/bittest.c deleted file mode 100644 index f13d358..0000000 --- a/bittest.c +++ /dev/null @@ -1,58 +0,0 @@ -/* -*-c-*- - * - * $Id: bittest.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Check the bit operations work - * - * (c) 2002 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include "bitops.h" -#include "mpx.h" - -/*----- Main code ---------------------------------------------------------*/ - -int main(void) -{ - int rc = 0; -#define CHECK(string) do { \ - const char *ref = #string; \ - char buf[5]; \ - buf[0] = B##string(0u, 0u) & 1u? '1' : '0'; \ - buf[1] = B##string(0u, 1u) & 1u? '1' : '0'; \ - buf[2] = B##string(1u, 0u) & 1u? '1' : '0'; \ - buf[3] = B##string(1u, 1u) & 1u? '1' : '0'; \ - buf[4] = 0; \ - if (strcmp(buf, ref) != 0) { \ - fprintf(stderr, "mismatch ref `%s' != buf `%s'\n", ref, buf); \ - rc = 1; \ - } \ -} while (0); - MPX_DOBIN(CHECK) - return (rc); -} -/*----- That's all, folks -------------------------------------------------*/ diff --git a/blkc.h b/blkc.h deleted file mode 100644 index d95c4f9..0000000 --- a/blkc.h +++ /dev/null @@ -1,347 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Common definitions for block ciphers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_BLKC_H -#define CATACOMB_BLKC_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Theory of operation -----------------------------------------------* - * - * A block cipher has associated with it a triple, called PRE_CLASS, of the - * form `(TYPE, ENDIAN, BITS)', where TYPE is either `N' (representing an - * implemented bit size) or `X' (representing an unimplemented bit size, - * causing loops to be compiled rather than unrolled code), ENDIAN is `B' - * (big) or `L' (little), and BITS is the block size of the cipher in bits. - */ - -/*----- Data movement macros ----------------------------------------------*/ - -/* - * `The C preprocessor. You will never find a more wretched hive of bogus - * hackery. We must be cautious.' - */ - -/* --- General dispatch macros --- */ - -#define BLKC_DOGLUE(x, y) x ## y -#define BLKC_GLUE(x, y) BLKC_DOGLUE(x, y) -#define BLKC_APPLY(f, x) f x -#define BLKC_FIRST(x, y, z) x -#define BLKC_SECOND(x, y, z) y -#define BLKC_THIRD(x, y, z) z -#define BLKC_TYPE(PRE) BLKC_APPLY(BLKC_FIRST, PRE##_CLASS) -#define BLKC_ENDIAN(PRE) BLKC_APPLY(BLKC_SECOND, PRE##_CLASS) -#define BLKC_BITS(PRE) BLKC_APPLY(BLKC_THIRD, PRE##_CLASS) - -#define BLKC_STORE_E(PRE) BLKC_GLUE(STORE32_, BLKC_ENDIAN(PRE)) -#define BLKC_LOAD_E(PRE) BLKC_GLUE(LOAD32_, BLKC_ENDIAN(PRE)) - -/* --- Interface macros --- */ - -#define BLKC_STORE(PRE, b, w) \ - BLKC_GLUE(BLKC_STORE_, BLKC_TYPE(PRE)) \ - (PRE, b, w, BLKC_STORE_E(PRE), BLKC_BITS(PRE)) - -#define BLKC_XSTORE(PRE, b, w, wx) \ - BLKC_GLUE(BLKC_XSTORE_, BLKC_TYPE(PRE)) \ - (PRE, b, w, wx, BLKC_STORE_E(PRE), BLKC_BITS(PRE)) - -#define BLKC_LOAD(PRE, w, b) \ - BLKC_GLUE(BLKC_LOAD_, BLKC_TYPE(PRE)) \ - (PRE, w, b, BLKC_LOAD_E(PRE), BLKC_BITS(PRE)) - -#define BLKC_XLOAD(PRE, w, b) \ - BLKC_GLUE(BLKC_XLOAD_, BLKC_TYPE(PRE)) \ - (PRE, w, b, BLKC_LOAD_E(PRE), BLKC_BITS(PRE)) - -#define BLKC_MOVE(PRE, w, wx) \ - BLKC_GLUE(BLKC_MOVE_, BLKC_TYPE(PRE)) \ - (PRE, w, wx, BLKC_BITS(PRE)) - -#define BLKC_XMOVE(PRE, w, wx) \ - BLKC_GLUE(BLKC_XMOVE_, BLKC_TYPE(PRE)) \ - (PRE, w, wx, BLKC_BITS(PRE)) - -#define BLKC_STEP(PRE, w) \ - BLKC_GLUE(BLKC_STEP_X_, BLKC_ENDIAN(PRE)) \ - (PRE, w) - -#define BLKC_ZERO(PRE, w) \ - BLKC_GLUE(BLKC_ZERO_, BLKC_TYPE(PRE)) \ - (PRE, w, BLKC_BITS(PRE)) - -#define BLKC_SET(PRE, w, x) \ - BLKC_GLUE(BLKC_SET_X_, BLKC_ENDIAN(PRE)) \ - (PRE, w, x) - -#define BLKC_SHOW(PRE, tag, w) do { \ - fputs(tag ": ", stdout); \ - BLKC_SKEL_X(PRE, BLKC_W(w);, printf("%08x ", *_w++);); \ - fputc('\n', stdout); \ -} while (0) - -/* --- General implementation skeleton --- */ - -#define BLKC_SKEL(PRE, decl, guts) do { \ - decl \ - guts \ -} while (0) - -#define BLKC_P(p) register octet *_p = (octet *)(p) -#define BLKC_W(w) register uint32 *_w = (w) -#define BLKC_WX(wx) register uint32 *_wx = (wx) - -/* --- Implementation for unusual block sizes --- */ - -#define BLKC_SKEL_X(PRE, decl, guts) \ - BLKC_SKEL(PRE, unsigned _i; decl, \ - for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) { \ - guts \ - }) - -#define BLKC_STORE_X(PRE, b, w, op, n) \ - BLKC_SKEL_X(PRE, BLKC_P(b); const BLKC_W(w);, \ - op(_p, *_w); _p += 4; _w++; ) - -#define BLKC_XSTORE_X(PRE, b, w, wx, op, n) \ - BLKC_SKEL_X(PRE, BLKC_P(b); const BLKC_W(w); const BLKC_WX(wx);, \ - op(_p, *_w ^ *_wx); _p += 4; _w++; _wx++; ) - -#define BLKC_LOAD_X(PRE, w, b, op, n) \ - BLKC_SKEL_X(PRE, const BLKC_P(b); BLKC_W(w);, \ - *_w = op(_p); _p += 4; _w++; ) - -#define BLKC_XLOAD_X(PRE, w, b, op, n) \ - BLKC_SKEL_X(PRE, const BLKC_P(b); BLKC_W(w);, \ - *_w ^= op(_p); _p += 4; _w++; ) - -#define BLKC_MOVE_X(PRE, w, wx, n) \ - BLKC_SKEL_X(PRE, BLKC_W(w); const BLKC_WX(wx);, \ - *_w = *_wx; _w++; _wx++; ) \ - -#define BLKC_XMOVE_X(PRE, w, wx, n) \ - BLKC_SKEL_X(PRE, BLKC_W(w); const BLKC_WX(wx);, \ - *_w ^= *_wx; _w++; _wx++; ) \ - -#define BLKC_ZERO_X(PRE, w, n) \ - BLKC_SKEL_X(PRE, BLKC_W(w);, *_w++ = 0;) - -#define BLKC_STEP_X_B(PRE, w) do { \ - unsigned _i = PRE##_BLKSZ / 4; BLKC_W(w); uint32 _x = 0; \ - while (_i && !_x) { _i--; _w[_i] = _x = U32(_w[_i] + 1); } \ -} while (0) - -#define BLKC_STEP_X_L(PRE, w) do { \ - unsigned _i = 0; BLKC_W(w); uint32 _x = 0; \ - while (_i < PRE##_BLKSZ / 4 && !_x) \ - { _w[_i] = _x = U32(_w[_i] + 1); _i++; } \ -} while (0) - -#define BLKC_SET_X_B(PRE, w, x) do { \ - unsigned _i; BLKC_W(w); unsigned long _x = x; \ - for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) { \ - *_w++ = U32(_x); \ - _x = ((_x & ~MASK32) >> 16) >> 16; \ - } \ -} while (0) - -#define BLKC_SET_X_L(PRE, w, x) do { \ - unsigned _i; BLKC_W(w); unsigned long _x = x; _w += PRE##_BLKSZ / 4; \ - for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) { \ - *--_w = U32(_x); \ - _x = ((_x & ~MASK32) >> 16) >> 16; \ - } \ -} while (0) - -/* --- Implementation for known block sizes --- */ - -#define BLKC_SKEL_64(PRE, decl, op, guts) \ - BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1);) - -#define BLKC_SKEL_96(PRE, decl, op, guts) \ - BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1); guts(op, 2);) - -#define BLKC_SKEL_128(PRE, decl, op, guts) \ - BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3);) - -#define BLKC_SKEL_192(PRE, decl, op, guts) \ - BLKC_SKEL(PRE, decl, \ - guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3); \ - guts(op, 4); guts(op, 5);) - -#define BLKC_SKEL_256(PRE, decl, op, guts) \ - BLKC_SKEL(PRE, decl, \ - guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3); \ - guts(op, 4); guts(op, 5); guts(op, 6); guts(op, 7);) - -#define BLKC_STORE_GUTS(op, i) op(_p + 4 * i, _w[i]) -#define BLKC_XSTORE_GUTS(op, i) op(_p + 4 * i, _w[i] ^ _wx[i]) -#define BLKC_LOAD_GUTS(op, i) _w[i] = op(_p + 4 * i) -#define BLKC_XLOAD_GUTS(op, i) _w[i] ^= op(_p + 4 * i) -#define BLKC_MOVE_GUTS(op, i) _w[i] = _wx[i] -#define BLKC_XMOVE_GUTS(op, i) _w[i] ^= _wx[i] -#define BLKC_ZERO_GUTS(op, i) _w[i] = 0 - -#define BLKC_STORE_N(PRE, b, w, op, n) \ - BLKC_GLUE(BLKC_SKEL_, n) \ - (PRE, BLKC_P(b); const BLKC_W(w);, op, BLKC_STORE_GUTS) - -#define BLKC_XSTORE_N(PRE, b, w, wx, op, n) \ - BLKC_GLUE(BLKC_SKEL_, n) \ - (PRE, BLKC_P(b); const BLKC_W(w); const BLKC_WX(wx);, \ - op, BLKC_XSTORE_GUTS) - -#define BLKC_LOAD_N(PRE, w, b, op, n) \ - BLKC_GLUE(BLKC_SKEL_, n) \ - (PRE, const BLKC_P(b); BLKC_W(w);, op, BLKC_LOAD_GUTS) - -#define BLKC_XLOAD_N(PRE, w, b, op, n) \ - BLKC_GLUE(BLKC_SKEL_, n) \ - (PRE, const BLKC_P(b); BLKC_W(w);, op, BLKC_XLOAD_GUTS) - -#define BLKC_MOVE_N(PRE, w, wx, n) \ - BLKC_GLUE(BLKC_SKEL_, n) \ - (PRE, BLKC_W(w); const BLKC_WX(wx);, op, BLKC_MOVE_GUTS) - -#define BLKC_ZERO_N(PRE, w, n) \ - BLKC_GLUE(BLKC_SKEL_, n) \ - (PRE, BLKC_W(w); , op, BLKC_ZERO_GUTS) - -#define BLKC_XMOVE_N(PRE, w, wx, n) \ - BLKC_GLUE(BLKC_SKEL_, n) \ - (PRE, BLKC_W(w); const BLKC_WX(wx);, op, BLKC_XMOVE_GUTS) - -/*----- Test rig for block ciphers ----------------------------------------*/ - -/* --- @BLKC_TEST@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for cipher-specific definitions - * - * Use: Standard test rig for block ciphers. - */ - -#ifdef TEST_RIG - -#include - -#include -#include - -#define BLKC_VERIFY(PRE, pre) \ - \ -static int pre##_verify(dstr *v) \ -{ \ - pre##_ctx k; \ - uint32 p[PRE##_BLKSZ / 4]; \ - uint32 c[PRE##_BLKSZ / 4]; \ - uint32 d[PRE##_BLKSZ / 4]; \ - dstr b = DSTR_INIT; \ - int ok = 1; \ - \ - /* --- Initialize the key buffer --- */ \ - \ - dstr_ensure(&b, PRE##_BLKSZ); \ - b.len = PRE##_BLKSZ; \ - pre##_init(&k, v[0].buf, v[0].len); \ - BLKC_LOAD(PRE, p, v[1].buf); \ - BLKC_LOAD(PRE, c, v[2].buf); \ - \ - /* --- Test encryption --- */ \ - \ - BLKC_MOVE(PRE, d, p); \ - pre##_eblk(&k, d, d); \ - BLKC_STORE(PRE, b.buf, d); \ - if (memcmp(b.buf, v[2].buf, PRE##_BLKSZ)) { \ - ok = 0; \ - printf("\nfail encryption:" \ - "\n\tkey = "); \ - type_hex.dump(&v[0], stdout); \ - printf("\n\tplaintext = "); type_hex.dump(&v[1], stdout); \ - printf("\n\texpected = "); type_hex.dump(&v[2], stdout); \ - printf("\n\tcalculated = "); type_hex.dump(&b, stdout); \ - putchar('\n'); \ - } \ - \ - /* --- Test decryption --- */ \ - \ - BLKC_MOVE(PRE, d, c); \ - pre##_dblk(&k, d, d); \ - BLKC_STORE(PRE, b.buf, d); \ - if (memcmp(b.buf, v[1].buf, PRE##_BLKSZ)) { \ - ok = 0; \ - printf("\nfail decryption:" \ - "\n\tkey = "); \ - type_hex.dump(&v[0], stdout); \ - printf("\n\tciphertext = "); type_hex.dump(&v[2], stdout); \ - printf("\n\texpected = "); type_hex.dump(&v[1], stdout); \ - printf("\n\tcalculated = "); type_hex.dump(&b, stdout); \ - putchar('\n'); \ - } \ - \ - /* --- Return --- */ \ - \ - return (ok); \ -} - -#define BLKC_TEST(PRE, pre) \ - \ -BLKC_VERIFY(PRE, pre) \ - \ -static const test_chunk defs[] = { \ - { #pre, pre##_verify, { &type_hex, &type_hex, &type_hex, 0 } }, \ - { 0, 0, { 0 } } \ -}; \ - \ -int main(int argc, char *argv[]) \ -{ \ - test_run(argc, argv, defs, SRCDIR"/tests/" #pre); \ - return (0); \ -} - -#else -# define BLKC_VERIFY(PRE, pre) -# define BLKC_TEST(PRE, pre) -#endif - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/blowfish-mktab.c b/blowfish-mktab.c deleted file mode 100644 index 9d6fcb2..0000000 --- a/blowfish-mktab.c +++ /dev/null @@ -1,192 +0,0 @@ -/* -*-c-*- - * - * $Id: blowfish-mktab.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Build Blowfish key table - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @spigot@ --- * - * - * Arguments: @uint32 *buf@ = pointer to the output buffer - * @size_t n@ = number of output digits wanted - * - * Returns: --- - * - * Use: Writes digits of %$\pi$% to the given array. The algorithm - * is based on the Spigot algorithm by Stanley Rabinowitz and - * Stan Wagon, published in Amer.Math.Monthly, March 1995, with - * bug fixes by C. Haenel. I then bodged it to output hex - * digits rather than decimal ones, and to leave off the initial - * `3'. - * - * I've not analysed the algorithm very much. - */ - -#define SPIGOT_WORDS (18 + 4 * 256ul) -#define SPIGOT_BITS 8 -#define SPIGOT_RADIX (1ul << SPIGOT_BITS) -#define SPIGOT_BUFLEN (SPIGOT_WORDS * 32) - -#ifdef QUIET -# define Q(x) -#else -# define Q(x) x -#endif - -static void spigot(uint32 *buf, size_t n) -{ - uint32 acc = 0; - int b = -1; - unsigned a[SPIGOT_BUFLEN] = { 0 }; - uint32 p = 0; - unsigned f = 0; - unsigned max = 32 * n; - Q( size_t step = n / 60; ) - - Q( fputs("[ ]\r[", - stderr); ) - -#define EMIT(z) do { \ - if (b == -1) \ - b = 0; \ - else { \ - acc = (acc << SPIGOT_BITS) | (z); \ - b += SPIGOT_BITS; \ - if (b == 32) { \ - *buf++ = acc; \ - acc = 0; \ - b = 0; \ - n--; \ - if (!n) \ - goto done; \ - Q( if (n % step == 0) \ - fputc('.', stderr); ) \ - } \ - } \ -} while (0) - - while (n) { - uint32 q = 0; - uint32 i; - uint32 x = 0; - uint32 k = max * 2 - 1; - - for (i = max; i; i--) { - x = (b == -1 ? SPIGOT_RADIX * 2 : a[i - 1] << SPIGOT_BITS) + q * i; - q = x / k; - a[i - 1] = x - q * k; - k -= 2; - } - - k = x & (SPIGOT_RADIX - 1); - if (k == SPIGOT_RADIX - 1) - f++; - else { - EMIT(p + (x >> SPIGOT_BITS)); - if (f) { - unsigned d = (x >= SPIGOT_RADIX ? 0 : SPIGOT_RADIX - 1); - while (f) { - EMIT(d); - f--; - } - } - p = k; - } - } - -done:; - Q( fputc('\n', stderr); ) - -#undef EMIT -} - -/* --- @main@ --- */ - -int main(void) -{ - uint32 dbuf[SPIGOT_WORDS]; - int i, j; - uint32 *d = dbuf; - - spigot(d, SPIGOT_WORDS); - - fputs("\ -/* -*-c-*-\n\ - *\n\ - * Blowfish initial key table [generated]\n\ - */\n\ -\n\ -#ifndef CATACOMB_BLOWFISH_TAB_H\n\ -#define CATACOMB_BLOWFISH_TAB_H\n\ -\n\ -#define BLOWFISH_IKEY { \\\n\ - { ", stdout); - - for (i = 0; i < 18; i++) { - printf("0x%08x", *d++); - if (i == 17) - fputs(" }, \\\n\ - \\\n\ - { ", stdout); - else if (i % 4 == 3) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - for (j = 0; j < 4; j++) { - for (i = 0; i < 256; i++) { - printf("0x%08x", *d++); - if (i == 255) { - if (j == 3) - fputs(" } \\\n}\n\n#endif\n", stdout); - else - fputs(" }, \\\n\ - \\\n\ - { ", stdout); - } else if (i % 4 == 3) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - } - - if (fclose(stdout)) { - fprintf(stderr, "error writing data\n"); - exit(EXIT_FAILURE); - } - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/blowfish.c b/blowfish.c deleted file mode 100644 index 2750cfb..0000000 --- a/blowfish.c +++ /dev/null @@ -1,208 +0,0 @@ -/* -*-c-*- - * - * $Id: blowfish.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * The Blowfish block cipher - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "blowfish.h" -#include "blowfish-tab.h" -#include "blkc.h" -#include "gcipher.h" -#include "paranoia.h" - -/*----- Global variables --------------------------------------------------*/ - -static const blowfish_ctx ikey = BLOWFISH_IKEY; - -const octet blowfish_keysz[] = { KSZ_RANGE, BLOWFISH_KEYSZ, 1, 56, 1 }; - -/*----- Macros ------------------------------------------------------------*/ - -#define ROUND(k, x, y, r) do { \ - x ^= *r; \ - y ^= ((k->s0[U8(x >> 24)] + \ - k->s1[U8(x >> 16)]) ^ \ - k->s2[U8(x >> 8)]) + \ - k->s3[U8(x >> 0)]; \ -} while (0) - -#define EBLK(k, a, b, c, d) do { \ - const uint32 *_r = k->p; \ - uint32 _x = a; \ - uint32 _y = b; \ - ROUND(k, _x, _y, _r++); \ - ROUND(k, _y, _x, _r++); \ - ROUND(k, _x, _y, _r++); \ - ROUND(k, _y, _x, _r++); \ - ROUND(k, _x, _y, _r++); \ - ROUND(k, _y, _x, _r++); \ - ROUND(k, _x, _y, _r++); \ - ROUND(k, _y, _x, _r++); \ - ROUND(k, _x, _y, _r++); \ - ROUND(k, _y, _x, _r++); \ - ROUND(k, _x, _y, _r++); \ - ROUND(k, _y, _x, _r++); \ - ROUND(k, _x, _y, _r++); \ - ROUND(k, _y, _x, _r++); \ - ROUND(k, _x, _y, _r++); \ - ROUND(k, _y, _x, _r++); \ - c = _y ^ k->p[17]; \ - d = _x ^ k->p[16]; \ -} while (0) - -#define DBLK(k, a, b, c, d) do { \ - const uint32 *_r = k->p + 18; \ - uint32 _x = a; \ - uint32 _y = b; \ - ROUND(k, _x, _y, --_r); \ - ROUND(k, _y, _x, --_r); \ - ROUND(k, _x, _y, --_r); \ - ROUND(k, _y, _x, --_r); \ - ROUND(k, _x, _y, --_r); \ - ROUND(k, _y, _x, --_r); \ - ROUND(k, _x, _y, --_r); \ - ROUND(k, _y, _x, --_r); \ - ROUND(k, _x, _y, --_r); \ - ROUND(k, _y, _x, --_r); \ - ROUND(k, _x, _y, --_r); \ - ROUND(k, _y, _x, --_r); \ - ROUND(k, _x, _y, --_r); \ - ROUND(k, _y, _x, --_r); \ - ROUND(k, _x, _y, --_r); \ - ROUND(k, _y, _x, --_r); \ - c = _y ^ k->p[0]; \ - d = _x ^ k->p[1]; \ -} while (0) - -/*----- Low-level encryption interface ------------------------------------*/ - -/* --- @blowfish_init@ --- * - * - * Arguments: @blowfish_ctx *k@ = pointer to key block to fill in - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a Blowfish key buffer. Blowfish accepts - * a more-or-less arbitrary size key. - */ - -void blowfish_init(blowfish_ctx *k, const void *buf, size_t sz) -{ - KSZ_ASSERT(blowfish, sz); - - /* --- Copy the initial value over --- */ - - memcpy(k, &ikey, sizeof(ikey)); - - /* --- Initialize the %$P$% array --- */ - - { - const octet *p = buf; - const octet *q = p + sz; - int i = 0, j = 0; - uint32 x = 0; - - while (i < 18) { - x = (x << 8) | U8(*p++); - if (p >= q) - p = buf; - if (++j >= 4) { - k->p[i++] ^= x; - x = 0; - j = 0; - } - } - - x = 0; - } - - /* --- Now mangle the complete array of keys --- */ - - { - uint32 b[2]; - int i; - - b[0] = b[1] = 0; - - for (i = 0; i < 18; i += 2) { - blowfish_eblk(k, b, b); - k->p[i] = b[0]; k->p[i + 1] = b[1]; - } - - for (i = 0; i < 256; i += 2) { - blowfish_eblk(k, b, b); - k->s0[i] = b[0]; k->s0[i + 1] = b[1]; - } - - for (i = 0; i < 256; i += 2) { - blowfish_eblk(k, b, b); - k->s1[i] = b[0]; k->s1[i + 1] = b[1]; - } - - for (i = 0; i < 256; i += 2) { - blowfish_eblk(k, b, b); - k->s2[i] = b[0]; k->s2[i + 1] = b[1]; - } - - for (i = 0; i < 256; i += 2) { - blowfish_eblk(k, b, b); - k->s3[i] = b[0]; k->s3[i + 1] = b[1]; - } - - BURN(b); - } -} - -/* --- @blowfish_eblk@, @blowfish_dblk@ --- * - * - * Arguments: @const blowfish_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -void blowfish_eblk(const blowfish_ctx *k, const uint32 *s, uint32 *d) -{ - EBLK(k, s[0], s[1], d[0], d[1]); -} - -void blowfish_dblk(const blowfish_ctx *k, const uint32 *s, uint32 *d) -{ - DBLK(k, s[0], s[1], d[0], d[1]); -} - -BLKC_TEST(BLOWFISH, blowfish) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/blowfish.h b/blowfish.h deleted file mode 100644 index a9ece5e..0000000 --- a/blowfish.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -*-c-*- - * - * $Id: blowfish.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * The Blowfish block cipher - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the Blowfish block cipher --------------------------------* - * - * Blowfish was invented by Bruce Schneier. The algorithm is unpatented and - * free for anyone to use. It's fast, simple, offers a big key, and is - * looking relatively bulletproof. It's also this author's block cipher of - * choice, for what little that's worth. The disadvantage is that Blowfish - * has a particularly heavyweight key schedule. - */ - -#ifndef CATACOMB_BLOWFISH_H -#define CATACOMB_BLOWFISH_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magical numbers ---------------------------------------------------*/ - -#define BLOWFISH_BLKSZ 8 -#define BLOWFISH_KEYSZ 32 -#define BLOWFISH_CLASS (N, B, 64) - -extern const octet blowfish_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct blowfish_ctx { - uint32 p[18]; - uint32 s0[256], s1[256], s2[256], s3[256]; -} blowfish_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @blowfish_init@ --- * - * - * Arguments: @blowfish_ctx *k@ = pointer to key block to fill in - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a Blowfish key buffer. Blowfish accepts - * a more-or-less arbitrary size key. - */ - -extern void blowfish_init(blowfish_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @blowfish_eblk@, @blowfish_dblk@ --- * - * - * Arguments: @const blowfish_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void blowfish_eblk(const blowfish_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -extern void blowfish_dblk(const blowfish_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/buf.c b/buf.c deleted file mode 100644 index 0cf2cf0..0000000 --- a/buf.c +++ /dev/null @@ -1,129 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Buffer handling - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "mp.h" -#include "ec.h" -#include "buf.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @buf_getmp@ --- * - * - * Arguments: @buf *b@ = pointer to a buffer block - * - * Returns: A multiprecision integer, or null if there wasn't one there. - * - * Use: Gets a multiprecision integer from a buffer. - */ - -mp *buf_getmp(buf *b) -{ - uint16 sz; - size_t n; - mp *m; - if (buf_getu16(b, &sz) || buf_ensure(b, sz)) - return (0); - m = mp_loadb(MP_NEW, BCUR(b), sz); - n = mp_octets(m); - if (n != sz && n != 0 && sz != 1) { - mp_drop(m); - return (0); - } - BSTEP(b, sz); - return (m); -} - -/* --- @buf_putmp@ --- * - * - * Arguments: @buf *b@ = pointer to a buffer block - * @mp *m@ = a multiprecision integer - * - * Returns: Zero if it worked, nonzero if there wasn't enough space. - * - * Use: Puts a multiprecision integer to a buffer. - */ - -int buf_putmp(buf *b, mp *m) -{ - size_t sz = mp_octets(m); - assert(sz < MASK16); - if (!sz) sz = 1; - if (buf_putu16(b, sz) || buf_ensure(b, sz)) - return (-1); - mp_storeb(m, BCUR(b), sz); - BSTEP(b, sz); - return (0); -} - -/* --- @buf_getec@ --- * - * - * Arguments: @buf *b@ = pointer to a buffer block - * @ec *p@ = where to put the point - * - * Returns: Zero if it worked, nonzero if it failed. - * - * Use: Gets a multiprecision integer from a buffer. The point must - * be initialized. - */ - -int buf_getec(buf *b, ec *p) -{ - mp *x = 0, *y = 0; - uint16 n; - if (buf_ensure(b, 2)) return (-1); - n = LOAD16(BCUR(b)); if (!n) { BSTEP(b, 2); EC_SETINF(p); return (0); } - if ((x = buf_getmp(b)) == 0 || (y = buf_getmp(b)) == 0) { - mp_drop(x); mp_drop(y); return (-1); - } - EC_DESTROY(p); p->x = x; p->y = y; p->z = 0; - return (0); -} - -/* --- @buf_putec@ --- * - * - * Arguments: @buf *b@ = pointer to a buffer block - * @ec *p@ = an elliptic curve point - * - * Returns: Zero if it worked, nonzero if there wasn't enough space. - * - * Use: Puts an elliptic curve point to a buffer. - */ - -int buf_putec(buf *b, ec *p) -{ - if (EC_ATINF(p)) return (buf_putu16(b, 0)); - if (buf_putmp(b, p->x) || buf_putmp(b, p->y)) return (-1); - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/buf.h b/buf.h deleted file mode 100644 index 065db07..0000000 --- a/buf.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Reading and writing packet buffers - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_BUF_H -#define CATACOMB_BUF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_EC_H -# include "ec.h" -#endif - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @buf_getmp@ --- * - * - * Arguments: @buf *b@ = pointer to a buffer block - * - * Returns: A multiprecision integer, or null if there wasn't one there. - * - * Use: Gets a multiprecision integer from a buffer. - */ - -extern mp *buf_getmp(buf */*b*/); - -/* --- @buf_putmp@ --- * - * - * Arguments: @buf *b@ = pointer to a buffer block - * @mp *m@ = a multiprecision integer - * - * Returns: Zero if it worked, nonzero if there wasn't enough space. - * - * Use: Puts a multiprecision integer to a buffer. - */ - -extern int buf_putmp(buf */*b*/, mp */*m*/); - -/* --- @buf_getec@ --- * - * - * Arguments: @buf *b@ = pointer to a buffer block - * @ec *p@ = where to put the point - * - * Returns: Zero if it worked, nonzero if it failed. - * - * Use: Gets a multiprecision integer from a buffer. The point must - * be initialized. - */ - -extern int buf_getec(buf */*b*/, ec */*p*/); - -/* --- @buf_putec@ --- * - * - * Arguments: @buf *b@ = pointer to a buffer block - * @ec *p@ = an elliptic curve point - * - * Returns: Zero if it worked, nonzero if there wasn't enough space. - * - * Use: Puts an elliptic curve point to a buffer. - */ - -extern int buf_putec(buf */*b*/, ec */*p*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/build-setup b/build-setup index 50aabee..77af12e 100755 --- a/build-setup +++ b/build-setup @@ -1,2 +1,2 @@ #! /bin/sh -ex -if [ ! -r modes.am ]; then touch -t197001010000.00 modes.am; fi +if [ ! -r symm/modes.am ]; then touch -t197001010000.00 symm/modes.am; fi diff --git a/calc/ec2.cal b/calc/ec2.cal index e43c61b..3a37330 100644 --- a/calc/ec2.cal +++ b/calc/ec2.cal @@ -1,7 +1,5 @@ /* -*-apcalc-*- * - * $Id: ec2.cal,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * * Testbed for elliptic curve arithmetic over binary fields * * (c) 2004 Straylight/Edgeware diff --git a/calc/ecp.cal b/calc/ecp.cal index 4fedccf..700b18f 100644 --- a/calc/ecp.cal +++ b/calc/ecp.cal @@ -1,7 +1,5 @@ /* -*-apcalc-*- * - * $Id: ecp.cal,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * * Testbed for elliptic curve arithmetic over prime fields * * (c) 2000 Straylight/Edgeware diff --git a/calc/gfx-test.cal b/calc/gfx-test.cal index 3a5804f..1c2d4c6 100644 --- a/calc/gfx-test.cal +++ b/calc/gfx-test.cal @@ -1,7 +1,5 @@ /* -*-apcalc-*- * - * $Id: gfx-test.cal,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * * Generate test cases for %$\gf{2}[x]$% arithmetic * * (c) 2000 Straylight/Edgeware diff --git a/calc/gfx.cal b/calc/gfx.cal index 01d5c10..f898c45 100644 --- a/calc/gfx.cal +++ b/calc/gfx.cal @@ -1,7 +1,5 @@ /* -*-apcalc-*- * - * $Id: gfx.cal,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * * Testbed for %$\gf{2}$% poltnomial arithmetic * * (c) 2000 Straylight/Edgeware diff --git a/cast-base.h b/cast-base.h deleted file mode 100644 index 36cd42b..0000000 --- a/cast-base.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*-c-*- - * - * $Id: cast-base.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Basic macros and definitions for CAST-128 and CAST-256 - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_CAST_BASE_H -#define CATACOMB_CAST_BASE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -/*----- Round functions ---------------------------------------------------*/ - -#define CAST_R_guts(km, kr, xx, yy, aop, bop, cop) do { \ - uint32 i = km aop yy; \ - unsigned _r = kr; \ - i = ROL32(i, _r); \ - xx ^= ((cast_s[0][U8(i >> 24)] bop \ - cast_s[1][U8(i >> 16)]) cop \ - cast_s[2][U8(i >> 8)]) aop \ - cast_s[3][U8(i >> 0)]; \ -} while (0) - -#define CAST_R1(km, kr, xx, yy) CAST_R_guts(km, kr, xx, yy, +, ^, -) -#define CAST_R2(km, kr, xx, yy) CAST_R_guts(km, kr, xx, yy, ^, -, +) -#define CAST_R3(km, kr, xx, yy) CAST_R_guts(km, kr, xx, yy, -, +, ^) - -/*----- Global variables --------------------------------------------------*/ - -extern const uint32 cast_s[4][256], cast_sk[4][256]; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/cast-s.c b/cast-s.c deleted file mode 100644 index e9b1e6a..0000000 --- a/cast-s.c +++ /dev/null @@ -1,41 +0,0 @@ -/* -*-c-*- - * - * $Id: cast-s.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Basic S-boxes for CAST-128 and CAST-256 - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "cast-base.h" -#include "cast-tab.h" - -/*----- Global variables --------------------------------------------------*/ - -const uint32 cast_s[4][256] = CAST_S; - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/cast-sk.c b/cast-sk.c deleted file mode 100644 index 25210b7..0000000 --- a/cast-sk.c +++ /dev/null @@ -1,41 +0,0 @@ -/* -*-c-*- - * - * $Id: cast-sk.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Key-schedule S-boxes for CAST-128 - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "cast-base.h" -#include "cast-tab.h" - -/*----- Global variables --------------------------------------------------*/ - -const uint32 cast_sk[4][256] = CAST_SK; - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/cast-tab.h b/cast-tab.h deleted file mode 100644 index 6155f92..0000000 --- a/cast-tab.h +++ /dev/null @@ -1,569 +0,0 @@ -/* -*-c-*- - * - * $Id: cast-tab.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * S-boxes for CAST-128 and CAST-256 - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_CAST_TAB_H -#define CATACOMB_CAST_TAB_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- S-box tables ------------------------------------------------------*/ - -#define CAST_S { \ - { 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, \ - 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, \ - 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, \ - 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, \ - 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, \ - 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, \ - 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, \ - 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, \ - 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, \ - 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, \ - 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, \ - 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, \ - 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, \ - 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, \ - 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, \ - 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, \ - 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, \ - 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, \ - 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, \ - 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, \ - 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, \ - 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, \ - 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, \ - 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, \ - 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, \ - 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, \ - 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, \ - 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, \ - 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, \ - 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, \ - 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, \ - 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, \ - 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, \ - 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, \ - 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, \ - 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, \ - 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, \ - 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, \ - 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, \ - 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, \ - 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, \ - 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, \ - 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, \ - 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, \ - 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, \ - 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, \ - 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, \ - 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, \ - 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, \ - 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, \ - 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, \ - 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, \ - 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, \ - 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, \ - 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, \ - 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, \ - 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, \ - 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, \ - 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, \ - 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, \ - 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, \ - 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, \ - 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, \ - 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf }, \ - \ - { 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, \ - 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, \ - 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, \ - 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, \ - 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, \ - 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, \ - 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, \ - 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, \ - 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, \ - 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, \ - 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, \ - 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, \ - 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, \ - 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, \ - 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, \ - 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, \ - 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, \ - 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, \ - 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, \ - 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, \ - 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, \ - 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, \ - 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, \ - 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, \ - 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, \ - 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, \ - 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, \ - 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, \ - 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, \ - 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, \ - 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, \ - 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, \ - 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, \ - 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, \ - 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, \ - 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, \ - 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, \ - 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, \ - 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, \ - 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, \ - 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, \ - 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, \ - 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, \ - 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, \ - 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, \ - 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, \ - 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, \ - 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, \ - 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, \ - 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, \ - 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, \ - 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, \ - 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, \ - 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, \ - 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, \ - 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, \ - 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, \ - 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, \ - 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, \ - 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, \ - 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, \ - 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, \ - 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, \ - 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 }, \ - \ - { 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, \ - 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, \ - 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, \ - 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, \ - 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, \ - 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, \ - 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, \ - 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, \ - 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, \ - 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, \ - 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, \ - 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, \ - 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, \ - 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, \ - 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, \ - 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, \ - 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, \ - 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, \ - 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, \ - 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, \ - 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, \ - 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, \ - 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, \ - 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, \ - 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, \ - 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, \ - 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, \ - 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, \ - 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, \ - 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, \ - 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, \ - 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, \ - 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, \ - 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, \ - 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, \ - 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, \ - 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, \ - 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, \ - 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, \ - 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, \ - 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, \ - 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, \ - 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, \ - 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, \ - 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, \ - 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, \ - 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, \ - 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, \ - 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, \ - 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, \ - 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, \ - 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, \ - 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, \ - 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, \ - 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, \ - 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, \ - 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, \ - 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, \ - 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, \ - 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, \ - 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, \ - 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, \ - 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, \ - 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 }, \ - \ - { 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, \ - 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, \ - 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, \ - 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, \ - 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, \ - 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, \ - 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, \ - 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, \ - 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, \ - 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, \ - 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, \ - 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, \ - 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, \ - 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, \ - 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, \ - 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, \ - 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, \ - 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, \ - 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, \ - 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, \ - 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, \ - 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, \ - 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, \ - 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, \ - 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, \ - 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, \ - 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, \ - 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, \ - 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, \ - 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, \ - 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, \ - 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, \ - 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, \ - 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, \ - 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, \ - 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, \ - 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, \ - 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, \ - 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, \ - 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, \ - 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, \ - 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, \ - 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, \ - 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, \ - 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, \ - 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, \ - 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, \ - 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, \ - 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, \ - 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, \ - 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, \ - 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, \ - 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, \ - 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, \ - 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, \ - 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, \ - 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, \ - 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, \ - 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, \ - 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, \ - 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, \ - 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, \ - 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, \ - 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 } \ -} - -#define CAST_SK { \ - { 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, \ - 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, \ - 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, \ - 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, \ - 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, \ - 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, \ - 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, \ - 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, \ - 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, \ - 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, \ - 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, \ - 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, \ - 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, \ - 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, \ - 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, \ - 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, \ - 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, \ - 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, \ - 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, \ - 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, \ - 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, \ - 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, \ - 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, \ - 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, \ - 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, \ - 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, \ - 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, \ - 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, \ - 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, \ - 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, \ - 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, \ - 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, \ - 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, \ - 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, \ - 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, \ - 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, \ - 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, \ - 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, \ - 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, \ - 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, \ - 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, \ - 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, \ - 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, \ - 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, \ - 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, \ - 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, \ - 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, \ - 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, \ - 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, \ - 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, \ - 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, \ - 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, \ - 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, \ - 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, \ - 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, \ - 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, \ - 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, \ - 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, \ - 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, \ - 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, \ - 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, \ - 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, \ - 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, \ - 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 }, \ - \ - { 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, \ - 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, \ - 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, \ - 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, \ - 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, \ - 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, \ - 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, \ - 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, \ - 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, \ - 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, \ - 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, \ - 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, \ - 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, \ - 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, \ - 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, \ - 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, \ - 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, \ - 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, \ - 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, \ - 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, \ - 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, \ - 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, \ - 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, \ - 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, \ - 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, \ - 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, \ - 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, \ - 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, \ - 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, \ - 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, \ - 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, \ - 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, \ - 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, \ - 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, \ - 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, \ - 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, \ - 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, \ - 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, \ - 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, \ - 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, \ - 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, \ - 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, \ - 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, \ - 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, \ - 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, \ - 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, \ - 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, \ - 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, \ - 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, \ - 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, \ - 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, \ - 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, \ - 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, \ - 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, \ - 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, \ - 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, \ - 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, \ - 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, \ - 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, \ - 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, \ - 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, \ - 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, \ - 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, \ - 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f }, \ - \ - { 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, \ - 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, \ - 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, \ - 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, \ - 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, \ - 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, \ - 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, \ - 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, \ - 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, \ - 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, \ - 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, \ - 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, \ - 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, \ - 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, \ - 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, \ - 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, \ - 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, \ - 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, \ - 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, \ - 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, \ - 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, \ - 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, \ - 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, \ - 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, \ - 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, \ - 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, \ - 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, \ - 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, \ - 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, \ - 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, \ - 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, \ - 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, \ - 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, \ - 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, \ - 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, \ - 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, \ - 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, \ - 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, \ - 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, \ - 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, \ - 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, \ - 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, \ - 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, \ - 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, \ - 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, \ - 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, \ - 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, \ - 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, \ - 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, \ - 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, \ - 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, \ - 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, \ - 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, \ - 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, \ - 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, \ - 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, \ - 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, \ - 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, \ - 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, \ - 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, \ - 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, \ - 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, \ - 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, \ - 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 }, \ - \ - { 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, \ - 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, \ - 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, \ - 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, \ - 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, \ - 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, \ - 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, \ - 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, \ - 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, \ - 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, \ - 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, \ - 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, \ - 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, \ - 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, \ - 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, \ - 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, \ - 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, \ - 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, \ - 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, \ - 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, \ - 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, \ - 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, \ - 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, \ - 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, \ - 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, \ - 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, \ - 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, \ - 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, \ - 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, \ - 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, \ - 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, \ - 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, \ - 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, \ - 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, \ - 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, \ - 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, \ - 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, \ - 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, \ - 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, \ - 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, \ - 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, \ - 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, \ - 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, \ - 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, \ - 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, \ - 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, \ - 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, \ - 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, \ - 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, \ - 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, \ - 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, \ - 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, \ - 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, \ - 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, \ - 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, \ - 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, \ - 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, \ - 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, \ - 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, \ - 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, \ - 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, \ - 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, \ - 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, \ - 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e } \ -} - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/cast128.c b/cast128.c deleted file mode 100644 index 5f13614..0000000 --- a/cast128.c +++ /dev/null @@ -1,302 +0,0 @@ -/* -*-c-*- - * - * $Id: cast128.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The CAST-128 block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include - -#include "blkc.h" -#include "cast-base.h" -#include "cast128.h" -#include "gcipher.h" -#include "paranoia.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet cast128_keysz[] = { KSZ_RANGE, CAST128_KEYSZ, 0, 16, 1 }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @cast128_init@ --- * - * - * Arguments: @cast128_ctx *k@ = pointer to key block to fill in - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a CAST-128 key buffer. CAST-128 accepts - * 128-bit keys or shorter. - */ - -void cast128_init(cast128_ctx *k, const void *buf, size_t sz) -{ - const octet *p = buf; - uint32 kk[4]; - unsigned i; - uint32 a, b, c, d, aa, bb, cc, dd; - - /* --- Fiddle with the key size a bit --- */ - - KSZ_ASSERT(cast128, sz); - - if (sz > 10) - k->r = 16; - else - k->r = 12; - - /* --- Read the key into the array --- */ - - i = 0; - b = 32; aa = 0; - for (;;) { - if (!sz) - break; - b -= 8; - aa |= ((uint32)*p++ << b); - sz--; - if (b == 0) { - kk[i++] = aa; - if (i == 4) - break; - aa = 0; - b = 32; - } - } - - for (; i < 4; i++) { - kk[i] = aa; - aa = 0; - } - - /* --- Read the key words out --- */ - - a = kk[0]; b = kk[1]; c = kk[2]; d = kk[3]; - -#define X_0123 a -#define X_4567 b -#define X_89ab c -#define X_cdef d - -#define X_0 U8(X_0123 >> 24) -#define X_1 U8(X_0123 >> 16) -#define X_2 U8(X_0123 >> 8) -#define X_3 U8(X_0123 >> 0) -#define X_4 U8(X_4567 >> 24) -#define X_5 U8(X_4567 >> 16) -#define X_6 U8(X_4567 >> 8) -#define X_7 U8(X_4567 >> 0) -#define X_8 U8(X_89ab >> 24) -#define X_9 U8(X_89ab >> 16) -#define X_a U8(X_89ab >> 8) -#define X_b U8(X_89ab >> 0) -#define X_c U8(X_cdef >> 24) -#define X_d U8(X_cdef >> 16) -#define X_e U8(X_cdef >> 8) -#define X_f U8(X_cdef >> 0) - -#define Z_0123 aa -#define Z_4567 bb -#define Z_89ab cc -#define Z_cdef dd - -#define Z_0 U8(Z_0123 >> 24) -#define Z_1 U8(Z_0123 >> 16) -#define Z_2 U8(Z_0123 >> 8) -#define Z_3 U8(Z_0123 >> 0) -#define Z_4 U8(Z_4567 >> 24) -#define Z_5 U8(Z_4567 >> 16) -#define Z_6 U8(Z_4567 >> 8) -#define Z_7 U8(Z_4567 >> 0) -#define Z_8 U8(Z_89ab >> 24) -#define Z_9 U8(Z_89ab >> 16) -#define Z_a U8(Z_89ab >> 8) -#define Z_b U8(Z_89ab >> 0) -#define Z_c U8(Z_cdef >> 24) -#define Z_d U8(Z_cdef >> 16) -#define Z_e U8(Z_cdef >> 8) -#define Z_f U8(Z_cdef >> 0) - -#define SK(w, x, y, z) \ - cast_sk[0][w] ^ cast_sk[1][x] ^ cast_sk[2][y] ^ cast_sk[3][z] - - i = 0; - Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8]; - Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a]; - Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9]; - Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b]; - k->km[i++] = SK(Z_8, Z_9, Z_7, Z_6) ^ cast_sk[0][Z_2]; - k->km[i++] = SK(Z_a, Z_b, Z_5, Z_4) ^ cast_sk[1][Z_6]; - k->km[i++] = SK(Z_c, Z_d, Z_3, Z_2) ^ cast_sk[2][Z_9]; - k->km[i++] = SK(Z_e, Z_f, Z_1, Z_0) ^ cast_sk[3][Z_c]; - X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0]; - X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2]; - X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1]; - X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3]; - k->km[i++] = SK(X_3, X_2, X_c, X_d) ^ cast_sk[0][X_8]; - k->km[i++] = SK(X_1, X_0, X_e, X_f) ^ cast_sk[1][X_d]; - k->km[i++] = SK(X_7, X_6, X_8, X_9) ^ cast_sk[2][X_3]; - k->km[i++] = SK(X_5, X_4, X_a, X_b) ^ cast_sk[3][X_7]; - Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8]; - Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a]; - Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9]; - Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b]; - k->km[i++] = SK(Z_3, Z_2, Z_c, Z_d) ^ cast_sk[0][Z_9]; - k->km[i++] = SK(Z_1, Z_0, Z_e, Z_f) ^ cast_sk[1][Z_c]; - k->km[i++] = SK(Z_7, Z_6, Z_8, Z_9) ^ cast_sk[2][Z_2]; - k->km[i++] = SK(Z_5, Z_4, Z_a, Z_b) ^ cast_sk[3][Z_6]; - X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0]; - X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2]; - X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1]; - X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3]; - k->km[i++] = SK(X_8, X_9, X_7, X_6) ^ cast_sk[0][X_3]; - k->km[i++] = SK(X_a, X_b, X_5, X_4) ^ cast_sk[1][X_7]; - k->km[i++] = SK(X_c, X_d, X_3, X_2) ^ cast_sk[2][X_8]; - k->km[i++] = SK(X_e, X_f, X_1, X_0) ^ cast_sk[3][X_d]; - - i = 0; - Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8]; - Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a]; - Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9]; - Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b]; - k->kr[i++] = (SK(Z_8, Z_9, Z_7, Z_6) ^ cast_sk[0][Z_2]) & 0x1f; - k->kr[i++] = (SK(Z_a, Z_b, Z_5, Z_4) ^ cast_sk[1][Z_6]) & 0x1f; - k->kr[i++] = (SK(Z_c, Z_d, Z_3, Z_2) ^ cast_sk[2][Z_9]) & 0x1f; - k->kr[i++] = (SK(Z_e, Z_f, Z_1, Z_0) ^ cast_sk[3][Z_c]) & 0x1f; - X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0]; - X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2]; - X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1]; - X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3]; - k->kr[i++] = (SK(X_3, X_2, X_c, X_d) ^ cast_sk[0][X_8]) & 0x1f; - k->kr[i++] = (SK(X_1, X_0, X_e, X_f) ^ cast_sk[1][X_d]) & 0x1f; - k->kr[i++] = (SK(X_7, X_6, X_8, X_9) ^ cast_sk[2][X_3]) & 0x1f; - k->kr[i++] = (SK(X_5, X_4, X_a, X_b) ^ cast_sk[3][X_7]) & 0x1f; - Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8]; - Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a]; - Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9]; - Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b]; - k->kr[i++] = (SK(Z_3, Z_2, Z_c, Z_d) ^ cast_sk[0][Z_9]) & 0x1f; - k->kr[i++] = (SK(Z_1, Z_0, Z_e, Z_f) ^ cast_sk[1][Z_c]) & 0x1f; - k->kr[i++] = (SK(Z_7, Z_6, Z_8, Z_9) ^ cast_sk[2][Z_2]) & 0x1f; - k->kr[i++] = (SK(Z_5, Z_4, Z_a, Z_b) ^ cast_sk[3][Z_6]) & 0x1f; - X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0]; - X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2]; - X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1]; - X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3]; - k->kr[i++] = (SK(X_8, X_9, X_7, X_6) ^ cast_sk[0][X_3]) & 0x1f; - k->kr[i++] = (SK(X_a, X_b, X_5, X_4) ^ cast_sk[1][X_7]) & 0x1f; - k->kr[i++] = (SK(X_c, X_d, X_3, X_2) ^ cast_sk[2][X_8]) & 0x1f; - k->kr[i++] = (SK(X_e, X_f, X_1, X_0) ^ cast_sk[3][X_d]) & 0x1f; - - BURN(kk); -} - -/* --- @cast128_eblk@, @cast128_dblk@ --- * - * - * Arguments: @const cast128_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -void cast128_eblk(const cast128_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 a = s[0], b = s[1]; - const uint32 *km = k->km; - const octet *kr = k->kr; - - switch (k->r) { - default: - CAST_R1(*km++, *kr++, a, b); - CAST_R2(*km++, *kr++, b, a); - CAST_R3(*km++, *kr++, a, b); - CAST_R1(*km++, *kr++, b, a); - CAST_R2(*km++, *kr++, a, b); - CAST_R3(*km++, *kr++, b, a); - CAST_R1(*km++, *kr++, a, b); - CAST_R2(*km++, *kr++, b, a); - CAST_R3(*km++, *kr++, a, b); - CAST_R1(*km++, *kr++, b, a); - CAST_R2(*km++, *kr++, a, b); - CAST_R3(*km++, *kr++, b, a); - if (k->r == 12) - break; - CAST_R1(*km++, *kr++, a, b); - CAST_R2(*km++, *kr++, b, a); - CAST_R3(*km++, *kr++, a, b); - CAST_R1(*km++, *kr++, b, a); - break; - } - - d[0] = b; d[1] = a; -} - -void cast128_dblk(const cast128_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 a = s[0], b = s[1]; - const uint32 *km = k->km + k->r; - const octet *kr = k->kr + k->r; - - switch (k->r) { - case 16: - default: - CAST_R1(*--km, *--kr, a, b); - CAST_R3(*--km, *--kr, b, a); - CAST_R2(*--km, *--kr, a, b); - CAST_R1(*--km, *--kr, b, a); - case 12: - CAST_R3(*--km, *--kr, a, b); - CAST_R2(*--km, *--kr, b, a); - CAST_R1(*--km, *--kr, a, b); - CAST_R3(*--km, *--kr, b, a); - CAST_R2(*--km, *--kr, a, b); - CAST_R1(*--km, *--kr, b, a); - CAST_R3(*--km, *--kr, a, b); - CAST_R2(*--km, *--kr, b, a); - CAST_R1(*--km, *--kr, a, b); - CAST_R3(*--km, *--kr, b, a); - CAST_R2(*--km, *--kr, a, b); - CAST_R1(*--km, *--kr, b, a); - break; - } - - d[0] = b; d[1] = a; -} - -BLKC_TEST(CAST128, cast128) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/cast128.h b/cast128.h deleted file mode 100644 index fb51416..0000000 --- a/cast128.h +++ /dev/null @@ -1,116 +0,0 @@ -/* -*-c-*- - * - * $Id: cast128.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The CAST-128 block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the CAST-128 block cipher --------------------------------* - * - * CAST, designed by Carlisle Adams and Stafford Tavares, is a method for - * designing block ciphers, based around the concept of `bent functions'. It - * is described in the paper `Constructing Symmetric Ciphers using the CAST - * Design Procedure' by Carlisle Adams. - * - * CAST-128, defined in RFC2144, is a particular instance of the CAST design - * procedure, The cipher seems strong and fairly quick. The design procedure - * itself is patented, although the cipher CAST-128 is free to use. - * - * Although CAST ciphers are resistant to differential and linear - * cryptanalysis, some instances have been broken by more advanced techniques - * -- the CAST procedure does not guarantee a strong cipher. However, - * CAST-128 has so far resisted all attacks against it, and has now been - * accepted by the Canadian government for protection of all `Designated' - * material. - */ - -#ifndef CATACOMB_CAST128_H -#define CATACOMB_CAST128_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -/*----- Magic numbers -----------------------------------------------------*/ - -#define CAST128_BLKSZ 8 -#define CAST128_KEYSZ 16 -#define CAST128_CLASS (N, B, 64) - -extern const octet cast128_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct cast128_ctx { - unsigned r; - uint32 km[16]; - octet kr[16]; -} cast128_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @cast128_init@ --- * - * - * Arguments: @cast128_ctx *k@ = pointer to key block to fill in - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a CAST-128 key buffer. CAST-128 accepts - * 128-bit keys or shorter. - */ - -extern void cast128_init(cast128_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @cast128_eblk@, @cast128_dblk@ --- * - * - * Arguments: @const cast128_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void cast128_eblk(const cast128_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -extern void cast128_dblk(const cast128_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/cast256.c b/cast256.c deleted file mode 100644 index 36546b0..0000000 --- a/cast256.c +++ /dev/null @@ -1,205 +0,0 @@ -/* -*-c-*- - * - * $Id: cast256.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The CAST-256 block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include - -#include "blkc.h" -#include "cast-base.h" -#include "cast256.h" -#include "gcipher.h" -#include "paranoia.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet cast256_keysz[] = { KSZ_RANGE, CAST256_KEYSZ, 0, 32, 1 }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @cast256_init@ --- * - * - * Arguments: @cast128_ctx *k@ = pointer to key block to fill in - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a CAST-256 key buffer. CAST-256 accepts - * 256-bit keys or shorter. - */ - -void cast256_init(cast256_ctx *k, const void *buf, size_t sz) -{ - const octet *p = buf; - uint32 kk[8]; - uint32 *km; - octet *kr; - unsigned i, j; - uint32 a, b, c, d, e, f, g, h; - uint32 m; - unsigned r; - - /* --- Fiddle with the key size --- */ - - KSZ_ASSERT(cast256, sz); - - /* --- Read the key into the array --- */ - - i = 0; - b = 32; a = 0; - for (;;) { - if (!sz) - break; - b -= 8; - a |= ((uint32)*p++ << b); - sz--; - if (b == 0) { - kk[i++] = a; - if (i == 8) - break; - a = 0; - b = 32; - } - } - - for (; i < 8; i++) { - kk[i] = a; - a = 0; - } - - /* --- Read the key words out --- */ - - a = kk[0]; b = kk[1]; c = kk[2]; d = kk[3]; - e = kk[4]; f = kk[5]; g = kk[6]; h = kk[7]; - -#define ROOT2 0x5a827999 -#define ROOT3 0x6ed9eba1 - - m = ROOT2; - r = 19; - - km = k->km; - kr = k->kr; - for (i = 0; i < 12; i++) { - for (j = 0; j < 2; j++) { - CAST_R1(m, r, g, h); m += ROOT3; r = (r + 17) & 0x1f; - CAST_R2(m, r, f, g); m += ROOT3; r = (r + 17) & 0x1f; - CAST_R3(m, r, e, f); m += ROOT3; r = (r + 17) & 0x1f; - CAST_R1(m, r, d, e); m += ROOT3; r = (r + 17) & 0x1f; - CAST_R2(m, r, c, d); m += ROOT3; r = (r + 17) & 0x1f; - CAST_R3(m, r, b, c); m += ROOT3; r = (r + 17) & 0x1f; - CAST_R1(m, r, a, b); m += ROOT3; r = (r + 17) & 0x1f; - CAST_R2(m, r, h, a); m += ROOT3; r = (r + 17) & 0x1f; - } - km[0] = h; km[1] = f; km[2] = d; km[3] = b; - kr[0] = a & 0x1f; kr[1] = c & 0x1f; kr[2] = e & 0x1f; kr[3] = g & 0x1f; - km += 4; kr += 4; - } -} - -/* --- @cast256_eblk@, @cast256_dblk@ --- * - * - * Arguments: @const cast256_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -#define Q0(k, r, a, b, c, d) do { \ - CAST_R1(k[0], r[0], c, d); \ - CAST_R2(k[1], r[1], b, c); \ - CAST_R3(k[2], r[2], a, b); \ - CAST_R1(k[3], r[3], d, a); \ -} while (0) - -#define Q1(k, r, a, b, c, d) do { \ - CAST_R1(k[3], r[3], d, a); \ - CAST_R3(k[2], r[2], a, b); \ - CAST_R2(k[1], r[1], b, c); \ - CAST_R1(k[0], r[0], c, d); \ -} while (0) - -void cast256_eblk(const cast256_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3]; - const uint32 *km = k->km; - const octet *kr = k->kr; - - Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4; - Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4; - Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4; - Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4; - Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4; - Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4; - - Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4; - Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4; - Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4; - Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4; - Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4; - Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4; - - d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd; -} - -void cast256_dblk(const cast256_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3]; - const uint32 *km = k->km + 48; - const octet *kr = k->kr + 48; - - km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd); - km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd); - km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd); - km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd); - km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd); - km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd); - - km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd); - km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd); - km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd); - km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd); - km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd); - km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd); - - d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd; -} - -BLKC_TEST(CAST256, cast256) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/cast256.h b/cast256.h deleted file mode 100644 index 7e65a83..0000000 --- a/cast256.h +++ /dev/null @@ -1,111 +0,0 @@ -/* -*-c-*- - * - * $Id: cast256.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The CAST-128 block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the CAST-256 block cipher --------------------------------* - * - * CAST, designed by Carlisle Adams and Stafford Tavares, is a method for - * designing block ciphers, based around the concept of `bent functions'. It - * is described in the paper `Constructing Symmetric Ciphers using the CAST - * Design Procedure' by Carlisle Adams. - * - * CAST-256, defined in RFC2612, is a particular instance of the CAST design - * procedure. It is an `incomplete' Feistel network. It uses the same - * S-boxes and round functions as CAST-128. - * - * CAST-256 was submitted to the AES contest, but was not selected as one of - * the five `finalist' algorithms. - */ - -#ifndef CATACOMB_CAST256_H -#define CATACOMB_CAST256_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -/*----- Magic numbers -----------------------------------------------------*/ - -#define CAST256_BLKSZ 16 -#define CAST256_KEYSZ 32 -#define CAST256_CLASS (N, B, 128) - -extern const octet cast256_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct cast256_ctx { - uint32 km[48]; - octet kr[48]; -} cast256_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @cast256_init@ --- * - * - * Arguments: @cast256_ctx *k@ = pointer to key block to fill in - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a CAST-256 key buffer. CAST-256 accepts - * 256-bit keys or shorter. - */ - -extern void cast256_init(cast256_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @cast256_eblk@, @cast256_dblk@ --- * - * - * Arguments: @const cast256_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void cast256_eblk(const cast256_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -extern void cast256_dblk(const cast256_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/catcrypt.c b/catcrypt.c deleted file mode 100644 index 08fb7e0..0000000 --- a/catcrypt.c +++ /dev/null @@ -1,771 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Command-line encryption tool - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _FILE_OFFSET_BITS 64 - -#include "config.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "buf.h" -#include "rand.h" -#include "noise.h" -#include "mprand.h" -#include "key.h" -#include "cc.h" - -#include "ectab.h" -#include "ptab.h" - -/*----- Static variables --------------------------------------------------*/ - -static const char *keyring = "keyring"; - -/*----- Data format -------------------------------------------------------*/ - -/* --- Overview --- * - * - * The encrypted message is divided into chunks, each preceded by a two-octet - * length. The chunks don't need to be large -- the idea is that we can - * stream the chunks in and out. - * - * The first chunk is a header. It contains the decryption key-id, and maybe - * the verification key-id if the message is signed. - * - * Next comes the key-encapsulation chunk. This is decrypted in some - * KEM-specific way to yield a secret hash. The hash is expanded using an - * MGF (or similar) to make a symmetric encryption and MAC key. - * - * If the message is signed, there comes a signature chunk. The signature is - * on the header and key-encapsulation chunks, and further output of the MGF. - * This means that the recipient can modify the message and still have a - * valid signature, so it's not useful for proving things to other people; - * but it also means that the recipient knows that the message is from - * someone who knows the hash, which limits the possiblities to (a) whoever - * encrypted the message (good!) and (b) whoever knows the recipient's - * private key. - * - * Then come message chunks. Each one begins with a MAC over an implicit - * sequence number and the ciphertext. The final chunk's ciphertext is - * empty; no other chunk is empty. Thus can the correct end-of-file be - * discerned. - */ - -/*----- Chunk I/O ---------------------------------------------------------*/ - -static void chunk_write(enc *e, buf *b) -{ - octet l[2]; - size_t n = BLEN(b); - assert(n <= MASK16); - STORE16(l, n); - if (e->ops->write(e, l, 2) || - e->ops->write(e, BBASE(b), BLEN(b))) - die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); -} - -static void chunk_read(enc *e, dstr *d, buf *b) -{ - octet l[2]; - size_t n; - - dstr_reset(d); - errno = 0; - if (e->ops->read(e, l, 2) != 2) - goto err; - n = LOAD16(l); - dstr_ensure(d, n); - if (e->ops->read(e, d->buf, n) != n) - goto err; - d->len = n; - buf_init(b, d->buf, d->len); - return; - -err: - if (!errno) die(EXIT_FAILURE, "unexpected end-of-file on input"); - else die(EXIT_FAILURE, "error reading input: %s", strerror(errno)); -} - -/*----- Encryption --------------------------------------------------------*/ - -static int encrypt(int argc, char *argv[]) -{ - const char *fn, *of = 0, *kn = "ccrypt", *skn = 0; - FILE *ofp = 0; - FILE *fp = 0; - const char *ef = "binary"; - fprogress ff; - const char *err; - int i; - int en; - size_t n, chsz; - dstr d = DSTR_INIT; - octet *tag, *ct; - buf b; - size_t seq; - char bb[65536]; - unsigned f = 0; - key_file kf; - key *k; - key *sk = 0; - kem *km; - sig *s = 0; - gcipher *cx, *c; - gmac *m; - ghash *h; - const encops *eo; - enc *e; - -#define f_bogus 1u -#define f_nocheck 2u -#define f_progress 4u - - for (;;) { - static const struct option opt[] = { - { "key", OPTF_ARGREQ, 0, 'k' }, - { "sign-key", OPTF_ARGREQ, 0, 's' }, - { "armour", 0, 0, 'a' }, - { "armor", 0, 0, 'a' }, - { "format", OPTF_ARGREQ, 0, 'f' }, - { "output", OPTF_ARGREQ, 0, 'o' }, - { "progress", 0, 0, 'p' }, - { "nocheck", 0, 0, 'C' }, - { 0, 0, 0, 0 } - }; - i = mdwopt(argc, argv, "k:s:af:o:pC", opt, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'k': kn = optarg; break; - case 's': skn = optarg; break; - case 'a': ef = "pem"; break; - case 'f': ef = optarg; break; - case 'o': of = optarg; break; - case 'p': f |= f_progress; break; - case 'C': f |= f_nocheck; break; - default: f |= f_bogus; break; - } - } - if (argc - optind > 1 || (f & f_bogus)) - die(EXIT_FAILURE, "Usage: encrypt [-OPTIONS] [FILE]"); - - if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0)) - die(EXIT_FAILURE, "can't open keyring `%s'", keyring); - if ((k = key_bytag(&kf, kn)) == 0) - die(EXIT_FAILURE, "key `%s' not found", kn); - if (skn && (sk = key_bytag(&kf, skn)) == 0) - die(EXIT_FAILURE, "key `%s' not found", skn); - - if ((eo = getenc(ef)) == 0) - die(EXIT_FAILURE, "encoding `%s' not found", ef); - - fn = optind < argc ? argv[optind++] : "-"; - if (strcmp(fn, "-") == 0) - fp = stdin; - else if ((fp = fopen(fn, "rb")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s': %s", - fn, strerror(errno)); - } - - if (!of || strcmp(of, "-") == 0) - ofp = stdout; - else if ((ofp = fopen(of, eo->wmode)) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - ofp, strerror(errno)); - } - - dstr_reset(&d); - key_fulltag(k, &d); - e = initenc(eo, ofp, "CATCRYPT ENCRYPTED MESSAGE"); - km = getkem(k, "cckem", 0); - if (!(f & f_nocheck) && (err = km->ops->check(km)) != 0) - moan("key %s fails check: %s", d.buf, err); - if (sk) { - dstr_reset(&d); - key_fulltag(sk, &d); - s = getsig(sk, "ccsig", 1); - if ((err = s->ops->check(s)) != 0) - moan("key %s fails check: %s", d.buf, err); - } - - /* --- Build the header chunk --- */ - - dstr_reset(&d); - dstr_ensure(&d, 256); - buf_init(&b, d.buf, 256); - buf_putu32(&b, k->id); - if (sk) buf_putu32(&b, sk->id); - assert(BOK(&b)); - if (s) GH_HASHBUF16(s->h, BBASE(&b), BLEN(&b)); - chunk_write(e, &b); - - /* --- Build the KEM chunk --- */ - - dstr_reset(&d); - if (setupkem(km, &d, &cx, &c, &m)) - die(EXIT_FAILURE, "failed to encapsulate key"); - buf_init(&b, d.buf, d.len); - BSTEP(&b, d.len); - if (s) GH_HASHBUF16(s->h, BBASE(&b), BLEN(&b)); - chunk_write(e, &b); - - /* --- Write the signature chunk --- */ - - if (s) { - GC_ENCRYPT(cx, 0, bb, 1024); - GH_HASH(s->h, bb, 1024); - dstr_reset(&d); - if ((en = s->ops->doit(s, &d)) != 0) - die(EXIT_FAILURE, "error creating signature: %s", key_strerror(en)); - buf_init(&b, d.buf, d.len); - BSTEP(&b, d.len); - chunk_write(e, &b); - } - - /* --- Now do the main crypto --- */ - - if (f & f_progress) { - if (fprogress_init(&ff, fn, fp)) { - die(EXIT_FAILURE, "failed to initialize progress display: %s", - strerror(errno)); - } - } - - assert(GC_CLASS(c)->blksz <= sizeof(bb)); - dstr_ensure(&d, sizeof(bb) + GM_CLASS(m)->hashsz); - seq = 0; - chsz = MASK16 - GM_CLASS(m)->hashsz; - for (;;) { - h = GM_INIT(m); - GH_HASHU32(h, seq); - seq++; - if (GC_CLASS(c)->blksz) { - GC_ENCRYPT(cx, 0, bb, GC_CLASS(c)->blksz); - GC_SETIV(c, bb); - } - n = fread(bb, 1, chsz, fp); - if (!n) break; - if (f & f_progress) fprogress_update(&ff, n); - buf_init(&b, d.buf, d.sz); - tag = buf_get(&b, GM_CLASS(m)->hashsz); - ct = buf_get(&b, n); - assert(tag); assert(ct); - GC_ENCRYPT(c, bb, ct, n); - GH_HASH(h, ct, n); - GH_DONE(h, tag); - GH_DESTROY(h); - chunk_write(e, &b); - } - - /* --- Final terminator packet --- */ - - buf_init(&b, d.buf, d.sz); - tag = buf_get(&b, GM_CLASS(m)->hashsz); - assert(tag); - GH_DONE(h, tag); - GH_DESTROY(h); - chunk_write(e, &b); - - /* --- All done --- */ - - if (f & f_progress) fprogress_done(&ff); - e->ops->encdone(e); - GM_DESTROY(m); - GC_DESTROY(c); - GC_DESTROY(cx); - freeenc(e); - if (s) freesig(s); - freekem(km); - if (fp != stdin) fclose(fp); - if (of) fclose(ofp); - key_close(&kf); - dstr_destroy(&d); - return (0); - -#undef f_bogus -#undef f_nocheck -#undef f_progress -} - -/*---- Decryption ---------------------------------------------------------*/ - -static int decrypt(int argc, char *argv[]) -{ - const char *fn, *of = 0; - FILE *ofp = 0, *rfp = 0; - FILE *fp = 0; - const char *ef = "binary"; - fprogress ff; - int i; - size_t n; - dstr d = DSTR_INIT; - buf b; - key_file kf; - size_t seq; - uint32 id; - key *k; - key *sk = 0; - kem *km; - sig *s = 0; - gcipher *cx; - gcipher *c; - ghash *h; - gmac *m; - octet *tag; - unsigned f = 0; - const encops *eo; - const char *err; - int verb = 1; - enc *e; - -#define f_bogus 1u -#define f_buffer 2u -#define f_nocheck 4u -#define f_progress 8u - - for (;;) { - static const struct option opt[] = { - { "armour", 0, 0, 'a' }, - { "armor", 0, 0, 'a' }, - { "buffer", 0, 0, 'b' }, - { "verbose", 0, 0, 'v' }, - { "quiet", 0, 0, 'q' }, - { "nocheck", 0, 0, 'C' }, - { "format", OPTF_ARGREQ, 0, 'f' }, - { "output", OPTF_ARGREQ, 0, 'o' }, - { "progress", 0, 0, 'p' }, - { 0, 0, 0, 0 } - }; - i = mdwopt(argc, argv, "abf:o:pqvC", opt, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'a': ef = "pem"; break; - case 'b': f |= f_buffer; break; - case 'v': verb++; break; - case 'q': if (verb) verb--; break; - case 'C': f |= f_nocheck; break; - case 'f': ef = optarg; break; - case 'o': of = optarg; break; - case 'p': f |= f_progress; break; - default: f |= f_bogus; break; - } - } - if (argc - optind > 1 || (f & f_bogus)) - die(EXIT_FAILURE, "Usage: decrypt [-OPTIONS] [FILE]"); - - if ((eo = getenc(ef)) == 0) - die(EXIT_FAILURE, "encoding `%s' not found", ef); - - fn = optind < argc ? argv[optind++] : "-"; - if (strcmp(fn, "-") == 0) - fp = stdin; - else if ((fp = fopen(fn, eo->rmode)) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s': %s", - fn, strerror(errno)); - } - - if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0)) - die(EXIT_FAILURE, "can't open keyring `%s'", keyring); - - e = initdec(eo, fp, checkbdry, "CATCRYPT ENCRYPTED MESSAGE"); - - if (f & f_progress) { - if (fprogress_init(&ff, fn, fp)) { - die(EXIT_FAILURE, "failed to initialize progress display: %s", - strerror(errno)); - } - } - - /* --- Read the header chunk --- */ - - chunk_read(e, &d, &b); - if (f & f_progress) - fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw); - if (buf_getu32(&b, &id)) { - if (f & f_progress) fprogress_done(&ff); - if (verb) printf("FAIL malformed header: missing keyid\n"); - exit(EXIT_FAILURE); - } - if ((k = key_byid(&kf, id)) == 0) { - if (f & f_progress) fprogress_done(&ff); - if (verb) printf("FAIL key id %08lx not found\n", (unsigned long)id); - exit(EXIT_FAILURE); - } - if (BLEFT(&b)) { - if (buf_getu32(&b, &id)) { - if (f & f_progress) fprogress_done(&ff); - if (verb) printf("FAIL malformed header: missing signature keyid\n"); - exit(EXIT_FAILURE); - } - if ((sk = key_byid(&kf, id)) == 0) { - if (f & f_progress) fprogress_done(&ff); - if (verb) printf("FAIL key id %08lx not found\n", (unsigned long)id); - exit(EXIT_FAILURE); - } - } - if (BLEFT(&b)) { - if (f & f_progress) fprogress_done(&ff); - if (verb) printf("FAIL malformed header: junk at end\n"); - exit(EXIT_FAILURE); - } - if (sk) { - s = getsig(sk, "ccsig", 0); - if (!(f & f_nocheck) && verb && (err = s->ops->check(s)) != 0) { - dstr_reset(&d); - key_fulltag(sk, &d); - printf("WARN verification key %s fails check: %s\n", d.buf, err); - } - GH_HASHBUF16(s->h, BBASE(&b), BSZ(&b)); - } - - /* --- Find the key --- */ - - km = getkem(k, "cckem", 1); - - /* --- Read the KEM chunk --- */ - - chunk_read(e, &d, &b); - if (f & f_progress) - fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw); - if (setupkem(km, &d, &cx, &c, &m)) { - if (f & f_progress) fprogress_done(&ff); - if (verb) printf("FAIL failed to decapsulate key\n"); - exit(EXIT_FAILURE); - } - if (s) GH_HASHBUF16(s->h, d.buf, d.len); - - /* --- Verify the signature, if there is one --- */ - - if (sk) { - dstr_reset(&d); - dstr_ensure(&d, 1024); - GC_ENCRYPT(cx, 0, d.buf, 1024); - GH_HASH(s->h, d.buf, 1024); - chunk_read(e, &d, &b); - if (f & f_progress) - fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw); - if (s->ops->doit(s, &d)) { - if (f & f_progress) fprogress_done(&ff); - if (verb) printf("FAIL signature verification failed\n"); - exit(EXIT_FAILURE); - } - if (verb) { - dstr_reset(&d); - key_fulltag(sk, &d); - if (f & f_progress) fprogress_clear(&ff); - printf("INFO good-signature %s\n", d.buf); - } - freesig(s); - } else if (verb) { - if (f & f_progress) fprogress_clear(&ff); - printf("INFO no-signature\n"); - } - - /* --- Now decrypt the main body --- */ - - if (!of || strcmp(of, "-") == 0) { - ofp = stdout; - f |= f_buffer; - } - if (!(f & f_buffer)) { - if ((ofp = fopen(of, "wb")) == 0) { - if (f & f_progress) fprogress_done(&ff); - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - ofp, strerror(errno)); - } - rfp = ofp; - } else if ((rfp = tmpfile()) == 0) { - if (f & f_progress) fprogress_done(&ff); - die(EXIT_FAILURE, "couldn't create temporary file: %s", strerror(errno)); - } - - seq = 0; - dstr_ensure(&d, GC_CLASS(c)->blksz); - dstr_ensure(&d, 4); - for (;;) { - if (GC_CLASS(c)->blksz) { - GC_ENCRYPT(cx, 0, d.buf, GC_CLASS(c)->blksz); - GC_SETIV(c, d.buf); - } - h = GM_INIT(m); - GH_HASHU32(h, seq); - seq++; - chunk_read(e, &d, &b); - if (f & f_progress) - fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw); - if ((tag = buf_get(&b, GM_CLASS(m)->hashsz)) == 0) { - if (f & f_progress) fprogress_done(&ff); - if (verb) printf("FAIL bad ciphertext chunk: no tag\n"); - exit(EXIT_FAILURE); - } - GH_HASH(h, BCUR(&b), BLEFT(&b)); - if (memcmp(tag, GH_DONE(h, 0), GM_CLASS(m)->hashsz) != 0) { - if (f & f_progress) fprogress_done(&ff); - if (verb) - printf("FAIL bad ciphertext chunk: authentication failure\n"); - exit(EXIT_FAILURE); - } - GH_DESTROY(h); - if (!BLEFT(&b)) - break; - GC_DECRYPT(c, BCUR(&b), BCUR(&b), BLEFT(&b)); - if (fwrite(BCUR(&b), 1, BLEFT(&b), rfp) != BLEFT(&b)) { - if (f & f_progress) fprogress_done(&ff); - if (verb) printf("FAIL error writing output: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - } - - if (f & f_progress) fprogress_done(&ff); - if (fflush(rfp) || ferror(rfp)) { - if (verb) printf("FAIL error writing output: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - if (f & f_buffer) { - if (!ofp && (ofp = fopen(of, "wb")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - of, strerror(errno)); - } - rewind(rfp); - if (f & f_progress) fprogress_init(&ff, "copying buffer", rfp); - dstr_reset(&d); - dstr_ensure(&d, 65536); - if (verb && ofp == stdout) printf("DATA\n"); - for (;;) { - n = fread(d.buf, 1, d.sz, rfp); - if (!n) break; - if (f & f_progress) fprogress_update(&ff, n); - if (fwrite(d.buf, 1, n, ofp) < n) { - if (f & f_progress) fprogress_done(&ff); - die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); - } - } - if (f & f_progress) fprogress_done(&ff); - if (ferror(rfp) || fclose(rfp)) - die(EXIT_FAILURE, "error unbuffering output: %s", strerror(errno)); - } - - e->ops->decdone(e); - if (verb && ofp != stdout) - printf("OK decrypted successfully\n"); - if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp))) - die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); - freeenc(e); - GC_DESTROY(c); - GC_DESTROY(cx); - GM_DESTROY(m); - freekem(km); - if (fp != stdin) fclose(fp); - key_close(&kf); - dstr_destroy(&d); - return (0); - -#undef f_bogus -#undef f_buffer -#undef f_nocheck -#undef f_progress -} - -/*----- Main code ---------------------------------------------------------*/ - -#define LISTS(LI) \ - LI("Lists", list, \ - listtab[i].name, listtab[i].name) \ - LI("Key-encapsulation mechanisms", kem, \ - kemtab[i].name, kemtab[i].name) \ - LI("Signature schemes", sig, \ - sigtab[i].name, sigtab[i].name) \ - LI("Encodings", enc, \ - enctab[i].name, enctab[i].name) \ - LI("Symmetric encryption algorithms", cipher, \ - gciphertab[i], gciphertab[i]->name) \ - LI("Hash functions", hash, \ - ghashtab[i], ghashtab[i]->name) \ - LI("Message authentication codes", mac, \ - gmactab[i], gmactab[i]->name) - -MAKELISTTAB(listtab, LISTS) - -int cmd_show(int argc, char *argv[]) -{ - return (displaylists(listtab, argv + 1)); -} - -static int cmd_help(int, char **); - -static cmd cmdtab[] = { - { "help", cmd_help, "help [COMMAND...]" }, - { "show", cmd_show, "show [ITEM...]" }, - CMD_ENCODE, - CMD_DECODE, - { "encrypt", encrypt, - "encrypt [-apC] [-k TAG] [-s TAG] [-f FORMAT]\n\t\ -[-o OUTPUT] [FILE]", "\ -Options:\n\ -\n\ --a, --armour Same as `-f pem'.\n\ --f, --format=FORMAT Encode as FORMAT.\n\ --k, --key=TAG Use public encryption key named by TAG.\n\ --s, --sign-key=TAG Use private signature key named by TAG.\n\ --o, --output=FILE Write output to FILE.\n\ --p, --progress Show progress on large files.\n\ --C, --nocheck Don't check the public key.\n\ -" }, - { "decrypt", decrypt, - "decrypt [-abpqvC] [-f FORMAT] [-o OUTPUT] [FILE]", "\ -Options:\n\ -\n\ --a, --armour Same as `-f pem'.\n\ --b, --buffer Buffer output until we're sure we have it all.\n\ --f, --format=FORMAT Decode as FORMAT.\n\ --o, --output=FILE Write output to FILE.\n\ --p, --progress Show progress on large files.\n\ --q, --quiet Produce fewer messages.\n\ --v, --verbose Produce more verbose messages.\n\ --C, --nocheck Don't check the private key.\n\ -" }, - { 0, 0, 0 } -}; - -static int cmd_help(int argc, char **argv) -{ - sc_help(cmdtab, stdout, argv + 1); - return (0); -} - -void version(FILE *fp) -{ - pquis(fp, "$, Catacomb version " VERSION "\n"); -} - -static void usage(FILE *fp) -{ - pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n"); -} - -void help_global(FILE *fp) -{ - usage(fp); - fputs("\n\ -Encrypt and decrypt files.\n\ -\n\ -Global command-line options:\n\ -\n\ --h, --help [COMMAND...] Show this help message, or help for COMMANDs.\n\ --v, --version Show program version number.\n\ --u, --usage Show a terse usage message.\n\ -\n\ --k, --keyring=FILE Read keys from FILE.\n", - fp); -} - -/* --- @main@ --- * - * - * Arguments: @int argc@ = number of command line arguments - * @char *argv[]@ = vector of command line arguments - * - * Returns: Zero if successful, nonzero otherwise. - * - * Use: Encrypts or decrypts files. - */ - -int main(int argc, char *argv[]) -{ - unsigned f = 0; - -#define f_bogus 1u - - /* --- Initialize the library --- */ - - ego(argv[0]); - sub_init(); - rand_noisesrc(RAND_GLOBAL, &noise_source); - rand_seed(RAND_GLOBAL, 160); - - /* --- Parse options --- */ - - for (;;) { - static struct option opts[] = { - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'v' }, - { "usage", 0, 0, 'u' }, - { "keyring", OPTF_ARGREQ, 0, 'k' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+hvu k:", opts, 0, 0, 0); - if (i < 0) - break; - switch (i) { - case 'h': - sc_help(cmdtab, stdout, argv + optind); - exit(0); - break; - case 'v': - version(stdout); - exit(0); - break; - case 'u': - usage(stdout); - exit(0); - case 'k': - keyring = optarg; - break; - default: - f |= f_bogus; - break; - } - } - - argc -= optind; - argv += optind; - optind = 0; - if (f & f_bogus || argc < 1) { - usage(stderr); - exit(EXIT_FAILURE); - } - - /* --- Dispatch to the correct subcommand handler --- */ - - return (findcmd(cmdtab, argv[0])->cmd(argc, argv)); - -#undef f_bogus -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/catsign.c b/catsign.c deleted file mode 100644 index 3bbd7b2..0000000 --- a/catsign.c +++ /dev/null @@ -1,1276 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Sign files - * - * (c) 2005 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _FILE_OFFSET_BITS 64 - -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "buf.h" -#include "rand.h" -#include "noise.h" -#include "mprand.h" -#include "key.h" -#include "getdate.h" -#include "cc.h" - -#include "ectab.h" -#include "ptab.h" - -/*----- Static variables --------------------------------------------------*/ - -static const char *keyring = "keyring"; - -/*----- Data formats ------------------------------------------------------* - * - * Our crypto stuff is split into three parts: a header describing the key, - * the message itself, and the signature. In a detached signature, the - * message is separate, and the header and signature are combined into one - * encoded chunk. In an attached signature, the message is included. There - * are two forms of message: binary and text. Binary messages are divided - * into chunks, each preceded by a 2-octet length, and terminated by a - * zero-length chunk. Text messages are byte-stuffed, as for RFC821, and - * trailing whitespace before a newline is ignored. - */ - -typedef struct sigmsg { - unsigned f; /* Flags */ -#define F_DETACH 1u -#define F_BINARY 2u -#define F_SIGMASK 3u -#define F_HASHMASK (F_BINARY) - uint32 keyid; /* Key identifier */ - time_t t; /* When the signature was made */ - dstr kh; /* Key fingerprint (sanity check) */ - dstr sig; /* Signature */ - sig *s; /* Signature algorithm */ -} sigmsg; - -#define F_MIDLINE 16u -#define F_EOF 32u -#define F_NOCLOSE 64u -#define F_BOGUS 128u -#define F_BUFFER 256u -#define F_UTC 512u -#define F_NOCHECK 1024u -#define F_PROGRESS 2048u - -/*----- Chunk I/O ---------------------------------------------------------*/ - -static void chunk_write(enc *e, const void *p, size_t n) -{ - octet b[2]; - - assert(n <= 0xffff); - STORE16(b, n); - if (e->ops->write(e, b, 2) || e->ops->write(e, p, n)) - die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); -} - -static size_t chunk_read(enc *e, void *p) -{ - octet b[2]; - size_t n; - - if (e->ops->read(e, b, 2) != 2) - goto err; - n = LOAD16(b); - if (n && e->ops->read(e, p, n) != n) - goto err; - return (n); - -err: - if (!errno) die(EXIT_FAILURE, "unexpected end-of-file on input"); - else die(EXIT_FAILURE, "error reading input: %s", strerror(errno)); - return (0); -} - -/*----- Message canonification --------------------------------------------*/ - -#define MSGBUFSZ 65536 -#define MSGBUFTHRESH 32768 - -typedef struct msgcanon { - unsigned f; - FILE *fp; - enc *e; - fprogress ff; - size_t (*read)(struct msgcanon *, void *); - void (*write)(struct msgcanon *, const void *, size_t); - void (*close)(struct msgcanon *); -} msgcanon; - -#define MC_INIT { 0 } - -static size_t textread(msgcanon *m, void *bp) -{ - size_t n = 0, nsp = 0; - int ch; - char *b = bp; - unsigned f = m->f; - - if (f & F_EOF) return (0); - for (;;) { - if ((ch = getc(m->fp)) == EOF) goto eof; - if (!(f & (F_DETACH | F_MIDLINE)) && ch == '.') { - ch = getc(m->fp); - if (ch == '\n') goto eof; - } - if (ch == '\n') { - n -= nsp; nsp = 0; - if (n >= MSGBUFTHRESH) goto full; - b[n++] = ch; - f &= ~F_MIDLINE; - } else if (isspace(ch)) { - f |= F_MIDLINE; - if (n >= MSGBUFSZ) goto full; - b[n++] = ch; nsp++; - } else { - f |= F_MIDLINE; - nsp = 0; - if (n >= MSGBUFTHRESH) goto full; - b[n++] = ch; - } - } -eof: - f |= F_EOF; - goto done; -full: - ungetc(ch, m->fp); -done: - m->f = f; - if (m->f & F_PROGRESS) fprogress_update(&m->ff, n); - return (n); -} - -static void textwrite(msgcanon *m, const void *bp, size_t n) -{ - const char *p = bp, *l = p + n; - unsigned f = m->f; - - while (p < l) { - if (!(f & (F_MIDLINE | F_DETACH)) && - (*p == '.' || *p == '-')) - putc('.', m->fp); - if (*p == '\n') f &= ~F_MIDLINE; - else f |= F_MIDLINE; - putc(*p, m->fp); - p++; - } - m->f = f; -} - -static size_t binreadembed(msgcanon *m, void *bp) -{ - size_t n = chunk_read(m->e, bp); - if (m->f & F_PROGRESS) fprogress_update(&m->ff, n); - return (n); -} - -static size_t binreaddetach(msgcanon *m, void *bp) -{ - size_t n = fread(bp, 1, MSGBUFSZ - 1, m->fp); - if (m->f & F_PROGRESS) fprogress_update(&m->ff, n); - return (n); -} - -static void binwriteembed(msgcanon *m, const void *bp, size_t n) - { chunk_write(m->e, bp, n); } - -static void nullwrite(msgcanon *m, const void *bp, size_t n) { ; } - -static void mcsetup_readfile(msgcanon *m, unsigned f, const char *fn) -{ - m->f = F_DETACH | (f & (F_BINARY | F_PROGRESS)); - if (!fn || strcmp(fn, "-") == 0) { - m->fp = stdin; - m->f |= F_NOCLOSE; - } else if ((m->fp = fopen(fn, (f & F_BINARY) ? "rb" : "r")) == 0) - die(EXIT_FAILURE, "couldn't open file `%s': %s", fn, strerror(errno)); - if (m->f & F_PROGRESS) { - if (fprogress_init(&m->ff, fn, m->fp)) { - die(EXIT_FAILURE, "failed to initialize progress indicator: %s", - strerror(errno)); - } - } - m->read = (f & F_BINARY) ? binreaddetach : textread; -} - -static void mcsetup_writenull(msgcanon *m) { m->write = nullwrite; } - -static void mcsetup_read(msgcanon *m, unsigned f, enc **ee, - const char *fn, const char *dfn) -{ - enc *e = *ee; - - m->f = f | F_NOCLOSE; - - if (dfn && !(f & F_DETACH)) die(EXIT_FAILURE, "signature is not detached"); - if (f & F_BINARY) { - if (!(f & F_DETACH)) { - m->e = e; - *ee = 0; - m->fp = e->fp; - m->read = binreadembed; - if (m->f & F_PROGRESS) { - if (fprogress_init(&m->ff, fn, m->fp)) { - die(EXIT_FAILURE, "failed to initialize progress indicator: %s", - strerror(errno)); - } - } - } else { - m->read = binreaddetach; - if (!dfn || strcmp(dfn, "-") == 0) - m->fp = stdin; - else if ((m->fp = fopen(dfn, "rb")) == 0) - die(EXIT_FAILURE, "can't open `%s': %s", dfn, strerror(errno)); - else - m->f &= ~F_NOCLOSE; - if (m->f & F_PROGRESS) { - if (fprogress_init(&m->ff, dfn, m->fp)) { - die(EXIT_FAILURE, "failed to initialize progress indicator: %s", - strerror(errno)); - } - } - } - } else { - m->read = textread; - if (!(f & F_DETACH)) { - if (e->ops->decdone(e) || ferror(e->fp)) - die(EXIT_FAILURE, "error at end of signature header"); - m->fp = e->fp; - e->ops->destroy(e); - *ee = 0; - if (m->f & F_PROGRESS) { - if (fprogress_init(&m->ff, fn, m->fp)) { - die(EXIT_FAILURE, "failed to initialize progress indicator: %s", - strerror(errno)); - } - } - } else { - if (!dfn || strcmp(dfn, "-") == 0) - m->fp = stdin; - else if ((m->fp = fopen(dfn, "r")) == 0) - die(EXIT_FAILURE, "can't read file `%s': %s", dfn, strerror(errno)); - else - m->f &= ~F_NOCLOSE; - if (m->f & F_PROGRESS) { - if (fprogress_init(&m->ff, dfn, m->fp)) { - die(EXIT_FAILURE, "failed to initialize progress indicator: %s", - strerror(errno)); - } - } - } - } -} - -static void mcsetup_write(msgcanon *m, unsigned f, enc **ee) -{ - enc *e = *ee; - - m->f = f | F_NOCLOSE; - - if (f & F_DETACH) - m->write = nullwrite; - else if (f & F_BINARY) { - m->e = e; - *ee = 0; - m->fp = e->fp; - m->write = binwriteembed; - } else { - if (e->ops->encdone(e) || ferror(e->fp)) - die(EXIT_FAILURE, "error at end of signature header"); - m->fp = e->fp; - e->ops->destroy(e); - *ee = 0; - m->write = textwrite; - } -} - -static void mc_endread(msgcanon *m, const encops *eops, enc **ee) -{ - if (!(m->f & F_DETACH)) { - if (m->f & F_BINARY) - *ee = m->e; - else - *ee = initdec(eops, m->fp, checkbdry, "CATSIGN SIGNATURE"); - } - if (m->fp && !(m->f & F_NOCLOSE)) { - if (ferror(m->fp) || fclose(m->fp)) - die(EXIT_FAILURE, "error closing message file: %s", strerror(errno)); - } - if (m->f & F_PROGRESS) fprogress_done(&m->ff); -} - -static void mc_endwrite(msgcanon *m, const encops *eops, enc **ee) -{ - if (!(m->f & F_BINARY)) { - if (m->f & F_MIDLINE) putc('\n', m->fp); - if (!(m->f & F_DETACH)) { - putc('.', m->fp); putc('\n', m->fp); - *ee = initenc(eops, m->fp, "CATSIGN SIGNATURE"); - } - } else if (!(m->f & F_DETACH)) { - chunk_write(m->e, 0, 0); - *ee = m->e; - } - if (m->fp && !(m->f & F_NOCLOSE)) { - if (fflush(m->fp) || ferror(m->fp) || fclose(m->fp)) - die(EXIT_FAILURE, "error closing message file: %s", strerror(errno)); - } -} - -/*----- Signature reading and writing -------------------------------------*/ - -static void sig_init(sigmsg *s, unsigned f, uint32 keyid) -{ - s->f = f & F_SIGMASK; - s->keyid = keyid; - time(&s->t); - s->s = 0; - dstr_create(&s->kh); - dstr_create(&s->sig); -} - -static void sig_destroy(sigmsg *s) -{ - dstr_destroy(&s->kh); - dstr_destroy(&s->sig); - if (s->s) freesig(s->s); -} - -static void sigtobuffer(sigmsg *s, buf *b, int hashp) -{ - kludge64 t; - - ASSIGN64(t, s->t); - if (hashp) buf_putu16(b, s->f & F_HASHMASK); - else buf_putu16(b, s->f & F_SIGMASK); - buf_putu32(b, s->keyid); - buf_putu32(b, HI64(t)); - buf_putu32(b, LO64(t)); - buf_putdstr16(b, &s->kh); - assert(BOK(b)); -} - -static void dohash(ghash *h, const void *p, size_t n) -{ -/* trace_block(1, "hashing", p, n); */ - GH_HASH(h, p, n); -} - -static void sig_hash(sigmsg *s) -{ - octet bb[16384]; - buf b; - - buf_init(&b, bb, sizeof(bb)); - sigtobuffer(s, &b, 1); - dohash(s->s->h, BBASE(&b), BLEN(&b)); -} - -static void keyhash(key *k, sig *s, dstr *d) -{ - ghash *h; - key_filter kf; - - h = GH_INIT(s->ch); - kf.f = KCAT_PUB; - kf.m = KF_CATMASK; - key_fingerprint(k, h, &kf); - dstr_ensure(d, GH_CLASS(h)->hashsz); - GH_DONE(h, d->buf + d->len); - d->len += GH_CLASS(h)->hashsz; - GH_DESTROY(h); -} - -static void sig_writeheader(enc *e, sigmsg *s) -{ - octet bb[16384]; - buf b; - - buf_init(&b, bb, sizeof(bb)); - sigtobuffer(s, &b, 0); - chunk_write(e, BBASE(&b), BLEN(&b)); -} - -static void sig_writesig(enc *e, sigmsg *s) - { chunk_write(e, s->sig.buf, s->sig.len); } - -static void diechoke(const char *m, void *p) - { die(EXIT_FAILURE, "%s%s%s", p, p ? ": " : "", m); } - -static void sig_readheader(enc *e, sigmsg *s, - void (*choke)(const char *, void *), void *p) -{ - uint16 f; - octet bb[MSGBUFSZ]; - uint32 x, y; - kludge64 t; - buf b; - size_t n; - - n = chunk_read(e, bb); - buf_init(&b, bb, n); - if (buf_getu16(&b, &f)) choke("missing flags", p); - if (buf_getu32(&b, &x)) choke("missing keyid", p); - sig_init(s, f, x); - if (buf_getu32(&b, &x) || buf_getu32(&b, &y)) - choke("missing datestamp", p); - SET64(t, x, y); s->t = GET64(time_t, t); - if (buf_getdstr16(&b, &s->kh)) - choke("missing key hash", p); - if (BLEFT(&b)) - choke("junk at end", p); -} - -static void sig_readsig(enc *e, sigmsg *s) -{ - octet bb[MSGBUFSZ]; - size_t n; - - n = chunk_read(e, bb); - dstr_putm(&s->sig, bb, n); -} - -/*----- Signing -----------------------------------------------------------*/ - -static int sign(int argc, char *argv[]) -{ - const char *ef = "binary", *fn = 0, *of = 0, *kn = "ccsig", *err; - unsigned f = 0; - key_file kf; - key *k; - sigmsg s; - FILE *ofp = 0; - int i; - char bb[MSGBUFSZ]; - size_t n; - dstr d = DSTR_INIT; - const encops *eo; - msgcanon mc_in = MC_INIT, mc_out = MC_INIT; - enc *e; - - for (;;) { - static const struct option opt[] = { - { "armour", 0, 0, 'a' }, - { "armor", 0, 0, 'a' }, - { "binary", 0, 0, 'b' }, - { "detach", 0, 0, 'd' }, - { "key", OPTF_ARGREQ, 0, 'k' }, - { "format", OPTF_ARGREQ, 0, 'f' }, - { "output", OPTF_ARGREQ, 0, 'o' }, - { "progress", 0, 0, 'p' }, - { "text", 0, 0, 't' }, - { "nocheck", 0, 0, 'C' }, - { 0, 0, 0, 0 } - }; - i = mdwopt(argc, argv, "k:f:o:abdptC", opt, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'k': kn = optarg; break; - case 'f': ef = optarg; break; - case 'o': of = optarg; break; - case 'a': ef = "pem"; break; - case 't': f &= ~F_BINARY; break; - case 'b': f |= F_BINARY; break; - case 'd': f |= F_DETACH; break; - case 'C': f |= F_NOCHECK; break; - case 'p': f |= F_PROGRESS; break; - default: f |= F_BOGUS; break; - } - } - if (argc - optind > 1 || (f & F_BOGUS)) - die(EXIT_FAILURE, "Usage: sign [-OPTIONS] [FILE]"); - - if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0)) - die(EXIT_FAILURE, "can't open keyring `%s'", keyring); - if ((k = key_bytag(&kf, kn)) == 0) - die(EXIT_FAILURE, "key `%s' not found", kn); - - if ((eo = getenc(ef)) == 0) - die(EXIT_FAILURE, "encoding `%s' not found", ef); - - fn = (optind >= argc) ? 0 : argv[optind++]; - - if (!of || strcmp(of, "-") == 0) - ofp = stdout; - else if ((ofp = fopen(of, eo->wmode)) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - ofp, strerror(errno)); - } - - /* --- Start the work --- */ - - sig_init(&s, f, k->id); - dstr_reset(&d); - key_fulltag(k, &d); - s.s = getsig(k, "ccsig", 1); - if (!(f & F_NOCHECK) && (err = s.s->ops->check(s.s)) != 0) - moan("key %s fails check: %s", d.buf, err); - keyhash(k, s.s, &s.kh); - e = initenc(eo, ofp, - (f & F_DETACH) ? "CATSIGN SIGNATURE" : - (f & F_BINARY) ? "CATSIGN MESSAGE" : - "CATSIGN MESSAGE HEADER"); - sig_writeheader(e, &s); - - /* --- Hash the message --- */ - - mcsetup_readfile(&mc_in, f, fn); - mcsetup_write(&mc_out, f, &e); - sig_hash(&s); - for (;;) { - n = mc_in.read(&mc_in, bb); - if (!n) break; - dohash(s.s->h, bb, n); - mc_out.write(&mc_out, bb, n); - } - mc_endread(&mc_in, 0, 0); - mc_endwrite(&mc_out, eo, &e); - - /* --- Write the signature --- */ - - if (s.s->ops->doit(s.s, &s.sig)) - die(EXIT_FAILURE, "signature failed"); - sig_writesig(e, &s); - e->ops->encdone(e); - if (fflush(ofp) || ferror(ofp) || fclose(ofp)) - die(EXIT_FAILURE, "error writing signature: %s", strerror(errno)); - - /* --- All done --- */ - - freeenc(e); - key_close(&kf); - sig_destroy(&s); - dstr_destroy(&d); - return (0); -} - -/*----- Verifying ---------------------------------------------------------*/ - -typedef struct vrfctx { - unsigned f, m; - int verb; - const char *what; -} vrfctx; - -static int vrfbdry(const char *b, void *p) -{ - vrfctx *v = p; - - if (strcmp(b, "CATSIGN MESSAGE") == 0) { - v->f |= F_BINARY; - v->m |= F_BINARY | F_DETACH; - return (1); - } else if (strcmp(b, "CATSIGN MESSAGE HEADER") == 0) { - v->m |= F_BINARY | F_DETACH; - return (1); - } else if (strcmp(b, "CATSIGN SIGNATURE") == 0) { - v->f |= F_DETACH; - v->m |= F_DETACH; - return (1); - } else - return (0); -} - -static void vrfchoke(const char *m, void *p) -{ - vrfctx *v = p; - if (v->verb) printf("FAIL %s: %s\n", v->what, m); - exit(EXIT_FAILURE); -} - -static int verify(int argc, char *argv[]) -{ - const char *ef = "binary", *of = 0, *fn, *dfn = 0, *kn = 0, *err; - vrfctx v = { 0, 0, 1 }; - key_file kf; - key *k, *kk = 0; - sigmsg s; - FILE *fp, *ofp = 0, *rfp = 0; - fprogress ff; - struct tm *tm; - int i; - char bb[MSGBUFSZ]; - size_t n; - time_t t_fresh = 0; - dstr d = DSTR_INIT, dd = DSTR_INIT; - const encops *eo; - msgcanon mc_in = MC_INIT; - enc *e; - - for (;;) { - static const struct option opt[] = { - { "armour", 0, 0, 'a' }, - { "armor", 0, 0, 'a' }, - { "buffer", 0, 0, 'b' }, - { "key", OPTF_ARGREQ, 0, 'k' }, - { "format", OPTF_ARGREQ, 0, 'f' }, - { "output", OPTF_ARGREQ, 0, 'o' }, - { "progress", 0, 0, 'p' }, - { "quiet", 0, 0, 'q' }, - { "utc", 0, 0, 'u' }, - { "fresh-time", 0, 0, 't' }, - { "gmt", 0, 0, 'u' }, - { "verbose", 0, 0, 'v' }, - { "nocheck", 0, 0, 'C' }, - { 0, 0, 0, 0 } - }; - i = mdwopt(argc, argv, "k:f:o:abpqt:uvC", opt, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'a': ef = "pem"; break; - case 'b': v.f |= F_BUFFER; break; - case 'k': kn = optarg; break; - case 'f': ef = optarg; break; - case 'o': of = optarg; break; - case 'u': v.f |= F_UTC; break; - case 'C': v.f |= F_NOCHECK; break; - case 't': - if (strcmp(optarg, "always") == 0) t_fresh = 0; - else if ((t_fresh = get_date(optarg, 0)) < 0) - die(EXIT_FAILURE, "bad freshness time"); - break; - case 'q': if (v.verb > 0) v.verb--; break; - case 'v': if (v.verb < 10) v.verb++; break; - case 'p': v.f |= F_PROGRESS; break; - default: v.f |= F_BOGUS; break; - } - } - if (argc - optind > 2 || (v.f & F_BOGUS)) - die(EXIT_FAILURE, "Usage: verify [-OPTIONS] [FILE [MESSAGE]]"); - - if ((eo = getenc(ef)) == 0) - die(EXIT_FAILURE, "encoding `%s' not found", ef); - - fn = optind < argc ? argv[optind++] : "-"; - if (strcmp(fn, "-") == 0) - fp = stdin; - else if ((fp = fopen(fn, eo->rmode)) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s': %s", - fn, strerror(errno)); - } - - if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0)) - die(EXIT_FAILURE, "can't open keyring `%s'", keyring); - if (kn && (kk = key_bytag(&kf, kn)) == 0) - die(EXIT_FAILURE, "key `%s' not found", kn); - - e = initdec(eo, fp, vrfbdry, &v); - - /* --- Read the header chunk --- */ - - v.what = "malformed header"; - sig_readheader(e, &s, vrfchoke, &v); - - if (((s.f ^ v.f) & v.m) != 0) { - if (v.verb) printf("FAIL boundary string inconsistent with contents\n"); - exit(EXIT_FAILURE); - } - v.f |= s.f; - - if ((k = key_byid(&kf, s.keyid)) == 0) { - if (v.verb) printf("FAIL key id %08lx not found\n", - (unsigned long)s.keyid); - exit(EXIT_FAILURE); - } - if (kk && k->id != kk->id) { - if (v.verb) { - dstr_reset(&d); key_fulltag(k, &d); - dstr_reset(&dd); key_fulltag(kk, &dd); - printf("FAIL signing key is %s; expected key %s\n", d.buf, dd.buf); - } - exit(EXIT_FAILURE); - } - - s.s = getsig(k, "ccsig", 0); - dstr_reset(&d); key_fulltag(k, &d); - if (!(v.f & F_NOCHECK) && v.verb && (err = s.s->ops->check(s.s)) != 0) - printf("WARN verification key %s fails check: %s\n", d.buf, err); - - dstr_reset(&dd); keyhash(k, s.s, &dd); - if (dd.len != s.kh.len || memcmp(dd.buf, s.kh.buf, dd.len) != 0) { - if (v.verb) printf("FAIL key hash mismatch\n"); - exit(EXIT_FAILURE); - } - - /* --- Now a merry dance --- */ - - if (v.f & F_DETACH) - sig_readsig(e, &s); - if (optind < argc) - dfn = argv[optind++]; - mcsetup_read(&mc_in, v.f, &e, fn, dfn); - - if (!of && (v.f & F_DETACH)) { - rfp = ofp = 0; - v.f &= ~F_BUFFER; - } else if (!of || strcmp(of, "-") == 0) { - v.f |= F_BUFFER; - ofp = stdout; - } - if (of && !(v.f & F_BUFFER)) { - if ((ofp = fopen(of, (v.f & F_BINARY) ? "wb" : "w")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - of, strerror(errno)); - } - rfp = ofp; - } else if ((rfp = tmpfile()) == 0) - die(EXIT_FAILURE, "couldn't create temporary file: %s", strerror(errno)); - - /* --- Read the message and verify the signature --- */ - - sig_hash(&s); - for (;;) { - n = mc_in.read(&mc_in, bb); - if (!n) break; - dohash(s.s->h, bb, n); - if (rfp) fwrite(bb, 1, n, rfp); - } - mc_endread(&mc_in, eo, &e); - if (!(v.f & F_DETACH)) - sig_readsig(e, &s); - if (rfp && (ferror(rfp) || fflush(rfp))) { - if (v.verb) printf("FAIL error writing message: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - - /* --- Check the signature --- */ - - if (s.s->ops->doit(s.s, &s.sig)) { - if (v.verb) printf("FAIL signature verification failed\n"); - exit(EXIT_FAILURE); - } - if (t_fresh && s.t < t_fresh) { - if (v.verb) printf("FAIL signature is stale\n"); - exit(EXIT_FAILURE); - } - if (s.t > time(0)) { - if (v.verb) printf("FAIL signature timestamp in the future\n"); - exit(EXIT_FAILURE); - } - if (v.verb) { - tm = (v.f & F_UTC) ? gmtime(&s.t) : localtime(&s.t); - strftime(bb, sizeof(bb), "%Y-%m-%d %H:%M:%S %Z", tm); - printf("INFO good-signature %s\n", d.buf); - printf("INFO date %s\n", bb); - } - - /* --- Unbuffer buffered input --- */ - - if (v.f & F_BUFFER) { - if (!ofp && (ofp = fopen(of, "wb")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - of, strerror(errno)); - } - rewind(rfp); - if (v.f & F_PROGRESS) fprogress_init(&ff, "copying buffer", rfp); - if (v.verb && ofp == stdout) printf("DATA\n"); - for (;;) { - n = fread(bb, 1, sizeof(bb), rfp); - if (!n) break; - if (v.f & F_PROGRESS) fprogress_update(&ff, n); - if (fwrite(bb, 1, n, ofp) < n) { - if (v.f & F_PROGRESS) fprogress_done(&ff); - die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); - } - } - if (v.f & F_PROGRESS) fprogress_done(&ff); - if (ferror(rfp) || fclose(rfp)) - die(EXIT_FAILURE, "error unbuffering output: %s", strerror(errno)); - } - if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp))) - die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); - - /* --- Tidy up --- */ - - e->ops->decdone(e); - if (v.verb && ofp != stdout) - printf("OK verified successfully\n"); - freeenc(e); - key_close(&kf); - sig_destroy(&s); - dstr_destroy(&d); - dstr_destroy(&dd); - return (0); -} - -/*----- Reformatting ------------------------------------------------------*/ - -static int format(int argc, char *argv[]) -{ - const char *ief = "binary", *oef = "binary"; - const char *fn, *dfn = 0, *of = 0, *mf = 0; - sigmsg s; - FILE *fp, *ofp = 0, *mfp = 0; - int i; - size_t n; - msgcanon mc_in = MC_INIT, mc_out = MC_INIT; - char bb[MSGBUFSZ]; - vrfctx v = { 0, 0, 1 }; - unsigned f = 0, fm = ~F_SIGMASK, sf; - const encops *ieo, *oeo; - enc *ie, *oe; - - for (;;) { - static const struct option opt[] = { - { "armour-in", 0, 0, 'a' }, - { "armor-in", 0, 0, 'a' }, - { "armour-out", 0, 0, 'A' }, - { "armor-out", 0, 0, 'A' }, - { "detach", 0, 0, 'D' }, - { "embed", 0, 0, 'E' }, - { "format-in", OPTF_ARGREQ, 0, 'f' }, - { "format-out", OPTF_ARGREQ, 0, 'F' }, - { "message", OPTF_ARGREQ, 0, 'm' }, - { "output", OPTF_ARGREQ, 0, 'o' }, - { "progress", 0, 0, 'p' }, - { 0, 0, 0, 0 } - }; - i = mdwopt(argc, argv, "f:F:m:o:apADE", opt, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'a': ief = "pem"; break; - case 'A': oef = "pem"; break; - case 'f': ief = optarg; break; - case 'F': oef = optarg; break; - case 'D': f |= F_DETACH; fm |= F_DETACH; break; - case 'E': f &= ~F_DETACH; fm |= F_DETACH; break; - case 'm': mf = optarg; break; - case 'o': of = optarg; break; - case 'p': f |= F_PROGRESS; break; - default: f |= F_BOGUS; break; - } - } - - if (argc - optind > 2 || (f & F_BOGUS)) - die(EXIT_FAILURE, "Usage: format [-OPTIONS] [FILE [MESSAGE]]"); - - if ((ieo = getenc(ief)) == 0) - die(EXIT_FAILURE, "encoding `%s' not found", ief); - if ((oeo = getenc(oef)) == 0) - die(EXIT_FAILURE, "encoding `%s' not found", oef); - - fn = optind < argc ? argv[optind++] : "-"; - if (strcmp(fn, "-") == 0) - fp = stdin; - else if ((fp = fopen(fn, ieo->rmode)) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s': %s", - fn, strerror(errno)); - } - - if (optind < argc) - dfn = argv[optind++]; - - ie = initdec(ieo, fp, vrfbdry, &v); - - /* --- Read the header chunk --- */ - - sig_readheader(ie, &s, diechoke, "malformed header"); - - if (((s.f ^ v.f) & v.m) != 0) - moan("boundary string inconsistent with contents (ignoring)"); - - mcsetup_read(&mc_in, s.f, &ie, fn, dfn); - - /* --- Prepare the output stuff --- */ - - if (!of && !mf) of = "-"; - sf = s.f; - f = (f & fm) | (s.f & ~fm); - s.f = f & F_SIGMASK; - - if (sf & F_DETACH) - sig_readsig(ie, &s); - - if (!of) - mcsetup_writenull(&mc_out); - else { - if (strcmp(of, "-") == 0) - ofp = stdout; - else if ((ofp = fopen(of, oeo->wmode)) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - of, strerror(errno)); - } - oe = initenc(oeo, ofp, - (f & F_DETACH) ? "CATSIGN SIGNATURE" : - (f & F_BINARY) ? "CATSIGN MESSAGE" : - "CATSIGN MESSAGE HEADER"); - sig_writeheader(oe, &s); - mcsetup_write(&mc_out, f, &oe); - } - - if (mf) { - if (strcmp(mf, "-") == 0) - mfp = stdout; - else if ((mfp = fopen(mf, (f & F_BINARY) ? "wb" : "w")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - mf, strerror(errno)); - } - } - - /* --- Wade through the message body --- */ - - for (;;) { - n = mc_in.read(&mc_in, bb); - if (!n) break; - mc_out.write(&mc_out, bb, n); - if (mfp) fwrite(bb, 1, n, mfp); - } - mc_endread(&mc_in, ieo, &ie); - if (of) mc_endwrite(&mc_out, oeo, &oe); - - /* --- Write the signature --- */ - - if (!(sf & F_DETACH)) - sig_readsig(ie, &s); - if (of) { - sig_writesig(oe, &s); - oe->ops->encdone(oe); - } - - /* --- All done --- */ - - ie->ops->decdone(ie); - if (ferror(fp) || fclose(fp)) - die(EXIT_FAILURE, "error reading input signature: %s", strerror(errno)); - if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp))) - die(EXIT_FAILURE, "error writing output signature: %s", strerror(errno)); - if (mfp && (fflush(mfp) || ferror(mfp) || fclose(mfp))) - die(EXIT_FAILURE, "error writing output message: %s", strerror(errno)); - freeenc(ie); - if (of) freeenc(oe); - sig_destroy(&s); - return (0); -} - -static void infochoke(const char *m, void *p) -{ - vrfctx *v = p; - printf("BAD %s: %s\n", v->what, m); - exit(EXIT_FAILURE); -} - -static void infokeyreport(const char *file, int line, - const char *err, void *p) -{ /*whatever*/; } - -static int info(int argc, char *argv[]) -{ - const char *ef = "binary"; - vrfctx v = { 0, 0, 1 }; - key_file kf; - key *k; - sigmsg s; - FILE *fp; - int i; - struct tm *tm; - char bb[256]; - dstr d = DSTR_INIT; - const encops *eo; - enc *e; - - for (;;) { - static const struct option opt[] = { - { "armour", 0, 0, 'a' }, - { "armor", 0, 0, 'a' }, - { "format", OPTF_ARGREQ, 0, 'f' }, - { "gmt", 0, 0, 'u' }, - { "utc", 0, 0, 'u' }, - { 0, 0, 0, 0 } - }; - i = mdwopt(argc, argv, "f:au", opt, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'a': ef = "pem"; break; - case 'f': ef = optarg; break; - case 'u': v.f |= F_UTC; break; - default: v.f |= F_BOGUS; break; - } - } - if (argc - optind > 1 || (v.f & F_BOGUS)) - die(EXIT_FAILURE, "Usage: info [-OPTIONS] [FILE]"); - - if ((eo = getenc(ef)) == 0) - die(EXIT_FAILURE, "encoding `%s' not found", ef); - - if (optind >= argc) - fp = stdin; - else if (strcmp(argv[optind], "-") == 0) { - fp = stdin; - optind++; - } else if ((fp = fopen(argv[optind], eo->rmode)) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s': %s", - argv[optind], strerror(errno)); - } else - optind++; - - if (key_open(&kf, keyring, KOPEN_READ, infokeyreport, 0)) { - printf("NOTE can't open keyring `%s'\n", keyring); - keyring = 0; - } - e = initdec(eo, fp, vrfbdry, &v); - - v.what = "malformed header"; - sig_readheader(e, &s, infochoke, &v); - - printf("INFO flags %sdetach %sbinary\n", - (s.f & F_DETACH) ? "" : "!", - (s.f & F_BINARY) ? "" : "!"); - - if (((s.f ^ v.f) & v.m) != 0) { - printf("WARN boundary string inconsistent with contents\n"); - printf("INFO expected-flags"); - if (v.m & F_DETACH) printf(" %sdetach", (v.f & F_DETACH) ? "" : "!"); - if (v.m & F_BINARY) printf(" %sbinary", (v.f & F_BINARY) ? "" : "!"); - putchar('\n'); - } - v.f |= s.f; - - tm = (v.f & F_UTC) ? gmtime(&s.t) : localtime(&s.t); - strftime(bb, sizeof(bb), "%Y-%m-%d %H:%M:%S %Z", tm); - printf("INFO date %s\n", bb); - - if (keyring && (k = key_byid(&kf, s.keyid)) != 0) { - dstr_reset(&d); key_fulltag(k, &d); - printf("INFO key %s\n", d.buf); - } else - printf("INFO unknown-key %08lx\n", (unsigned long)s.keyid); - - if (keyring) key_close(&kf); - dstr_destroy(&d); - sig_destroy(&s); - return (0); -} - -/*----- Main code ---------------------------------------------------------*/ - -#define LISTS(LI) \ - LI("Lists", list, \ - listtab[i].name, listtab[i].name) \ - LI("Signature schemes", sig, \ - sigtab[i].name, sigtab[i].name) \ - LI("Encodings", enc, \ - enctab[i].name, enctab[i].name) \ - LI("Hash functions", hash, \ - ghashtab[i], ghashtab[i]->name) - -MAKELISTTAB(listtab, LISTS) - -int cmd_show(int argc, char *argv[]) -{ - return (displaylists(listtab, argv + 1)); -} - -static int cmd_help(int, char **); - -static cmd cmdtab[] = { - { "help", cmd_help, "help [COMMAND...]" }, - { "show", cmd_show, "show [ITEM...]" }, - CMD_ENCODE, - CMD_DECODE, - { "sign", sign, - "sign [-adptC] [-k TAG] [-f FORMAT] [-o OUTPUT] [FILE]", "\ -Options:\n\ -\n\ --a, --armour Same as `-f pem'.\n\ --b, --binary Treat the input message as binary data.\n\ --d, --detach Produce a detached signature.\n\ --f, --format=FORMAT Encode as FORMAT.\n\ --k, --key=TAG Use public encryption key named by TAG.\n\ --o, --output=FILE Write output to FILE.\n\ --p, --progress Show progress on large files.\n\ --t, --text Canonify input message as a text file.\n\ --C, --nocheck Don't check the private key.\n\ -" }, - { "verify", verify, - "verify [-abpquvC] [-f FORMAT] [-k TAG] [-o OUTPUT]\n\t\ -[FILE [MESSAGE]]", "\ -Options:\n\ -\n\ --a, --armour Same as `-f pem'.\n\ --b, --buffer Buffer message until signature is verified.\n\ --f, --format=FORMAT Decode as FORMAT.\n\ --k, --key=TAG Require that the message be signed by key TAG.\n\ --o, --output=FILE Write message to FILE.\n\ --p, --progress Show progress on large files.\n\ --q, --quiet Produce fewer messages.\n\ --t, --freshtime=TIME Only accept signatures made after this time.\n\ --u, --utc Show dates in UTC rather than local time.\n\ --v, --verbose Produce more verbose messages.\n\ --C, --nocheck Don't check the public key.\n\ -" }, - { "info", info, - "info [-au] [-f FORMAT] [FILE]", "\ -Options:\n\ -\n\ --a, --armour Same as `-f pem'.\n\ --f, --format=FORMAT Decode as FORMAT.\n\ --u, --utc Show dates in UTC rather than local time.\n\ -"}, - { "format", format, - "format [-apuADE] [-f FORMAT] [-F format] [-m FILE] [-o FILE]\n\t\ -[FILE [MESSAGE]]", "\ -Options:\n\ -\n\ --a, --armour-in Same as `-f pem'.\n\ --A, --armour-out Same as `-F pem'.\n\ --D, --detach Create detached signature.\n\ --E, --embed Create signature with embedded message.\n\ --f, --format-in=FORMAT Decode input as FORMAT.\n\ --F, --format-out=FORMAT Encode output as FORMAT.\n\ --m, --message=FILE Write message to FILE.\n\ --o, --output=FILE Write new signature to FILE.\n\ --p, --progress Show progress on large files.\n\ -"}, - { 0, 0, 0 } -}; /* " Emacs seems confused. */ - -static int cmd_help(int argc, char **argv) -{ - sc_help(cmdtab, stdout, argv + 1); - return (0); -} - -void version(FILE *fp) -{ - pquis(fp, "$, Catacomb version " VERSION "\n"); -} - -static void usage(FILE *fp) -{ - pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n"); -} - -void help_global(FILE *fp) -{ - usage(fp); - fputs("\n\ -Sign and verify data.\n\ -\n\ -Global command-line options:\n\ -\n\ --h, --help [COMMAND...] Show this help message, or help for COMMANDs.\n\ --v, --version Show program version number.\n\ --u, --usage Show a terse usage message.\n\ -\n\ --k, --keyring=FILE Read keys from FILE.\n", - fp); -} - -/* --- @main@ --- * - * - * Arguments: @int argc@ = number of command line arguments - * @char *argv[]@ = vector of command line arguments - * - * Returns: Zero if successful, nonzero otherwise. - * - * Use: Encrypts or decrypts files. - */ - -int main(int argc, char *argv[]) -{ - unsigned f = 0; - -#define f_bogus 1u - - /* --- Initialize the library --- */ - - ego(argv[0]); - sub_init(); - rand_noisesrc(RAND_GLOBAL, &noise_source); - rand_seed(RAND_GLOBAL, 160); -/* trace_on(stderr, 1); */ - - /* --- Parse options --- */ - - for (;;) { - static struct option opts[] = { - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'v' }, - { "usage", 0, 0, 'u' }, - { "keyring", OPTF_ARGREQ, 0, 'k' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+hvu k:", opts, 0, 0, 0); - if (i < 0) - break; - switch (i) { - case 'h': - sc_help(cmdtab, stdout, argv + optind); - exit(0); - break; - case 'v': - version(stdout); - exit(0); - break; - case 'u': - usage(stdout); - exit(0); - case 'k': - keyring = optarg; - break; - default: - f |= f_bogus; - break; - } - } - - argc -= optind; - argv += optind; - optind = 0; - if (f & f_bogus || argc < 1) { - usage(stderr); - exit(EXIT_FAILURE); - } - - /* --- Dispatch to the correct subcommand handler --- */ - - return (findcmd(cmdtab, argv[0])->cmd(argc, argv)); - -#undef f_bogus -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/cbc-def.h b/cbc-def.h deleted file mode 100644 index d14c952..0000000 --- a/cbc-def.h +++ /dev/null @@ -1,549 +0,0 @@ -/* -*-c-*- - * - * $Id: cbc-def.h,v 1.6 2004/04/17 09:58:36 mdw Exp $ - * - * Definitions for cipher block chaining mode - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_CBC_DEF_H -#define CATACOMB_CBC_DEF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include -#include - -#ifndef CATACOMB_ARENA_H -# include "arena.h" -#endif - -#ifndef CATACOMB_BLKC_H -# include "blkc.h" -#endif - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -#ifndef CATACOMB_PARANOIA_H -# include "paranoia.h" -#endif - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @CBC_DEF@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher - * - * Use: Creates an implementation for CBC stealing mode. - */ - -#define CBC_DEF(PRE, pre) \ - \ -/* --- @pre_cbcgetiv@ --- * \ - * \ - * Arguments: @const pre_cbcctx *ctx@ = pointer to CBC context block \ - * @void *iv@ = pointer to output data block \ - * \ - * Returns: --- \ - * \ - * Use: Reads the currently set IV. Reading and setting an IV \ - * is transparent to the CBC encryption or decryption \ - * process. \ - */ \ - \ -void pre##_cbcgetiv(const pre##_cbcctx *ctx, void *iv) \ -{ \ - BLKC_STORE(PRE, iv, ctx->iv); \ -} \ - \ -/* --- @pre_cbcsetiv@ --- * \ - * \ - * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ - * @cnost void *iv@ = pointer to IV to set \ - * \ - * Returns: --- \ - * \ - * Use: Sets the IV to use for subsequent encryption. \ - */ \ - \ -void pre##_cbcsetiv(pre##_cbcctx *ctx, const void *iv) \ -{ \ - BLKC_LOAD(PRE, ctx->iv, iv); \ -} \ - \ -/* --- @pre_cbcsetkey@ --- * \ - * \ - * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ - * @const pre_ctx *k@ = pointer to cipher context \ - * \ - * Returns: --- \ - * \ - * Use: Sets the CBC context to use a different cipher key. \ - */ \ - \ -void pre##_cbcsetkey(pre##_cbcctx *ctx, const pre##_ctx *k) \ -{ \ - ctx->ctx = *k; \ -} \ - \ -/* --- @pre_cbcinit@ --- * \ - * \ - * Arguments: @pre_cbcctx *ctx@ = pointer to cipher context \ - * @const void *key@ = pointer to the key buffer \ - * @size_t sz@ = size of the key \ - * @const void *iv@ = pointer to initialization vector \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a CBC context ready for use. The @iv@ \ - * argument may be passed as a null pointer to set a zero \ - * IV. Apart from that, this call is equivalent to calls \ - * to @pre_init@, @pre_cbcsetkey@ and @pre_cbcsetiv@. \ - */ \ - \ -void pre##_cbcinit(pre##_cbcctx *ctx, \ - const void *key, size_t sz, \ - const void *iv) \ -{ \ - static const octet zero[PRE##_BLKSZ] = { 0 }; \ - pre##_init(&ctx->ctx, key, sz); \ - BLKC_LOAD(PRE, ctx->iv, iv ? iv : zero); \ -} \ - \ -/* --- @pre_cbcencrypt@ --- * \ - * \ - * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Encrypts a block with a block cipher in CBC mode, with \ - * ciphertext stealing and other clever tricks. \ - * Essentially, data can be encrypted in arbitrary sized \ - * chunks, although decryption must use the same chunks. \ - */ \ - \ -void pre##_cbcencrypt(pre##_cbcctx *ctx, \ - const void *src, void *dest, \ - size_t sz) \ -{ \ - const octet *s = src; \ - octet *d = dest; \ - \ - /* --- Empty blocks are trivial --- */ \ - \ - if (!sz) \ - return; \ - \ - /* --- Extra magical case for a short block --- * \ - * \ - * Encrypt the IV, then exclusive-or the plaintext with the octets \ - * of the encrypted IV, shifting ciphertext octets in instead. This \ - * basically switches over to CFB. \ - */ \ - \ - if (sz < PRE##_BLKSZ) { \ - octet b[PRE##_BLKSZ]; \ - unsigned i; \ - \ - pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \ - BLKC_STORE(PRE, b, ctx->iv); \ - if (d) { \ - for (i = 0; i < sz; i++) \ - d[i] = b[i] ^ (s ? s[i] : 0); \ - } \ - memmove(b, b + sz, PRE##_BLKSZ - sz); \ - memcpy(b + PRE##_BLKSZ - sz, d, sz); \ - BLKC_LOAD(PRE, ctx->iv, b); \ - return; \ - } \ - \ - /* --- Do the main chunk of encryption --- * \ - * \ - * This will do the whole lot if it's a whole number of blocks. For \ - * each block, XOR it with the previous ciphertext in @iv@, encrypt, \ - * and keep a copy of the ciphertext for the next block. \ - */ \ - \ - while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \ - if (s) { \ - BLKC_XLOAD(PRE, ctx->iv, s); \ - s += PRE##_BLKSZ; \ - } \ - pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \ - if (d) { \ - BLKC_STORE(PRE, d, ctx->iv); \ - d += PRE##_BLKSZ; \ - } \ - sz -= PRE##_BLKSZ; \ - } \ - \ - /* --- Do the tail-end block and bit-left-over --- * \ - * \ - * This isn't very efficient. That shouldn't matter much. \ - */ \ - \ - if (sz) { \ - octet b[PRE##_BLKSZ]; \ - unsigned i; \ - \ - /* --- Let @sz@ be the size of the partial block --- */ \ - \ - sz -= PRE##_BLKSZ; \ - \ - /* --- First stage --- * \ - * \ - * XOR the complete block with the current IV, and encrypt it. The \ - * first part of the result is the partial ciphertext block. Don't \ - * write that out yet, because I've not read the partial plaintext \ - * block. \ - */ \ - \ - if (s) BLKC_XLOAD(PRE, ctx->iv, s); \ - pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \ - BLKC_STORE(PRE, b, ctx->iv); \ - \ - /* --- Second stage --- * \ - * \ - * Now XOR in the partial plaintext block, writing out the \ - * ciphertext as I go. Then encrypt, and write the complete \ - * ciphertext block. \ - */ \ - \ - if (s) s += PRE##_BLKSZ; \ - if (d) d += PRE##_BLKSZ; \ - for (i = 0; i < sz; i++) { \ - register octet x = b[i]; \ - if (s) b[i] ^= s[i]; \ - if (d) d[i] = x; \ - } \ - BLKC_LOAD(PRE, ctx->iv, b); \ - pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \ - if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, ctx->iv); \ - } \ - \ - /* --- Done --- */ \ - \ - return; \ -} \ - \ -/* --- @pre_cbcdecrypt@ --- * \ - * \ - * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Decrypts a block with a block cipher in CBC mode, with \ - * ciphertext stealing and other clever tricks. \ - * Essentially, data can be encrypted in arbitrary sized \ - * chunks, although decryption must use the same chunks. \ - */ \ - \ -void pre##_cbcdecrypt(pre##_cbcctx *ctx, \ - const void *src, void *dest, \ - size_t sz) \ -{ \ - const octet *s = src; \ - octet *d = dest; \ - \ - /* --- Empty blocks are trivial --- */ \ - \ - if (!sz) \ - return; \ - \ - /* --- Extra magical case for a short block --- * \ - * \ - * Encrypt the IV, then exclusive-or the ciphertext with the octets \ - * of the encrypted IV, shifting ciphertext octets in instead. This \ - * basically switches over to CFB. \ - */ \ - \ - if (sz < PRE##_BLKSZ) { \ - octet b[PRE##_BLKSZ], c[PRE##_BLKSZ]; \ - unsigned i; \ - \ - pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \ - BLKC_STORE(PRE, b, ctx->iv); \ - for (i = 0; i < sz; i++) { \ - register octet x = s[i]; \ - d[i] = b[i] ^ x; \ - c[i] = x; \ - } \ - memmove(b, b + sz, PRE##_BLKSZ - sz); \ - memcpy(b + PRE##_BLKSZ - sz, c, sz); \ - BLKC_LOAD(PRE, ctx->iv, b); \ - return; \ - } \ - \ - /* --- Do the main chunk of decryption --- * \ - * \ - * This will do the whole lot if it's a whole number of blocks. For \ - * each block, decrypt, XOR it with the previous ciphertext in @iv@, \ - * and keep a copy of the ciphertext for the next block. \ - */ \ - \ - while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \ - uint32 b[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4]; \ - BLKC_LOAD(PRE, niv, s); \ - pre##_dblk(&ctx->ctx, niv, b); \ - BLKC_XSTORE(PRE, d, b, ctx->iv); \ - BLKC_MOVE(PRE, ctx->iv, niv); \ - s += PRE##_BLKSZ; \ - d += PRE##_BLKSZ; \ - sz -= PRE##_BLKSZ; \ - } \ - \ - /* --- Do the tail-end block and bit-left-over --- * \ - * \ - * This isn't very efficient. That shouldn't matter much. \ - */ \ - \ - if (sz) { \ - octet b[PRE##_BLKSZ]; \ - uint32 bk[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4]; \ - unsigned i; \ - \ - /* --- Let @sz@ be the size of the partial block --- */ \ - \ - sz -= PRE##_BLKSZ; \ - \ - /* --- First stage --- * \ - * \ - * Take the complete ciphertext block, and decrypt it. This block \ - * is carried over for the next encryption operation. \ - */ \ - \ - BLKC_LOAD(PRE, niv, s); \ - pre##_dblk(&ctx->ctx, niv, bk); \ - \ - /* --- Second stage --- * \ - * \ - * XORing the first few bytes of this with the partial ciphertext \ - * block recovers the partial plaintext block. At the same time, \ - * write the partial ciphertext block's contents in ready for stage \ - * three. \ - */ \ - \ - BLKC_STORE(PRE, b, bk); \ - s += PRE##_BLKSZ; \ - d += PRE##_BLKSZ; \ - for (i = 0; i < sz; i++) { \ - register octet x = s[i]; \ - d[i] = b[i] ^ x; \ - b[i] = x; \ - } \ - \ - /* --- Third stage --- * \ - * \ - * Decrypt the block we've got left, and XOR with the initial IV to \ - * recover the complete plaintext block. \ - */ \ - \ - BLKC_LOAD(PRE, bk, b); \ - pre##_dblk(&ctx->ctx, bk, bk); \ - BLKC_XSTORE(PRE, d - PRE##_BLKSZ, bk, ctx->iv); \ - BLKC_MOVE(PRE, ctx->iv, niv); \ - } \ - \ - /* --- Done --- */ \ - \ - return; \ -} \ - \ -/* --- Generic cipher interface --- */ \ - \ -static const gcipher_ops gops; \ - \ -typedef struct gctx { \ - gcipher c; \ - pre##_cbcctx k; \ -} gctx; \ - \ -static gcipher *ginit(const void *k, size_t sz) \ -{ \ - gctx *g = S_CREATE(gctx); \ - g->c.ops = &gops; \ - pre##_cbcinit(&g->k, k, sz, 0); \ - return (&g->c); \ -} \ - \ -static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_cbcencrypt(&g->k, s, t, sz); \ -} \ - \ -static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_cbcdecrypt(&g->k, s, t, sz); \ -} \ - \ -static void gdestroy(gcipher *c) \ -{ \ - gctx *g = (gctx *)c; \ - BURN(*g); \ - S_DESTROY(g); \ -} \ - \ -static void gsetiv(gcipher *c, const void *iv) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_cbcsetiv(&g->k, iv); \ -} \ - \ -static const gcipher_ops gops = { \ - &pre##_cbc, \ - gencrypt, gdecrypt, gdestroy, gsetiv, 0 \ -}; \ - \ -const gccipher pre##_cbc = { \ - #pre "-cbc", pre##_keysz, PRE##_BLKSZ, \ - ginit \ -}; \ - \ -CBC_TEST(PRE, pre) - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#include "daftstory.h" - -/* --- @CBC_TEST@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions - * - * Use: Standard test rig for CBC functions. - */ - -#define CBC_TEST(PRE, pre) \ - \ -/* --- Initial plaintext for the test --- */ \ - \ -static const octet text[] = TEXT; \ - \ -/* --- Key and IV to use --- */ \ - \ -static const octet key[] = KEY; \ -static const octet iv[] = IV; \ - \ -/* --- Buffers for encryption and decryption output --- */ \ - \ -static octet ct[sizeof(text)]; \ -static octet pt[sizeof(text)]; \ - \ -static void hexdump(const octet *p, size_t sz) \ -{ \ - const octet *q = p + sz; \ - for (sz = 0; p < q; p++, sz++) { \ - printf("%02x", *p); \ - if ((sz + 1) % PRE##_BLKSZ == 0) \ - putchar(':'); \ - } \ -} \ - \ -int main(void) \ -{ \ - size_t sz = 0, rest; \ - pre##_cbcctx ctx; \ - pre##_ctx k; \ - int status = 0; \ - int done = 0; \ - \ - size_t keysz = PRE##_KEYSZ ? \ - PRE##_KEYSZ : strlen((const char *)key); \ - \ - fputs(#pre "-cbc: ", stdout); \ - \ - pre##_init(&k, key, keysz); \ - pre##_cbcsetkey(&ctx, &k); \ - \ - while (sz <= sizeof(text)) { \ - rest = sizeof(text) - sz; \ - memcpy(ct, text, sizeof(text)); \ - pre##_cbcsetiv(&ctx, iv); \ - pre##_cbcencrypt(&ctx, ct, ct, sz); \ - pre##_cbcencrypt(&ctx, ct + sz, ct + sz, rest); \ - memcpy(pt, ct, sizeof(text)); \ - pre##_cbcsetiv(&ctx, iv); \ - pre##_cbcdecrypt(&ctx, pt, pt, sz); \ - pre##_cbcdecrypt(&ctx, pt + sz, pt + sz, rest); \ - if (memcmp(pt, text, sizeof(text)) == 0) { \ - done++; \ - if (sizeof(text) < 40 || done % 8 == 0) \ - fputc('.', stdout); \ - if (done % 480 == 0) \ - fputs("\n\t", stdout); \ - fflush(stdout); \ - } else { \ - printf("\nError (sz = %lu)\n", (unsigned long)sz); \ - status = 1; \ - printf("\tplaintext = "); hexdump(text, sz); \ - printf(", "); hexdump(text + sz, rest); \ - fputc('\n', stdout); \ - printf("\tciphertext = "); hexdump(ct, sz); \ - printf(", "); hexdump(ct + sz, rest); \ - fputc('\n', stdout); \ - printf("\trecovered text = "); hexdump(pt, sz); \ - printf(", "); hexdump(pt + sz, rest); \ - fputc('\n', stdout); \ - fputc('\n', stdout); \ - } \ - if (sz < 63) \ - sz++; \ - else \ - sz += 9; \ - } \ - \ - fputs(status ? " failed\n" : " ok\n", stdout); \ - return (status); \ -} - -#else -# define CBC_TEST(PRE, pre) -#endif - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/cbc.h b/cbc.h deleted file mode 100644 index 651df8a..0000000 --- a/cbc.h +++ /dev/null @@ -1,173 +0,0 @@ -/* -*-c-*- - * - * $Id: cbc.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Ciphertext block chaining for block ciphers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_CBC_H -#define CATACOMB_CBC_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @CBC_DECL@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher - * - * Use: Creates declarations for CBC stealing mode. - */ - -#define CBC_DECL(PRE, pre) \ - \ -/* --- Cipher block chaining context --- */ \ - \ -typedef struct pre##_cbcctx { \ - pre##_ctx ctx; /* Underlying cipher context */ \ - uint32 iv[PRE##_BLKSZ / 4]; /* Previous ciphertext or IV */ \ -} pre##_cbcctx; \ - \ -/* --- @pre_cbcgetiv@ --- * \ - * \ - * Arguments: @const pre_cbcctx *ctx@ = pointer to CBC context block \ - * @void *iv@ = pointer to output data block \ - * \ - * Returns: --- \ - * \ - * Use: Reads the currently set IV. Reading and setting an IV \ - * is transparent to the CBC encryption or decryption \ - * process. \ - */ \ - \ -extern void pre##_cbcgetiv(const pre##_cbcctx */*ctx*/, \ - void */*iv*/); \ - \ -/* --- @pre_cbcsetiv@ --- * \ - * \ - * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ - * @cnost void *iv@ = pointer to IV to set \ - * \ - * Returns: --- \ - * \ - * Use: Sets the IV to use for subsequent encryption. \ - */ \ - \ -extern void pre##_cbcsetiv(pre##_cbcctx */*ctx*/, \ - const void */*iv*/); \ - \ -/* --- @pre_cbcsetkey@ --- * \ - * \ - * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ - * @const pre_ctx *k@ = pointer to cipher context \ - * \ - * Returns: --- \ - * \ - * Use: Sets the CBC context to use a different cipher key. \ - */ \ - \ -extern void pre##_cbcsetkey(pre##_cbcctx */*ctx*/, \ - const pre##_ctx */*k*/); \ - \ -/* --- @pre_cbcinit@ --- * \ - * \ - * Arguments: @pre_cbcctx *ctx@ = pointer to cipher context \ - * @const void *key@ = pointer to the key buffer \ - * @size_t sz@ = size of the key \ - * @const void *iv@ = pointer to initialization vector \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a CBC context ready for use. The @iv@ \ - * argument may be passed as a null pointer to set a zero \ - * IV. Apart from that, this call is equivalent to calls \ - * to @pre_init@, @pre_cbcsetkey@ and @pre_cbcsetiv@. \ - */ \ - \ -extern void pre##_cbcinit(pre##_cbcctx */*ctx*/, \ - const void */*key*/, size_t /*sz*/, \ - const void */*iv*/); \ - \ -/* --- @pre_cbcencrypt@ --- * \ - * \ - * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Encrypts a block with a block cipher in CBC mode, with \ - * ciphertext stealing and other clever tricks. \ - * Essentially, data can be encrypted in arbitrary sized \ - * chunks, although decryption must use the same chunks. \ - */ \ - \ -extern void pre##_cbcencrypt(pre##_cbcctx */*ctx*/, \ - const void */*src*/, void */*dest*/, \ - size_t /*sz*/); \ - \ -/* --- @pre_cbcdecrypt@ --- * \ - * \ - * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Decrypts a block with a block cipher in CBC mode, with \ - * ciphertext stealing and other clever tricks. \ - * Essentially, data can be encrypted in arbitrary sized \ - * chunks, although decryption must use the same chunks. \ - */ \ - \ -extern void pre##_cbcdecrypt(pre##_cbcctx */*ctx*/, \ - const void */*src*/, void */*dest*/, \ - size_t /*sz*/); \ - \ -/* --- Generic cipher interface --- */ \ - \ -extern const gccipher pre##_cbc; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/cc-enc.c b/cc-enc.c deleted file mode 100644 index 2b8b0fd..0000000 --- a/cc-enc.c +++ /dev/null @@ -1,530 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Catcrypt data encoding - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _FILE_OFFSET_BITS 64 - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "cc.h" - -typedef int encbdryp(const char *, void *); - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Binary --- */ - -static enc *bin_encinit(FILE *fp, const char *msg) - { enc *e = CREATE(enc); return (e); } -static enc *bin_decinit(FILE *fp, encbdryp *func, void *p) - { enc *e = CREATE(enc); return (e); } - -static int bin_read(enc *e, void *p, size_t sz) -{ - size_t n; - - if (!sz) return (0); - n = fread(p, 1, sz, e->fp); - if (!n || ferror(e->fp)) return (-1); - return (n); -} - -static int bin_write(enc *e, const void *p, size_t sz) - { if (sz && fwrite(p, 1, sz, e->fp) < sz) return (-1); return (0); } - -static int bin_done(enc *e) { return (0); } - -static void bin_destroy(enc *e) { DESTROY(e); } - -/* --- PEM --- */ - -typedef struct pem_encctx { - enc e; - char *msg; - unsigned f; - base64_ctx b; - dstr d; - size_t n; -#define PEMF_NL 1u -#define PEMF_EOF 2u -} pem_encctx; - -static enc *pem_encinit(FILE *fp, const char *msg) -{ - pem_encctx *pe = CREATE(pem_encctx); - base64_init(&pe->b); - fprintf(fp, "-----BEGIN %s-----\n", msg); - pe->msg = xstrdup(msg); - dstr_create(&pe->d); - pe->n = 0; - pe->f = 0; - return (&pe->e); -} - -int checkbdry(const char *b, void *p) { return (!p || strcmp(b, p) == 0); } - -static enc *pem_decinit(FILE *fp, encbdryp *func, void *p) -{ - char buf[128]; - int i, d; - pem_encctx *pe; - int ch; - - /* --- Go until I find a newline and `-----' --- */ - -top: - d = 0; - for (;;) { - if ((ch = getc(fp)) == EOF) goto fail; - switch (ch) { - case '\n': d = 0; break; - case '-': if (d >= 0) { d++; if (d == 5) goto banner; }; break; - default: d = -1; break; - } - } - - /* --- See what the banner looks like --- */ - -banner: - i = d = 0; - for (;;) { - if ((ch = getc(fp)) == EOF) goto fail; - if (ch == '-') { d++; continue; } - if (ch == '\n') break; - if (i + d + 1 >= sizeof(buf)) goto top; - while (d) { buf[i++] = '-'; d--; } - buf[i++] = ch; - } - buf[i] = 0; - - /* --- Check we have the right framing --- */ - - if (d != 5) goto top; - if (strncmp(buf, "BEGIN ", 6) != 0 || (func && !func(buf + 6, p))) - goto top; - - /* --- Ready --- */ - - pe = CREATE(pem_encctx); - base64_init(&pe->b); - pe->msg = xstrdup(buf + 6); - dstr_create(&pe->d); - pe->n = 0; - pe->f = PEMF_NL; - return (&pe->e); - - /* --- Failed --- */ - -fail: - die(EXIT_FAILURE, "initial encapsulation boundary not found"); - return (0); -} - -#define PEM_CHUNKSZ 4096 - -static int pem_read(enc *e, void *p, size_t sz) -{ - pem_encctx *pe = (pem_encctx *)e; - char buf[PEM_CHUNKSZ]; - char *pp = p; - int ch; - size_t n; - int rc = 0; - - for (;;) { - n = pe->d.len - pe->n; - if (n > sz) n = sz; - memcpy(pp, pe->d.buf + pe->n, n); - pe->n += n; - pp += n; - rc += n; - sz -= n; - if (!sz) break; - if (pe->f & PEMF_EOF) return (rc ? rc : -1); - dstr_reset(&pe->d); - n = 0; - for (;;) { - if ((ch = getc(pe->e.fp)) == EOF) return (-1); - if ((pe->f & PEMF_NL) && ch == '-') { - ungetc(ch, pe->e.fp); - pe->f |= PEMF_EOF; - break; - } - if (ch == '\n') { pe->f |= PEMF_NL; continue; } - pe->f &= ~PEMF_NL; - buf[n++] = ch; - if (n >= PEM_CHUNKSZ) break; - } - if (n) - base64_decode(&pe->b, buf, n, &pe->d); - if (pe->f & PEMF_EOF) - base64_decode(&pe->b, 0, 0, &pe->d); - pe->n = 0; - } - return (rc); -} - -static int pem_write(enc *e, const void *p, size_t sz) -{ - pem_encctx *pe = (pem_encctx *)e; - const char *pp = p; - size_t n; - - while (sz) { - n = PEM_CHUNKSZ; - if (n > sz) n = sz; - dstr_reset(&pe->d); - base64_encode(&pe->b, pp, n, &pe->d); - if (fwrite(pe->d.buf, 1, pe->d.len, pe->e.fp) < pe->d.len) - return (-1); - pp += n; - sz -= n; - } - return (0); -} - -static int pem_encdone(enc *e) -{ - pem_encctx *pe = (pem_encctx *)e; - dstr_reset(&pe->d); - base64_encode(&pe->b, 0, 0, &pe->d); - if (fwrite(pe->d.buf, 1, pe->d.len, pe->e.fp) < pe->d.len) - return (-1); - if (pe->b.lnlen) fputc('\n', pe->e.fp); - fprintf(pe->e.fp, "-----END %s-----\n", pe->msg); - return (0); -} - -static int pem_decdone(enc *e) -{ - pem_encctx *pe = (pem_encctx *)e; - char buf[128]; - int i, d; - int ch; - - for (d = 0; d < 5; d++) - if ((ch = getc(pe->e.fp)) != '-') goto fail; - i = d = 0; - for (;;) { - if ((ch = getc(pe->e.fp)) == EOF) goto fail; - if (ch == '-') { d++; continue; } - if (ch == '\n') break; - if (i + d + 1 >= sizeof(buf)) goto fail; - while (d) { buf[i++] = '-'; d--; } - buf[i++] = ch; - } - if (d != 5) goto fail; - buf[i] = 0; - if (strncmp(buf, "END ", 4) != 0 || strcmp(buf + 4, pe->msg) != 0) - goto fail; - return (0); - -fail: - die(EXIT_FAILURE, "final encapsulation boundary not found"); - return (-1); -} - -static void pem_destroy(enc *e) -{ - pem_encctx *pe = (pem_encctx *)e; - dstr_destroy(&pe->d); - xfree(pe->msg); - DESTROY(pe); -} - -/* --- Encoder table --- */ - -const encops enctab[] = { - { "binary", "rb", "wb", 1, 1, - bin_encinit, bin_decinit, - bin_read, bin_write, - bin_done, bin_done, - bin_destroy }, - { "pem", "r", "w", 3, 4, - pem_encinit, pem_decinit, - pem_read, pem_write, - pem_encdone, pem_decdone, - pem_destroy }, - { 0 } -}; - -/* --- @getenc@ --- * - * - * Arguments: @const char *enc@ = name of wanted encoding - * - * Returns: Pointer to encoder operations. - * - * Use: Finds a named encoder or decoder. - */ - -const encops *getenc(const char *enc) -{ - const encops *eo; - - for (eo = enctab; eo->name; eo++) { - if (strcmp(eo->name, enc) == 0) - goto e_found; - } - die(EXIT_FAILURE, "couldn't find encoding `%s'", enc); -e_found: - return (eo); -} - -/* --- @initenc@ --- * - * - * Arguments: @const encops *eo@ = operations (from @getenc@) - * @FILE *fp@ = file handle to attach - * @const char *msg@ = banner message - * - * Returns: The encoder object. - * - * Use: Initializes an encoder. - */ - -enc *initenc(const encops *eo, FILE *fp, const char *msg) -{ - enc *e = eo->initenc(fp, msg); - e->ops = eo; - e->fp = fp; - return (e); -} - -/* --- @initdec@ --- * - * - * Arguments: @const encops *eo@ = operations (from @getenc@) - * @FILE *fp@ = file handle to attach - * @int (*func)(const char *, void *)@ = banner check function - * @void *p@ = argument for @func@ - * - * Returns: The encoder object. - * - * Use: Initializes an encoder. - */ - -enc *initdec(const encops *eo, FILE *fp, - int (*func)(const char *, void *), void *p) -{ - enc *e = eo->initdec(fp, func, p); - e->ops = eo; - e->fp = fp; - return (e); -} - -/* --- @freeenc@ --- * - * - * Arguments: @enc *e@ = encoder object - * - * Returns: --- - * - * Use: Frees an encoder object. - */ - -void freeenc(enc *e) { e->ops->destroy(e); } - -/*----- Encoding and decoding commands ------------------------------------*/ - -int cmd_encode(int argc, char *argv[]) -{ - const char *fn, *of = 0; - FILE *ofp = 0; - FILE *fp = 0; - const char *ef = "binary"; - const char *bd = "MESSAGE"; - fprogress ff; - int i; - size_t n; - char buf[4096]; - unsigned f = 0; - const encops *eo; - enc *e; - -#define f_bogus 1u -#define f_progress 2u - - for (;;) { - static const struct option opt[] = { - { "format", OPTF_ARGREQ, 0, 'f' }, - { "boundary", OPTF_ARGREQ, 0, 'b' }, - { "output", OPTF_ARGREQ, 0, 'o' }, - { "progress", 0, 0, 'p' }, - { 0, 0, 0, 0 } - }; - i = mdwopt(argc, argv, "f:b:o:p", opt, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'f': ef = optarg; break; - case 'b': bd = optarg; break; - case 'o': of = optarg; break; - case 'p': f |= f_progress; break; - default: f |= f_bogus; break; - } - } - if (argc - optind > 1 || (f & f_bogus)) - die(EXIT_FAILURE, "Usage: encode [-OPTIONS] [FILE]"); - - if ((eo = getenc(ef)) == 0) - die(EXIT_FAILURE, "encoding `%s' not found", ef); - - fn = optind < argc ? argv[optind++] : "-"; - if (strcmp(fn, "-") == 0) - fp = stdin; - else if ((fp = fopen(fn, "rb")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s': %s", - fn, strerror(errno)); - } - - if (!of || strcmp(of, "-") == 0) - ofp = stdout; - else if ((ofp = fopen(of, eo->wmode)) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - ofp, strerror(errno)); - } - - e = initenc(eo, ofp, bd); - - if (f & f_progress) { - if (fprogress_init(&ff, fn, fp)) { - die(EXIT_FAILURE, "failed to initialize progress display: %s", - strerror(errno)); - } - } - - do { - n = fread(buf, 1, sizeof(buf), fp); - if (f & f_progress) fprogress_update(&ff, n); - if (e->ops->write(e, buf, n)) { - if (f & f_progress) fprogress_done(&ff); - die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); - } - } while (n == sizeof(buf)); - if (f & f_progress) fprogress_done(&ff); - e->ops->encdone(e); - freeenc(e); - return (0); - -#undef f_bogus -#undef f_progress -} - -int cmd_decode(int argc, char *argv[]) -{ - const char *fn, *of = 0; - FILE *ofp = 0; - FILE *fp = 0; - const char *ef = "binary"; - const char *bd = 0; - fprogress ff; - int i; - char buf[4096]; - unsigned f = 0; - const encops *eo; - enc *e; - -#define f_bogus 1u -#define f_progress 2u - - for (;;) { - static const struct option opt[] = { - { "format", OPTF_ARGREQ, 0, 'f' }, - { "boundary", OPTF_ARGREQ, 0, 'b' }, - { "output", OPTF_ARGREQ, 0, 'o' }, - { "progress", 0, 0, 'p' }, - { 0, 0, 0, 0 } - }; - i = mdwopt(argc, argv, "f:b:o:p", opt, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'f': ef = optarg; break; - case 'b': bd = optarg; break; - case 'o': of = optarg; break; - case 'p': f |= f_progress; break; - default: f |= f_bogus; break; - } - } - if (argc - optind > 1 || (f & f_bogus)) - die(EXIT_FAILURE, "Usage: decode [-OPTIONS] [FILE]"); - - if ((eo = getenc(ef)) == 0) - die(EXIT_FAILURE, "encoding `%s' not found", ef); - - fn = optind < argc ? argv[optind++] : "-"; - if (strcmp(fn, "-") == 0) - fp = stdin; - else if ((fp = fopen(fn, eo->rmode)) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s': %s", - fn, strerror(errno)); - } - - if (!of || strcmp(of, "-") == 0) - ofp = stdout; - else if ((ofp = fopen(of, "wb")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - ofp, strerror(errno)); - } - - e = initdec(eo, fp, checkbdry, (/*unconst*/ void *)bd); - - if (f & f_progress) { - if (fprogress_init(&ff, fn, fp)) { - die(EXIT_FAILURE, "failed to initialize progress display: %s", - strerror(errno)); - } - } - - do { - if ((i = e->ops->read(e, buf, sizeof(buf))) < 0) { - if (f & f_progress) fprogress_done(&ff); - die(EXIT_FAILURE, "error reading input: %s", strerror(errno)); - } - if (f & f_progress) - fprogress_update(&ff, i*e->ops->ncook/e->ops->nraw); - if (fwrite(buf, 1, i, ofp) < i) { - if (f & f_progress) fprogress_done(&ff); - die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); - } - } while (i == sizeof(buf)); - e->ops->decdone(e); - if (f & f_progress) fprogress_done(&ff); - freeenc(e); - return (0); - -#undef f_bogus -#undef f_progress -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/cc-kem.c b/cc-kem.c deleted file mode 100644 index 63199fc..0000000 --- a/cc-kem.c +++ /dev/null @@ -1,629 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Catcrypt key-encapsulation - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _FILE_OFFSET_BITS 64 - -#include - -#include -#include -#include -#include - -#include "mprand.h" -#include "rand.h" - -#include "ec.h" -#include "ec-keys.h" -#include "dh.h" -#include "rsa.h" - -#include "rmd160.h" -#include "blowfish-cbc.h" - -#include "cc.h" - -/*----- Key encapsulation -------------------------------------------------*/ - -/* --- RSA --- */ - -typedef struct rsa_encctx { - kem k; - rsa_pubctx rp; -} rsa_encctx; - -static kem *rsa_encinit(key *k, void *kd) -{ - rsa_encctx *re = CREATE(rsa_encctx); - rsa_pubcreate(&re->rp, kd); - return (&re->k); -} - -static int rsa_encdoit(kem *k, dstr *d, ghash *h) -{ - rsa_encctx *re = (rsa_encctx *)k; - mp *x = mprand_range(MP_NEW, re->rp.rp->n, &rand_global, 0); - mp *y = rsa_pubop(&re->rp, MP_NEW, x); - size_t n = mp_octets(re->rp.rp->n); - dstr_ensure(d, n); - mp_storeb(x, d->buf, n); - GH_HASH(h, d->buf, n); - mp_storeb(y, d->buf, n); - d->len += n; - mp_drop(x); - mp_drop(y); - return (0); -} - -static const char *rsa_lengthcheck(mp *n) -{ - if (mp_bits(n) < 1020) return ("key too short"); - return (0); -} - -static const char *rsa_enccheck(kem *k) -{ - rsa_encctx *re = (rsa_encctx *)k; - const char *e; - if ((e = rsa_lengthcheck(re->rp.rp->n)) != 0) return (e); - return (0); -} - -static void rsa_encdestroy(kem *k) -{ - rsa_encctx *re = (rsa_encctx *)k; - rsa_pubdestroy(&re->rp); - DESTROY(re); -} - -static const kemops rsa_encops = { - rsa_pubfetch, sizeof(rsa_pub), - rsa_encinit, rsa_encdoit, rsa_enccheck, rsa_encdestroy -}; - -typedef struct rsa_decctx { - kem k; - rsa_privctx rp; -} rsa_decctx; - -static kem *rsa_decinit(key *k, void *kd) -{ - rsa_decctx *rd = CREATE(rsa_decctx); - rsa_privcreate(&rd->rp, kd, &rand_global); - return (&rd->k); -} - -static int rsa_decdoit(kem *k, dstr *d, ghash *h) -{ - rsa_decctx *rd = (rsa_decctx *)k; - mp *x = mp_loadb(MP_NEW, d->buf, d->len); - size_t n; - char *p; - - if (MP_CMP(x, >=, rd->rp.rp->n)) { - mp_drop(x); - return (-1); - } - n = mp_octets(rd->rp.rp->n); - p = xmalloc(n); - x = rsa_privop(&rd->rp, x, x); - mp_storeb(x, p, n); - GH_HASH(h, p, n); - mp_drop(x); - xfree(p); - return (0); -} - -static const char *rsa_deccheck(kem *k) -{ - rsa_decctx *rd = (rsa_decctx *)k; - const char *e; - if ((e = rsa_lengthcheck(rd->rp.rp->n)) != 0) return (e); - return (0); -} - -static void rsa_decdestroy(kem *k) -{ - rsa_decctx *rd = (rsa_decctx *)k; - rsa_privdestroy(&rd->rp); - DESTROY(rd); -} - -static const kemops rsa_decops = { - rsa_privfetch, sizeof(rsa_priv), - rsa_decinit, rsa_decdoit, rsa_deccheck, rsa_decdestroy -}; - -/* --- DH and EC --- */ - -typedef struct dh_encctx { - kem k; - group *g; - mp *x; - ge *y; -} dh_encctx; - -static dh_encctx *dh_doinit(key *k, const gprime_param *gp, mp *y, - group *(*makegroup)(const gprime_param *), - const char *what) -{ - dh_encctx *de = CREATE(dh_encctx); - dstr t = DSTR_INIT; - - key_fulltag(k, &t); - if ((de->g = makegroup(gp)) == 0) - die(EXIT_FAILURE, "bad %s group in key `%s'", what, t.buf); - de->x = MP_NEW; - de->y = G_CREATE(de->g); - if (G_FROMINT(de->g, de->y, y)) - die(EXIT_FAILURE, "bad public key `%s'", t.buf); - dstr_destroy(&t); - return (de); -} - -static dh_encctx *ec_doinit(key *k, const char *cstr, const ec *y) -{ - dh_encctx *de = CREATE(dh_encctx); - ec_info ei; - const char *e; - dstr t = DSTR_INIT; - - key_fulltag(k, &t); - if ((e = ec_getinfo(&ei, cstr)) != 0 || - (de->g = group_ec(&ei)) == 0) - die(EXIT_FAILURE, "bad elliptic curve spec in key `%s': %s", t.buf, e); - de->x = MP_NEW; - de->y = G_CREATE(de->g); - if (G_FROMEC(de->g, de->y, y)) - die(EXIT_FAILURE, "bad public curve point `%s'", t.buf); - dstr_destroy(&t); - return (de); -} - -static kem *dh_encinit(key *k, void *kd) -{ - dh_pub *dp = kd; - dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_prime, "prime"); - return (&de->k); -} - -static kem *bindh_encinit(key *k, void *kd) -{ - dh_pub *dp = kd; - dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_binary, "binary"); - return (&de->k); -} - -static kem *ec_encinit(key *k, void *kd) -{ - ec_pub *ep = kd; - dh_encctx *de = ec_doinit(k, ep->cstr, &ep->p); - return (&de->k); -} - -static int dh_encdoit(kem *k, dstr *d, ghash *h) -{ - dh_encctx *de = (dh_encctx *)k; - mp *r = mprand_range(MP_NEW, de->g->r, &rand_global, 0); - ge *x = G_CREATE(de->g); - ge *y = G_CREATE(de->g); - size_t n = de->g->noctets; - buf b; - - G_EXP(de->g, x, de->g->g, r); - G_EXP(de->g, y, de->y, r); - dstr_ensure(d, n); - buf_init(&b, d->buf, n); - G_TORAW(de->g, &b, y); - GH_HASH(h, BBASE(&b), BLEN(&b)); - buf_init(&b, d->buf, n); - G_TORAW(de->g, &b, x); - GH_HASH(h, BBASE(&b), BLEN(&b)); - d->len += BLEN(&b); - mp_drop(r); - G_DESTROY(de->g, x); - G_DESTROY(de->g, y); - return (0); -} - -static const char *dh_enccheck(kem *k) -{ - dh_encctx *de = (dh_encctx *)k; - const char *e; - if ((e = G_CHECK(de->g, &rand_global)) != 0) - return (0); - if (group_check(de->g, de->y)) - return ("public key not in subgroup"); - return (0); -} - -static void dh_encdestroy(kem *k) -{ - dh_encctx *de = (dh_encctx *)k; - G_DESTROY(de->g, de->y); - mp_drop(de->x); - G_DESTROYGROUP(de->g); - DESTROY(de); -} - -static const kemops dh_encops = { - dh_pubfetch, sizeof(dh_pub), - dh_encinit, dh_encdoit, dh_enccheck, dh_encdestroy -}; - -static const kemops bindh_encops = { - dh_pubfetch, sizeof(dh_pub), - bindh_encinit, dh_encdoit, dh_enccheck, dh_encdestroy -}; - -static const kemops ec_encops = { - ec_pubfetch, sizeof(ec_pub), - ec_encinit, dh_encdoit, dh_enccheck, dh_encdestroy -}; - -static kem *dh_decinit(key *k, void *kd) -{ - dh_priv *dp = kd; - dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_prime, "prime"); - de->x = MP_COPY(dp->x); - return (&de->k); -} - -static kem *bindh_decinit(key *k, void *kd) -{ - dh_priv *dp = kd; - dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_binary, "binary"); - de->x = MP_COPY(dp->x); - return (&de->k); -} - -static kem *ec_decinit(key *k, void *kd) -{ - ec_priv *ep = kd; - dh_encctx *de = ec_doinit(k, ep->cstr, &ep->p); - de->x = MP_COPY(ep->x); - return (&de->k); -} - -static int dh_decdoit(kem *k, dstr *d, ghash *h) -{ - dh_encctx *de = (dh_encctx *)k; - ge *x = G_CREATE(de->g); - size_t n = de->g->noctets; - void *p = xmalloc(n); - buf b; - int rc = -1; - - buf_init(&b, d->buf, d->len); - if (G_FROMRAW(de->g, &b, x) || group_check(de->g, x)) - goto done; - G_EXP(de->g, x, x, de->x); - buf_init(&b, p, n); - G_TORAW(de->g, &b, x); - GH_HASH(h, BBASE(&b), BLEN(&b)); - GH_HASH(h, d->buf, d->len); - rc = 0; -done: - G_DESTROY(de->g, x); - xfree(p); - return (rc); -} - -static const kemops dh_decops = { - dh_privfetch, sizeof(dh_priv), - dh_decinit, dh_decdoit, dh_enccheck, dh_encdestroy -}; - -static const kemops bindh_decops = { - dh_privfetch, sizeof(dh_priv), - bindh_decinit, dh_decdoit, dh_enccheck, dh_encdestroy -}; - -static const kemops ec_decops = { - ec_privfetch, sizeof(ec_priv), - ec_decinit, dh_decdoit, dh_enccheck, dh_encdestroy -}; - -/* --- Symmetric --- */ - -typedef struct symm_ctx { - kem k; - key_packdef kp; - key_bin kb; -} symm_ctx; - -static kem *symm_init(key *k, void *kd) -{ - symm_ctx *s; - dstr d = DSTR_INIT; - int err; - - s = CREATE(symm_ctx); - - key_fulltag(k, &d); - s->kp.e = KENC_BINARY; - s->kp.p = &s->kb; - s->kp.kd = 0; - - if ((err = key_unpack(&s->kp, kd, &d)) != 0) { - die(EXIT_FAILURE, "failed to unpack symmetric key `%s': %s", - d.buf, key_strerror(err)); - } - dstr_destroy(&d); - return (&s->k); -} - -static int symm_decdoit(kem *k, dstr *d, ghash *h) -{ - symm_ctx *s = (symm_ctx *)k; - - GH_HASH(h, s->kb.k, s->kb.sz); - GH_HASH(h, d->buf, d->len); - return (0); -} - -static int symm_encdoit(kem *k, dstr *d, ghash *h) -{ - dstr_ensure(d, h->ops->c->hashsz); - d->len += h->ops->c->hashsz; - rand_get(RAND_GLOBAL, d->buf, d->len); - return (symm_decdoit(k, d, h)); -} - -static const char *symm_check(kem *k) { return (0); } - -static void symm_destroy(kem *k) - { symm_ctx *s = (symm_ctx *)k; key_unpackdone(&s->kp); } - -static const kemops symm_encops = { - 0, 0, - symm_init, symm_encdoit, symm_check, symm_destroy -}; - -static const kemops symm_decops = { - 0, 0, - symm_init, symm_decdoit, symm_check, symm_destroy -}; - -/* --- The switch table --- */ - -const struct kemtab kemtab[] = { - { "rsa", &rsa_encops, &rsa_decops }, - { "dh", &dh_encops, &dh_decops }, - { "bindh", &bindh_encops, &bindh_decops }, - { "ec", &ec_encops, &ec_decops }, - { "symm", &symm_encops, &symm_decops }, - { 0, 0, 0 } -}; - -/* --- @getkem@ --- * - * - * Arguments: @key *k@ = the key to load - * @const char *app@ = application name - * @int wantpriv@ = nonzero if we want to decrypt - * - * Returns: A key-encapsulating thing. - * - * Use: Loads a key. - */ - -kem *getkem(key *k, const char *app, int wantpriv) -{ - const char *kalg, *halg = 0, *calg = 0; - dstr d = DSTR_INIT; - dstr t = DSTR_INIT; - size_t n; - char *p = 0; - const char *q; - kem *kk; - const struct kemtab *kt; - const kemops *ko; - void *kd; - int e; - key_packdef *kp; - - /* --- Setup stuff --- */ - - key_fulltag(k, &t); - - /* --- Get the KEM name --- * - * - * Take the attribute if it's there; otherwise use the key type. - */ - - n = strlen(app); - if ((q = key_getattr(0, k, "kem")) != 0) { - dstr_puts(&d, q); - p = d.buf; - } else if (strncmp(k->type, app, n) == 0 && k->type[n] == '-') { - dstr_puts(&d, k->type); - p = d.buf + n + 1; - } else - die(EXIT_FAILURE, "no KEM for key `%s'", t.buf); - kalg = p; - - /* --- Grab the encryption scheme --- * - * - * Grab it from the KEM if it's there, but override it from the attribute. - */ - - if (p && (p = strchr(p, '/')) != 0) { - *p++ = 0; - calg = p; - } - if ((q = key_getattr(0, k, "cipher")) != 0) - calg = q; - - /* --- Grab the hash function --- */ - - if (p && (p = strchr(p, '/')) != 0) { - *p++ = 0; - halg = p; - } - if ((q = key_getattr(0, k, "hash")) != 0) - halg = q; - - /* --- Instantiate the KEM --- */ - - for (kt = kemtab; kt->name; kt++) { - if (strcmp(kt->name, kalg) == 0) - goto k_found; - } - die(EXIT_FAILURE, "key encapsulation mechanism `%s' not found in key `%s'", - kalg, t.buf); -k_found:; - ko = wantpriv ? kt->decops : kt->encops; - if (!ko->kf) { - kd = k->k; - key_incref(kd); - kp = 0; - } else { - kd = xmalloc(ko->kdsz); - kp = key_fetchinit(ko->kf, 0, kd); - if ((e = key_fetch(kp, k)) != 0) { - die(EXIT_FAILURE, "error fetching key `%s': %s", - t.buf, key_strerror(e)); - } - } - kk = ko->init(k, kd); - kk->kp = kp; - kk->ops = ko; - kk->kd = kd; - - /* --- Set up the algorithms --- */ - - if (!halg) - kk->h = &rmd160; - else if ((kk->h = ghash_byname(halg)) == 0) { - die(EXIT_FAILURE, "hash algorithm `%s' not found in key `%s'", - halg, t.buf); - } - - if (!calg) - kk->c = &blowfish_cbc; - else if ((kk->c = gcipher_byname(calg)) == 0) { - die(EXIT_FAILURE, "encryption scheme `%s' not found in key `%s'", - calg, t.buf); - } - - dstr_reset(&d); - if ((q = key_getattr(0, k, "kdf")) == 0) { - dstr_putf(&d, "%s-mgf", kk->h->name); - q = d.buf; - } - if ((kk->cx = gcipher_byname(q)) == 0) { - die(EXIT_FAILURE, "encryption scheme (KDF) `%s' not found in key `%s'", - q, t.buf); - } - - dstr_reset(&d); - if ((q = key_getattr(0, k, "mac")) == 0) { - dstr_putf(&d, "%s-hmac", kk->h->name); - q = d.buf; - } - if ((kk->m = gmac_byname(q)) == 0) { - die(EXIT_FAILURE, - "message authentication code `%s' not found in key `%s'", - q, t.buf); - } - - /* --- Tidy up --- */ - - dstr_destroy(&d); - dstr_destroy(&t); - return (kk); -} - -/* --- @setupkem@ --- * - * - * Arguments: @kem *k@ = key-encapsulation thing - * @dstr *d@ = key-encapsulation data - * @gcipher **cx@ = key-expansion function (for IVs) - * @gcipher **c@ = where to put initialized encryption scheme - * @gmac **m@ = where to put initialized MAC - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Initializes all the various symmetric things from a KEM. - */ - -int setupkem(kem *k, dstr *d, gcipher **cx, gcipher **c, gmac **m) -{ - octet *kd; - size_t n, cn, mn; - ghash *h; - int rc = -1; - - h = GH_INIT(k->h); - if (k->ops->doit(k, d, h)) - goto done; - n = keysz(GH_CLASS(h)->hashsz, k->cx->keysz); - if (!n) - goto done; - kd = GH_DONE(h, 0); - *cx = GC_INIT(k->cx, kd, n); - - cn = keysz(0, k->c->keysz); n = cn; - mn = keysz(0, k->m->keysz); if (mn > n) n = mn; - kd = xmalloc(n); - GC_ENCRYPT(*cx, 0, kd, cn); - *c = GC_INIT(k->c, kd, cn); - GC_ENCRYPT(*cx, 0, kd, mn); - *m = GM_KEY(k->m, kd, mn); - xfree(kd); - - rc = 0; -done: - GH_DESTROY(h); - return (rc); -} - -/* --- @freekem@ --- * - * - * Arguments: @kem *k@ = key-encapsulation thing - * - * Returns: --- - * - * Use: Frees up a key-encapsulation thing. - */ - -void freekem(kem *k) -{ - if (!k->ops->kf) - key_drop(k->kd); - else { - key_fetchdone(k->kp); - xfree(k->kd); - } - k->ops->destroy(k); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/cc-list.c b/cc-list.c deleted file mode 100644 index b182ba4..0000000 --- a/cc-list.c +++ /dev/null @@ -1,75 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Emit lists of things in tables - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _FILE_OFFSET_BITS 64 - -#include - -#include "cc.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @displaylists@ --- * - * - * Arguments: @const struct listent *listtab@ = table of lists to show - * @char *const argv[]@ = list of lists to show - * - * Returns: Nonzero if anything failed. - * - * Use: Dumps the named lists, or all of them. - */ - -int displaylists(const struct listent *listtab, char *const argv[]) -{ - const struct listent *li; - int i; - int rc = 0; - - if (!argv || !*argv) { - for (li = listtab; li->name; li++) - li->list(); - } else { - for (i = 0; argv[i]; i++) { - for (li = listtab; li->name; li++) { - if (strcmp(li->name, argv[i]) == 0) { - li->list(); - goto cool; - } - } - moan("unknown list `%s'", argv[i]); - rc = 1; - cool:; - } - } - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/cc-sig.c b/cc-sig.c deleted file mode 100644 index 54b58f3..0000000 --- a/cc-sig.c +++ /dev/null @@ -1,806 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Catcrypt signatures - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _FILE_OFFSET_BITS 64 - -#include - -#include - -#include "rand.h" -#include "sha.h" -#include "has160.h" - -#include "ec.h" -#include "ec-keys.h" -#include "dh.h" -#include "gdsa.h" -#include "gkcdsa.h" -#include "rsa.h" - -#include "cc.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- RSA PKCS1 --- */ - -typedef struct rsap1_sigctx { - sig s; - rsa_privctx rp; - pkcs1 p1; -} rsap1_sigctx; - -static sig *rsap1_siginit(key *k, void *kd, const gchash *hc) -{ - rsap1_sigctx *rs = CREATE(rsap1_sigctx); - rsa_privcreate(&rs->rp, kd, &rand_global); - rs->p1.r = &rand_global; - rs->p1.ep = hc->name; - rs->p1.epsz = strlen(hc->name) + 1; - rs->s.h = 0; - return (&rs->s); -} - -static int rsap1_sigdoit(sig *s, dstr *d) -{ - rsap1_sigctx *rs = (rsap1_sigctx *)s; - size_t n; - mp *m = rsa_sign(&rs->rp, MP_NEW, - GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz, - pkcs1_sigencode, &rs->p1); - if (!m) return (-1); - n = mp_octets(rs->rp.rp->n); dstr_ensure(d, n); mp_storeb(m, d->buf, n); - d->len += n; mp_drop(m); - return (0); -} - -static const char *rsa_lengthcheck(mp *n) -{ - if (mp_bits(n) < 1024) return ("key too short"); - return (0); -} - -static const char *rsap1_sigcheck(sig *s) -{ - rsap1_sigctx *rs = (rsap1_sigctx *)s; - const char *e; - if ((e = rsa_lengthcheck(rs->rp.rp->n)) != 0) return (e); - return (0); -} - -static void rsap1_sigdestroy(sig *s) -{ - rsap1_sigctx *rs = (rsap1_sigctx *)s; - rsa_privdestroy(&rs->rp); - DESTROY(rs); -} - -static const sigops rsap1_sig = { - rsa_privfetch, sizeof(rsa_priv), - rsap1_siginit, rsap1_sigdoit, rsap1_sigcheck, rsap1_sigdestroy -}; - -typedef struct rsap1_vrfctx { - sig s; - rsa_pubctx rp; - pkcs1 p1; -} rsap1_vrfctx; - -static sig *rsap1_vrfinit(key *k, void *kd, const gchash *hc) -{ - rsap1_vrfctx *rv = CREATE(rsap1_vrfctx); - rsa_pubcreate(&rv->rp, kd); - rv->p1.r = &rand_global; - rv->p1.ep = hc->name; - rv->p1.epsz = strlen(hc->name) + 1; - rv->s.h = 0; - return (&rv->s); -} - -static int rsap1_vrfdoit(sig *s, dstr *d) -{ - rsap1_vrfctx *rv = (rsap1_vrfctx *)s; - mp *m = mp_loadb(MP_NEW, d->buf, d->len); - int rc = rsa_verify(&rv->rp, m, - GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz, - 0, pkcs1_sigdecode, &rv->p1); - mp_drop(m); - return (rc); -} - -static const char *rsap1_vrfcheck(sig *s) -{ - rsap1_vrfctx *rv = (rsap1_vrfctx *)s; - const char *e; - if ((e = rsa_lengthcheck(rv->rp.rp->n)) != 0) return (e); - return (0); -} - -static void rsap1_vrfdestroy(sig *s) -{ - rsap1_vrfctx *rv = (rsap1_vrfctx *)s; - rsa_pubdestroy(&rv->rp); - DESTROY(rv); -} - -static const sigops rsap1_vrf = { - rsa_pubfetch, sizeof(rsa_pub), - rsap1_vrfinit, rsap1_vrfdoit, rsap1_vrfcheck, rsap1_vrfdestroy -}; - -/* --- RSA PSS --- */ - -static const gccipher *getmgf(key *k, const gchash *hc) -{ - dstr d = DSTR_INIT; - const gccipher *gc; - const char *mm; - - if ((mm = key_getattr(0, k, "mgf")) == 0) { - dstr_putf(&d, "%s-mgf", hc->name); - mm = d.buf; - } - if ((gc = gcipher_byname(mm)) == 0) - die(EXIT_FAILURE, "unknown encryption scheme `%s'", mm); - dstr_destroy(&d); - return (gc); -} - -typedef struct rsapss_sigctx { - sig s; - rsa_privctx rp; - pss p; -} rsapss_sigctx; - -static sig *rsapss_siginit(key *k, void *kd, const gchash *hc) -{ - rsapss_sigctx *rs = CREATE(rsapss_sigctx); - rsa_privcreate(&rs->rp, kd, &rand_global); - rs->p.r = &rand_global; - rs->p.cc = getmgf(k, hc); - rs->p.ch = hc; - rs->p.ssz = hc->hashsz; - rsa_privdestroy(&rs->rp); - return (&rs->s); -} - -static int rsapss_sigdoit(sig *s, dstr *d) -{ - rsapss_sigctx *rs = (rsapss_sigctx *)s; - size_t n; - mp *m = rsa_sign(&rs->rp, MP_NEW, - GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz, - pss_encode, &rs->p); - if (!m) return (-1); - n = mp_octets(rs->rp.rp->n); dstr_ensure(d, n); mp_storeb(m, d->buf, n); - d->len += n; mp_drop(m); - return (0); -} - -static const char *rsapss_sigcheck(sig *s) -{ - rsapss_sigctx *rs = (rsapss_sigctx *)s; - const char *e; - if ((e = rsa_lengthcheck(rs->rp.rp->n)) != 0) return (e); - return (0); -} - -static void rsapss_sigdestroy(sig *s) -{ - rsapss_sigctx *rs = (rsapss_sigctx *)s; - rsa_privdestroy(&rs->rp); - DESTROY(rs); -} - -static const sigops rsapss_sig = { - rsa_privfetch, sizeof(rsa_priv), - rsapss_siginit, rsapss_sigdoit, rsapss_sigcheck, rsapss_sigdestroy -}; - -typedef struct rsapss_vrfctx { - sig s; - rsa_pubctx rp; - pss p; -} rsapss_vrfctx; - -static sig *rsapss_vrfinit(key *k, void *kd, const gchash *hc) -{ - rsapss_vrfctx *rv = CREATE(rsapss_vrfctx); - rsa_pubcreate(&rv->rp, kd); - rv->p.r = &rand_global; - rv->p.cc = getmgf(k, hc); - rv->p.ch = hc; - rv->p.ssz = hc->hashsz; - return (&rv->s); -} - -static int rsapss_vrfdoit(sig *s, dstr *d) -{ - rsapss_vrfctx *rv = (rsapss_vrfctx *)s; - mp *m = mp_loadb(MP_NEW, d->buf, d->len); - int rc = rsa_verify(&rv->rp, m, - GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz, - 0, pss_decode, &rv->p); - mp_drop(m); - return (rc); -} - -static const char *rsapss_vrfcheck(sig *s) -{ - rsapss_vrfctx *rv = (rsapss_vrfctx *)s; - const char *e; - if ((e = rsa_lengthcheck(rv->rp.rp->n)) != 0) return (e); - return (0); -} - -static void rsapss_vrfdestroy(sig *s) -{ - rsapss_vrfctx *rv = (rsapss_vrfctx *)s; - rsa_pubdestroy(&rv->rp); - DESTROY(rv); -} - -static const sigops rsapss_vrf = { - rsa_pubfetch, sizeof(rsa_pub), - rsapss_vrfinit, rsapss_vrfdoit, rsapss_vrfcheck, rsapss_vrfdestroy -}; - -/* --- DSA and ECDSA --- */ - -typedef struct dsa_sigctx { - sig s; - gdsa g; -} dsa_sigctx; - -static void dsa_initcommon(dsa_sigctx *ds, const gchash *hc, - const char *ktag) -{ - ds->g.r = &rand_global; - ds->g.h = hc; - ds->g.u = MP_NEW; - ds->s.h = 0; -} - -static dsa_sigctx *dsa_doinit(key *k, const gprime_param *gp, - mp *y, const gchash *hc, - group *(*makegroup)(const gprime_param *), - const char *what) -{ - dsa_sigctx *ds = CREATE(dsa_sigctx); - dstr t = DSTR_INIT; - - key_fulltag(k, &t); - if ((ds->g.g = makegroup(gp)) == 0) - die(EXIT_FAILURE, "bad %s group in key `%s'", what, t.buf); - ds->g.p = G_CREATE(ds->g.g); - if (G_FROMINT(ds->g.g, ds->g.p, y)) - die(EXIT_FAILURE, "bad public key in key `%s'", t.buf); - dsa_initcommon(ds, hc, t.buf); - dstr_destroy(&t); - return (ds); -} - -static dsa_sigctx *ecdsa_doinit(key *k, const char *cstr, - ec *y, const gchash *hc) -{ - dsa_sigctx *ds = CREATE(dsa_sigctx); - ec_info ei; - const char *e; - dstr t = DSTR_INIT; - - key_fulltag(k, &t); - if ((e = ec_getinfo(&ei, cstr)) != 0) - die(EXIT_FAILURE, "bad curve in key `%s': %s", t.buf, e); - ds->g.g = group_ec(&ei); - ds->g.p = G_CREATE(ds->g.g); - if (G_FROMEC(ds->g.g, ds->g.p, y)) - die(EXIT_FAILURE, "bad public key in key `%s'", t.buf); - dsa_initcommon(ds, hc, t.buf); - dstr_destroy(&t); - return (ds); -} - -static sig *dsa_siginit(key *k, void *kd, const gchash *hc) -{ - dh_priv *dp = kd; - dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime"); - ds->g.u = MP_COPY(dp->x); - return (&ds->s); -} - -static sig *bindsa_siginit(key *k, void *kd, const gchash *hc) -{ - dh_priv *dp = kd; - dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary"); - ds->g.u = MP_COPY(dp->x); - return (&ds->s); -} - -static sig *ecdsa_siginit(key *k, void *kd, const gchash *hc) -{ - ec_priv *ep = kd; - dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc); - ds->g.u = MP_COPY(ep->x); - return (&ds->s); -} - -static int dsa_sigdoit(sig *s, dstr *d) -{ - dsa_sigctx *ds = (dsa_sigctx *)s; - gdsa_sig ss = GDSA_SIG_INIT; - size_t n = mp_octets(ds->g.g->r); - - gdsa_sign(&ds->g, &ss, GH_DONE(ds->s.h, 0), 0); - dstr_ensure(d, 2 * n); - mp_storeb(ss.r, d->buf, n); - mp_storeb(ss.s, d->buf + n, n); - d->len += 2 * n; - mp_drop(ss.r); mp_drop(ss.s); - return (0); -} - -static const char *dsa_sigcheck(sig *s) -{ - dsa_sigctx *ds = (dsa_sigctx *)s; - const char *e; - if ((e = G_CHECK(ds->g.g, &rand_global)) != 0) - return (0); - if (group_check(ds->g.g, ds->g.p)) - return ("public key not in subgroup"); - return (0); -} - -static void dsa_sigdestroy(sig *s) -{ - dsa_sigctx *ds = (dsa_sigctx *)s; - G_DESTROY(ds->g.g, ds->g.p); - mp_drop(ds->g.u); - G_DESTROYGROUP(ds->g.g); - DESTROY(ds); -} - -static const sigops dsa_sig = { - dh_privfetch, sizeof(dh_priv), - dsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy -}; - -static const sigops bindsa_sig = { - dh_privfetch, sizeof(dh_priv), - bindsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy -}; - -static const sigops ecdsa_sig = { - ec_privfetch, sizeof(ec_priv), - ecdsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy -}; - -static sig *dsa_vrfinit(key *k, void *kd, const gchash *hc) -{ - dh_pub *dp = kd; - dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime"); - return (&ds->s); -} - -static sig *bindsa_vrfinit(key *k, void *kd, const gchash *hc) -{ - dh_pub *dp = kd; - dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary"); - return (&ds->s); -} - -static sig *ecdsa_vrfinit(key *k, void *kd, const gchash *hc) -{ - ec_pub *ep = kd; - dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc); - return (&ds->s); -} - -static int dsa_vrfdoit(sig *s, dstr *d) -{ - dsa_sigctx *ds = (dsa_sigctx *)s; - gdsa_sig ss; - size_t n = d->len/2; - int rc; - - ss.r = mp_loadb(MP_NEW, d->buf, n); - ss.s = mp_loadb(MP_NEW, d->buf + n, d->len - n); - rc = gdsa_verify(&ds->g, &ss, GH_DONE(ds->s.h, 0)); - mp_drop(ss.r); mp_drop(ss.s); - return (rc); -} - -static const sigops dsa_vrf = { - dh_pubfetch, sizeof(dh_pub), - dsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy -}; - -static const sigops bindsa_vrf = { - dh_pubfetch, sizeof(dh_pub), - bindsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy -}; - -static const sigops ecdsa_vrf = { - ec_pubfetch, sizeof(ec_pub), - ecdsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy -}; - -/* --- KCDSA and ECKCDSA --- */ - -static void kcdsa_privkey(dsa_sigctx *ds, mp *x) - { ds->g.u = mp_modinv(MP_NEW, x, ds->g.g->r); } - -static void kcdsa_sethash(dsa_sigctx *ds, const gchash *hc) - { ds->s.h = gkcdsa_beginhash(&ds->g); } - -static sig *kcdsa_siginit(key *k, void *kd, const gchash *hc) -{ - dh_priv *dp = kd; - dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime"); - kcdsa_privkey(ds, dp->x); - kcdsa_sethash(ds, hc); - return (&ds->s); -} - -static sig *binkcdsa_siginit(key *k, void *kd, const gchash *hc) -{ - dh_priv *dp = kd; - dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary"); - kcdsa_privkey(ds, dp->x); - kcdsa_sethash(ds, hc); - return (&ds->s); -} - -static sig *eckcdsa_siginit(key *k, void *kd, const gchash *hc) -{ - ec_priv *ep = kd; - dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc); - kcdsa_privkey(ds, ep->x); - kcdsa_sethash(ds, hc); - return (&ds->s); -} - -static int kcdsa_sigdoit(sig *s, dstr *d) -{ - dsa_sigctx *ds = (dsa_sigctx *)s; - gkcdsa_sig ss = GKCDSA_SIG_INIT; - size_t hsz = ds->g.h->hashsz, n = mp_octets(ds->g.g->r); - - gkcdsa_sign(&ds->g, &ss, GH_DONE(ds->s.h, 0), 0); - dstr_ensure(d, hsz + n); - memcpy(d->buf, ss.r, hsz); - mp_storeb(ss.s, d->buf + hsz, n); - d->len += hsz + n; - xfree(ss.r); mp_drop(ss.s); - return (0); -} - -static const sigops kcdsa_sig = { - dh_privfetch, sizeof(dh_priv), - kcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy -}; - -static const sigops binkcdsa_sig = { - dh_privfetch, sizeof(dh_priv), - binkcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy -}; - -static const sigops eckcdsa_sig = { - ec_privfetch, sizeof(ec_priv), - eckcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy -}; - -static sig *kcdsa_vrfinit(key *k, void *kd, const gchash *hc) -{ - dh_pub *dp = kd; - dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime"); - kcdsa_sethash(ds, hc); - return (&ds->s); -} - -static sig *binkcdsa_vrfinit(key *k, void *kd, const gchash *hc) -{ - dh_pub *dp = kd; - dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary"); - kcdsa_sethash(ds, hc); - return (&ds->s); -} - -static sig *eckcdsa_vrfinit(key *k, void *kd, const gchash *hc) -{ - ec_pub *ep = kd; - dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc); - kcdsa_sethash(ds, hc); - return (&ds->s); -} - -static int kcdsa_vrfdoit(sig *s, dstr *d) -{ - dsa_sigctx *ds = (dsa_sigctx *)s; - gkcdsa_sig ss; - size_t hsz = ds->g.h->hashsz, n = d->len - hsz; - int rc; - - if (d->len < hsz) - return (-1); - ss.r = (octet *)d->buf; - ss.s = mp_loadb(MP_NEW, d->buf + hsz, n); - rc = gkcdsa_verify(&ds->g, &ss, GH_DONE(ds->s.h, 0)); - mp_drop(ss.s); - return (rc); -} - -static const sigops kcdsa_vrf = { - dh_pubfetch, sizeof(dh_pub), - kcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy -}; - -static const sigops binkcdsa_vrf = { - dh_pubfetch, sizeof(dh_pub), - binkcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy -}; - -static const sigops eckcdsa_vrf = { - ec_pubfetch, sizeof(ec_pub), - eckcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy -}; - -/* --- Symmetric message authentication --- */ - -typedef struct mac_ctx { - sig s; - const gcmac *mc; - gmac *m; - key_packdef kp; - key_bin kb; -} mac_ctx; - -static sig *mac_init(key *k, void *kd, const gchash *hc) -{ - mac_ctx *m; - dstr d = DSTR_INIT; - int err; - const char *mm; - - m = CREATE(mac_ctx); - - key_fulltag(k, &d); - m->kp.e = KENC_BINARY; - m->kp.p = &m->kb; - m->kp.kd = 0; - - if ((mm = key_getattr(0 /*yik*/, k, "mac")) == 0) { - dstr_putf(&d, "%s-hmac", hc->name); - mm = d.buf; - } - if ((m->mc = gmac_byname(mm)) == 0) - die(EXIT_FAILURE, "unknown message authentication scheme `%s'", mm); - dstr_reset(&d); - - if ((err = key_unpack(&m->kp, kd, &d)) != 0) { - die(EXIT_FAILURE, "failed to unpack symmetric key `%s': %s", - d.buf, key_strerror(err)); - } - dstr_destroy(&d); - - if (keysz(m->kb.sz, m->mc->keysz) != m->kb.sz) { - die(EXIT_FAILURE, "bad key size %lu for `%s'", - (unsigned long)m->kb.sz, m->mc->name); - } - m->m = GM_KEY(m->mc, m->kb.k, m->kb.sz); - m->s.h = GM_INIT(m->m); - return (&m->s); -} - -static int mac_sigdoit(sig *s, dstr *d) -{ - mac_ctx *m = (mac_ctx *)s; - - dstr_ensure(d, m->mc->hashsz); - GH_DONE(m->s.h, d->buf); - d->len += m->mc->hashsz; - return (0); -} - -static int mac_vrfdoit(sig *s, dstr *d) -{ - mac_ctx *m = (mac_ctx *)s; - const octet *t; - - t = GH_DONE(m->s.h, 0); - if (d->len != m->mc->hashsz || memcmp(d->buf, t, d->len) != 0) - return (-1); - return (0); -} - -static const char *mac_check(sig *s) { return (0); } - -static void mac_destroy(sig *s) -{ - mac_ctx *m = (mac_ctx *)s; - GM_DESTROY(m->m); - key_unpackdone(&m->kp); -} - -static const sigops mac_sig = { - 0, 0, - mac_init, mac_sigdoit, mac_check, mac_destroy -}; - -static const sigops mac_vrf = { - 0, 0, - mac_init, mac_vrfdoit, mac_check, mac_destroy -}; - -/* --- The switch table --- */ - -const struct sigtab sigtab[] = { - { "rsapkcs1", &rsap1_sig, &rsap1_vrf, &sha }, - { "rsapss", &rsapss_sig, &rsapss_vrf, &sha }, - { "dsa", &dsa_sig, &dsa_vrf, &sha }, - { "bindsa", &bindsa_sig, &bindsa_vrf, &sha }, - { "ecdsa", &ecdsa_sig, &ecdsa_vrf, &sha }, - { "kcdsa", &kcdsa_sig, &kcdsa_vrf, &has160 }, - { "binkcdsa", &binkcdsa_sig, &binkcdsa_vrf, &has160 }, - { "eckcdsa", &eckcdsa_sig, &eckcdsa_vrf, &has160 }, - { "mac", &mac_sig, &mac_vrf, &rmd160 }, - { 0, 0, 0 } -}; - -/* --- @getsig@ --- * - * - * Arguments: @key *k@ = the key to load - * @const char *app@ = application name - * @int wantpriv@ = nonzero if we want to sign - * - * Returns: A signature-making thing. - * - * Use: Loads a key and starts hashing. - */ - -sig *getsig(key *k, const char *app, int wantpriv) -{ - const char *salg, *halg = 0; - dstr d = DSTR_INIT; - dstr t = DSTR_INIT; - char *p = 0; - const char *q; - sig *s; - size_t n; - const struct sigtab *st; - const sigops *so; - const gchash *ch; - void *kd; - int e; - key_packdef *kp; - - /* --- Setup stuff --- */ - - key_fulltag(k, &t); - - /* --- Get the signature algorithm --- * - * - * Take the attribute if it's there; otherwise use the key type. - */ - - n = strlen(app); - if ((q = key_getattr(0, k, "sig")) != 0) { - dstr_puts(&d, q); - p = d.buf; - } else if (strncmp(k->type, app, n) == 0 && k->type[n] == '-') { - dstr_puts(&d, k->type); - p = d.buf + n + 1; - } else - die(EXIT_FAILURE, "no signature algorithm for key `%s'", t.buf); - - /* --- Grab the hash algorithm --- * - * - * Grab it from the signature algorithm if it's there. But override that - * from the attribute. - */ - - salg = p; - if ((p = strchr(p, '/')) != 0) { - *p++ = 0; - halg = p; - } - if ((q = key_getattr(0, k, "hash")) != 0) - halg = q; - - /* --- Look up the algorithms in the table --- */ - - for (st = sigtab; st->name; st++) { - if (strcmp(st->name, salg) == 0) - goto s_found; - } - die(EXIT_FAILURE, "signature algorithm `%s' not found in key `%s'", - salg, t.buf); -s_found:; - if (!halg) - ch = st->ch; - else { - if ((ch = ghash_byname(halg)) == 0) { - die(EXIT_FAILURE, "hash algorithm `%s' not found in key `%s'", - halg, t.buf); - } - } - so = wantpriv ? st->signops : st->verifyops; - - /* --- Load the key --- */ - - if (!so->kf) { - kd = k->k; - key_incref(kd); - kp = 0; - } else { - kd = xmalloc(so->kdsz); - kp = key_fetchinit(so->kf, 0, kd); - if ((e = key_fetch(kp, k)) != 0) { - die(EXIT_FAILURE, "error fetching key `%s': %s", - t.buf, key_strerror(e)); - } - } - s = so->init(k, kd, ch); - if (!s->h) - s->h = GH_INIT(ch); - s->kp = kp; - s->ops = so; - s->kd = kd; - s->ch = ch; - - /* --- Free stuff up --- */ - - dstr_destroy(&d); - dstr_destroy(&t); - return (s); -} - -/* --- @freesig@ --- * - * - * Arguments: @sig *s@ = signature-making thing - * - * Returns: --- - * - * Use: Frees up a signature-making thing - */ - -void freesig(sig *s) -{ - GH_DESTROY(s->h); - if (!s->ops->kf) - key_drop(s->kd); - else { - key_fetchdone(s->kp); - xfree(s->kd); - } - s->ops->destroy(s); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/cc-subcmd.c b/cc-subcmd.c deleted file mode 100644 index c8f8b51..0000000 --- a/cc-subcmd.c +++ /dev/null @@ -1,111 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Subcommand infrastructure - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _FILE_OFFSET_BITS 64 - -#include -#include - -#include "cc.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @findcmd@ --- * - * - * Arguments: @const cmd *cmds@ = pointer to command table - * @const char *name@ = a command name - * - * Returns: Pointer to the command structure. - * - * Use: Looks up a command by name. If the command isn't found, an - * error is reported and the program is terminated. - */ - -const cmd *findcmd(const cmd *cmds, const char *name) -{ - const cmd *c, *chosen = 0; - size_t sz = strlen(name); - - for (c = cmds; c->name; c++) { - if (strncmp(name, c->name, sz) == 0) { - if (c->name[sz] == 0) { - chosen = c; - break; - } else if (chosen) - die(EXIT_FAILURE, "ambiguous command name `%s'", name); - else - chosen = c; - } - } - if (!chosen) - die(EXIT_FAILURE, "unknown command name `%s'", name); - return (chosen); -} - -/* --- @sc_help@ --- * - * - * Arguments: @const cmd *cmds@ = pointer to command table - * @FILE *fp@ = output file handle - * @char *const *argv@ = remaining arguments - * - * Returns: --- - * - * Use: Prints a help message, maybe with help about subcommands. - */ - -void sc_help(const cmd *cmds, FILE *fp, char *const *argv) -{ - const cmd *c; - - version(fp); - fputc('\n', fp); - if (!*argv) { - help_global(fp); - fputs("\n\ -The following commands are understood:\n\n", - fp); - for (c = cmds; c->name; c++) - fprintf(fp, "%s\n", c->usage); - } else { - while (*argv) { - c = findcmd(cmds, *argv); - fprintf(fp, "Usage: %s [-OPTIONS] %s\n", QUIS, c->usage); - if (c->help) { - fputc('\n', fp); - pquis(fp, c->help); - } - argv++; - if (*argv) fputc('\n', fp); - } - } -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/cc.h b/cc.h deleted file mode 100644 index f3a03f3..0000000 --- a/cc.h +++ /dev/null @@ -1,659 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Catcrypt common stuff - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_CC_H -#define CATACOMB_CC_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#if _FILE_OFFSET_BITS != 64 -# error "Must set _FILE_OFFSET_BITS to 64." -#endif - -#include -#include -#include - -#include -#include - -#include - -#include "key.h" -#include "gcipher.h" -#include "ghash.h" -#include "gmac.h" - -/*----- Cryptographic object tables ---------------------------------------*/ - -/* --- Key encapsulation --- */ - -typedef struct kem { - const struct kemops *ops; - key_packdef *kp; - void *kd; - const gchash *h; - const gccipher *c, *cx; - const gcmac *m; -} kem; - -typedef struct kemops { - const key_fetchdef *kf; /* Key fetching structure */ - size_t kdsz; /* Size of the key-data structure */ - kem *(*init)(key */*k*/, void */*kd*/); - int (*doit)(kem */*k*/, dstr */*d*/, ghash */*h*/); - const char *(*check)(kem */*k*/); - void (*destroy)(kem */*k*/); -} kemops; - -struct kemtab { - const char *name; - const kemops *encops; - const kemops *decops; -}; - -extern const struct kemtab kemtab[]; - -/* --- @getkem@ --- * - * - * Arguments: @key *k@ = the key to load - * @const char *app@ = application name - * @int wantpriv@ = nonzero if we want to decrypt - * - * Returns: A key-encapsulating thing. - * - * Use: Loads a key. - */ - -extern kem *getkem(key */*k*/, const char */*app*/, int /*wantpriv*/); - -/* --- @setupkem@ --- * - * - * Arguments: @kem *k@ = key-encapsulation thing - * @dstr *d@ = key-encapsulation data - * @gcipher **cx@ = key-expansion function (for IVs) - * @gcipher **c@ = where to put initialized encryption scheme - * @gmac **m@ = where to put initialized MAC - * - * Returns: Zero for success, nonzero on faliure. - * - * Use: Initializes all the various symmetric things from a KEM. - */ - -extern int setupkem(kem */*k*/, dstr */*d*/, - gcipher **/*cx*/, gcipher **/*c*/, gmac **/*m*/); - -/* --- @freekem@ --- * - * - * Arguments: @kem *k@ = key-encapsulation thing - * - * Returns: --- - * - * Use: Frees up a key-encapsulation thing. - */ - -extern void freekem(kem */*k*/); - -/* --- Signing --- */ - -typedef struct sig { - const struct sigops *ops; - key_packdef *kp; - void *kd; - const gchash *ch; - ghash *h; -} sig; - -typedef struct sigops { - const key_fetchdef *kf; /* Key fetching structure */ - size_t kdsz; /* Size of the key-data structure */ - sig *(*init)(key */*k*/, void */*kd*/, const gchash */*hc*/); - int (*doit)(sig */*s*/, dstr */*d*/); - const char *(*check)(sig */*s*/); - void (*destroy)(sig */*s*/); -} sigops; - -struct sigtab { - const char *name; - const sigops *signops; - const sigops *verifyops; - const gchash *ch; -}; - -extern const struct sigtab sigtab[]; - -/* --- @getsig@ --- * - * - * Arguments: @key *k@ = the key to load - * @const char *app@ = application name - * @int wantpriv@ = nonzero if we want to sign - * - * Returns: A signature-making thing. - * - * Use: Loads a key and starts hashing. - */ - -extern sig *getsig(key */*k*/, const char */*app*/, int /*wantpriv*/); - -/* --- @freesig@ --- * - * - * Arguments: @sig *s@ = signature-making thing - * - * Returns: --- - * - * Use: Frees up a signature-making thing - */ - -extern void freesig(sig */*s*/); - -/*----- File encodings ----------------------------------------------------*/ - -/* --- Data encoding --- */ - -typedef struct enc { - const struct encops *ops; - FILE *fp; -} enc; - -typedef struct encops { - const char *name; - const char *rmode, *wmode; - int nraw, ncook; - enc *(*initenc)(FILE */*fp*/, const char */*msg*/); - enc *(*initdec)(FILE */*fp*/, - int (*/*func*/)(const char *, void *), void */*p*/); - int (*read)(enc */*e*/, void */*p*/, size_t /*sz*/); - int (*write)(enc */*e*/, const void */*p*/, size_t /*sz*/); - int (*encdone)(enc */*e*/); - int (*decdone)(enc */*e*/); - void (*destroy)(enc */*e*/); -} encops; - -extern const encops enctab[]; - -/* --- @getenc@ --- * - * - * Arguments: @const char *enc@ = name of wanted encoding - * - * Returns: Pointer to encoder operations. - * - * Use: Finds a named encoder or decoder. - */ - -extern const encops *getenc(const char */*enc*/); - -/* --- @checkbdry@ --- * - * - * Arguments: @const char *b@ = boundary string found - * @void *p@ = boundary string wanted - * - * Returns: Nonzero if the boundary string is the one we wanted. - * - * Use: Pass as @func@ to @initdec@ if you just want a simple life. - */ - -extern int checkbdry(const char */*b*/, void */*p*/); - -/* --- @initenc@ --- * - * - * Arguments: @const encops *eo@ = operations (from @getenc@) - * @FILE *fp@ = file handle to attach - * @const char *msg@ = banner message - * - * Returns: The encoder object. - * - * Use: Initializes an encoder. - */ - -extern enc *initenc(const encops */*eo*/, FILE */*fp*/, const char */*msg*/); - -/* --- @initdec@ --- * - * - * Arguments: @const encops *eo@ = operations (from @getenc@) - * @FILE *fp@ = file handle to attach - * @int (*func)(const char *, void *)@ = banner check function - * @void *p@ = argument for @func@ - * - * Returns: The encoder object. - * - * Use: Initializes an encoder. - */ - -extern enc *initdec(const encops */*eo*/, FILE */*fp*/, - int (*/*func*/)(const char *, void *), void */*p*/); - -/* --- @freeenc@ --- * - * - * Arguments: @enc *e@ = encoder object - * - * Returns: --- - * - * Use: Frees an encoder object. - */ - -extern void freeenc(enc */*e*/); - -/* --- @cmd_encode@, @cmd_decode@ --- */ - -#define CMD_ENCODE { \ - "encode", cmd_encode, \ - "encode [-p] [-f FORMAT] [-b LABEL] [-o OUTPUT] [FILE]", \ - "\ -Options:\n\ -\n\ --f, --format=FORMAT Encode to FORMAT.\n\ --b, --boundary=LABEL PEM boundary is LABEL.\n\ --o, --output=FILE Write output to FILE.\n\ --p, --progress Show progress on large files.\n\ -" } - -#define CMD_DECODE { \ - "decode", cmd_decode, \ - "decode [-p] [-f FORMAT] [-b LABEL] [-o OUTPUT] [FILE]", \ - "\ -Options:\n\ -\n\ --f, --format=FORMAT Decode from FORMAT.\n\ --b, --boundary=LABEL PEM boundary is LABEL.\n\ --o, --output=FILE Write output to FILE.\n\ --p, --progress Show progress on large files.\n\ -" } - -extern int cmd_encode(int /*argc*/, char */*argv*/[]); -extern int cmd_decode(int /*argc*/, char */*argv*/[]); - -/*----- Hash encoding functions -------------------------------------------*/ - -/* --- Table --- */ - -#define ENCODINGS(_) \ - _(HEX, hex) \ - _(BASE64, base64) \ - _(BASE32, base32) - -enum { -#define ENUM(tag, name) ENC_##tag, - ENCODINGS(ENUM) -#undef ENUM - ENC_LIMIT -}; - -typedef struct encodeops { - const char *name; - void (*put)(const octet *, size_t, FILE *); - size_t (*get)(const char *, octet *, size_t, char **); -} encodeops; - -extern const encodeops encodingtab[]; - -/* --- @getencoding@ --- * - * - * Arguments: @const char *ename@ = encoding name - * - * Returns: Pointer to encoding table entry, or null. - * - * Use: Finds an encoding entry given its name. - */ - -extern const encodeops *getencoding(const char */*ename*/); - -/*----- File hashing ------------------------------------------------------*/ - -typedef struct fhashstate { - const gchash *gch; - unsigned f; - struct fhent *ents; -} fhashstate; - -#define FHF_BINARY 0x100u -#define FHF_PROGRESS 0x200u -#define FHF_JUNK 0x400u - -#define FHF_MASK 0xff00u - -/* --- @gethash@ --- * - * - * Arguments: @const char *name@ = pointer to name string - * - * Returns: Pointer to appropriate hash class. - * - * Use: Chooses a hash function by name. - */ - -extern const gchash *gethash(const char */*name*/); - -/* --- @describefile@ --- * - * - * Arguments: @const struct stat *st@ = pointer to file state - * - * Returns: A snappy one-word description of the file. - */ - -extern const char *describefile(const struct stat */*st*/); - -/* --- @fhash_init@ ---* - * - * Arguments: @fhashstate *fh@ = pointer to fhash state to initialize - * @const gchash *gch@ = hash class to set - * @unsigned f@ initial flags to set - * - * Returns: --- - * - * Use: Initializes an @fhashstate@ structure. - */ - -extern void fhash_init(fhashstate */*fh*/, - const gchash */*gch*/, unsigned /*f*/); - -/* --- @fhash_free@ --- * - * - * Arguments: @fhashstate *fh@ = pointer to fhash state to free - * - * Returns: --- - * - * Use: Frees an fhash state. - */ - -extern void fhash_free(fhashstate */*fh*/); - -/* --- @fhash@ --- * - * - * Arguments: @fhashstate *fh@ = pointer to fhash state - * @const char *file@ = file name to be hashed (null for stdin) - * @void *buf@ = pointer to hash output buffer - * - * Returns: Zero if it worked, nonzero on error. - * - * Use: Hashes a file. - */ - -extern int fhash(fhashstate */*fh*/, const char */*file*/, void */*buf*/); - -/* --- @fhash_junk@ --- * - * - * Arguments: @fhashstate *fh@ = pointer to fhash state - * @void (*func)(const char *, const struct stat *, void *)@ - * @void *p@ = pointer to pass to function - * - * Returns: Positive if any junk was found, negative on error, zero if - * everything was fine. - * - * Use: Reports junk files in any directories covered by the hash - * state. - */ - -extern int fhash_junk(fhashstate */*fh*/, - int (*/*func*/)(const char *, - const struct stat *, - void *), - void */*p*/); - -/* --- @hfparse@ --- * - * - * Arguments: @hfpctx *hfp@ = pointer to the context structure - * - * Returns: A code indicating what happened. - * - * Use: Parses a line from the input file. - */ - -enum { /* Meaning and members set */ - HF_FILE, /* File hash: @dline@ and @hbuf@ */ - HF_ENC, /* Encoding: @ee@ */ - HF_HASH, /* Hash function: @gch@ */ - HF_ESC, /* Name escape: @f@ */ - HF_EOF, /* End of file */ - HF_BAD /* Unrecognized line */ -}; - -typedef struct hfpctx { - unsigned f; /* Flags to read */ -#define HFF_ESCAPE 1u /* File names are escaped */ - FILE *fp; /* Input file to read */ - dstr *dline; /* Line contents, corrupted */ - const gchash *gch; /* Hash function to use */ - const encodeops *ee; /* Encoding to apply to hashes */ - dstr *dfile; /* File name for @HF_FILE@ lines */ - octet *hbuf; /* Output buffer for hash data */ -} hfpctx; - -extern int hfparse(hfpctx */*hfp*/); - -/*----- String I/O --------------------------------------------------------*/ - -#define GSF_RAW 4096u -#define GSF_FILE 0u -#define GSF_STRING 8192u - -#define GSF_MASK 61440u - -/* --- @getstring@ --- * - * - * Arguments: @void *in@ = input source - * @dstr *d@ = destination string - * @unsigned f@ = input flags - * - * Returns: Zero if OK, nonzero on end-of-file. - * - * Use: Reads a filename (or something similar) from a stream. - */ - -extern int getstring(void */*in*/, dstr */*d*/, unsigned /*f*/); - -/* --- @putstring@ --- * - * - * Arguments: @FILE *fp@ = stream to write on - * @const char *p@ = pointer to text - * @unsigned f@ = output flags - * - * Returns: --- - * - * Use: Emits a string to a stream. - */ - -extern void putstring(FILE */*fp*/, const char */*p*/, unsigned /*f*/); - -/*----- Lists of things ---------------------------------------------------*/ - -/* --- @LIST(STRING, FP, END-TEST, NAME-EXPR)@ --- * - * - * Produce list of things. Requires @i@ and @w@ variables in scope. - * END-TEST and NAME-EXPR are in terms of @i@. - */ - -#define LIST(what, fp, end, name) do { \ - fputs(what ":\n ", fp); \ - w = 2; \ - for (i = 0; end; i++) { \ - if (w == 2) \ - w += strlen(name); \ - else { \ - if (strlen(name) + w > 76) { \ - fputs("\n ", fp); \ - w = 2 + strlen(name); \ - } else { \ - fputc(' ', fp); \ - w += strlen(name) + 1; \ - } \ - } \ - fputs(name, fp); \ - } \ - fputc('\n', fp); \ -} while (0) - -#define STDLISTS(LI) \ - LI("Hash functions", hash, \ - ghashtab[i], ghashtab[i]->name) \ - LI("Encryption schemes", enc, \ - gciphertab[i], gciphertab[i]->name) \ - LI("Message authentication schemes", mac, \ - gmactab[i], gmactab[i]->name) \ - LI("Elliptic curves", ec, \ - ectab[i].name, ectab[i].name) \ - LI("Diffie-Hellman groups", dh, \ - ptab[i].name, ptab[i].name) - -#define LIDECL(text, tag, test, name) \ - static void show_##tag(void); - -#define LIDEF(text, tag, test, name) \ - static void show_##tag(void) \ - { \ - unsigned i, w; \ - LIST(text, stdout, test, name); \ - } - -#define LIENT(text, tag, test, name) \ - { #tag, show_##tag }, - -struct listent { - const char *name; - void (*list)(void); -}; - -#define MAKELISTTAB(listtab, LISTS) \ - LISTS(LIDECL) \ - static const struct listent listtab[] = { \ - LISTS(LIENT) \ - { 0, 0 } \ - }; \ - LISTS(LIDEF) - -extern int displaylists(const struct listent */*listtab*/, - char *const /*argv*/[]); - -/*----- Progress indicators -----------------------------------------------*/ - -typedef struct fprogress { - const char *bp; - off_t o, sz, olast; - time_t start, last; - char name[24]; -} fprogress; - -/* --- @fprogress_init@ --- * - * - * Arguments: @fprogress *f@ = progress context to be initialized - * @const char *name@ = file name string to show - * @FILE *fp@ = file we're reading from - * - * Returns: Zero on success, nonzero if the file's state is now broken. - * - * Use: Initializes a progress context. Nothing is actually - * displayed yet. - */ - -extern int fprogress_init(fprogress */*f*/, - const char */*name*/, FILE */*fp*/); - -/* --- @fprogress_update@ --- * - * - * Arguments: @fprogress *f@ = progress context - * @size_t n@ = how much progress has been made - * - * Returns: --- - * - * Use: Maybe updates the display to show that some progress has been - * made. - */ - -extern void fprogress_update(fprogress */*f*/, size_t /*n*/); - -/* --- @fprogress_clear@ --- * - * - * Arguments: @fprogress *f@ = progress context - * - * Returns: --- - * - * Use: Clears the progress display from the screen. - */ - -extern void fprogress_clear(fprogress */*f*/); - -/* --- @fprogress_done@ --- * - * - * Arguments: @fprogress *f@ = progress context - * - * Returns: --- - * - * Use: Clear up the progress context and removes any display. - */ - -extern void fprogress_done(fprogress */*f*/); - -/*----- Subcommand dispatch -----------------------------------------------*/ - -typedef struct cmd { - const char *name; - int (*cmd)(int /*argc*/, char */*argv*/[]); - const char *usage; - const char *help; -} cmd; - -extern void version(FILE */*fp*/); -extern void help_global(FILE */*fp*/); - -/* --- @findcmd@ --- * - * - * Arguments: @const cmd *cmds@ = pointer to command table - * @const char *name@ = a command name - * - * Returns: Pointer to the command structure. - * - * Use: Looks up a command by name. If the command isn't found, an - * error is reported and the program is terminated. - */ - -const cmd *findcmd(const cmd */*cmds*/, const char */*name*/); - -/* --- @sc_help@ --- * - * - * Arguments: @const cmd *cmds@ = pointer to command table - * @FILE *fp@ = output file handle - * @char *const *argv@ = remaining arguments - * - * Returns: --- - * - * Use: Prints a help message, maybe with help about subcommands. - */ - -extern void sc_help(const cmd */*cmds*/, FILE */*fp*/, - char *const */*argv*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/cfb-def.h b/cfb-def.h deleted file mode 100644 index 357bb95..0000000 --- a/cfb-def.h +++ /dev/null @@ -1,508 +0,0 @@ -/* -*-c-*- - * - * $Id: cfb-def.h,v 1.6 2004/04/17 09:58:37 mdw Exp $ - * - * Definitions for ciphertext feedback mode - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_CFB_DEF_H -#define CATACOMB_CFB_DEF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include -#include - -#ifndef CATACOMB_ARENA_H -# include "arena.h" -#endif - -#ifndef CATACOMB_BLKC_H -# include "blkc.h" -#endif - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -#ifndef CATACOMB_PARANOIA_H -# include "paranoia.h" -#endif - -#ifndef CATACOMB_PARANOIA_H -# include "paranoia.h" -#endif - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @CFB_DEF@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher - * - * Use: Creates an implementation for CFB mode. - */ - -#define CFB_DEF(PRE, pre) \ - \ -/* --- @pre_cfbgetiv@ --- * \ - * \ - * Arguments: @const pre_cfbctx *ctx@ = pointer to CFB context block \ - * @void *iv@ = pointer to output data block \ - * \ - * Returns: --- \ - * \ - * Use: Reads the currently set IV. Reading and setting an IV \ - * is not transparent to the cipher. It will add a `step' \ - * which must be matched by a similar operation during \ - * decryption. \ - */ \ - \ -void pre##_cfbgetiv(const pre##_cfbctx *ctx, void *iv) \ -{ \ - octet *p = iv; \ - unsigned off = ctx->off; \ - unsigned rest = PRE##_BLKSZ - off; \ - memcpy(p, ctx->iv + off, rest); \ - memcpy(p + rest, ctx->iv, off); \ -} \ - \ -/* --- @pre_cfbsetiv@ --- * \ - * \ - * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ - * @cnost void *iv@ = pointer to IV to set \ - * \ - * Returns: --- \ - * \ - * Use: Sets the IV to use for subsequent encryption. \ - */ \ - \ -void pre##_cfbsetiv(pre##_cfbctx *ctx, const void *iv) \ -{ \ - memcpy(ctx->iv, iv, PRE##_BLKSZ); \ - ctx->off = PRE##_BLKSZ; \ -} \ - \ -/* --- @pre_cfbbdry@ --- * \ - * \ - * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ - * \ - * Returns: --- \ - * \ - * Use: Inserts a boundary during encryption. Successful \ - * decryption must place a similar boundary. \ - */ \ - \ -void pre##_cfbbdry(pre##_cfbctx *ctx) \ -{ \ - uint32 niv[PRE##_BLKSZ / 4]; \ - BLKC_LOAD(PRE, niv, ctx->iv); \ - pre##_eblk(&ctx->ctx, niv, niv); \ - BLKC_STORE(PRE, ctx->iv, niv); \ - ctx->off = PRE##_BLKSZ; \ - BURN(niv); \ -} \ - \ -/* --- @pre_cfbsetkey@ --- * \ - * \ - * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ - * @const pre_ctx *k@ = pointer to cipher context \ - * \ - * Returns: --- \ - * \ - * Use: Sets the CFB context to use a different cipher key. \ - */ \ - \ -void pre##_cfbsetkey(pre##_cfbctx *ctx, const pre##_ctx *k) \ -{ \ - ctx->ctx = *k; \ - ctx->off = PRE##_BLKSZ; \ -} \ - \ -/* --- @pre_cfbinit@ --- * \ - * \ - * Arguments: @pre_cfbctx *ctx@ = pointer to cipher context \ - * @const void *key@ = pointer to the key buffer \ - * @size_t sz@ = size of the key \ - * @const void *iv@ = pointer to initialization vector \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a CFB context ready for use. You should \ - * ensure that the IV chosen is unique: reusing an IV will \ - * compromise the security of at least the first block \ - * encrypted. This is equivalent to calls to @pre_init@, \ - * @pre_cfbsetkey@ and @pre_cfbsetiv@. \ - */ \ - \ -void pre##_cfbinit(pre##_cfbctx *ctx, \ - const void *key, size_t sz, \ - const void *iv) \ -{ \ - static const octet zero[PRE##_BLKSZ] = { 0 }; \ - pre##_init(&ctx->ctx, key, sz); \ - pre##_cfbsetiv(ctx, iv ? iv : zero); \ -} \ - \ -/* --- @pre_cfbencrypt@ --- * \ - * \ - * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Encrypts a block with a block cipher in CFB mode. The \ - * input block may be arbitrary in size. CFB mode is not \ - * sensitive to block boundaries. \ - */ \ - \ -void pre##_cfbencrypt(pre##_cfbctx *ctx, \ - const void *src, void *dest, \ - size_t sz) \ -{ \ - const octet *s = src; \ - octet *d = dest; \ - unsigned off = ctx->off; \ - \ - /* --- Empty blocks are trivial --- */ \ - \ - if (!sz) \ - return; \ - \ - /* --- If I can deal with the block from my buffer, do that --- */ \ - \ - if (sz < PRE##_BLKSZ - off) \ - goto small; \ - \ - /* --- Finish off what's left in my buffer --- */ \ - \ - while (off < PRE##_BLKSZ) { \ - register octet x = *s++; \ - ctx->iv[off] ^= x; \ - if (d) *d++ = ctx->iv[off]; \ - off++; \ - sz--; \ - } \ - \ - /* --- Main encryption loop --- */ \ - \ - { \ - uint32 iv[PRE##_BLKSZ / 4]; \ - BLKC_LOAD(PRE, iv, ctx->iv); \ - \ - for (;;) { \ - pre##_eblk(&ctx->ctx, iv, iv); \ - if (sz < PRE##_BLKSZ) \ - break; \ - if (s) { \ - BLKC_XLOAD(PRE, iv, s); \ - s += PRE##_BLKSZ; \ - } \ - if (d) { \ - BLKC_STORE(PRE, d, iv); \ - d += PRE##_BLKSZ; \ - } \ - sz -= PRE##_BLKSZ; \ - } \ - off = 0; \ - BLKC_STORE(PRE, ctx->iv, iv); \ - } \ - \ - /* --- Tidying up the tail end --- */ \ - \ - if (sz) { \ - small: \ - do { \ - register octet x = *s++; \ - ctx->iv[off] ^= x; \ - if (d) *d++ = ctx->iv[off]; \ - off++; \ - sz--; \ - } while (sz); \ - } \ - \ - /* --- Done --- */ \ - \ - ctx->off = off; \ - return; \ -} \ - \ -/* --- @pre_cfbdecrypt@ --- * \ - * \ - * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Decrypts a block with a block cipher in CFB mode. The \ - * input block may be arbitrary in size. CFB mode is not \ - * sensitive to block boundaries. \ - */ \ - \ -void pre##_cfbdecrypt(pre##_cfbctx *ctx, \ - const void *src, void *dest, \ - size_t sz) \ -{ \ - const octet *s = src; \ - octet *d = dest; \ - unsigned off = ctx->off; \ - \ - /* --- Empty blocks are trivial --- */ \ - \ - if (!sz) \ - return; \ - \ - /* --- If I can deal with the block from my buffer, do that --- */ \ - \ - if (sz < PRE##_BLKSZ - off) \ - goto small; \ - \ - /* --- Finish off what's left in my buffer --- */ \ - \ - while (off < PRE##_BLKSZ) { \ - register octet x = *s++; \ - *d++ = ctx->iv[off] ^ x; \ - ctx->iv[off++] = x; \ - sz--; \ - } \ - \ - /* --- Main encryption loop --- */ \ - \ - { \ - uint32 iv[PRE##_BLKSZ / 4]; \ - BLKC_LOAD(PRE, iv, ctx->iv); \ - \ - for (;;) { \ - uint32 x[PRE##_BLKSZ / 4]; \ - pre##_eblk(&ctx->ctx, iv, iv); \ - if (sz < PRE##_BLKSZ) \ - break; \ - BLKC_LOAD(PRE, x, s); \ - BLKC_XSTORE(PRE, d, iv, x); \ - BLKC_MOVE(PRE, iv, x); \ - s += PRE##_BLKSZ; \ - d += PRE##_BLKSZ; \ - sz -= PRE##_BLKSZ; \ - } \ - off = 0; \ - BLKC_STORE(PRE, ctx->iv, iv); \ - } \ - \ - /* --- Tidying up the tail end --- */ \ - \ - if (sz) { \ - small: \ - do { \ - register octet x = *s++; \ - *d++ = ctx->iv[off] ^ x; \ - ctx->iv[off++] = x; \ - sz--; \ - } while (sz); \ - } \ - \ - /* --- Done --- */ \ - \ - ctx->off = off; \ - return; \ -} \ - \ -/* --- Generic cipher interface --- */ \ - \ -static const gcipher_ops gops; \ - \ -typedef struct gctx { \ - gcipher c; \ - pre##_cfbctx k; \ -} gctx; \ - \ -static gcipher *ginit(const void *k, size_t sz) \ -{ \ - gctx *g = S_CREATE(gctx); \ - g->c.ops = &gops; \ - pre##_cfbinit(&g->k, k, sz, 0); \ - return (&g->c); \ -} \ - \ -static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_cfbencrypt(&g->k, s, t, sz); \ -} \ - \ -static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_cfbdecrypt(&g->k, s, t, sz); \ -} \ - \ -static void gdestroy(gcipher *c) \ -{ \ - gctx *g = (gctx *)c; \ - BURN(*g); \ - S_DESTROY(g); \ -} \ - \ -static void gsetiv(gcipher *c, const void *iv) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_cfbsetiv(&g->k, iv); \ -} \ - \ -static void gbdry(gcipher *c) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_cfbbdry(&g->k); \ -} \ - \ -static const gcipher_ops gops = { \ - &pre##_cfb, \ - gencrypt, gdecrypt, gdestroy, gsetiv, gbdry \ -}; \ - \ -const gccipher pre##_cfb = { \ - #pre "-cfb", pre##_keysz, PRE##_BLKSZ, \ - ginit \ -}; \ - \ -CFB_TEST(PRE, pre) - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#include "daftstory.h" - -/* --- @CFB_TEST@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions - * - * Use: Standard test rig for CFB functions. - */ - -#define CFB_TEST(PRE, pre) \ - \ -/* --- Initial plaintext for the test --- */ \ - \ -static const octet text[] = TEXT; \ - \ -/* --- Key and IV to use --- */ \ - \ -static const octet key[] = KEY; \ -static const octet iv[] = IV; \ - \ -/* --- Buffers for encryption and decryption output --- */ \ - \ -static octet ct[sizeof(text)]; \ -static octet pt[sizeof(text)]; \ - \ -static void hexdump(const octet *p, size_t sz) \ -{ \ - const octet *q = p + sz; \ - for (sz = 0; p < q; p++, sz++) { \ - printf("%02x", *p); \ - if ((sz + 1) % PRE##_BLKSZ == 0) \ - putchar(':'); \ - } \ -} \ - \ -int main(void) \ -{ \ - size_t sz = 0, rest; \ - pre##_cfbctx ctx; \ - int status = 0; \ - int done = 0; \ - pre##_ctx k; \ - \ - size_t keysz = PRE##_KEYSZ ? \ - PRE##_KEYSZ : strlen((const char *)key); \ - \ - fputs(#pre "-cfb: ", stdout); \ - \ - pre##_init(&k, key, keysz); \ - pre##_cfbsetkey(&ctx, &k); \ - \ - while (sz <= sizeof(text)) { \ - rest = sizeof(text) - sz; \ - memcpy(ct, text, sizeof(text)); \ - pre##_cfbsetiv(&ctx, iv); \ - pre##_cfbencrypt(&ctx, ct, ct, sz); \ - pre##_cfbencrypt(&ctx, ct + sz, ct + sz, rest); \ - memcpy(pt, ct, sizeof(text)); \ - pre##_cfbsetiv(&ctx, iv); \ - pre##_cfbdecrypt(&ctx, pt, pt, rest); \ - pre##_cfbdecrypt(&ctx, pt + rest, pt + rest, sz); \ - if (memcmp(pt, text, sizeof(text)) == 0) { \ - done++; \ - if (sizeof(text) < 40 || done % 8 == 0) \ - fputc('.', stdout); \ - if (done % 480 == 0) \ - fputs("\n\t", stdout); \ - fflush(stdout); \ - } else { \ - printf("\nError (sz = %lu)\n", (unsigned long)sz); \ - status = 1; \ - printf("\tplaintext = "); hexdump(text, sz); \ - printf(", "); hexdump(text + sz, rest); \ - fputc('\n', stdout); \ - printf("\tciphertext = "); hexdump(ct, sz); \ - printf(", "); hexdump(ct + sz, rest); \ - fputc('\n', stdout); \ - printf("\trecovered text = "); hexdump(pt, sz); \ - printf(", "); hexdump(pt + sz, rest); \ - fputc('\n', stdout); \ - fputc('\n', stdout); \ - } \ - if (sz < 63) \ - sz++; \ - else \ - sz += 9; \ - } \ - \ - fputs(status ? " failed\n" : " ok\n", stdout); \ - return (status); \ -} - -#else -# define CFB_TEST(PRE, pre) -#endif - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/cfb.h b/cfb.h deleted file mode 100644 index e2082a1..0000000 --- a/cfb.h +++ /dev/null @@ -1,186 +0,0 @@ -/* -*-c-*- - * - * $Id: cfb.h,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Ciphertext feedback for block ciphers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_CFB_H -#define CATACOMB_CFB_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- @CFB_DECL@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher - * - * Use: Creates declarations for CFB mode. - */ - -#define CFB_DECL(PRE, pre) \ - \ -/* --- Ciphertext feedback context --- */ \ - \ -typedef struct pre##_cfbctx { \ - pre##_ctx ctx; /* Underlying cipher context */ \ - unsigned off; /* Offset into @iv@ buffer */ \ - octet iv[PRE##_BLKSZ]; /* Previous ciphertext or IV */ \ -} pre##_cfbctx; \ - \ -/* --- @pre_cfbgetiv@ --- * \ - * \ - * Arguments: @const pre_cfbctx *ctx@ = pointer to CFB context block \ - * @void *iv@ = pointer to output data block \ - * \ - * Returns: --- \ - * \ - * Use: Reads the currently set IV. Reading and setting an IV \ - * is not transparent to the cipher. It will add a `step' \ - * which must be matched by a similar operation during \ - * decryption. \ - */ \ - \ -extern void pre##_cfbgetiv(const pre##_cfbctx */*ctx*/, \ - void */*iv*/); \ - \ -/* --- @pre_cfbsetiv@ --- * \ - * \ - * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ - * @cnost void *iv@ = pointer to IV to set \ - * \ - * Returns: --- \ - * \ - * Use: Sets the IV to use for subsequent encryption. \ - */ \ - \ -extern void pre##_cfbsetiv(pre##_cfbctx */*ctx*/, \ - const void */*iv*/); \ - \ -/* --- @pre_cfbbdry@ --- * \ - * \ - * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ - * \ - * Returns: --- \ - * \ - * Use: Inserts a boundary during encryption. Successful \ - * decryption must place a similar boundary. \ - */ \ - \ -extern void pre##_cfbbdry(pre##_cfbctx */*ctx*/); \ - \ -/* --- @pre_cfbsetkey@ --- * \ - * \ - * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ - * @const pre_ctx *k@ = pointer to cipher context \ - * \ - * Returns: --- \ - * \ - * Use: Sets the CFB context to use a different cipher key. \ - */ \ - \ -extern void pre##_cfbsetkey(pre##_cfbctx */*ctx*/, \ - const pre##_ctx */*k*/); \ - \ -/* --- @pre_cfbinit@ --- * \ - * \ - * Arguments: @pre_cfbctx *ctx@ = pointer to cipher context \ - * @const void *key@ = pointer to the key buffer \ - * @size_t sz@ = size of the key \ - * @const void *iv@ = pointer to initialization vector \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a CFB context ready for use. You should \ - * ensure that the IV chosen is unique: reusing an IV will \ - * compromise the security of at least the first block \ - * encrypted. This is equivalent to calls to @pre_init@, \ - * @pre_cfbsetkey@ and @pre_cfbsetiv@. \ - */ \ - \ -extern void pre##_cfbinit(pre##_cfbctx */*ctx*/, \ - const void */*key*/, size_t /*sz*/, \ - const void */*iv*/); \ - \ -/* --- @pre_cfbencrypt@ --- * \ - * \ - * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Encrypts a block with a block cipher in CFB mode. The \ - * input block may be arbitrary in size. CFB mode is not \ - * sensitive to block boundaries. \ - */ \ - \ -extern void pre##_cfbencrypt(pre##_cfbctx */*ctx*/, \ - const void */*src*/, void */*dest*/, \ - size_t /*sz*/); \ - \ -/* --- @pre_cfbencrypt@ --- * \ - * \ - * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Decrypts a block with a block cipher in CFB mode. The \ - * input block may be arbitrary in size. CFB mode is not \ - * sensitive to block boundaries. \ - */ \ - \ -extern void pre##_cfbdecrypt(pre##_cfbctx */*ctx*/, \ - const void */*src*/, void */*dest*/, \ - size_t /*sz*/); \ - \ -/* --- Generic cipher interface --- */ \ - \ -extern const gccipher pre##_cfb; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/configure.ac b/configure.ac index 9aff84a..aca24fe 100644 --- a/configure.ac +++ b/configure.ac @@ -46,6 +46,9 @@ AC_SUBST(AM_CFLAGS) dnl-------------------------------------------------------------------------- dnl C programming environment. +dnl Find out if we're cross-compiling. +AM_CONDITIONAL([CROSS_COMPILING], [test "$cross_compiling" = yes]) + dnl Various standard types. AC_CHECK_TYPE([pid_t], [int]) AC_TYPE_UID_T @@ -119,7 +122,15 @@ dnl Produce output. AC_CONFIG_HEADER([config/config.h]) AC_CONFIG_FILES( - [Makefile]) + [Makefile] + [base/Makefile] + [key/Makefile] + [math/Makefile] + [misc/Makefile] + [pub/Makefile] + [rand/Makefile] + [symm/Makefile] + [progs/Makefile]) AC_OUTPUT dnl----- That's all, folks -------------------------------------------------- diff --git a/cookie.c b/cookie.c deleted file mode 100644 index 8fa07da..0000000 --- a/cookie.c +++ /dev/null @@ -1,694 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Generate and validate cryptographic cookies - * - * (c) 1999 Mark Wooding - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb 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 2 of the License, or - * (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Catacomb; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _FILE_OFFSET_BITS 64 - -#include "config.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "cc.h" -#include "key.h" -#include "gmac.h" -#include "getdate.h" - -/*----- Handy global state ------------------------------------------------*/ - -static const char *keyfile = "keyring"; - -/*----- Cookie format -----------------------------------------------------*/ - -/* --- Cookie header structure (unpacked) --- */ - -typedef struct cookie { - uint32 k; - time_t exp; -} cookie; - -/* --- Size of a cookie header (packed) --- */ - -#define COOKIE_SZ (4 + 8) - -/* --- @COOKIE_PACK@ --- * - * - * Arguments: @p@ = pointer to destination buffer - * @c@ = pointer to source cookie header block - * - * Use: Packs a cookie header into an octet buffer in a machine- - * independent way. - */ - -#define COOKIE_PACK(p, c) do { \ - octet *_p = (octet *)(p); \ - const cookie *_c = (c); \ - STORE32(_p + 0, _c->k); \ - STORE32(_p + 4, ((_c->exp & ~MASK32) >> 16) >> 16); \ - STORE32(_p + 8, _c->exp); \ -} while (0) - -/* --- @COOKIE_UNPACK@ --- * - * - * Arguments: @c@ = pointer to destination cookie header - * @p@ = pointer to source buffer - * - * Use: Unpacks a cookie header from an octet buffer into a - * machine-specific but comprehensible structure. - */ - -#define COOKIE_UNPACK(c, p) do { \ - cookie *_c = (c); \ - const octet *_p = (const octet *)(p); \ - _c->k = LOAD32(_p + 0); \ - _c->exp = ((time_t)(((LOAD32(_p + 4) << 16) << 16) & ~MASK32) | \ - (time_t)LOAD32(_p + 8)); \ -} while (0) - -/*----- Useful shared functions -------------------------------------------*/ - -/* --- @doopen@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * @unsigned how@ = method to open file with - * - * Returns: --- - * - * Use: Opens a key file and handles errors by panicking - * appropriately. - */ - -static void doopen(key_file *f, unsigned how) -{ - if (key_open(f, keyfile, how, key_moan, 0)) { - die(EXIT_FAILURE, "couldn't open file `%s': %s", - keyfile, strerror(errno)); - } -} - -/* --- @doclose@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * - * Returns: --- - * - * Use: Closes a key file and handles errors by panicking - * appropriately. - */ - -static void doclose(key_file *f) -{ - switch (key_close(f)) { - case KWRITE_FAIL: - die(EXIT_FAILURE, "couldn't write file `%s': %s", - keyfile, strerror(errno)); - case KWRITE_BROKEN: - die(EXIT_FAILURE, "keyring file `%s' broken: %s (repair manually)", - keyfile, strerror(errno)); - } -} - -/* --- @getmac@ --- * - * - * Arguments: @key *k@ = key to use - * @const char *app@ = application name - * - * Returns: The MAC to use. - * - * Use: Finds the right MAC for the given key. - */ - -static gmac *getmac(key *k, const char *app) -{ - dstr t = DSTR_INIT; - dstr d = DSTR_INIT; - char *p = 0; - const char *q; - size_t n; - key_bin kb; - key_packdef kp; - const gcmac *cm; - int e; - gmac *m; - - /* --- Set up --- */ - - key_fulltag(k, &t); - - /* --- Pick out the right MAC --- */ - - n = strlen(app); - if ((q = key_getattr(0, k, "mac")) != 0) { - dstr_puts(&d, q); - p = d.buf; - } else if (strncmp(k->type, app, n) == 0 && k->type[n] == '-') { - dstr_puts(&d, k->type); - p = d.buf + n + 1; - } else - die(EXIT_FAILURE, "no MAC algorithm for key `%s'", t.buf); - if ((cm = gmac_byname(p)) == 0) { - die(EXIT_FAILURE, "MAC algorithm `%s' not found in key `%s'", - p, t.buf); - } - - /* --- Unlock the key --- */ - - kp.e = KENC_BINARY; - kp.p = &kb; - if ((e = key_unpack(&kp, k->k, &t)) != 0) { - die(EXIT_FAILURE, "error unpacking key `%s': %s", - t.buf, key_strerror(e)); - } - - /* --- Make the MAC object --- */ - - if (keysz(kb.sz, cm->keysz) != kb.sz) - die(EXIT_FAILURE, "key %s has bad length (%lu) for MAC %s", - t.buf, (unsigned long)kb.sz, cm->name); - m = cm->key(kb.k, kb.sz); - key_unpackdone(&kp); - return (m); -} - -/*----- Command implementation --------------------------------------------*/ - -/* --- @cmd_gen@ --- */ - -static int cmd_gen(int argc, char *argv[]) -{ - key_file f; - key *k; - gmac *m; - ghash *h; - const char *tag = "cookie"; - int err; - cookie c = { 0, KEXP_EXPIRE }; - unsigned fl = 0; - int bits = 32; - const octet *t; - dstr d = DSTR_INIT; - octet buf[COOKIE_SZ]; - base64_ctx b; - - /* --- Various useful flag bits --- */ - -#define f_bogus 1u - - /* --- Parse options for the subcommand --- */ - - for (;;) { - static struct option opt[] = { - { "bits", OPTF_ARGREQ, 0, 'b' }, - { "expire", OPTF_ARGREQ, 0, 'e' }, - { "key", OPTF_ARGREQ, 0, 'k' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+b:e:i:t:", opt, 0, 0, 0); - if (i < 0) - break; - - /* --- Handle the various options --- */ - - switch (i) { - - /* --- Fetch a size in bits --- */ - - case 'b': - if (!(bits = atoi(optarg)) || bits % 8) - die(EXIT_FAILURE, "bad number of bits: `%s'", optarg); - break; - - /* --- Fetch an expiry time --- */ - - case 'e': - if (strcmp(optarg, "forever") == 0) - c.exp = KEXP_FOREVER; - else if ((c.exp = get_date(optarg, 0)) == -1) - die(EXIT_FAILURE, "bad expiry date: `%s'", optarg); - break; - - /* --- Fetch a key type --- */ - - case 'k': - tag = optarg; - break; - - /* --- Other things are bogus --- */ - - default: - fl |= f_bogus; - break; - } - } - - /* --- Various sorts of bogosity --- */ - - if (fl & f_bogus || optind + 1 < argc) - die(EXIT_FAILURE, - "Usage: generate [-b BITS] [-e TIME] [-k TAG] [DATA]"); - - /* --- Choose a default expiry time --- */ - - if (c.exp == KEXP_EXPIRE) - c.exp = time(0) + 7 * 24 * 60 * 60; - - /* --- Open the key file and get the key --- */ - - doopen(&f, KOPEN_WRITE); - if ((k = key_bytag(&f, tag)) == 0) { - die(EXIT_FAILURE, "no key with tag `%s' in keyring `%s'", - tag, keyfile); - } - - c.k = k->id; - if ((err = key_used(&f, k, c.exp)) != 0) - die(EXIT_FAILURE, "can't generate cookie: %s", key_strerror(err)); - m = getmac(k, "cookie"); - if (bits/8 > GM_CLASS(m)->hashsz) { - die(EXIT_FAILURE, "inapproriate bit length for `%s' MACs", - GM_CLASS(m)->name); - } - - /* --- Store and MAC the cookie --- */ - - COOKIE_PACK(buf, &c); - - h = GM_INIT(m); - GH_HASH(h, buf, sizeof(buf)); - if (argv[optind]) - GH_HASH(h, argv[optind], strlen(argv[optind])); - t = GH_DONE(h, 0); - - /* --- Encode and emit the finished cookie --- */ - - base64_init(&b); - b.indent = ""; - base64_encode(&b, buf, sizeof(buf), &d); - base64_encode(&b, t, bits/8, &d); - base64_encode(&b, 0, 0, &d); - DWRITE(&d, stdout); - fputc('\n', stdout); - DDESTROY(&d); - GH_DESTROY(h); - GM_DESTROY(m); - - doclose(&f); - return (0); - -#undef f_bogus -} - -/* --- @cmd_verify@ --- */ - -static int cmd_verify(int argc, char *argv[]) -{ - key_file f; - dstr d = DSTR_INIT; - unsigned fl = 0; - int bits = -1, minbits = 32; - int v = 1; - base64_ctx b; - gmac *m; - ghash *h; - cookie c; - key *k; - int cbits; - const octet *t; - time_t now = time(0); - - /* --- Various useful flag bits --- */ - -#define f_bogus 1u -#define f_forever 2u -#define f_utc 4u - - /* --- Parse options for the subcommand --- */ - - for (;;) { - static struct option opt[] = { - { "bits", OPTF_ARGREQ, 0, 'b' }, - { "min-bits", OPTF_ARGREQ, 0, 'm' }, - { "forever", 0, 0, 'f' }, - { "quiet", 0, 0, 'q' }, - { "verbose", 0, 0, 'v' }, - { "utc", 0, 0, 'u' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+b:m:fqvu", opt, 0, 0, 0); - if (i < 0) - break; - - /* --- Handle the various options --- */ - - switch (i) { - - /* --- Fetch a size in bits --- */ - - case 'b': - if (!(bits = atoi(optarg)) || bits % 8) - die(EXIT_FAILURE, "bad number of bits: `%s'", optarg); - break; - case 'm': - if (!(minbits = atoi(optarg)) || minbits % 8) - die(EXIT_FAILURE, "bad number of bits: `%s'", optarg); - break; - - /* --- Miscellaneous flags --- */ - - case 'f': - fl |= f_forever; - break; - case 'u': - fl |= f_utc; - break; - case 'q': - if (v > 0) v--; - break; - case 'v': - v++; - break; - - /* --- Other things are bogus --- */ - - default: - fl |= f_bogus; - break; - } - } - - /* --- Various sorts of bogosity --- */ - - if (fl & f_bogus || optind == argc || optind + 2 < argc) { - die(EXIT_FAILURE, - "Usage: verify [-fuqv] [-b BITS] [-m BITS] COOKIE [DATA]"); - } - doopen(&f, KOPEN_READ); - - /* --- Decode the base64 wrapping --- */ - - base64_init(&b); - base64_decode(&b, argv[optind], strlen(argv[optind]), &d); - base64_decode(&b, 0, 0, &d); - - if (d.len < COOKIE_SZ + 1) { - if (v) printf("FAIL cookie too small\n"); - goto fail; - } - - /* --- Extract the relevant details --- */ - - COOKIE_UNPACK(&c, d.buf); - - if (v > 1) { - char buf[64]; - if (c.exp == KEXP_FOREVER) - strcpy(buf, "forever"); - else { - struct tm *tm; - const char *fmt; - - if (fl & f_utc) { - tm = gmtime(&c.exp); - fmt = "%Y-%m-%d %H:%M:%S UTC"; - } else { - tm = localtime(&c.exp); - fmt = "%Y-%m-%d %H:%M:%S %Z"; - } - strftime(buf, sizeof(buf), fmt, tm); - } - printf("INFO keyid = %08lx; expiry = %s\n", (unsigned long)c.k, buf); - } - - /* --- Check the authentication token width --- */ - - cbits = (d.len - COOKIE_SZ) * 8; - if (v > 2) printf("INFO authentication token width = %i bits\n", cbits); - if (bits == -1) { - if (cbits < minbits) { - if (v) printf("FAIL authentication token too narrow\n"); - goto fail; - } - } else { - if (cbits != bits) { - if (v) printf("FAIL authentication token width doesn't match\n"); - goto fail; - } - } - /* --- Get the key --- */ - - if ((k = key_byid(&f, c.k)) == 0) { - if (v) printf("FAIL keyid %08lx unavailable\n", (unsigned long)c.k); - goto fail; - } - - /* --- Check that the cookie authenticates OK --- */ - - m = getmac(k, "cookie"); - h = GM_INIT(m); - GH_HASH(h, d.buf, COOKIE_SZ); - if (argv[optind + 1]) - GH_HASH(h, argv[optind + 1], strlen(argv[optind + 1])); - t = GH_DONE(h, 0); - - if (memcmp(t, d.buf + COOKIE_SZ, cbits / 8) != 0) { - if (v) printf("FAIL bad authentication token\n"); - goto fail; - } - - /* --- See whether the cookie has expired --- */ - - if (c.exp == KEXP_FOREVER) { - if (!(fl & f_forever)) { - if (v) printf("FAIL forever cookies not allowed\n"); - goto fail; - } - if (k->exp != KEXP_FOREVER) { - if (v) printf("FAIL cookie lasts forever but key will expire\n"); - goto fail; - } - } else if (c.exp < now) { - if (v) printf("FAIL cookie has expired\n"); - goto fail; - } - - if (v) printf("OK\n"); - key_close(&f); - GM_DESTROY(m); - GH_DESTROY(h); - dstr_destroy(&d); - return (0); - -fail: - key_close(&f); - dstr_destroy(&d); - return (1); - -#undef f_bogus -#undef f_forever -#undef f_utc -} - -/*----- Main command table ------------------------------------------------*/ - -static int cmd_help(int, char **); - -#define LISTS(LI) \ - LI("Lists", list, \ - listtab[i].name, listtab[i].name) \ - LI("Message authentication algorithms", mac, \ - gmactab[i], gmactab[i]->name) - -MAKELISTTAB(listtab, LISTS) - -static int cmd_show(int argc, char *argv[]) -{ - return (displaylists(listtab, argv + 1)); -} - -static cmd cmds[] = { - { "help", cmd_help, "help [COMMAND...]" }, - { "show", cmd_show, "show [ITEM...]" }, - { "generate", cmd_gen, - "generate [-b BITS] [-e TIME] [-k TAG] [DATA]", "\ -Options:\n\ -\n\ --b, --bits=N Use an N-bit token in the cookie.\n\ --e, --expire=TIME Make the cookie expire after TIME.\n\ --k, --key=TAG Use key TAG to create the token.\n\ -" }, - { "verify", cmd_verify, - "verify [-fuqv] [-b BITS] [-m BITS] COOKIE [DATA]", "\ -Options:\n\ -\n\ --b, --bits=N Accept tokens exactly N bits long only.\n\ --m, --min-bits=N Accept tokens N bits long or more.\n\ --f, --forever Accept cookies which never expire.\n\ --u, --utc Output cookie expiry dates in UTC.\n\ --q, --quiet Produce less output while checking cookies.\n\ --v, --verbose Produce more output while checking cookies.\n\ -" }, - { 0, 0, 0 } -}; - -static int cmd_help(int argc, char *argv[]) -{ - sc_help(cmds, stdout, argv + 1); - return (0); -} - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Helpful GNUy functions --- */ - -static void usage(FILE *fp) -{ - fprintf(fp, "Usage: %s [-k KEYRING] COMMAND [ARGS]\n", QUIS); -} - -void version(FILE *fp) -{ - fprintf(fp, "%s, Catacomb version " VERSION "\n", QUIS); -} - -void help_global(FILE *fp) -{ - usage(fp); - fputs("\n\ -Generates and validates cryptographic cookies. Command line options\n\ -recognized are:\n\ -\n\ --h, --help [COMMAND] Display this help text (or help for COMMAND).\n\ --v, --version Display version number.\n\ --u, --usage Display short usage summary.\n\ -\n\ --k, --key-file=FILE Read and write keys in FILE.\n", - fp); -} - -/* --- @main@ --- * - * - * Arguments: @int argc@ = number of command line arguments - * @char *argv[]@ = array of arguments - * - * Returns: Zero if OK, nonzero if not. - * - * Use: Generates and validates cryptographic cookies. - */ - -int main(int argc, char *argv[]) -{ - unsigned f = 0; - -#define f_bogus 1u -#define f_forever 2u - - /* --- Initialize the library --- */ - - ego(argv[0]); - sub_init(); - - /* --- Options parsing --- */ - - for (;;) { - static struct option opt[] = { - - /* --- Standard GNUy help options --- */ - - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'v' }, - { "usage", 0, 0, 'u' }, - - /* --- Actual relevant options --- */ - - { "keyring", OPTF_ARGREQ, 0, 'k' }, - - /* --- Magic terminator --- */ - - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+hvu k:", opt, 0, 0, 0); - - if (i < 0) - break; - switch (i) { - - /* --- Helpful GNUs --- */ - - case 'u': - usage(stdout); - exit(0); - case 'v': - version(stdout); - exit(0); - case 'h': - sc_help(cmds, stdout, argv + optind); - exit(0); - - /* --- Real genuine useful options --- */ - - case 'k': - keyfile = optarg; - break; - - /* --- Bogus things --- */ - - default: - f |= f_bogus; - break; - } - } - - if ((f & f_bogus) || optind == argc) { - usage(stderr); - exit(EXIT_FAILURE); - } - - /* --- Dispatch to appropriate command handler --- */ - - argc -= optind; - argv += optind; - optind = 0; - return (findcmd(cmds, argv[0])->cmd(argc, argv)); - -#undef f_bogus -#undef f_forever -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/counter-def.h b/counter-def.h deleted file mode 100644 index 129efd9..0000000 --- a/counter-def.h +++ /dev/null @@ -1,535 +0,0 @@ -/* -*-c-*- - * - * $Id: counter-def.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Block cipher counter mode (or long cycle mode) - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_COUNTER_DEF_H -#define CATACOMB_COUNTER_DEF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include -#include - -#ifndef CATACOMB_ARENA_H -# include "arena.h" -#endif - -#ifndef CATACOMB_BLKC_H -# include "blkc.h" -#endif - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -#ifndef CATACOMB_PARANOIA_H -# include "paranoia.h" -#endif - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @COUNTER_DEF@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher - * - * Use: Creates definitions for counter mode. - */ - -#define COUNTER_DEF(PRE, pre) \ - \ -/* --- @pre_countergetiv@ --- * \ - * \ - * Arguments: @const pre_counterctx *ctx@ = pointer to counter \ - * context \ - * @void *iv@ = pointer to output data block \ - * \ - * Returns: --- \ - * \ - * Use: Reads the currently set IV. Reading and setting an IV \ - * is not transparent to the cipher. It will add a `step' \ - * which must be matched by a similar operation during \ - * decryption. \ - */ \ - \ -void pre##_countergetiv(const pre##_counterctx *ctx, void *iv) \ -{ \ - BLKC_STORE(PRE, iv, ctx->n); \ -} \ - \ -/* --- @pre_countersetiv@ --- * \ - * \ - * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ - * @cnost void *iv@ = pointer to IV to set \ - * \ - * Returns: --- \ - * \ - * Use: Sets the IV to use for subsequent encryption. \ - */ \ - \ -void pre##_countersetiv(pre##_counterctx *ctx, const void *iv) \ -{ \ - BLKC_LOAD(PRE, ctx->n, iv); \ - ctx->off = PRE##_BLKSZ; \ -} \ - \ -/* --- @pre_counterbdry@ --- * \ - * \ - * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ - * \ - * Returns: --- \ - * \ - * Use: Inserts a boundary during encryption. Successful \ - * decryption must place a similar boundary. \ - */ \ - \ -void pre##_counterbdry(pre##_counterctx *ctx) \ -{ \ - BLKC_STEP(PRE, ctx->n); \ - ctx->off = PRE##_BLKSZ; \ -} \ - \ -/* --- @pre_countersetkey@ --- * \ - * \ - * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ - * @const pre_ctx *k@ = pointer to cipher context \ - * \ - * Returns: --- \ - * \ - * Use: Sets the counter context to use a different cipher key. \ - */ \ - \ -void pre##_countersetkey(pre##_counterctx *ctx, const pre##_ctx *k) \ -{ \ - ctx->ctx = *k; \ -} \ - \ -/* --- @pre_counterinit@ --- * \ - * \ - * Arguments: @pre_counterctx *ctx@ = pointer to cipher context \ - * @const void *key@ = pointer to the key buffer \ - * @size_t sz@ = size of the key \ - * @const void *iv@ = pointer to initialization vector \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a counter context ready for use. You \ - * should ensure that the IV chosen is unique: reusing an \ - * IV will compromise the security of the entire \ - * plaintext. This is equivalent to calls to @pre_init@, \ - * @pre_countersetkey@ and @pre_countersetiv@. \ - */ \ - \ -void pre##_counterinit(pre##_counterctx *ctx, \ - const void *key, size_t sz, \ - const void *iv) \ -{ \ - static const octet zero[PRE##_BLKSZ] = { 0 }; \ - pre##_init(&ctx->ctx, key, sz); \ - pre##_countersetiv(ctx, iv ? iv : zero); \ -} \ - \ -/* --- @pre_counterencrypt@ --- * \ - * \ - * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Encrypts or decrypts a block with a block cipher in \ - * counter mode: encryption and decryption are the same in \ - * counter. The destination may be null to just churn the \ - * feedback round for a bit. The source may be null to \ - * use the cipher as a random data generator. \ - */ \ - \ -void pre##_counterencrypt(pre##_counterctx *ctx, \ - const void *src, void *dest, \ - size_t sz) \ -{ \ - const octet *s = src; \ - octet *d = dest; \ - unsigned off = ctx->off; \ - \ - /* --- Empty blocks are trivial --- */ \ - \ - if (!sz) \ - return; \ - \ - /* --- If I can deal with the block from my buffer, do that --- */ \ - \ - if (sz < PRE##_BLKSZ - off) \ - goto small; \ - \ - /* --- Finish off what's left in my buffer --- */ \ - \ - if (!d) \ - sz -= PRE##_BLKSZ - off; \ - else { \ - while (off < PRE##_BLKSZ) { \ - register octet x = s ? *s++ : 0; \ - *d++ = ctx->buf[off++] ^ x; \ - sz--; \ - } \ - } \ - \ - /* --- Main encryption loop --- */ \ - \ - { \ - uint32 n[PRE##_BLKSZ / 4]; \ - \ - for (;;) { \ - pre##_eblk(&ctx->ctx, ctx->n, n); \ - BLKC_STEP(PRE, ctx->n); \ - if (sz < PRE##_BLKSZ) \ - break; \ - if (d) { \ - if (!s) \ - BLKC_STORE(PRE, d, n); \ - else { \ - uint32 x[PRE##_BLKSZ / 4]; \ - BLKC_LOAD(PRE, x, s); \ - BLKC_XSTORE(PRE, d, n, x); \ - s += PRE##_BLKSZ; \ - } \ - d += PRE##_BLKSZ; \ - } \ - sz -= PRE##_BLKSZ; \ - } \ - \ - BLKC_STORE(PRE, ctx->buf, n); \ - off = 0; \ - } \ - \ - /* --- Tidying up the tail end --- */ \ - \ - if (sz) { \ - small: \ - if (!d) \ - off += sz; \ - else do { \ - register octet x = s ? *s++ : 0; \ - *d++ = ctx->buf[off++] ^ x; \ - sz--; \ - } while (sz); \ - } \ - \ - /* --- Done --- */ \ - \ - ctx->off = off; \ - return; \ -} \ - \ -/* --- Generic cipher interface --- */ \ - \ -static const gcipher_ops gops; \ - \ -typedef struct gctx { \ - gcipher c; \ - pre##_counterctx k; \ -} gctx; \ - \ -static gcipher *ginit(const void *k, size_t sz) \ -{ \ - gctx *g = S_CREATE(gctx); \ - g->c.ops = &gops; \ - pre##_counterinit(&g->k, k, sz, 0); \ - return (&g->c); \ -} \ - \ -static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_counterencrypt(&g->k, s, t, sz); \ -} \ - \ -static void gdestroy(gcipher *c) \ -{ \ - gctx *g = (gctx *)c; \ - BURN(*g); \ - S_DESTROY(g); \ -} \ - \ -static void gsetiv(gcipher *c, const void *iv) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_countersetiv(&g->k, iv); \ -} \ - \ -static void gbdry(gcipher *c) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_counterbdry(&g->k); \ -} \ - \ -static const gcipher_ops gops = { \ - &pre##_counter, \ - gencrypt, gencrypt, gdestroy, gsetiv, gbdry \ -}; \ - \ -const gccipher pre##_counter = { \ - #pre "-counter", pre##_keysz, PRE##_BLKSZ, \ - ginit \ -}; \ - \ -/* --- Generic random number generator interface --- */ \ - \ -typedef struct grctx { \ - grand r; \ - pre##_counterctx k; \ -} grctx; \ - \ -static void grdestroy(grand *r) \ -{ \ - grctx *g = (grctx *)r; \ - BURN(*g); \ - S_DESTROY(g); \ -} \ - \ -static int grmisc(grand *r, unsigned op, ...) \ -{ \ - grctx *g = (grctx *)r; \ - va_list ap; \ - int rc = 0; \ - octet buf[PRE##_BLKSZ]; \ - va_start(ap, op); \ - \ - switch (op) { \ - case GRAND_CHECK: \ - switch (va_arg(ap, unsigned)) { \ - case GRAND_CHECK: \ - case GRAND_SEEDINT: \ - case GRAND_SEEDUINT32: \ - case GRAND_SEEDBLOCK: \ - case GRAND_SEEDRAND: \ - rc = 1; \ - break; \ - default: \ - rc = 0; \ - break; \ - } \ - break; \ - case GRAND_SEEDINT: \ - BLKC_SET(PRE, g->k.n, va_arg(ap, unsigned)); \ - g->k.off = PRE##_BLKSZ; \ - break; \ - case GRAND_SEEDUINT32: \ - BLKC_SET(PRE, g->k.n, va_arg(ap, uint32)); \ - g->k.off = PRE##_BLKSZ; \ - break; \ - case GRAND_SEEDBLOCK: { \ - const void *p = va_arg(ap, const void *); \ - size_t sz = va_arg(ap, size_t); \ - if (sz < sizeof(buf)) { \ - memset(buf, 0, sizeof(buf)); \ - memcpy(buf, p, sz); \ - p = buf; \ - } \ - pre##_countersetiv(&g->k, p); \ - } break; \ - case GRAND_SEEDRAND: { \ - grand *rr = va_arg(ap, grand *); \ - rr->ops->fill(rr, buf, sizeof(buf)); \ - pre##_countersetiv(&g->k, buf); \ - } break; \ - default: \ - GRAND_BADOP; \ - break; \ - } \ - \ - va_end(ap); \ - return (rc); \ -} \ - \ -static octet grbyte(grand *r) \ -{ \ - grctx *g = (grctx *)r; \ - octet o; \ - pre##_counterencrypt(&g->k, 0, &o, 1); \ - return (o); \ -} \ - \ -static uint32 grword(grand *r) \ -{ \ - grctx *g = (grctx *)r; \ - octet b[4]; \ - pre##_counterencrypt(&g->k, 0, b, sizeof(b)); \ - return (LOAD32(b)); \ -} \ - \ -static void grfill(grand *r, void *p, size_t sz) \ -{ \ - grctx *g = (grctx *)r; \ - pre##_counterencrypt(&g->k, 0, p, sz); \ -} \ - \ -static const grand_ops grops = { \ - #pre "-counter", \ - GRAND_CRYPTO, 0, \ - grmisc, grdestroy, \ - grword, grbyte, grword, grand_range, grfill \ -}; \ - \ -/* --- @pre_counterrand@ --- * \ - * \ - * Arguments: @const void *k@ = pointer to key material \ - * @size_t sz@ = size of key material \ - * \ - * Returns: Pointer to generic random number generator interface. \ - * \ - * Use: Creates a random number interface wrapper around an \ - * counter-mode block cipher. \ - */ \ - \ -grand *pre##_counterrand(const void *k, size_t sz) \ -{ \ - grctx *g = S_CREATE(grctx); \ - g->r.ops = &grops; \ - pre##_counterinit(&g->k, k, sz, 0); \ - return (&g->r); \ -} \ - \ -COUNTER_TEST(PRE, pre) - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#include "daftstory.h" - -/* --- @COUNTER_TEST@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions - * - * Use: Standard test rig for counter functions. - */ - -#define COUNTER_TEST(PRE, pre) \ - \ -/* --- Initial plaintext for the test --- */ \ - \ -static const octet text[] = TEXT; \ - \ -/* --- Key and IV to use --- */ \ - \ -static const octet key[] = KEY; \ -static const octet iv[] = IV; \ - \ -/* --- Buffers for encryption and decryption output --- */ \ - \ -static octet ct[sizeof(text)]; \ -static octet pt[sizeof(text)]; \ - \ -static void hexdump(const octet *p, size_t sz) \ -{ \ - const octet *q = p + sz; \ - for (sz = 0; p < q; p++, sz++) { \ - printf("%02x", *p); \ - if ((sz + 1) % PRE##_BLKSZ == 0) \ - putchar(':'); \ - } \ -} \ - \ -int main(void) \ -{ \ - size_t sz = 0, rest; \ - pre##_counterctx ctx; \ - int status = 0; \ - int done = 0; \ - pre##_ctx k; \ - \ - size_t keysz = PRE##_KEYSZ ? \ - PRE##_KEYSZ : strlen((const char *)key); \ - \ - fputs(#pre "-counter: ", stdout); \ - \ - pre##_init(&k, key, keysz); \ - pre##_countersetkey(&ctx, &k); \ - \ - while (sz <= sizeof(text)) { \ - rest = sizeof(text) - sz; \ - memcpy(ct, text, sizeof(text)); \ - pre##_countersetiv(&ctx, iv); \ - pre##_counterencrypt(&ctx, ct, ct, sz); \ - pre##_counterencrypt(&ctx, ct + sz, ct + sz, rest); \ - memcpy(pt, ct, sizeof(text)); \ - pre##_countersetiv(&ctx, iv); \ - pre##_counterencrypt(&ctx, pt, pt, rest); \ - pre##_counterencrypt(&ctx, pt + rest, pt + rest, sz); \ - if (memcmp(pt, text, sizeof(text)) == 0) { \ - done++; \ - if (sizeof(text) < 40 || done % 8 == 0) \ - fputc('.', stdout); \ - if (done % 480 == 0) \ - fputs("\n\t", stdout); \ - fflush(stdout); \ - } else { \ - printf("\nError (sz = %lu)\n", (unsigned long)sz); \ - status = 1; \ - printf("\tplaintext = "); hexdump(text, sz); \ - printf(", "); hexdump(text + sz, rest); \ - fputc('\n', stdout); \ - printf("\tciphertext = "); hexdump(ct, sz); \ - printf(", "); hexdump(ct + sz, rest); \ - fputc('\n', stdout); \ - printf("\trecovered text = "); hexdump(pt, sz); \ - printf(", "); hexdump(pt + sz, rest); \ - fputc('\n', stdout); \ - fputc('\n', stdout); \ - } \ - if (sz < 63) \ - sz++; \ - else \ - sz += 9; \ - } \ - \ - fputs(status ? " failed\n" : " ok\n", stdout); \ - return (status); \ -} - -#else -# define COUNTER_TEST(PRE, pre) -#endif - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/counter.h b/counter.h deleted file mode 100644 index 0cfaa72..0000000 --- a/counter.h +++ /dev/null @@ -1,189 +0,0 @@ -/* -*-c-*- - * - * $Id: counter.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Block cipher counter mode (or long cycle mode) - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_COUNTER_H -#define CATACOMB_COUNTER_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @COUNTER_DECL@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions - * - * Use: Makes declarations for counter mode. - */ - -#define COUNTER_DECL(PRE, pre) \ - \ -/* --- Counter mode context --- */ \ - \ -typedef struct pre##_counterctx { \ - pre##_ctx ctx; /* Underlying cipher context */ \ - unsigned off; /* Current offset in buffer */ \ - octet buf[PRE##_BLKSZ]; /* Output buffer */ \ - uint32 n[PRE##_BLKSZ / 4]; /* Counter */ \ -} pre##_counterctx; \ - \ -/* --- @pre_countergetiv@ --- * \ - * \ - * Arguments: @const pre_counterctx *ctx@ = pointer to counter \ - * context \ - * @void *iv@ = pointer to output data block \ - * \ - * Returns: --- \ - * \ - * Use: Reads the currently set IV. Reading and setting an IV \ - * is not transparent to the cipher. It will add a `step' \ - * which must be matched by a similar operation during \ - * decryption. \ - */ \ - \ -extern void pre##_countergetiv(const pre##_counterctx */*ctx*/, \ - void */*iv*/); \ - \ -/* --- @pre_countersetiv@ --- * \ - * \ - * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ - * @cnost void *iv@ = pointer to IV to set \ - * \ - * Returns: --- \ - * \ - * Use: Sets the IV to use for subsequent encryption. \ - */ \ - \ -extern void pre##_countersetiv(pre##_counterctx */*ctx*/, \ - const void */*iv*/); \ - \ -/* --- @pre_counterbdry@ --- * \ - * \ - * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ - * \ - * Returns: --- \ - * \ - * Use: Inserts a boundary during encryption. Successful \ - * decryption must place a similar boundary. \ - */ \ - \ -extern void pre##_counterbdry(pre##_counterctx */*ctx*/); \ - \ -/* --- @pre_countersetkey@ --- * \ - * \ - * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ - * @const pre_ctx *k@ = pointer to cipher context \ - * \ - * Returns: --- \ - * \ - * Use: Sets the counter context to use a different cipher key. \ - */ \ - \ -extern void pre##_countersetkey(pre##_counterctx */*ctx*/, \ - const pre##_ctx */*k*/); \ - \ -/* --- @pre_counterinit@ --- * \ - * \ - * Arguments: @pre_counterctx *ctx@ = pointer to cipher context \ - * @const void *key@ = pointer to the key buffer \ - * @size_t sz@ = size of the key \ - * @const void *iv@ = pointer to initialization vector \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a counter context ready for use. You \ - * should ensure that the IV chosen is unique: reusing an \ - * IV will compromise the security of the entire \ - * plaintext. This is equivalent to calls to @pre_init@, \ - * @pre_countersetkey@ and @pre_countersetiv@. \ - */ \ - \ -extern void pre##_counterinit(pre##_counterctx */*ctx*/, \ - const void */*key*/, size_t /*sz*/, \ - const void */*iv*/); \ - \ -/* --- @pre_counterencrypt@ --- * \ - * \ - * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Encrypts or decrypts a block with a block cipher in \ - * counter mode: encryption and decryption are the same in \ - * counter. The destination may be null to just churn the \ - * feedback round for a bit. The source may be null to \ - * use the cipher as a random data generator. \ - */ \ - \ -extern void pre##_counterencrypt(pre##_counterctx */*ctx*/, \ - const void */*src*/, void */*dest*/, \ - size_t /*sz*/); \ - \ -/* --- @pre_counterrand@ --- * \ - * \ - * Arguments: @const void *k@ = pointer to key material \ - * @size_t sz@ = size of key material \ - * \ - * Returns: Pointer to generic random number generator interface. \ - * \ - * Use: Creates a random number interface wrapper around an \ - * counter-mode block cipher. \ - */ \ - \ -extern grand *pre##_counterrand(const void */*k*/, size_t /*sz*/); \ - \ -/* --- Generic cipher interface --- */ \ - \ -extern const gccipher pre##_counter; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/crc32.c b/crc32.c deleted file mode 100644 index 3bccfa3..0000000 --- a/crc32.c +++ /dev/null @@ -1,91 +0,0 @@ -/* -*-c-*- - * - * $Id: crc32.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Generic hash wrapper for CRC32 - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include "arena.h" -#include "crc32.h" -#include "ghash.h" -#include "paranoia.h" - -/*----- Main code ---------------------------------------------------------*/ - -typedef struct gctx { - ghash h; - uint32 c; - octet buf[4]; -} gctx; - -static const ghash_ops gops; - -static ghash *ghinit(void) -{ - gctx *g = S_CREATE(gctx); - g->h.ops = &gops; - g->c = 0; - return (&g->h); -} - -static void ghhash(ghash *h, const void *p, size_t sz) -{ - gctx *g = (gctx *)h; - CRC32(g->c, g->c, p, sz); -} - -static octet *ghdone(ghash *h, void *buf) -{ - gctx *g = (gctx *)h; - if (!buf) - buf = g->buf; - STORE32(buf, g->c); - return (buf); -} - -static void ghdestroy(ghash *h) -{ - gctx *g = (gctx *)h; - BURN(*g); - S_DESTROY(g); -} - -static ghash *ghcopy(ghash *h) -{ - gctx *g = (gctx *)h; - gctx *gg = S_CREATE(gctx); - memcpy(gg, g, sizeof(gctx)); - return (&gg->h); -} - -static const ghash_ops gops = { &gcrc32, ghhash, ghdone, ghdestroy, ghcopy }; -const gchash gcrc32 = { "crc32", 4, ghinit }; - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/crc32.h b/crc32.h deleted file mode 100644 index 1cf164f..0000000 --- a/crc32.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*-c-*- - * - * $Id: crc32.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Generic hash wrapper for CRC32 - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_CRC32_H -#define CATACOMB_CRC32_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Generic interface -------------------------------------------------*/ - -extern const gchash gcrc32; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/daftstory.h b/daftstory.h deleted file mode 100644 index 30313a4..0000000 --- a/daftstory.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*-c-*- - * - * $Id: daftstory.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Daft story for use in test encryptions - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_DAFTSTORY_H -#define CATACOMB_DAFTSTORY_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Macros ------------------------------------------------------------*/ - -/* --- Don't ask --- */ - -#ifdef SMALL_TEST -# define TEXT "A small piece of text for testing encryption." -#else -# define STORY "\ -Once upon a time there were a beautiful princess, a slightly nutty wizard,\n\ -and a watermelon. Now, the watermelon had decided that it probably wasn't\n\ -going to get very far with the princess unless it did something pretty\n\ -drastic. So it asked the wizard to turn it into a handsome prince.\n\ -\n\ -At least, this is the way that the wizard viewed the situation. He might\n\ -have just hallucinated it all; those mushrooms had looked ever so nice.\n\ -\n\ -Back to the point. The watermelon had expressed its desire not to be a\n\ -watermelon any more. And the wizard was probably tripping something quite\n\ -powerful. He hunted around a bit for his staff, and mumbled something\n\ -that film directors would think of as sounding appropriately arcane and\n\ -mystical (but was, in fact, just the ingredients list for an ancient\n\ -remedy for athlete's foot) and *pop*. Cooked watermelon. Yuk.\n\ -\n\ -Later in the year, the princess tripped over the hem of her dress, fell\n\ -down a spiral staircase, and died. The king ordered dressmakers to attach\n\ -safety warnings to long dresses.\n\ -\n\ -And the wizard? Who cares?\n\ -" -# define TEXT STORY STORY -#endif - -#define KEY "Penguins rule OK, rhubarb cauliflower" -#define IV "EdgewareCatacomb, parsley, sage, rosemary and thyme" - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/des-base.c b/des-base.c deleted file mode 100644 index 1003cb6..0000000 --- a/des-base.c +++ /dev/null @@ -1,41 +0,0 @@ -/* -*-c-*- - * - * $Id: des-base.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Common features for DES implementation - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "des-base.h" -#include "des-tab.h" - -/*----- Global variables --------------------------------------------------*/ - -const uint32 des_sp[8][64] = DES_SP; - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/des-base.h b/des-base.h deleted file mode 100644 index 709877b..0000000 --- a/des-base.h +++ /dev/null @@ -1,158 +0,0 @@ -/* -*-c-*- - * - * $Id: des-base.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Common features for DES implementation - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_DES_BASE_H -#define CATACOMB_DES_BASE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -/*----- External data -----------------------------------------------------*/ - -extern const uint32 des_sp[8][64]; - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @DES_ROUND@ --- * - * - * This is the basic DES round function. The inputs are the two subkey - * halves, and the left and right block halves. Note that the block halves - * are rotated left one place at this point. This wraps what's meant to be - * the top bit around to the bottom, so I get a clear run at the S-boxes. - */ - -#define DES_ROUND(ka, kb, x, y) do { \ - uint32 _t = (y) ^ (ka); \ - (x) ^= des_sp[7][(_t >> 0) & 0x3f] ^ \ - des_sp[5][(_t >> 8) & 0x3f] ^ \ - des_sp[3][(_t >> 16) & 0x3f] ^ \ - des_sp[1][(_t >> 24) & 0x3f]; \ - _t = ROR32((y), 4) ^ (kb); \ - (x) ^= des_sp[6][(_t >> 0) & 0x3f] ^ \ - des_sp[4][(_t >> 8) & 0x3f] ^ \ - des_sp[2][(_t >> 16) & 0x3f] ^ \ - des_sp[0][(_t >> 24) & 0x3f]; \ -} while (0) - -/* --- @DES_IP@, @DES_IPINV@ --- * - * - * The cryptographically useless initial and final permutations. The initial - * permutation also rotates the two block halves left by one place. This is - * undone by the inverse permutation at the end. - */ - -#define DES_IP(x, y) do { \ - uint32 _t; \ - _t = (y ^ (x >> 4)) & 0x0f0f0f0f; y ^= _t; x ^= _t << 4; \ - _t = (x ^ (x >> 18)) & 0x00003333; x ^= _t; x ^= _t << 18; \ - _t = (y ^ (y >> 18)) & 0x00003333; y ^= _t; y ^= _t << 18; \ - _t = (x ^ (x >> 9)) & 0x00550055; x ^= _t; x ^= _t << 9; \ - _t = (y ^ (y >> 9)) & 0x00550055; y ^= _t; y ^= _t << 9; \ - _t = (x ^ (x >> 24)) & 0x000000ff; x ^= _t; x ^= _t << 24; \ - _t = (y ^ (y >> 24)) & 0x000000ff; y ^= _t; y ^= _t << 24; \ - _t = (y ^ (x >> 16)) & 0x0000ffff; y ^= _t; x ^= _t << 16; \ - x = ROL32(x, 1); y = ROL32(y, 1); \ -} while (0) - -#define DES_IPINV(x, y) do { \ - uint32 _t; \ - x = ROR32(x, 1); y = ROR32(y, 1); \ - _t = (y ^ (x >> 16)) & 0x0000ffff; y ^= _t; x ^= _t << 16; \ - _t = (x ^ (x >> 24)) & 0x000000ff; x ^= _t; x ^= _t << 24; \ - _t = (y ^ (y >> 24)) & 0x000000ff; y ^= _t; y ^= _t << 24; \ - _t = (y ^ (x >> 4)) & 0x0f0f0f0f; y ^= _t; x ^= _t << 4; \ - _t = (x ^ (x >> 18)) & 0x00003333; x ^= _t; x ^= _t << 18; \ - _t = (y ^ (y >> 18)) & 0x00003333; y ^= _t; y ^= _t << 18; \ - _t = (x ^ (x >> 9)) & 0x00550055; x ^= _t; x ^= _t << 9; \ - _t = (y ^ (y >> 9)) & 0x00550055; y ^= _t; y ^= _t << 9; \ -} while (0) - -/* --- @DES_EBLK@, @DES_DBLK@ --- * - * - * Whole block encryption and decryption. - */ - -#define DES_EBLK(k, a, b, c, d) do { \ - const uint32 *_k = (k); \ - uint32 _x = (a), _y = (b); \ - DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ - DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ - DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ - DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ - DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ - DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ - DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ - DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ - DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ - DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ - DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ - DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ - DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ - DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ - DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ - DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ - (c) = _y; \ - (d) = _x; \ -} while (0) - -#define DES_DBLK(k, a, b, c, d) do { \ - const uint32 *_k = (k) + 32; \ - uint32 _x = (a), _y = (b); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ - _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ - (c) = _y; \ - (d) = _x; \ -} while (0) - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/des-mktab.c b/des-mktab.c deleted file mode 100644 index 9f27e62..0000000 --- a/des-mktab.c +++ /dev/null @@ -1,287 +0,0 @@ -/* -*-c-*- - * - * $Id: des-mktab.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Build combined S-P tables for DES - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include - -/*----- Static variables --------------------------------------------------*/ - -/* --- S boxes --- */ - -static const char s[8][4][16] = { - - /* --- S1 --- */ - - { { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 }, - { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 }, - { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 }, - { 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } }, - - /* --- S2 --- */ - - { { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 }, - { 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 }, - { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 }, - { 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } }, - - /* --- S3 --- */ - - { { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 }, - { 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 }, - { 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 }, - { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } }, - - /* --- S4 --- */ - - { { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 }, - { 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 }, - { 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 }, - { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } }, - - /* --- S5 --- */ - - { { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 }, - { 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 }, - { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 }, - { 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } }, - - /* --- S6 --- */ - - { { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 }, - { 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 }, - { 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 }, - { 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } }, - - /* --- S7 --- */ - - { { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 }, - { 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 }, - { 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 }, - { 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } }, - - /* --- S8 --- */ - - { { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 }, - { 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 }, - { 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 }, - { 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } } -}; - -/* --- P table --- */ - -static char p[32] = { - 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, - 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 -}; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @unique@ --- * - * - * Arguments: @const char *t@ = pointer to table - * @int base@ = base of the data - * @int sz@ = number of elements - * @const char *name@ = name of this table - * @...@ = things to fill in - * - * Returns: Zero if it failed, nonzero if it didn't. - * - * Use: Validates a table. All the elements must be in range and - * unique. - */ - -static int unique(const char *t, int base, int sz, const char *name, ...) -{ - char u[32]; - char nbuf[128]; - int i; - int ok = 1; - - { - va_list ap; - va_start(ap, name); - vsprintf(nbuf, name, ap); - va_end(ap); - } - - if (sz > sizeof(u)) { - fprintf(stderr, "internal error: table `%s' too large\n", nbuf); - exit(EXIT_FAILURE); - } - memset(u, 0, sizeof(u)); - for (i = 0; i < sz; i++) { - int x = t[i] - base; - if (x >= sz) { - fprintf(stderr, "validation error: %i too big (index %i) in %s\n", - x + base, i, nbuf); - ok = 0; - } else if (u[x]) { - fprintf(stderr, "validation error: duplicate %i (index %i) in %s\n", - x + base, i, nbuf); - ok = 0; - } - u[x] = 1; - } - for (i = 0; i < sz; i++) { - if (!u[i]) { - fprintf(stderr, "validation error: missing %i in %s\n", - i + base, nbuf); - ok = 0; - } - } - - return (ok); -} - -/* --- @validate@ --- * - * - * Arguments: --- - * - * Returns: Only if everything's OK. - * - * Use: Validates the tables. A bit. Not much at all... - */ - -static void validate(void) -{ - int i, j; - int ok = 1; - - for (i = 0; i < 8; i++) for (j = 0; j < 4; j++) - if (!unique(s[i][j], 0, 16, "sbox %i, row %i", i, j)) ok = 0; - if (!unique(p, 1, 32, "p")) ok = 0; - if (!ok) - exit(EXIT_FAILURE); -} - -/* --- @permute@ --- * - * - * Arguments: @unsigned long x@ = value to permute - * - * Returns: Permuted version of @x@. - * - * Use: Permutes a number. The result is the input value after - * having been spewed through the @P@ permutation, and then - * (and this is important) rotated left one place. - */ - -static unsigned long permute(unsigned long x) -{ - unsigned long y = 0; - unsigned i; - - for (i = 0; i < 32; i++) { - if (x & (1 << (32 - p[i]))) - y |= (1 << (31 - i)); - } - return (ROL32(y, 1)); -} - -/* --- @mangle@ --- * - * - * Arguments: @const char s[4][16]@ = an s-box - * @unsigned long ss[64]@ = output buffer - * @int bitoff@ = bit offset to use - * - * Returns: --- - * - * Use: Mangles the s-box. Specifically, the bizarre indexing is - * transformed into something sensible, and the result is - * permuted according to the @p@ table. - */ - -static void mangle(const char s[4][16], unsigned long *ss, int bitoff) -{ - unsigned i; - for (i = 0; i < 64; i++) { - unsigned row = ((i & 0x20) >> 4) | (i & 0x01); - unsigned col = (i & 0x1e) >> 1; - ss[i] = permute(s[row][col] << bitoff); - } -} - -/* --- @main@ --- */ - -int main(void) -{ - int i, j; - unsigned long ss[64]; - const char *sep; - - validate(); - - fputs("\ -/* -*-c-*-\n\ - *\n\ - * DES tables [generated]\n\ - */\n\ -\n\ -#ifndef CATACOMB_DES_TAB_H\n\ -#define CATACOMB_DES_TAB_H\n\ -\n\ -#define DES_SP { \\\n\ -", stdout); - for (i = 0; i < 8; i++) { - mangle(s[i], ss, 28 - 4 * i); - printf("\ - \\\n\ - /* --- SP[%i] --- */ \\\n\ - \\\n\ -", i); - sep = " { "; - for (j = 0; j < 64; j++) { - printf("%s0x%08lx", sep, ss[j]); - if (j % 4 == 3) - sep = ", \\\n "; - else - sep = ", "; - } - printf(" }%s \\\n", i == 7 ? "" : ","); - } - fputs("\ -}\n\ -\n\ -#endif\n\ -", stdout); - - if (fclose(stdout)) { - fprintf(stderr, "error writing data\n"); - exit(EXIT_FAILURE); - } - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/des.c b/des.c deleted file mode 100644 index e2f0761..0000000 --- a/des.c +++ /dev/null @@ -1,281 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * The Data Encryption Standard - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include - -#include "blkc.h" -#include "des-base.h" -#include "des.h" -#include "gcipher.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet des_keysz[] = { KSZ_SET, 7, 8, 0 }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @permute@ --- * - * - * Arguments: @const char *p@ = pointer to permutation table - * @uint32 a, b@ = source value to permute - * @uint32 *d@ = destination for value - * - * Returns: --- - * - * Use: Performs a 64-bit permutation. The table is given in the - * normal (but bizarre) DES bit numbering system. That's not to - * say that the tables in this source file are like the normal - * DES tables, because they're not. - */ - -static void permute(const char *p, uint32 a, uint32 b, uint32 *d) -{ - uint32 x = 0, y = 0; - int i; - - for (i = 0; i < 32; i++) { - int q = p[i]; - uint32 t; - if (!q) - continue; - else if (q <= 32) - t = a; - else { - t = b; - q -= 32; - } - if (t & (1 << (32 - q))) - x |= (1 << (31 - i)); - } - - p += 32; - - for (i = 0; i < 32; i++) { - int q = p[i]; - uint32 t; - if (!q) - continue; - else if (q <= 32) - t = a; - else { - t = b; - q -= 32; - } - if (t & (1 << (32 - q))) - y |= (1 << (31 - i)); - } - - d[0] = x; - d[1] = y; -} - -/* --- @des_expand@ --- * - * - * Arguments: @const octet *k@ = pointer to key material - * @size_t n@ = number of octets of key material (7 or 8) - * @uint32 *xx, *yy@ = where to put the results - * - * Returns: --- - * - * Use: Extracts 64 bits of key material from the given buffer, - * possibly expanding it from 56 to 64 bits on the way. - * Parity is set correctly if the key is expanded. - */ - -void des_expand(const octet *k, size_t n, uint32 *xx, uint32 *yy) -{ - uint32 x, y, z; - - if (n == 8) { - x = LOAD32(k + 0); - y = LOAD32(k + 4); - } else { - x = LOAD32(k + 0); - x = (x & 0xfe000000) | ((x & 0x01fffff0) >> 1); - x = (x & 0xfffe0000) | ((x & 0x0001fff8) >> 1); - x = (x & 0xfffffe00) | ((x & 0x000001fc) >> 1); - z = x; z ^= z >> 4; z ^= z >> 2; z ^= z >> 1; - x |= (z & 0x01010101) ^ 0x01010101; - y = LOAD32(k + 3) << 1; /* Note: misaligned */ - y = (y & 0x000000fe) | ((y & 0x1fffff00) << 1); - y = (y & 0x0000fefe) | ((y & 0x3fff0000) << 1); - y = (y & 0x00fefefe) | ((y & 0x7f000000) << 1); - z = y; z ^= z >> 4; z ^= z >> 2; z ^= z >> 1; - y |= (z & 0x01010101) ^ 0x01010101; - } - *xx = x; *yy = y; -} - -/* --- @des_init@ --- * - * - * Arguments: @des_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a DES key buffer. The key buffer may be either 7 - * or 8 bytes long. If it's 8 bytes, the key is assumed to be - * padded with parity bits in the low order bit of each octet. - * These are stripped out without checking prior to the actual - * key scheduling. - */ - -void des_init(des_ctx *k, const void *buf, size_t sz) -{ - uint32 x, y; - uint32 *kp = k->k; - uint32 ka[2]; - int i; - - /* --- @pc1@ --- * - * - * This cryptographically useless permutation is used to mangle the key - * before it's subjected to the key schedule proper. I've not actually - * messed it about much except for inserting padding at the beginning of - * the two halves of the key. - */ - - static const char pc1[] = { - 0, 0, 0, 0, - 57, 49, 41, 33, 25, 17, 9, - 1, 58, 50, 42, 34, 26, 18, - 10, 2, 59, 51, 43, 35, 27, - 19, 11, 3, 60, 52, 44, 36, - 0, 0, 0, 0, - 63, 55, 47, 39, 31, 23, 15, - 7, 62, 54, 46, 38, 30, 22, - 14, 6, 61, 53, 45, 37, 29, - 21, 13, 5, 28, 20, 12, 4 - }; - - /* --- @pc2@ --- * - * - * This irritating but necessary permutation mangles the key between the - * simple rotation-based schedule and the actual XOR with which it modifies - * the behaviour of the cipher. - * - * This version of the table doesn't look much like the original. This is - * because some parts of the world have been permuted in order to make - * things simpler for the round function. In particular, everything is - * rotated left one place to avoid problems with the wraparound of the - * expansion permutation, and the key is split between odd and even S-boxes - * rather than high and low ones. That's without the complication of the - * padding bits in the representation of the 56-bit proto-key. - */ - - static const char pc2[] = { - 0, 0, 3 + 4, 28 + 4, 15 + 4, 6 + 4, 21 + 4, 10 + 4, /* S-box 2 */ - 0, 0, 16 + 4, 7 + 4, 27 + 4, 20 + 4, 13 + 4, 2 + 4, /* S-box 4 */ - 0, 0, 30 + 8, 40 + 8, 51 + 8, 45 + 8, 33 + 8, 48 + 8, /* S-box 6 */ - 0, 0, 46 + 8, 42 + 8, 50 + 8, 36 + 8, 29 + 8, 32 + 8, /* S-box 8 */ - 0, 0, 14 + 4, 17 + 4, 11 + 4, 24 + 4, 1 + 4, 5 + 4, /* S-box 1 */ - 0, 0, 23 + 4, 19 + 4, 12 + 4, 4 + 4, 26 + 4, 8 + 4, /* S-box 3 */ - 0, 0, 41 + 8, 52 + 8, 31 + 8, 37 + 8, 47 + 8, 55 + 8, /* S-box 5 */ - 0, 0, 44 + 8, 49 + 8, 39 + 8, 56 + 8, 34 + 8, 53 + 8 /* S-box 7 */ - }; - - /* --- @v@ --- * - * - * Contains the rotation amounts for the key halves. - */ - - static const char v[] = { - 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 - }; - - /* --- Extract the key into my registers --- * - * - * The 7 byte case is rather horrible. It expands the key to the 8 byte - * case before going any further. It could probably do with its own @pc1@ - * table. - */ - - KSZ_ASSERT(des, sz); - des_expand(buf, sz, &x, &y); - - /* --- Permute using the pointless PC1 --- */ - - permute(pc1, x, y, ka); - x = ka[0]; y = ka[1]; - - /* --- Now for the key schedule proper --- */ - - for (i = 0; i < 16; i++) { - if (v[i] == 1) { - x = ((x << 1) | (x >> 27)) & 0x0fffffff; - y = ((y << 1) | (y >> 27)) & 0x0fffffff; - } else { - x = ((x << 2) | (x >> 26)) & 0x0fffffff; - y = ((y << 2) | (y >> 26)) & 0x0fffffff; - } - permute(pc2, x, y, kp); - kp += 2; - } -} - -/* --- @des_eblk@, @des_dblk@ --- * - * - * Arguments: @const des_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -void des_eblk(const des_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 x = s[0], y = s[1]; - DES_IP(x, y); - DES_EBLK(k->k, x, y, x, y); - DES_IPINV(x, y); - d[0] = x, d[1] = y; -} - -void des_dblk(const des_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 x = s[0], y = s[1]; - DES_IP(x, y); - DES_DBLK(k->k, x, y, x, y); - DES_IPINV(x, y); - d[0] = x, d[1] = y; -} - -BLKC_TEST(DES, des) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/des.h b/des.h deleted file mode 100644 index f3fe91c..0000000 --- a/des.h +++ /dev/null @@ -1,126 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * The Data Encryption Standard - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the Data Encryption Standard -----------------------------* - * - * Almost twenty years after it was first accepted, DES is still the standard - * block cipher. It's showing its age in its small key size and poor - * optimiziation for software implementations, but it's not really been badly - * dented by the intensive analysis thrown at it. - * - * This interface is here for compatibility with existing protocols, and - * because it's a trivial veneer over the base DES code which is used by the - * @des3@ interface which implements proper strong triple-DES. - */ - -#ifndef CATACOMB_DES_H -#define CATACOMB_DES_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magical numbers ---------------------------------------------------*/ - -#define DES_BLKSZ 8 -#define DES_KEYSZ 7 -#define DES_CLASS (N, B, 64) - -extern const octet des_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct des_ctx { - uint32 k[32]; -} des_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @des_expand@ --- * - * - * Arguments: @const octet *k@ = pointer to key material - * @size_t n@ = number of octets of key material (7 or 8) - * @uint32 *xx, *yy@ = where to put the results - * - * Returns: --- - * - * Use: Extracts 64 bits of key material from the given buffer, - * possibly expanding it from 56 to 64 bits on the way. - * Parity is set correctly if the key is expanded. - */ - -extern void des_expand(const octet */*k*/, size_t /*n*/, - uint32 */*xx*/, uint32 */*yy*/); - -/* --- @des_init@ --- * - * - * Arguments: @des_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a DES key buffer. The key buffer may be either 7 - * or 8 bytes long. If it's 8 bytes, the key is assumed to be - * padded with parity bits in the low order bit of each octet. - * These are stripped out without checking prior to the actual - * key scheduling. - */ - -extern void des_init(des_ctx */*k*/, const void */*buf*/, size_t /*sz*/); - -/* --- @des_eblk@, @des_dblk@ --- * - * - * Arguments: @const des_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void des_eblk(const des_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); -extern void des_dblk(const des_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/des3.c b/des3.c deleted file mode 100644 index 66f8243..0000000 --- a/des3.c +++ /dev/null @@ -1,119 +0,0 @@ -/* -*-c-*- - * - * $Id: des3.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Implementation of double- and triple-DES - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include - -#include "blkc.h" -#include "des-base.h" -#include "des.h" -#include "des3.h" -#include "gcipher.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet des3_keysz[] = { KSZ_SET, 21, 7, 8, 14, 16, 24, 0 }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @des3_init@ --- * - * - * Arguments: @des3_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a DES key buffer. The key buffer may have length - * 7, 8, 14, 16, 21, or 24. These correspond to one, two or - * three DES keys, either packed or unpacked (i.e., still - * containing parity bits). - */ - -void des3_init(des3_ctx *k, const void *buf, size_t sz) -{ - size_t step; - const octet *p = buf; - - KSZ_ASSERT(des3, sz); - - if (sz % 7 == 0) - step = 7; - else - step = 8; - - des_init(&k->a, p, step); - if (sz > 8) p += step; - des_init(&k->b, p, step); - if (sz > 16) p += step; else p = buf; - des_init(&k->c, p, step); -} - -/* --- @des3_eblk@, @des3_dblk@ --- * - * - * Arguments: @const des3_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -void des3_eblk(const des3_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 x = s[0], y = s[1]; - DES_IP(x, y); - DES_EBLK(k->a.k, x, y, x, y); - DES_DBLK(k->b.k, x, y, x, y); - DES_EBLK(k->c.k, x, y, x, y); - DES_IPINV(x, y); - d[0] = x, d[1] = y; -} - -void des3_dblk(const des3_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 x = s[0], y = s[1]; - DES_IP(x, y); - DES_DBLK(k->c.k, x, y, x, y); - DES_EBLK(k->b.k, x, y, x, y); - DES_DBLK(k->a.k, x, y, x, y); - DES_IPINV(x, y); - d[0] = x, d[1] = y; -} - -BLKC_TEST(DES3, des3) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/des3.h b/des3.h deleted file mode 100644 index f4f3311..0000000 --- a/des3.h +++ /dev/null @@ -1,110 +0,0 @@ -/* -*-c-*- - * - * $Id: des3.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Implementation of double- and triple-DES - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_DES3_H -#define CATACOMB_DES3_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Notes on double- and triple-DES -----------------------------------* - * - * The normal recommendation for using DES now is `triple DES'. - * Conventionally, this involves an encrypt-decrypt-encrypt sequence, - * although whether the first and last operations use the same key is - * unfortunately not agreed upon. This interface handles both cases (and the - * single-key one too, although the simple @des@ calls are quicker for that). - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#ifndef CATACOMB_DES_H -# include "des.h" -#endif - -/*----- Magical numbers ---------------------------------------------------*/ - -#define DES3_BLKSZ 8 -#define DES3_KEYSZ 21 -#define DES3_CLASS (N, B, 64) - -extern const octet des3_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct des3_ctx { - des_ctx a, b, c; -} des3_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @des3_init@ --- * - * - * Arguments: @des3_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a DES key buffer. The key buffer may have length - * 7, 8, 14, 16, 21, or 24. These correspond to one, two or - * three DES keys, either packed or unpacked (i.e., still - * containing parity bits). - */ - -extern void des3_init(des3_ctx */*k*/, const void */*buf*/, size_t /*sz*/); - -/* --- @des3_eblk@, @des_dblk@ --- * - * - * Arguments: @const des3_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void des3_eblk(const des3_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); -extern void des3_dblk(const des3_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/desx-tab.h b/desx-tab.h deleted file mode 100644 index 7c892e5..0000000 --- a/desx-tab.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*-c-*- - * - * $Id: desx-tab.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Tables for DESX - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_DESX_TAB_H -#define CATACOMB_DESX_TAB_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- S-box table -------------------------------------------------------*/ - -#define DESX_S { \ - 0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, \ - 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0, \ - 0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, \ - 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a, \ - 0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda, \ - 0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36, \ - 0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8, \ - 0x34, 0xa9, 0x13, 0xf0, 0xa6, 0x3f, 0xd8, 0x0c, \ - 0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17, \ - 0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x07, 0xb8, 0x60, \ - 0x48, 0xe6, 0x1e, 0x53, 0xf3, 0x92, 0xa4, 0x72, \ - 0x8c, 0x08, 0x15, 0x6e, 0x86, 0x00, 0x84, 0xfa, \ - 0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd, \ - 0x14, 0x8d, 0x50, 0x12, 0xba, 0x3c, 0x06, 0x4e, \ - 0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b, \ - 0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf, \ - 0x3a, 0xde, 0x96, 0x0e, 0xbc, 0x0a, 0xed, 0x77, \ - 0xfc, 0x37, 0x6b, 0x03, 0x79, 0x89, 0x62, 0xc6, \ - 0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3, \ - 0x5b, 0x05, 0x5d, 0x02, 0x75, 0xd5, 0x61, 0xe3, \ - 0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0x0b, 0x5e, \ - 0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c, \ - 0xb4, 0xc5, 0xcc, 0x70, 0xb2, 0x91, 0x59, 0x0d, \ - 0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x01, 0xe2, \ - 0x16, 0x38, 0xc4, 0x6f, 0x3b, 0x0f, 0x65, 0x46, \ - 0xbe, 0x7e, 0x2d, 0x7b, 0x82, 0xf9, 0x40, 0xb5, \ - 0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97, \ - 0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5, \ - 0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, \ - 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f, \ - 0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, \ - 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab, \ -} - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/desx.c b/desx.c deleted file mode 100644 index d779482..0000000 --- a/desx.c +++ /dev/null @@ -1,151 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Implementation of DESX - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include - -#include "blkc.h" -#include "des-base.h" -#include "des.h" -#include "desx.h" -#include "desx-tab.h" -#include "gcipher.h" - -/*----- Tables ------------------------------------------------------------*/ - -static const octet s[256] = DESX_S; - -/*----- Global variables --------------------------------------------------*/ - -const octet desx_keysz[] = { KSZ_SET, 23, 7, 8, 15, 16, 24, 0 }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @desx_init@ --- * - * - * Arguments: @desx_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a DESX key buffer. The key buffer contains, in - * order, a single-DES key (either 7 or 8 bytes), an optional - * 8-byte pre-whitening key, and an optional 8-byte - * port-whitening key. If no whitening keys are specified, the - * algorithm becomes the same as single-DES. - */ - -static void mangle(octet *b, const octet *p) -{ - unsigned i; - - for (i = 0; i < 8; i++) - b[i] = *p++ ^ s[b[i] ^ b[(i + 1) & 7u]]; -} - -void desx_init(desx_ctx *k, const void *buf, size_t sz) -{ - const octet *p = buf, *kk = buf; - size_t n; - - KSZ_ASSERT(desx, sz); - - n = sz % 8 == 7 ? 7 : 8; - des_init(&k->k, p, n); - p += n; - sz -= n; - if (!sz) - k->prea = k->preb = k->posta = k->postb = 0; - else { - const octet *q = p; - k->prea = LOAD32(q + 0); - k->preb = LOAD32(q + 4); - p += 8; - sz -= 8; - if (sz) { - k->posta = LOAD32(p + 0); - k->postb = LOAD32(p + 4); - } else { - octet b[16]; - uint32 x, y; - - des_expand(kk, n, &x, &y); - STORE32(b + 8, x); STORE32(b + 12, y); - memset(b, 0, 8); - mangle(b, b + 8); - mangle(b, q); - k->posta = LOAD32(b + 0); - k->postb = LOAD32(b + 4); - } - } -} - -/* --- @desx_eblk@, @desx_dblk@ --- * - * - * Arguments: @const desx_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -void desx_eblk(const desx_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 x = s[0], y = s[1]; - x ^= k->prea; y ^= k->preb; - DES_IP(x, y); - DES_EBLK(k->k.k, x, y, x, y); - DES_IPINV(x, y); - x ^= k->posta; y ^= k->postb; - d[0] = x, d[1] = y; -} - -void desx_dblk(const desx_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 x = s[0], y = s[1]; - x ^= k->posta; y ^= k->postb; - DES_IP(x, y); - DES_DBLK(k->k.k, x, y, x, y); - DES_IPINV(x, y); - x ^= k->prea; y ^= k->preb; - d[0] = x, d[1] = y; -} - -BLKC_TEST(DESX, desx) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/desx.h b/desx.h deleted file mode 100644 index bee363e..0000000 --- a/desx.h +++ /dev/null @@ -1,111 +0,0 @@ -/* -*-c-*- - * - * $Id: desx.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The DESX algorithm - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on DESX -----------------------------------------------------* - * - * DESX was designed by Ron Rivest in 1986 as a simple and cheap way to - * strengthen DES against exhaustive search. It also increases the - * difficulty of differential and linear attacks. - */ - -#ifndef CATACOMB_DESX_H -#define CATACOMB_DESX_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#ifndef CATACOMB_DES_H -# include "des.h" -#endif - -/*----- Magical numbers ---------------------------------------------------*/ - -#define DESX_BLKSZ 8 -#define DESX_KEYSZ 23 -#define DESX_CLASS (N, B, 64) - -extern const octet desx_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct desx_ctx { - des_ctx k; - uint32 prea, preb; - uint32 posta, postb; -} desx_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @desx_init@ --- * - * - * Arguments: @desx_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a DESX key buffer. The key buffer contains, in - * order, an optional 8-byte pre-whitening key, a single-DES key - * (either 7 or 8 bytes), and an optional 8-byte port-whitening - * key. If no whitening keys are specified, the algorithm - * becomes the same as single-DES. - */ - -extern void desx_init(desx_ctx */*k*/, const void */*buf*/, size_t /*sz*/); - -/* --- @desx_eblk@, @desx_dblk@ --- * - * - * Arguments: @const desx_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void desx_eblk(const desx_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); -extern void desx_dblk(const desx_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/dh-check.c b/dh-check.c deleted file mode 100644 index ef07e66..0000000 --- a/dh-check.c +++ /dev/null @@ -1,172 +0,0 @@ -/* -*-c-*- - * - * $Id: dh-check.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Checks Diffie-Hellman group parameters - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "dh.h" -#include "keycheck.h" -#include "mp.h" -#include "mpmont.h" -#include "mpmul.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @dh_checkparam@ --- * - * - * Arguments: @keycheck *kc@ = keycheck state - * @const dh_param *dp@ = pointer to the parameter set - * @mp **v@ = optional vector of factors - * @size_t n@ = size of vector - * - * Returns: Zero if all OK, or return status from function. - * - * Use: Checks a set of Diffie-Hellman parameters for consistency and - * security. - */ - -int dh_checkparam(keycheck *kc, const dh_param *dp, mp **v, size_t n) -{ - int rc = 0; - mpmont mm; - mp *pm1 = MP_NEW; - mp *q = MP_NEW; - mp *x; - mpmul mu; - size_t i; - - /* --- Check that the numbers which are supposed to be prime are --- */ - - if ((!v && keycheck_prime(kc, KCSEV_WARN, dp->q, "q")) || - keycheck_prime(kc, KCSEV_ERR, dp->p, "p")) - goto fail; - - /* --- Ensure that %$q$% is a sensible choice of number --- */ - - pm1 = mp_sub(pm1, dp->p, MP_ONE); - mp_div(0, &q, pm1, dp->q); - if (!mp_eq(q, MP_ZERO) && - keycheck_report(kc, KCSEV_ERR, "q not a factor of p - 1")) - goto fail; - - /* --- Check that %$g$% is actually right --- * - * - * This isn't perfect. If %$q$% is composite and we don't have the factors - * of %$p - 1$% then the order of %$g$% may be some factor of %$q$% which - * we can't find. (If we do have the factors, we check them all lower - * down.) We do strip out powers of two from %$q$% before testing, though. - */ - - if ((mp_eq(dp->g, MP_ONE) || mp_eq(dp->g, pm1)) && - keycheck_report(kc, KCSEV_ERR, "g is degenerate (+/-1 mod p)")) - goto fail; - q = mp_odd(q, dp->q, &i); - mpmont_create(&mm, dp->p); - x = mpmont_mul(&mm, MP_NEW, dp->g, mm.r2); - q = mpmont_expr(&mm, q, x, q); - mp_drop(x); - do { - if (mp_eq(q, mm.r) != !i) { - if (keycheck_report(kc, KCSEV_ERR, "order of g != q")) { - mpmont_destroy(&mm); - goto fail; - } - break; - } - if (i) { - q = mp_sqr(q, q); - q = mpmont_reduce(&mm, q, q); - } - } while (i--); - - /* --- Check Lim-Lee primes more carefully --- * - * - * In this case, we really can be sure whether the order of %$g$% is - * actually %$q$% as advertised. Also ensure that the individual primes - * are really prime, and that their product is correct. - */ - - if (!v) - mpmont_destroy(&mm); - else { - dstr d = DSTR_INIT; - mp *r = MP_NEW; - - mpmul_init(&mu); - for (i = 0; i < n; i++) { - DRESET(&d); - dstr_putf(&d, "factor f_%lu of p", (unsigned long)i); - if ((rc = keycheck_prime(kc, KCSEV_ERR, v[i], d.buf)) != 0) - break; - mp_div(&q, &r, dp->q, v[i]); - if (mp_eq(r, MP_ZERO) && !mp_eq(q, MP_ONE)) { - q = mpmont_exp(&mm, q, dp->g, q); - if (mp_eq(q, MP_ONE) && - (rc = keycheck_report(kc, KCSEV_ERR, - "order of g is proper divisor of q")) != 0) - break; - } - mpmul_add(&mu, v[i]); - } - mp_drop(q); - mp_drop(r); - q = mpmul_done(&mu); - mpmont_destroy(&mm); - dstr_destroy(&d); - if (rc) - goto fail; - q = mp_lsl(q, q, 1); - if (!mp_eq(q, pm1) && - keycheck_report(kc, KCSEV_ERR, "product of f_i != (p - 1)/2")) - goto fail; - } - - /* --- Finally, check the key sizes --- */ - - if ((mp_bits(dp->p) < 1024 && - keycheck_report(kc, KCSEV_WARN, - "p too small to resist index calculus attacks")) || - (mp_bits(dp->q) < 160 && - keycheck_report(kc, KCSEV_WARN, - "q too small to resist collision-finding attacks"))) - goto fail; - - /* --- Done --- */ - -tidy: - mp_drop(q); - mp_drop(pm1); - return (rc); -fail: - rc = -1; - goto tidy; -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/dh-fetch.c b/dh-fetch.c deleted file mode 100644 index 57439d2..0000000 --- a/dh-fetch.c +++ /dev/null @@ -1,100 +0,0 @@ -/* -*-c-*- - * - * $Id: dh-fetch.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Key fetching for Diffie-Hellman public and private keys - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "dh.h" -#include "key.h" - -/*----- Key fetching ------------------------------------------------------*/ - -const key_fetchdef dh_paramfetch[] = { - { "p", offsetof(dh_param, p), KENC_MP, 0 }, - { "q", offsetof(dh_param, q), KENC_MP, 0 }, - { "g", offsetof(dh_param, g), KENC_MP, 0 }, - { 0, 0, 0, 0 } -}; - -const key_fetchdef dh_pubfetch[] = { - { "p", offsetof(dh_pub, dp.p), KENC_MP, 0 }, - { "q", offsetof(dh_pub, dp.q), KENC_MP, 0 }, - { "g", offsetof(dh_pub, dp.g), KENC_MP, 0 }, - { "y", offsetof(dh_pub, y), KENC_MP, 0 }, - { 0, 0, 0, 0 } -}; - -static const key_fetchdef priv[] = { - { "x", offsetof(dh_priv, x), KENC_MP, 0 }, - { 0, 0, 0, 0 } -}; - -const key_fetchdef dh_privfetch[] = { - { "p", offsetof(dh_priv, dp.p), KENC_MP, 0 }, - { "q", offsetof(dh_priv, dp.q), KENC_MP, 0 }, - { "g", offsetof(dh_priv, dp.g), KENC_MP, 0 }, - { "y", offsetof(dh_priv, y), KENC_MP, 0 }, - { "private", 0, KENC_STRUCT, priv }, - { 0, 0, 0, 0 } -}; - -/* --- @dh_paramfree@, @dh_pubfree@, @dh_privfree@ --- * - * - * Arguments: @dh_param *dp@, @dh_pub *dp@, @dh_priv *dp@ = pointer - * to key block to free - * - * Returns: --- - * - * Use: Frees a Diffie-Hellman key block. - */ - -void dh_paramfree(dh_param *dp) -{ - mp_drop(dp->p); - mp_drop(dp->q); - mp_drop(dp->g); -} - -void dh_pubfree(dh_pub *dp) -{ - mp_drop(dp->dp.p); - mp_drop(dp->dp.q); - mp_drop(dp->dp.g); - mp_drop(dp->y); -} - -void dh_privfree(dh_priv *dp) -{ - mp_drop(dp->dp.p); - mp_drop(dp->dp.q); - mp_drop(dp->dp.g); - mp_drop(dp->y); - mp_drop(dp->x); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/dh-gen.c b/dh-gen.c deleted file mode 100644 index a1b61a1..0000000 --- a/dh-gen.c +++ /dev/null @@ -1,163 +0,0 @@ -/* -*-c-*- - * - * $Id: dh-gen.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Generate Diffie-Hellman parameters - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "dh.h" -#include "grand.h" -#include "mp.h" -#include "mpmont.h" -#include "mprand.h" -#include "pfilt.h" -#include "pgen.h" -#include "prim.h" -#include "rabin.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @dh_gen@ --- * - * - * Arguments: @dh_param *dp@ = pointer to output parameter block - * @unsigned ql@ = length of %$q$% in bits, or zero - * @unsigned pl@ = length of %$p$% in bits - * @unsigned steps@ = number of steps to go - * @grand *r@ = random number source - * @pgen_proc *event@ = event handler function - * @void *ectx@ = argument for the event handler - * - * Returns: @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't. - * - * Use: Generates Diffie-Hellman parameters. - * - * The parameters are a prime %$q$%, relatively small, and a - * large prime %$p = kq + 1$% for some %$k$%, together with a - * generator %$g$% of the cyclic subgroup of order %$q$%. These - * are actually the same as the DSA parameter set, but the - * generation algorithm is different. Also, if @ql@ is zero, - * this algorithm forces %$k = 2$%, and chooses %$g = 4$%. Make - * sure you have something interesting to do if you choose this - * option. - */ - -int dh_gen(dh_param *dp, unsigned ql, unsigned pl, unsigned steps, grand *r, - pgen_proc *event, void *ectx) -{ - /* --- If @ql@ is zero, do the time consuming safe-prime thing --- */ - - if (!ql) { - pgen_simulprime sp[2]; - pgen_simulctx ss; - - mp *m = mprand(MP_NEW, pl - 1, r, 1); - ss.step = MP_TWO; - sp[0].mul = MP_ONE; sp[0].add = MP_ZERO; sp[0].f = 0; - sp[1].mul = MP_TWO; sp[1].add = MP_ONE; sp[1].f = PGENF_KEEP; - ss.v = sp; ss.n = N(sp); - dp->q = pgen("p", MP_NEW, m, event, ectx, steps, pgen_simulstep, &ss, - rabin_iters(pl), pgen_simultest, &ss); - mp_drop(m); - if (!dp->q) { - mp_drop(sp[1].u.x); - return (PGEN_ABORT); - } - dp->p = sp[1].u.x; - dp->g = MP_FOUR; - return (PGEN_DONE); - } - - /* --- Otherwise the job is much simpler --- * - * - * But doesn't look it... - */ - - else { - pgen_filterctx c; - pgen_jumpctx j; - rabin rb; - prim_ctx p; - int i; - mp *m = MP_NEW; - mp *x, *y; - - /* --- Generate @q@ first --- */ - - c.step = 2; - m = mprand(MP_NEW, ql, r, 1); - dp->q = pgen("q", MP_NEW, m, event, ectx, steps, pgen_filter, &c, - rabin_iters(ql), pgen_test, &rb); - if (!dp->q) - goto fail_q; - - /* --- Now pick a suitable @p@ --- */ - - m = mp_lsl(m, dp->q, 1); - x = mprand(MP_NEW, pl, r, 0); - y = MP_NEW; mp_div(0, &y, x, m); - x = mp_sub(x, x, y); - x = mp_add(x, x, MP_ONE); - mp_drop(y); - pfilt_create(&c.f, m); - j.j = &c.f; - dp->p = pgen("p", MP_NEW, x, event, ectx, steps, pgen_jump, &j, - rabin_iters(pl), pgen_test, &rb); - pfilt_destroy(&c.f); - mp_drop(x); - if (!dp->p) - goto fail_p; - - /* --- And finally a suitable @g@ --- */ - - mpmont_create(&p.mm, dp->p); - mp_div(&m, 0, dp->p, dp->q); - i = 0; - p.exp = m; - p.n = 0; - dp->g = pgen("g", MP_NEW, MP_NEW, event, ectx, 0, prim_step, &i, - 1, prim_test, &p); - mpmont_destroy(&p.mm); - if (!dp->g) - goto fail_g; - mp_drop(m); - return (PGEN_DONE); - - /* --- Tidy up --- */ - - fail_g: - mp_drop(dp->q); - fail_q: - mp_drop(dp->p); - fail_p: - mp_drop(m); - return (PGEN_ABORT); - } -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/dh-kcdsa.c b/dh-kcdsa.c deleted file mode 100644 index b503a5b..0000000 --- a/dh-kcdsa.c +++ /dev/null @@ -1,125 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Generate KCDSA prime groups - * - * (c) 2006 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "dh.h" -#include "mprand.h" -#include "pgen.h" -#include "prim.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @dh_kcdsagen@ --- * - * - * Arguments: @dh_param *dp@ = pointer to output parameter block - * @unsigned ql@ = size of small factor of %$(p - 1)/2$% - * @unsigned pl@ = size of %$p$% in bits - * @unsigned flags@ = other generation flags - * @unsigned steps@ = number of steps to go - * @grand *r@ = random number source - * @pgen_proc *ev@ = event handler function - * @void *ec@ = context for the event handler - * - * Returns: @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it failed. - * - * Use: Generates a KCDSA prime group. That is, it chooses a prime - * %$p$%, such that $%p = 2 q v + 1$%, for primes %$q$% and - * %$v$%. The actual group of interest is the subgroup of order - * %$q$%. - */ - -int dh_kcdsagen(dh_param *dp, unsigned ql, unsigned pl, - unsigned flags, unsigned steps, grand *r, - pgen_proc *ev, void *ec) -{ - pgen_filterctx pf; - pgen_simulprime sp[2]; - pgen_simulctx ss; - prim_ctx pc; - rabin rb; - int rc = PGEN_ABORT; - int i; - mp *x; - - /* --- First trick: find %$q$% --- */ - - pf.step = 2; - x = mprand(MP_NEW, pl - ql, r, 1); - x = pgen("v", x, x, ev, ec, - steps, pgen_filter, &pf, - rabin_iters(pl - ql), pgen_test, &rb); - if (!x) - goto fail_0; - - /* --- Second trick: find %$p$% and %$v$% --- */ - - x = mp_lsl(x, x, 1); - sp[0].add = MP_ZERO; sp[0].mul = MP_ONE; sp[0].f = 0; - sp[1].add = MP_ONE; sp[1].mul = x; sp[1].f = PGENF_KEEP; - ss.step = MP_TWO; ss.v = sp; ss.n = N(sp); - x = mprand(MP_NEW, ql, r, 1); - dp->q = pgen("p", MP_NEW, x, ev, ec, - steps, pgen_simulstep, &ss, - rabin_iters(ql), pgen_simultest, &ss); - mp_drop(sp[0].mul); - if (!dp->q) - goto fail_1; - dp->p = sp[1].u.x; - - /* --- Third trick: find a generator --- */ - - mpmont_create(&pc.mm, dp->p); - mp_div(&x, 0, dp->p, dp->q); - i = 0; - pc.exp = x; - pc.n = 0; - dp->g = pgen("g", MP_NEW, MP_NEW, ev, ec, - 0, prim_step, &i, 1, prim_test, &pc); - mpmont_destroy(&pc.mm); - if (!dp->g) - goto fail_2; - - rc = PGEN_DONE; - goto done; - - /* --- Tidying up and going home --- */ - -fail_2: - mp_drop(dp->p); -fail_1: -fail_0: -done: - mp_drop(x); - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/dh-limlee.c b/dh-limlee.c deleted file mode 100644 index 26666a3..0000000 --- a/dh-limlee.c +++ /dev/null @@ -1,140 +0,0 @@ -/* -*-c-*- - * - * $Id: dh-limlee.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Generate Diffie-Hellman parameters from Lim-Lee primes - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "dh.h" -#include "limlee.h" -#include "mpmont.h" -#include "prim.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @dh_limlee@ --- * - * - * Arguments: @dh_param *dp@ = pointer to output parameter block - * @unsigned ql@ = length of smallest factor of %$(p - 1)/2$% - * @unsigned pl@ = length of %$p$% in bits - * @unsigned flags@ = other generation flags - * @unsigned steps@ = number of steps to go - * @grand *r@ = random number source - * @pgen_proc *oev@ = outer event handler function - * @void *oec@ = argument for the outer event handler - * @pgen_proc *iev@ = inner event handler function - * @void *iec@ = argument for the inner event handler - * @size_t *nf@, @mp ***f@ = output array for factors - * - * Returns: @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't. - * - * Use: Generates Diffie-Hellman parameters based on a Lim-Lee prime. - * - * The modulus is a large prime %$p = 2 \prod q_i + 1$%, @pl@ - * bits long, where the %$q_i$% are smaller primes each at least - * @ql@ bits long. It is safe to set @nf@ and @f@ to zero if - * you're not interested in the factor values. - * - * The returned %$g$% generates a subgroup of order %$q_0$% (the - * first factor, returned as @f[0]@), if the flag @DH_SUBGROUP@ - * is set on entry; otherwise %$g$% will have order - * %$(p - 1)/2$%. - */ - -int dh_limlee(dh_param *dp, unsigned ql, unsigned pl, - unsigned flags, unsigned steps, grand *r, - pgen_proc *oev, void *oec, pgen_proc *iev, - void *iec, size_t *nf, mp ***f) -{ - mp **ff; - size_t nff; - prim_ctx pc; - size_t i; - int j; - mp *pp; - - /* --- Generate the Lim-Lee prime --- */ - - if ((dp->p = limlee("p", MP_NEW, MP_NEW, ql, pl, - r, steps, oev, oec, iev, iec, &nff, &ff)) == 0) - return (PGEN_ABORT); - - /* --- Now find a primitive element --- */ - - mpmont_create(&pc.mm, dp->p); - pp = mp_sub(MP_NEW, dp->p, MP_ONE); - if (flags & DH_SUBGROUP) { - dp->q = mp_copy(ff[0]); - pc.exp = MP_NEW; - mp_div(&pc.exp, 0, pp, dp->q); - pc.n = 0; - pc.f = 0; - } else { - dp->q = mp_lsr(MP_NEW, dp->p, 1); - pc.exp = MP_TWO; - pc.n = nff; - pc.f = xmalloc(nff * sizeof(mp *)); - for (i = 0; i < nff; i++) { - pc.f[i] = MP_NEW; - mp_div(&pc.f[i], 0, pp, ff[i]); - } - } - - j = 0; - dp->g = pgen("g", MP_NEW, MP_NEW, oev, oec, - 0, prim_step, &j, 1, prim_test, &pc); - - mp_drop(pp); - if (pc.f) { - for (i = 0; i < pc.n; i++) - mp_drop(pc.f[i]); - xfree(pc.f); - } - mpmont_destroy(&pc.mm); - - /* --- Do something sensible with the list of primes --- */ - - if (dp->g && f) { - *f = ff; - *nf = nff; - } else { - for (i = 0; i < nff; i++) - mp_drop(ff[i]); - xfree(ff); - } - - /* --- Tidy up and return --- */ - - if (!dp->g) { - mp_drop(dp->p); - mp_drop(dp->q); - return (PGEN_ABORT); - } - return (PGEN_DONE); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/dh-param.c b/dh-param.c deleted file mode 100644 index e1e5374..0000000 --- a/dh-param.c +++ /dev/null @@ -1,172 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Reading Diffie-Hellman parameters - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "dh.h" -#include "ptab.h" -#include "bintab.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* ---- @dh_infofromdata@ --- * - * - * Arguments: @dh_param *dp@ = parameters to fill in - * @pdata *pd@ = packed data structure - * - * Returns: --- - * - * Use: Fills in a parameters structure from a packed data block. - */ - -void dh_infofromdata(dh_param *dp, pdata *pd) - { dp->p = &pd->p; dp->q = &pd->q; dp->g = &pd->g; } - -/* --- @dh_parse@, @dhbin_parse@ --- * - * - * Arguments: @qd_parse *qd@ = parser context - * @dh_param *dp@ = parameters to fill in - * - * Returns: Zero if OK, nonzero on error. - * - * Use: Parses a prime group string. This is either one of the - * standard group strings, or a %$p$%, %$q$%, %$g$% triple - * separated by commas. - */ - -static int parse(qd_parse *qd, gprime_param *dp) -{ - mp *p = MP_NEW, *q = MP_NEW, *g = MP_NEW; - - if ((p = qd_getmp(qd)) == 0) goto fail; - qd_delim(qd, ','); if ((q = qd_getmp(qd)) == 0) goto fail; - qd_delim(qd, ','); if ((g = qd_getmp(qd)) == 0) goto fail; - dp->p = p; dp->q = q; dp->g = g; - return (0); -fail: - mp_drop(p); mp_drop(q); mp_drop(g); - return (-1); -} - -int dh_parse(qd_parse *qd, dh_param *dp) -{ - const pentry *pe; - - for (pe = ptab; pe->name; pe++) { - if (qd_enum(qd, pe->name) >= 0) { - dh_infofromdata(dp, pe->data); - goto found; - } - } - if (parse(qd, dp)) - return (-1); -found: - return (0); -} - -int dhbin_parse(qd_parse *qd, gbin_param *gb) -{ - const binentry *be; - - for (be = bintab; be->name; be++) { - if (qd_enum(qd, be->name) >= 0) { - dh_infofromdata(gb, be->data); - goto found; - } - } - if (parse(qd, gb)) - return (-1); -found: - return (0); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include "fibrand.h" - -int main(int argc, char *argv[]) -{ - const pentry *pe; - const binentry *be; - const char *e; - int ok = 1, aok = 1; - grand *gr; - - gr = fibrand_create(0); - fputs("checking standard prime groups:", stdout); - fflush(stdout); - for (pe = ptab; pe->name; pe++) { - dh_param dp; - group *g; - dh_infofromdata(&dp, pe->data); - g = group_prime(&dp); - if (mp_bits(dp.p) > 2048 && - (!argv[1] || strcmp(argv[1], "keen") != 0)) { - printf(" [%s skipped]", pe->name); - fflush(stdout); - continue; - } - e = G_CHECK(g, gr); - G_DESTROYGROUP(g); - dh_paramfree(&dp); - if (e) { - printf(" [%s failed: %s]", pe->name, e); - ok = aok = 0; - } else - printf(" %s", pe->name); - fflush(stdout); - } - fputs(ok ? " ok\n" : " failed\n", stdout); - ok = 1; - fputs("checking standard binary groups:", stdout); - for (be = bintab; be->name; be++) { - gbin_param gb; - group *g; - dh_infofromdata(&gb, be->data); - g = group_binary(&gb); - e = G_CHECK(g, gr); - G_DESTROYGROUP(g); - dh_paramfree(&gb); - if (e) { - printf(" [%s failed: %s]", be->name, e); - ok = aok = 0; - } else - printf(" %s", be->name); - fflush(stdout); - } - fputs(ok ? " ok\n" : " failed\n", stdout); - gr->ops->destroy(gr); - return (!aok); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/dh.h b/dh.h deleted file mode 100644 index 04b526e..0000000 --- a/dh.h +++ /dev/null @@ -1,242 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Diffie-Hellman and related public-key systems - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_DH_H -#define CATACOMB_DH_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GROUP_H -# include "group.h" -#endif - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -#ifndef CATACOMB_KEY_H -# include "key.h" -#endif - -#ifndef CATACOMB_KEYCHECK_H -# include "keycheck.h" -#endif - -#ifndef CATACOMB_PGEN_H -# include "pgen.h" -#endif - -#ifndef CATACOMB_QDPARSE_H -# include "qdparse.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef gprime_param dh_param; /* Group parameters */ - -typedef struct dh_pub { - dh_param dp; /* Shared parameters */ - mp *y; /* Public key */ -} dh_pub; - -typedef struct dh_priv { - dh_param dp; /* Shared parameters */ - mp *x; /* Private key */ - mp *y; /* %$y \equiv g^x \pmod{p}$% */ -} dh_priv; - -/*----- Key fetching ------------------------------------------------------*/ - -extern const key_fetchdef dh_paramfetch[]; -#define DH_PARAMFETCHSZ 5 - -extern const key_fetchdef dh_pubfetch[]; -#define DH_PUBFETCHSZ 6 - -extern const key_fetchdef dh_privfetch[]; -#define DH_PRIVFETCHSZ 9 - -/* --- @dh_paramfree@, @dh_pubfree@, @dh_privfree@ --- * - * - * Arguments: @dh_param *dp@, @dh_pub *dp@, @dh_priv *dp@ = pointer to - * key block to free - * - * Returns: --- - * - * Use: Frees a Diffie-Hellman key block. - */ - -extern void dh_paramfree(dh_param */*dp*/); -extern void dh_pubfree(dh_pub */*dp*/); -extern void dh_privfree(dh_priv */*dp*/); - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @dh_gen@ --- * - * - * Arguments: @dh_param *dp@ = pointer to output parameter block - * @unsigned ql@ = length of %$q$% in bits, or zero - * @unsigned pl@ = length of %$p$% in bits - * @unsigned steps@ = number of steps to go - * @grand *r@ = random number source - * @pgen_proc *event@ = event handler function - * @void *ectx@ = argument for the event handler - * - * Returns: @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't. - * - * Use: Generates Diffie-Hellman parameters. - * - * The parameters are a prime %$q$%, relatively small, and a - * large prime %$p = kq + 1$% for some %$k$%, together with a - * generator %$g$% of the cyclic subgroup of order %$q$%. These - * are actually the same as the DSA parameter set, but the - * generation algorithm is different. Also, if @ql@ is zero, - * this algorithm forces %$k = 2$%, and chooses %$g = 4$%. Make - * sure you have something interesting to do if you choose this - * option. - */ - -extern int dh_gen(dh_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/, - unsigned /*steps*/, grand */*r*/, pgen_proc */*event*/, - void */*ectx*/); - -/* --- @dh_limlee@ --- * - * - * Arguments: @dh_param *dp@ = pointer to output parameter block - * @unsigned ql@ = length of smallest factor of %$(p - 1)/2$% - * @unsigned pl@ = length of %$p$% in bits - * @unsigned flags@ = other generation flags - * @unsigned steps@ = number of steps to go - * @grand *r@ = random number source - * @pgen_proc *oev@ = outer event handler function - * @void *oec@ = argument for the outer event handler - * @pgen_proc *iev@ = inner event handler function - * @void *iec@ = argument for the inner event handler - * @size_t *nf@, @mp ***f@ = output array for factors - * - * Returns: @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't. - * - * Use: Generates Diffie-Hellman parameters based on a Lim-Lee prime. - * - * The modulus is a large prime %$p = 2 \prod q_i + 1$%, @pl@ - * bits long, where the %$q_i$% are smaller primes each at least - * @ql@ bits long. It is safe to set @nf@ and @f@ to zero if - * you're not interested in the factor values. - * - * The returned %$g$% generates a subgroup of order %$q_0$% (the - * first factor, returned as @f[0]@), if the flag @DH_SUBGROUP@ - * is set on entry; otherwise %$g$% will have order - * %$(p - 1)/2$%. - */ - -#define DH_SUBGROUP 1u - -extern int dh_limlee(dh_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/, - unsigned /*flags*/, unsigned /*steps*/, grand */*r*/, - pgen_proc */*oev*/, void */*oec*/, pgen_proc */*iev*/, - void */*iec*/, size_t */*nf*/, mp ***/*f*/); - -/* --- @dh_kcdsagen@ --- * - * - * Arguments: @dh_param *dp@ = pointer to output parameter block - * @unsigned ql@ = size of small factor of %$(p - 1)/2$% - * @unsigned pl@ = size of %$p$% in bits - * @unsigned flags@ = other generation flags (none defined) - * @unsigned steps@ = number of steps to go - * @grand *r@ = random number source - * @pgen_proc *ev@ = event handler function - * @void *ec@ = context for the event handler - * - * Returns: @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it failed. - * - * Use: Generates a KCDSA prime group. That is, it chooses a prime - * %$p$%, such that $%p = 2 q v + 1$%, for primes %$q$% and - * %$v$%. The actual group of interest is the subgroup of order - * %$q$%. - */ - -extern int dh_kcdsagen(dh_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/, - unsigned /*flags*/, unsigned /*steps*/, grand */*r*/, - pgen_proc */*ev*/, void */*ec*/); - -/* --- @dh_checkparam@ --- * - * - * Arguments: @keycheck *kc@ = keycheck state - * @const dh_param *dp@ = pointer to the parameter set - * @mp **v@ = optional vector of factors - * @size_t n@ = size of vector - * - * Returns: Zero if all OK, or return status from function. - * - * Use: Checks a set of Diffie-Hellman parameters for consistency and - * security. - */ - -extern int dh_checkparam(keycheck */*kc*/, const dh_param */*dp*/, - mp **/*v*/, size_t /*n*/); - -/* ---- @dh_infofromdata@ --- * - * - * Arguments: @dh_param *dp@ = parameters to fill in - * @pdata *pd@ = packed data structure - * - * Returns: --- - * - * Use: Fills in a parameters structure from a packed data block. - */ - -struct pdata; -extern void dh_infofromdata(dh_param */*dp*/, struct pdata */*pd*/); - -/* --- @dh_parse@, @dhbin_parse@ --- * - * - * Arguments: @qd_parse *qd@ = parser context - * @dh_param *dp@ = parameters to fill in - * - * Returns: Zero if OK, nonzero on error. - * - * Use: Parses a prime/binary group string. This is either one of - * the standard group strings, or a %$p$%, %$q$%, %$g$% triple - * separated by commas. - */ - -extern int dh_parse(qd_parse */*qd*/, dh_param */*dp*/); -extern int dhbin_parse(qd_parse */*qd*/, gbin_param */*gb*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/dsa-check.c b/dsa-check.c deleted file mode 100644 index a99cd0e..0000000 --- a/dsa-check.c +++ /dev/null @@ -1,89 +0,0 @@ -/* -*-c-*- - * - * $Id: dsa-check.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Consistency checking for DSA keys - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "dh.h" -#include "dsa.h" -#include "dsarand.h" -#include "grand.h" -#include "keycheck.h" -#include "mp.h" -#include "mprand.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @dsa_checkparam@ --- * - * - * Arguments: @keycheck *kc@ = keycheck state - * @const dsa_param *dp@ = pointer to the parameter set - * @const dsa_seed *ds@ = pointer to seed information - * - * Returns: Zero if all OK, or return status from function. - * - * Use: Checks a set of DSA parameters for consistency and security. - */ - -int dsa_checkparam(keycheck *kc, const dsa_param *dp, const dsa_seed *ds) -{ - if (ds) { - grand *r = dsarand_create(ds->p, ds->sz); - mp *p = MP_NEW, *q = MP_NEW; - int rc = 0; - unsigned i; - unsigned long n; - - r->ops->misc(r, DSARAND_PASSES, 2); - q = mprand(q, mp_bits(dp->q), r, 1); - if (!mp_eq(q, dp->q) && - keycheck_report(kc, KCSEV_ERR, "q doesn't match seed provided")) - rc = -1; - else { - n = mp_bits(dp->p); - r->ops->misc(r, DSARAND_PASSES, 1); - for (i = 0; i <= ds->count; i++) - p = mprand(p, n, r, 0); - q = mp_lsl(q, q, 1); - mp_div(0, &q, p, q); - p = mp_sub(p, p, q); - p->v[0] |= 1; - if (!mp_eq(p, dp->p) && - keycheck_report(kc, KCSEV_ERR, "p doesn't match seed provided")) - rc = -1; - } - mp_drop(p); - mp_drop(q); - r->ops->destroy(r); - if (rc) - return (rc); - } - return (dh_checkparam(kc, dp, 0, 0)); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/dsa-gen.c b/dsa-gen.c deleted file mode 100644 index adb8d9a..0000000 --- a/dsa-gen.c +++ /dev/null @@ -1,301 +0,0 @@ -/* -*-c-*- - * - * $Id: dsa-gen.c,v 1.10 2004/04/08 01:36:15 mdw Exp $ - * - * Generate DSA shared parameters - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include "dsa.h" -#include "dsarand.h" -#include "fibrand.h" -#include "mp.h" -#include "mprand.h" -#include "pgen.h" -#include "prim.h" -#include "sha.h" - -/*----- The DSA stepper ---------------------------------------------------*/ - -/* --- @next@ --- * - * - * Arguments: @pgen_event *ev@ = pointer to event block - * @dsa_stepctx *d@ = pointer to stepping context - * - * Returns: A @PGEN@ result code. - * - * Use: Steps the generator once, reads the result, and tests it. - */ - -static int next(pgen_event *ev, dsa_stepctx *d) -{ - mp *m; - int rc; - - /* --- Load the new candidate --- */ - - if (d->seedbuf) - d->r->ops->misc(d->r, DSARAND_GETSEED, d->seedbuf); - m = mprand(ev->m, d->bits, d->r, 0); - - /* --- Force to be a multiple of @q@ --- */ - - if (d->q) { - mp *r = MP_NEW; - mp_div(0, &r, m, d->q); - m = mp_sub(m, m, r); - mp_drop(r); - } - m->v[0] |= d->or; - ev->m = m; - - /* --- Do the trial division --- */ - - rc = pfilt_smallfactor(m); - d->count++; - - /* --- Return the result --- */ - - return (rc); -} - -/* --- @dsa_step@ --- */ - -int dsa_step(int rq, pgen_event *ev, void *p) -{ - dsa_stepctx *d = p; - - switch (rq) { - case PGEN_BEGIN: - case PGEN_TRY: - return (next(ev, d)); - case PGEN_DONE: - return (PGEN_DONE); - } - return (PGEN_ABORT); -} - -/*----- Glue code ---------------------------------------------------------*/ - -/* --- @dsa_gen@ --- * - * - * Arguments: @dsa_param *dp@ = where to store parameters - * @unsigned ql@ = length of @q@ in bits - * @unsigned pl@ = length of @p@ in bits - * @unsigned steps@ = number of steps to find @q@ - * @const void *k@ = pointer to key material - * @size_t sz@ = size of key material - * @dsa_seed *ds@ = optional pointer for output seed information - * @pgen_proc *event@ = event handler function - * @void *ectx@ = argument for event handler - * - * Returns: @PGEN_DONE@ if everything worked ok; @PGEN_ABORT@ otherwise. - * - * Use: Generates the DSA shared parameters from a given seed value. - * - * The parameters are a prime %$q$%, relatively small, and a - * large prime %$p = kq + 1$% for some %$k$%, together with a - * generator %$g$% of the cyclic subgroup of order %$q$%. These - * are actually the same as the Diffie-Hellman parameter set, - * but the generation algorithm is different. - * - * The algorithm used is a compatible extension of the method - * described in the DSA standard, FIPS 186. The standard - * requires that %$q$% be 160 bits in size (i.e., @ql == 160@) - * and that the length of %$p$% be %$L = 512 + 64l$% for some - * %$l$%. Neither limitation applies to this implementation. - */ - -int dsa_gen(dsa_param *dp, unsigned ql, unsigned pl, unsigned steps, - const void *k, size_t sz, dsa_seed *ds, - pgen_proc *event, void *ectx) -{ - dsa_stepctx s; - prim_ctx p; - int i; - rabin r; - mp *qc; - - /* --- Initialize the stepping context --- */ - - s.r = dsarand_create(k, sz); - - /* --- Find @q@ --- */ - - s.q = 0; - s.r->ops->misc(s.r, DSARAND_PASSES, 2); - s.bits = ql; - s.count = 0; - s.or = 1; - if (!ds) - s.seedbuf = 0; - else { - ds->sz = sz; - ds->p = s.seedbuf = xmalloc(sz); - } - if ((dp->q = pgen("q", MP_NEW, MP_NEW, event, ectx, steps, dsa_step, &s, - rabin_iters(ql), pgen_test, &r)) == 0) - goto fail_q; - - /* --- Find @p@ --- */ - - s.count = ~0; - s.q = mp_lsl(MP_NEW, dp->q, 1); - s.r->ops->misc(s.r, DSARAND_PASSES, 1); - s.bits = pl; - s.seedbuf = 0; - if ((dp->p = pgen("p", MP_NEW, MP_NEW, event, ectx, 4096, dsa_step, &s, - rabin_iters(pl), pgen_test, &r)) == 0) - goto fail_p; - mp_drop(s.q); - if (ds) - ds->count = s.count; - - /* --- Find @g@ --- * - * - * The division returns remainder 1. This doesn't matter. - */ - - mpmont_create(&p.mm, dp->p); - qc = MP_NEW; mp_div(&qc, 0, dp->p, dp->q); - i = 0; - p.exp = qc; - p.n = 0; - if ((dp->g = pgen("g", MP_NEW, MP_NEW, event, ectx, 0, prim_step, &i, - 1, prim_test, &p)) == 0) - goto fail_g; - - /* --- Done --- */ - - mp_drop(qc); - mpmont_destroy(&p.mm); - s.r->ops->destroy(s.r); - return (PGEN_DONE); - - /* --- Tidy up when things go wrong --- */ - -fail_g: - mp_drop(qc); - mpmont_destroy(&p.mm); -fail_p: - mp_drop(dp->q); - mp_drop(s.q); -fail_q: - s.r->ops->destroy(s.r); - if (ds) - xfree(ds->p); - return (PGEN_ABORT); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int verify(dstr *v) -{ - mp *q = *(mp **)v[4].buf; - mp *p = *(mp **)v[5].buf; - mp *g = *(mp **)v[6].buf; - dsa_param dp; - dsa_seed ds; - unsigned long l = *(unsigned long *)v[1].buf; - unsigned long n = *(unsigned long *)v[3].buf; - int ok = 1; - int rc; - keycheck kc; - keycheck_reportctx kcr; - - rc = dsa_gen(&dp, 160, l, 16, v[0].buf, v[0].len, &ds, pgen_evspin, 0); - if (rc || ds.count != n || ds.sz != v[2].len || - memcmp(ds.p, v[2].buf, v[2].len) != 0 || - !MP_EQ(q, dp.q) || !MP_EQ(p, dp.p) || !MP_EQ(g, dp.g)) { - fputs("\n*** gen failed", stderr); - fputs("\nseed_in = ", stderr); type_hex.dump(&v[0], stderr); - fprintf(stderr, "\nl = %lu", l); - fputs("\nseed_out = ", stderr); type_hex.dump(&v[2], stderr); - fprintf(stderr, "\ncount = %lu", n); - fputs("\n q = ", stderr); mp_writefile(q, stderr, 16); - fputs("\n p = ", stderr); mp_writefile(p, stderr, 16); - fputs("\n g = ", stderr); mp_writefile(g, stderr, 16); - if (!rc) { - dstr d; - d.buf = ds.p; d.len = ds.sz; - fputs("\nds.seed = ", stderr); type_hex.dump(&d, stderr); - fprintf(stderr, "\nds.count = %u", ds.count); - fputs("\ndp.q = ", stderr); mp_writefile(dp.q, stderr, 16); - fputs("\ndp.p = ", stderr); mp_writefile(dp.p, stderr, 16); - fputs("\ndp.g = ", stderr); mp_writefile(dp.g, stderr, 16); - } - fputc('\n', stderr); - ok = 0; - } - - kcr.fp = stderr; - kcr.sev = KCSEV_ERR; - keycheck_init(&kc, keycheck_stdreport, &kcr); - if (!rc) - dsa_checkparam(&kc, &dp, &ds); - if (!keycheck_allclear(&kc, KCSEV_ERR)) { - fputs("\n*** gen failed check", stderr); - fputs("\nseed_in = ", stderr); type_hex.dump(&v[0], stderr); - fprintf(stderr, "\nl = %lu", l); - fputs("\nseed_out = ", stderr); type_hex.dump(&v[2], stderr); - fprintf(stderr, "\ncount = %lu", n); - fputs("\n q = ", stderr); mp_writefile(q, stderr, 16); - fputs("\n p = ", stderr); mp_writefile(p, stderr, 16); - fputs("\n g = ", stderr); mp_writefile(g, stderr, 16); - fputc('\n', stderr); - ok = 0; - } - - mp_drop(q); mp_drop(p); mp_drop(g); - if (!rc) { - mp_drop(dp.q); mp_drop(dp.p); mp_drop(dp.g); xfree(ds.p); - } - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "gen", verify, - { &type_hex, &type_ulong, &type_hex, &type_ulong, - &type_mp, &type_mp, &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/dsa"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/dsa-sign.c b/dsa-sign.c deleted file mode 100644 index 9d30dd9..0000000 --- a/dsa-sign.c +++ /dev/null @@ -1,200 +0,0 @@ -/* -*-c-*- - * - * $Id: dsa-sign.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * DSA signing operation - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "dsa.h" -#include "mp.h" -#include "mpbarrett.h" -#include "mpmont.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @dsa_mksig@ --- * - * - * Arguments: @const dsa_param *dp@ = pointer to DSA parameters - * @mp *a@ = secret signing key - * @mp *m@ = message to be signed - * @mp *k@ = random data - * @mp **rr, **ss@ = where to put output parameters - * - * Returns: --- - * - * Use: Computes a DSA signature of a message. - */ - -void dsa_mksig(const dsa_param *dp, mp *a, mp *m, mp *k, mp **rr, mp **ss) -{ - mpmont pm; - mpbarrett qb; - mp *k1, *r; - mp *ar; - - /* --- Compute %$r = (g^k \bmod p) \bmod q$% --- */ - - mpmont_create(&pm, dp->p); - r = mpmont_exp(&pm, MP_NEW, dp->g, k); - mpmont_destroy(&pm); - mp_div(0, &r, r, dp->q); - - /* --- Compute %$k^{-1} \bmod q$% --- */ - - k1 = mp_modinv(MP_NEW, k, dp->q); - - /* --- Now for %$k^{-1}(m + ar)$% --- */ - - mpbarrett_create(&qb, dp->q); - ar = mp_mul(MP_NEW, a, r); - ar = mp_add(ar, ar, m); - ar = mpbarrett_reduce(&qb, ar, ar); - ar = mp_mul(ar, ar, k1); - ar = mpbarrett_reduce(&qb, ar, ar); - mpbarrett_destroy(&qb); - MP_DROP(k1); - if (*rr) MP_DROP(*rr); - if (*ss) MP_DROP(*ss); - *rr = r; - *ss = ar; -} - -/* --- @dsa_sign@ --- * - * - * Arguments: @dsa_param *dp@ = pointer to DSA parameters - * @mp *a@ = pointer to secret signing key - * @const void *m@ = pointer to message - * @size_t msz@ = size of the message - * @const void *k@ = secret random data for securing signature - * @size_t ksz@ = size of secret data - * @void *r@ = pointer to output space for @r@ - * @size_t rsz@ = size of output space for @r@ - * @void *s@ = pointer to output space for @s@ - * @size_t ssz@ = size of output space for @s@ - * - * Returns: --- - * - * Use: Signs a message, storing the results in a big-endian binary - * form. - */ - -void dsa_sign(dsa_param *dp, mp *a, - const void *m, size_t msz, const void *k, size_t ksz, - void *r, size_t rsz, void *s, size_t ssz) -{ - mp *mm = dsa_h2n(MP_NEW, dp->q, m, msz); - mp *km = mp_loadb(MP_NEW, k, ksz); - mp *rm = MP_NEW, *sm = MP_NEW; - dsa_mksig(dp, a, mm, km, &rm, &sm); - mp_storeb(rm, r, rsz); - mp_storeb(sm, s, ssz); - mp_drop(mm); mp_drop(km); - mp_drop(rm); mp_drop(sm); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#include "sha.h" - -static int verify(dstr *v) -{ - dsa_param dp; - mp *x; - sha_ctx c; - octet hash[SHA_HASHSZ]; - dsa_sig s; - int ok = 1; - - dp.q = *(mp **)v[0].buf; - dp.p = *(mp **)v[1].buf; - dp.g = *(mp **)v[2].buf; - x = *(mp **)v[3].buf; - - sha_init(&c); - sha_hash(&c, v[4].buf, v[4].len); - sha_done(&c, hash); - - dsa_sign(&dp, x, hash, sizeof(hash), v[5].buf, v[5].len, - s.r, sizeof(s.r), s.s, sizeof(s.s)); - - if (v[6].len != sizeof(s.r) || v[7].len != sizeof(s.s) || - memcmp(s.r, v[6].buf, sizeof(s.r)) != 0 || - memcmp(s.s, v[7].buf, sizeof(s.s)) != 0) { - fputs("\n*** signature failed", stderr); - fputs("\nq = ", stderr); mp_writefile(dp.q, stderr, 16); - fputs("\np = ", stderr); mp_writefile(dp.p, stderr, 16); - fputs("\ng = ", stderr); mp_writefile(dp.g, stderr, 16); - fputs("\nx = ", stderr); mp_writefile(x, stderr, 16); - fprintf(stderr, "\nmessage = `%s'", v[4].buf); - fputs("\nk = ", stderr); type_hex.dump(&v[5], stderr); - fputs("\nR = ", stderr); type_hex.dump(&v[6], stderr); - fputs("\nS = ", stderr); type_hex.dump(&v[7], stderr); - - { - mp *m = MP_NEW; - m = mp_loadb(m, hash, sizeof(hash)); - fputs("\nm = ", stderr); mp_writefile(m, stderr, 16); - m = mp_loadb(m, s.r, sizeof(s.r)); - fputs("\nr = ", stderr); mp_writefile(m, stderr, 16); - m = mp_loadb(m, s.s, sizeof(s.s)); - fputs("\ns = ", stderr); mp_writefile(m, stderr, 16); - mp_drop(m); - } - - fputc('\n', stderr); - ok = 0; - } - - mp_drop(dp.p); - mp_drop(dp.q); - mp_drop(dp.g); - mp_drop(x); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "sign", verify, - { &type_mp, &type_mp, &type_mp, &type_mp, - &type_string, &type_hex, &type_hex, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/dsa"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/dsa-verify.c b/dsa-verify.c deleted file mode 100644 index 90895b4..0000000 --- a/dsa-verify.c +++ /dev/null @@ -1,207 +0,0 @@ -/* -*-c-*- - * - * $Id: dsa-verify.c,v 1.7 2004/04/08 01:36:15 mdw Exp $ - * - * DSA signature verification - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "dsa.h" -#include "mp.h" -#include "mpmont.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @dsa_vrfy@ --- * - * - * Arguments: @const dsa_param *dp@ = pointer to DSA parameters - * @mp *y@ = public verification key - * @mp *m@ = message which was signed - * @mp *r, *s@ = the signature - * - * Returns: Zero if the signature is a forgery, nonzero if it's valid. - * - * Use: Verifies a DSA digital signature. - */ - -int dsa_vrfy(const dsa_param *dp, mp *y, mp *m, mp *r, mp *s) -{ - mpmont pm, qm; - mp *w; - mp_expfactor f[2]; - int ok; - - /* --- Ensure that all of the signature bits are in range --- */ - - if ((r->f | s->f) & MP_NEG) - return (0); - if (MP_CMP(r, >=, dp->q) || MP_CMP(s, >=, dp->q)) - return (0); - - /* --- Set up Montgomery contexts --- */ - - mpmont_create(&pm, dp->p); - mpmont_create(&qm, dp->q); - - /* --- Compute %$w = s^{-1} \bmod q$% --- */ - - { - mp *z = mp_modinv(MP_NEW, s, dp->q); - w = mpmont_mul(&qm, MP_NEW, z, qm.r2); - mp_drop(z); - } - - /* --- Compute %$wr$% and %$wm$% --- */ - - f[0].exp = mpmont_mul(&qm, MP_NEW, w, m); - f[1].exp = mpmont_mul(&qm, MP_NEW, w, r); - mp_drop(w); - mpmont_destroy(&qm); - - /* --- Do the exponentiation and take residue mod @q@ --- */ - - f[0].base = dp->g; - f[1].base = y; - w = mpmont_mexp(&pm, MP_NEW, f, 2); - mp_div(0, &w, w, dp->q); - ok = MP_EQ(w, r); - - /* --- Tidy up --- */ - - mp_drop(w); - mp_drop(f[0].exp); - mp_drop(f[1].exp); - mpmont_destroy(&pm); - return (ok); -} - -/* --- @dsa_verify@ --- * - * - * Arguments: @const dsa_param *dp@ = pointer to DSA parameters - * @mp *y@ = public verification key - * @const void *m@ = pointer to message block - * @size_t msz@ = size of message block - * @const void *r@ = pointer to @r@ signature half - * @size_t rsz@ = size of @r@ - * @const void *s@ = pointer to @s@ signature half - * @size_t ssz@ = size of @s@ - * - * Returns: Zero if the signature is a forgery, nonzero if it's valid. - * - * Use: Verifies a DSA digital signature. - */ - -int dsa_verify(const dsa_param *dp, mp *y, - const void *m, size_t msz, - const void *r, size_t rsz, - const void *s, size_t ssz) -{ - mp *mm = dsa_h2n(MP_NEW, dp->q, m, msz); - mp *rm = mp_loadb(MP_NEW, r, rsz); - mp *sm = mp_loadb(MP_NEW, s, ssz); - int ok = dsa_vrfy(dp, y, mm, rm, sm); - mp_drop(mm); - mp_drop(rm); - mp_drop(sm); - return (ok); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#include "sha.h" - -static int verify(int good, dstr *v) -{ - dsa_param dp; - mp *y; - sha_ctx c; - octet hash[SHA_HASHSZ]; - int ok = 1; - int rc; - - dp.q = *(mp **)v[0].buf; - dp.p = *(mp **)v[1].buf; - dp.g = *(mp **)v[2].buf; - y = *(mp **)v[3].buf; - - sha_init(&c); - sha_hash(&c, v[4].buf, v[4].len); - sha_done(&c, hash); - - rc = dsa_verify(&dp, y, hash, sizeof(hash), - v[5].buf, v[5].len, v[6].buf, v[6].len); - - if (!rc != !good) { - if (good) - fputs("\n*** verification failed", stderr); - else - fputs("\n*** verification succeeded", stderr); - fputs("\nq = ", stderr); mp_writefile(dp.q, stderr, 16); - fputs("\np = ", stderr); mp_writefile(dp.p, stderr, 16); - fputs("\ng = ", stderr); mp_writefile(dp.g, stderr, 16); - fputs("\ny = ", stderr); mp_writefile(y, stderr, 16); - fprintf(stderr, "\nmessage = `%s'", v[4].buf); - fputs("\nr = ", stderr); type_hex.dump(&v[5], stderr); - fputs("\ns = ", stderr); type_hex.dump(&v[6], stderr); - fputc('\n', stderr); - ok = 0; - } - - mp_drop(dp.p); - mp_drop(dp.q); - mp_drop(dp.g); - mp_drop(y); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vgood(dstr *v) { return verify(1, v); } -static int vbad(dstr *v) { return verify(0, v); } - -static test_chunk tests[] = { - { "verify-good", vgood, - { &type_mp, &type_mp, &type_mp, &type_mp, - &type_string, &type_hex, &type_hex, 0 } }, - { "verify-bad", vbad, - { &type_mp, &type_mp, &type_mp, &type_mp, - &type_string, &type_hex, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/dsa"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/dsa.h b/dsa.h deleted file mode 100644 index 43ff845..0000000 --- a/dsa.h +++ /dev/null @@ -1,279 +0,0 @@ -/* -*-c-*- - * - * $Id: dsa.h,v 1.9 2004/04/08 01:36:15 mdw Exp $ - * - * Digital Signature Algorithm - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_DSA_H -#define CATACOMB_DSA_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Notes on the Digital Signature Algorithm --------------------------* - * - * The Digital Signature Algorithm was designed by the NSA for US Government - * use. It's defined in FIPS 186-1. Whether it's covered by patents is - * under dispute, although it looks relatively clear. It produces compact - * signatures, and is relatively easy to compute. It seems strong, if - * appropriate parameters are chosen. - */ - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_DH_H -# include "dh.h" -#endif - -#ifndef CATACOMB_KEY_H -# include "key.h" -#endif - -#ifndef CATACOMB_KEYCHECK_H -# include "keycheck.h" -#endif - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_PGEN_H -# include "pgen.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- The parameters and keys are the same as for Diffie-Hellman --- */ - -typedef dh_param dsa_param; -typedef dh_pub dsa_pub; -typedef dh_priv dsa_priv; - -/* --- DSA key seed structure --- */ - -typedef struct dsa_seed { - void *p; /* Pointer to seed material */ - size_t sz; /* Size of seed material */ - unsigned count; /* Iterations to find @p@ */ -} dsa_seed; - -/* --- DSA signature structure --- * - * - * This is the recommended structure for a DSA signature. The actual signing - * function can cope with arbitrary-sized objects given appropriate - * parameters, however. - */ - -#define DSA_SIGLEN 20 - -typedef struct dsa_sig { - octet r[DSA_SIGLEN]; /* 160-bit @r@ value */ - octet s[DSA_SIGLEN]; /* 160-bit @s@ value */ -} dsa_sig; - -/*----- Key fetching ------------------------------------------------------*/ - -#define dsa_paramfetch dh_paramfetch -#define dsa_pubfetch dh_pubfetch -#define dsa_privfetch dh_privfetch - -#define DSA_PARAMFETCHSZ DH_PARAMFETCHSZ -#define DSA_PUBFETCHSZ DH_PUBFETCHSZ -#define DSA_PRIVFETCHSZ DH_PRIVFETCHSZ - -#define dsa_paramfree dh_paramfree -#define dsa_pubfree dh_pubfree -#define dsa_privfree dh_privfree - -/*----- DSA stepper -------------------------------------------------------*/ - -typedef struct dsa_stepctx { - - /* --- To be initialized by the client --- */ - - grand *r; /* Random number generator */ - mp *q; /* Force @p@ to be a multiple */ - size_t bits; /* Number of bits in the result */ - unsigned or; /* OR mask for low order bits */ - unsigned count; /* Counts the number of steps made */ - void *seedbuf; /* Pointer to seed buffer */ -} dsa_stepctx; - -/* --- @dsa_step@ --- * - * - * The stepper chooses random integers, ensures that they are a multiple of - * @q@ (if specified), sets the low-order bits, and then tests for - * divisibility by small primes. - */ - -extern pgen_proc dsa_step; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @dsa_gen@ --- * - * - * Arguments: @dsa_param *dp@ = where to store parameters - * @unsigned ql@ = length of @q@ in bits - * @unsigned pl@ = length of @p@ in bits - * @unsigned steps@ = number of steps to find @q@ - * @const void *k@ = pointer to key material - * @size_t sz@ = size of key material - * @dsa_seed *sd@ = optional pointer for output seed information - * @pgen_proc *event@ = event handler function - * @void *ectx@ = argument for event handler - * - * Returns: @PGEN_DONE@ if everything worked ok; @PGEN_ABORT@ otherwise. - * - * Use: Generates the DSA shared parameters from a given seed value. - * This can take quite a long time. - * - * The algorithm used is a compatible extension of the method - * described in the DSA standard, FIPS 186. The standard - * requires that %$q$% be 160 bits in size (i.e., @ql == 160@) - * and that the length of %$p$% be %$L = 512 + 64l$% for some - * %$l$%. Neither limitation applies to this implementation. - */ - -extern int dsa_gen(dsa_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/, - unsigned /*steps*/, const void */*k*/, size_t /*sz*/, - dsa_seed */*sd*/, pgen_proc */*event*/, void */*ectx*/); - -/* --- @dsa_checkparam@ --- * - * - * Arguments: @keycheck *kc@ = keycheck state - * @const dsa_param *dp@ = pointer to the parameter set - * @const dsa_seed *ds@ = pointer to seed information - * - * Returns: Zero if all OK, or return status from function. - * - * Use: Checks a set of DSA parameters for consistency and security. - */ - -extern int dsa_checkparam(keycheck */*kc*/, const dsa_param */*dp*/, - const dsa_seed */*ds*/); - -/* --- @dsa_h2n@ --- * - * - * Arguments: @mp *d@ = destination integer - * @mp *r@ = order of the DSA group - * @const void *h@ = pointer to message hash - * @size_t hsz@ = size (in bytes) of the hash output - * - * Returns: Resulting integer. - * - * Use: Converts a hash to an integer in the demented way necessary - * for DSA/ECDSA. This is, of course, completely insane, but - * there you go. - */ - -extern mp *dsa_h2n(mp */*d*/, mp */*r*/, const void */*h*/, size_t /*hsz*/); - -/* --- @dsa_mksig@ --- * - * - * Arguments: @const dsa_param *dp@ = pointer to DSA parameters - * @mp *a@ = secret signing key - * @mp *m@ = message to be signed - * @mp *k@ = random data - * @mp **rr, **ss@ = where to put output parameters - * - * Returns: --- - * - * Use: Computes a DSA signature of a message. - */ - -extern void dsa_mksig(const dsa_param */*dp*/, mp */*a*/, - mp */*m*/, mp */*k*/, - mp **/*rr*/, mp **/*ss*/); - -/* --- @dsa_sign@ --- * - * - * Arguments: @dsa_param *dp@ = pointer to DSA parameters - * @mp *a@ = pointer to secret signing key - * @const void *m@ = pointer to message - * @size_t msz@ = size of the message - * @const void *k@ = secret random data for securing signature - * @size_t ksz@ = size of secret data - * @void *r@ = pointer to output space for @r@ - * @size_t rsz@ = size of output space for @r@ - * @void *s@ = pointer to output space for @s@ - * @size_t ssz@ = size of output space for @s@ - * - * Returns: --- - * - * Use: Signs a message, storing the results in a big-endian binary - * form. - */ - -extern void dsa_sign(dsa_param */*dp*/, mp */*a*/, - const void */*m*/, size_t /*msz*/, - const void */*k*/, size_t /*ksz*/, - void */*r*/, size_t /*rsz*/, - void */*s*/, size_t /*ssz*/); - -/* --- @dsa_vrfy@ --- * - * - * Arguments: @const dsa_param *dp@ = pointer to DSA parameters - * @mp *y@ = public verification key - * @mp *m@ = message which was signed - * @mp *r, *s@ = the signature - * - * Returns: Zero if the signature is a forgery, nonzero if it's valid. - * - * Use: Verifies a DSA digital signature. - */ - -extern int dsa_vrfy(const dsa_param */*dp*/, mp */*y*/, - mp */*m*/, mp */*r*/, mp */*s*/); - -/* --- @dsa_verify@ --- * - * - * Arguments: @const dsa_param *dp@ = pointer to DSA parameters - * @mp *y@ = public verification key - * @const void *m@ = pointer to message block - * @size_t msz@ = size of message block - * @const void *r@ = pointer to @r@ signature half - * @size_t rsz@ = size of @r@ - * @const void *s@ = pointer to @s@ signature half - * @size_t ssz@ = size of @s@ - * - * Returns: Zero if the signature is a forgery, nonzero if it's valid. - * - * Use: Verifies a DSA digital signature. - */ - -extern int dsa_verify(const dsa_param */*dp*/, mp */*y*/, - const void */*m*/, size_t /*msz*/, - const void */*r*/, size_t /*rsz*/, - const void */*s*/, size_t /*ssz*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/dsarand.c b/dsarand.c deleted file mode 100644 index 5372b3f..0000000 --- a/dsarand.c +++ /dev/null @@ -1,337 +0,0 @@ -/* -*-c-*- - * - * $Id: dsarand.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Random number generator for DSA - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include -#include -#include - -#include "dsarand.h" -#include "grand.h" -#include "sha.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @STEP@ --- * - * - * Arguments: @dsarand *d@ = pointer to context - * - * Use: Increments the buffer by one, interpreting it as a big-endian - * integer. Carries outside the integer are discarded. - */ - -#define STEP(d) do { \ - dsarand *_d = (d); \ - octet *_p = _d->p; \ - octet *_q = _p + _d->sz; \ - unsigned _c = 1; \ - while (_c && _q > _p) { \ - _c += *--_q; \ - *_q = U8(_c); \ - _c >>= 8; \ - } \ -} while (0) - -/* --- @dsarand_init@ --- * - * - * Arguments: @dsarand *d@ = pointer to context - * @const void *p@ = pointer to seed buffer - * @size_t sz@ = size of the buffer - * - * Returns: --- - * - * Use: Initializes a DSA random number generator. - */ - -void dsarand_init(dsarand *d, const void *p, size_t sz) -{ - d->p = xmalloc(sz); - d->sz = sz; - d->passes = 1; - if (p) - memcpy(d->p, p, sz); -} - -/* --- @dsarand_reseed@ --- * - * - * Arguments: @dsarand *d@ = pointer to context - * @const void *p@ = pointer to seed buffer - * @size_t sz@ = size of the buffer - * - * Returns: --- - * - * Use: Initializes a DSA random number generator. - */ - -void dsarand_reseed(dsarand *d, const void *p, size_t sz) -{ - xfree(d->p); - d->p = xmalloc(sz); - d->sz = sz; - d->passes = 1; - if (p) - memcpy(d->p, p, sz); -} - -/* --- @dsarand_destroy@ --- * - * - * Arguments: @dsarand *d@ = pointer to context - * - * Returns: --- - * - * Use: Disposes of a DSA random number generation context. - */ - -void dsarand_destroy(dsarand *d) -{ - xfree(d->p); -} - -/* --- @dsarand_fill@ --- * - * - * Arguments: @dsarand *d@ = pointer to context - * @void *p@ = pointer to output buffer - * @size_t sz@ = size of output buffer - * - * Returns: --- - * - * Use: Fills an output buffer with pseudorandom data. - * - * Let %$p$% be the numerical value of the input buffer, and let - * %$b$% be the number of bytes required. Let - * %$z = \lceil b / 20 \rceil$% be the number of SHA outputs - * required. Then the output of pass %$n$% is - * - * %$P_n = \sum_{0 \le i < z} 2^{160i} SHA(p + nz + i)$% - * %${} \bmod 2^{8b}$% - * - * and the actual result in the output buffer is the XOR of all - * of the output passes. - * - * The DSA procedure for choosing @q@ involves two passes with - * %$z = 1$%; the procedure for choosing @p@ involves one pass - * with larger %$z$%. This generalization of the DSA generation - * procedure is my own invention but it seems relatively sound. - */ - -void dsarand_fill(dsarand *d, void *p, size_t sz) -{ - octet *q = p; - unsigned n = d->passes; - - /* --- Write out the first pass --- * - * - * This can write directly to the output buffer, so it's done differently - * from the latter passes. - */ - - { - size_t o = sz; - - while (o) { - sha_ctx h; - - /* --- Hash the input buffer --- */ - - sha_init(&h); - sha_hash(&h, d->p, d->sz); - - /* --- If enough space, extract the hash output directly --- */ - - if (o >= SHA_HASHSZ) { - o -= SHA_HASHSZ; - sha_done(&h, q + o); - } - - /* --- Otherwise take the hash result out of line and copy it --- */ - - else { - octet hash[SHA_HASHSZ]; - sha_done(&h, hash); - memcpy(q, hash + (SHA_HASHSZ - o), o); - o = 0; - } - - /* --- Step the input buffer --- */ - - STEP(d); - } - - /* --- Another pass has been done --- */ - - n--; - } - - /* --- Write out subsequent passes --- * - * - * The hash output has to be done offline, so this is slightly easier. - */ - - while (n) { - size_t o = sz; - - while (o) { - sha_ctx h; - octet hash[SHA_HASHSZ]; - size_t n; - octet *pp, *qq; - - /* --- Hash the input buffer --- */ - - sha_init(&h); - sha_hash(&h, d->p, d->sz); - sha_done(&h, hash); - - /* --- Work out how much output is wanted --- */ - - n = SHA_HASHSZ; - if (n > o) - n = o; - o -= n; - - /* --- XOR the data out --- */ - - for (pp = hash + (SHA_HASHSZ - n), qq = q + o; - pp < hash + SHA_HASHSZ; pp++, qq++) - *qq ^= *pp; - - /* --- Step the input buffer --- */ - - STEP(d); - } - - /* --- Another pass is done --- */ - - n--; - } -} - -/*----- Generic pseudorandom-number generator interface -------------------*/ - -static const grand_ops gops; - -typedef struct gctx { - grand r; - dsarand d; -} gctx; - -static void gdestroy(grand *r) -{ - gctx *g = (gctx *)r; - dsarand_destroy(&g->d); - DESTROY(g); -} - -static int gmisc(grand *r, unsigned op, ...) -{ - gctx *g = (gctx *)r; - va_list ap; - int rc = 0; - va_start(ap, op); - - switch (op) { - case GRAND_CHECK: - switch (va_arg(ap, unsigned)) { - case GRAND_CHECK: - case GRAND_SEEDBLOCK: - case GRAND_SEEDRAND: - case DSARAND_PASSES: - case DSARAND_SEEDSZ: - case DSARAND_GETSEED: - rc = 1; - break; - default: - rc = 0; - break; - } - break; - case GRAND_SEEDBLOCK: { - const void *p = va_arg(ap, const void *); - size_t sz = va_arg(ap, size_t); - dsarand_reseed(&g->d, p, sz); - } break; - case GRAND_SEEDRAND: { - grand *rr = va_arg(ap, grand *); - rr->ops->fill(rr, g->d.p, g->d.sz); - } break; - case DSARAND_PASSES: - g->d.passes = va_arg(ap, unsigned); - break; - case DSARAND_SEEDSZ: - rc = g->d.sz; - break; - case DSARAND_GETSEED: - memcpy(va_arg(ap, void *), g->d.p, g->d.sz); - break; - default: - GRAND_BADOP; - break; - } - - va_end(ap); - return (rc); -} - -static void gfill(grand *r, void *p, size_t sz) -{ - gctx *g = (gctx *)r; - dsarand_fill(&g->d, p, sz); -} - -static const grand_ops gops = { - "dsarand", - 0, 0, - gmisc, gdestroy, - grand_word, grand_byte, grand_word, grand_range, gfill -}; - -/* --- @dsarand_create@ --- * - * - * Arguments: @const void *p@ = pointer to seed buffer - * @size_t sz@ = size of seed buffer - * - * Returns: Pointer to a generic generator. - * - * Use: Constructs a generic generator interface over a Catacomb - * entropy pool generator. - */ - -grand *dsarand_create(const void *p, size_t sz) -{ - gctx *g = CREATE(gctx); - g->r.ops = &gops; - dsarand_init(&g->d, p, sz); - return (&g->r); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/dsarand.h b/dsarand.h deleted file mode 100644 index bc5e700..0000000 --- a/dsarand.h +++ /dev/null @@ -1,153 +0,0 @@ -/* -*-c-*- - * - * $Id: dsarand.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Random number generator for DSA - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_DSARAND_H -#define CATACOMB_DSARAND_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -#ifndef CATACOMB_SHA_H -# include "sha.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct dsarand { - octet *p; /* Pointer to seed (modified) */ - size_t sz; /* Size of the seed buffer */ - unsigned passes; /* Number of passes to make */ -} dsarand; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @dsarand_init@ --- * - * - * Arguments: @dsarand *d@ = pointer to context - * @const void *p@ = pointer to seed buffer - * @size_t sz@ = size of the buffer - * - * Returns: --- - * - * Use: Initializes a DSA random number generator. - */ - -extern void dsarand_init(dsarand */*d*/, const void */*p*/, size_t /*sz*/); - -/* --- @dsarand_reseed@ --- * - * - * Arguments: @dsarand *d@ = pointer to context - * @const void *p@ = pointer to seed buffer - * @size_t sz@ = size of the buffer - * - * Returns: --- - * - * Use: Initializes a DSA random number generator. - */ - -extern void dsarand_reseed(dsarand */*d*/, const void */*p*/, size_t /*sz*/); - -/* --- @dsarand_destroy@ --- * - * - * Arguments: @dsarand *d@ = pointer to context - * - * Returns: --- - * - * Use: Disposes of a DSA random number generation context. - */ - -extern void dsarand_destroy(dsarand */*d*/); - -/* --- @dsarand_fill@ --- * - * - * Arguments: @dsarand *d@ = pointer to context - * @void *p@ = pointer to output buffer - * @size_t sz@ = size of output buffer - * - * Returns: --- - * - * Use: Fills an output buffer with pseudorandom data. - * - * Let %$p$% be the numerical value of the input buffer, and let - * %$b$% be the number of bytes required. Let - * %$z = \lceil b / 20 \rceil$% be the number of SHA outputs - * required. Then the output of pass %$n$% is - * - * %$P_n = \sum_{0 \le i < z} 2^{160i} SHA(p + nz + i)$% - * %${} \bmod 2^{8b}$% - * - * and the actual result in the output buffer is the XOR of all - * of the output passes. - * - * The DSA procedure for choosing @q@ involves two passes with - * %$z = 1$%; the procedure for choosing @p@ involves one pass - * with larger %$z$%. This generalization of the DSA generation - * procedure is my own invention but it seems relatively sound. - */ - -extern void dsarand_fill(dsarand */*d*/, void */*p*/, size_t /*sz*/); - -/*----- Generic pseudorandom-number generator interface -------------------*/ - -/* --- Miscellaneous operations --- */ - -enum { - DSARAND_PASSES = GRAND_SPECIFIC('D'), /* @unsigned n@ */ - DSARAND_SEEDSZ, /* No args */ - DSARAND_GETSEED /* @void *buf@ */ -}; - -/* --- @dsarand_create@ --- * - * - * Arguments: @const void *p@ = pointer to seed buffer - * @size_t sz@ = size of seed buffer - * - * Returns: Pointer to a generic generator. - * - * Use: Constructs a generic generator interface to a DSA generator. - */ - -extern grand *dsarand_create(const void */*p*/, size_t /*sz*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/dsig.c b/dsig.c deleted file mode 100644 index a7fa5a9..0000000 --- a/dsig.c +++ /dev/null @@ -1,1126 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Verify signatures on distribuitions of files - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _FILE_OFFSET_BITS 64 - -#include "config.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "getdate.h" -#include "rand.h" -#include "ghash.h" -#include "key.h" -#include "key-data.h" -#include "noise.h" -#include "cc.h" - -/*----- Data formatting ---------------------------------------------------*/ - -/* --- Binary data structure --- * - * - * The binary format, which is used for hashing and for the optional binary - * output, consists of a sequence of tagged blocks. The tag describes the - * format and meaining of the following data. - */ - -enum { - /* --- Block tags --- */ - - T_IDENT = 0, /* An identifying marker */ - T_KEYID, /* Key identifier */ - T_BEGIN, /* Begin hashing here */ - T_COMMENT = T_BEGIN, /* A textual comment */ - T_DATE, /* Creation date of signature */ - T_EXPIRE, /* Expiry date of signature */ - T_FILE, /* File and corresponding hash */ - T_SIGNATURE, /* Final signature block */ - - /* --- Error messages --- */ - - E_EOF = -1, - E_BIN = -2, - E_TAG = -3, - E_DATE = -4 -}; - -/* --- Name translation table --- */ - -static const char *tagtab[] = { - "ident:", "keyid:", - "comment:", "date:", "expires:", "file:", - "signature:", - 0 -}; - -static const char *errtab[] = { - "Off-by-one bug", - "Unexpected end-of-file", - "Binary object too large", - "Unrecognized tag", - "Bad date string" -}; - -/* --- Memory representation of block types --- */ - -typedef struct block { - int tag; /* Type tag */ - dstr d; /* String data */ - dstr b; /* Binary data */ - time_t t; /* Timestamp */ - uint32 k; /* Keyid */ -} block; - -/* --- @timestring@ --- * - * - * Arguments: @time_t t@ = a timestamp - * @dstr *d@ = a string to write on - * - * Returns: --- - * - * Use: Writes a textual representation of the timestamp to the - * string. - */ - -static void timestring(time_t t, dstr *d) -{ - if (t == KEXP_FOREVER) - DPUTS(d, "forever"); - else { - struct tm *tm = localtime(&t); - DENSURE(d, 32); - d->len += strftime(d->buf + d->len, 32, "%Y-%m-%d %H:%M:%S %Z", tm); - DPUTZ(d); - } -} - -/* --- @breset@ --- * - * - * Arguments: @block *b@ = block to reset - * - * Returns: --- - * - * Use: Resets a block so that more stuff can be put in it. - */ - -static void breset(block *b) -{ - b->tag = 0; - DRESET(&b->d); - DRESET(&b->b); - b->k = 0; - b->t = KEXP_EXPIRE; -} - -/* --- @binit@ --- * - * - * Arguments: @block *b@ = block to initialize - * - * Returns: --- - * - * Use: Initializes a block as something to read into. - */ - -static void binit(block *b) -{ - dstr_create(&b->d); - dstr_create(&b->b); - breset(b); -} - -/* --- @bdestroy@ --- * - * - * Arguments: @block *b@ = block to destroy - * - * Returns: --- - * - * Use: Destroys a block's contents. - */ - -static void bdestroy(block *b) -{ - dstr_destroy(&b->d); - dstr_destroy(&b->b); -} - -/* --- @bget@ --- * - * - * Arguments: @block *b@ = pointer to block - * @FILE *fp@ = stream to read from - * @unsigned bin@ = binary switch - * - * Returns: Tag of block, or an error tag. - * - * Use: Reads a block from a stream. - */ - -static int bget(block *b, FILE *fp, unsigned bin) -{ - int tag; - - /* --- Read the tag --- */ - - if (bin) - tag = getc(fp); - else { - dstr d = DSTR_INIT; - if (getstring(fp, &d, GSF_FILE)) - return (E_EOF); - for (tag = 0; tagtab[tag]; tag++) { - if (strcmp(tagtab[tag], d.buf) == 0) - goto done; - } - return (E_TAG); - done:; - } - - /* --- Decide what to do next --- */ - - breset(b); - b->tag = tag; - switch (tag) { - - /* --- Reading of strings --- */ - - case T_IDENT: - case T_COMMENT: - if (getstring(fp, &b->d, GSF_FILE | (bin ? GSF_RAW : 0))) - return (E_EOF); - break; - - /* --- Timestamps --- */ - - case T_DATE: - case T_EXPIRE: - if (bin) { - octet buf[8]; - if (fread(buf, sizeof(buf), 1, fp) < 1) - return (E_EOF); - b->t = ((time_t)(((LOAD32(buf + 0) << 16) << 16) & ~MASK32) | - (time_t)LOAD32(buf + 4)); - } else { - if (getstring(fp, &b->d, GSF_FILE)) - return (E_EOF); - if (strcmp(b->d.buf, "forever") == 0) - b->t = KEXP_FOREVER; - else if ((b->t = get_date(b->d.buf, 0)) == -1) - return (E_DATE); - } - break; - - /* --- Key ids --- */ - - case T_KEYID: - if (bin) { - octet buf[4]; - if (fread(buf, sizeof(buf), 1, fp) < 1) - return (E_EOF); - b->k = LOAD32(buf); - } else { - if (getstring(fp, &b->d, GSF_FILE)) - return (E_EOF); - b->k = strtoul(b->d.buf, 0, 16); - } - break; - - /* --- Reading of binary data --- */ - - case T_FILE: - case T_SIGNATURE: - if (bin) { - octet buf[2]; - uint32 sz; - if (fread(buf, sizeof(buf), 1, fp) < 1) - return (E_EOF); - sz = LOAD16(buf); - if (sz > 4096) - return (E_BIN); - DENSURE(&b->b, sz); - if (fread(b->b.buf + b->b.len, 1, sz, fp) < sz) - return (E_EOF); - b->b.len += sz; - } else { - base64_ctx b64; - if (getstring(fp, &b->d, GSF_FILE)) - return (E_EOF); - base64_init(&b64); - base64_decode(&b64, b->d.buf, b->d.len, &b->b); - base64_decode(&b64, 0, 0, &b->b); - DRESET(&b->d); - } - if (tag == T_FILE && - getstring(fp, &b->d, GSF_FILE | (bin ? GSF_RAW : 0))) - return (E_EOF); - break; - - /* --- Anything else --- */ - - default: - return (E_TAG); - } - - return (tag); -} - -/* --- @blob@ --- * - * - * Arguments: @block *b@ = pointer to block to emit - * @dstr *d@ = output buffer - * - * Returns: --- - * - * Use: Encodes a block in a binary format. - */ - -static void blob(block *b, dstr *d) -{ - DPUTC(d, b->tag); - switch (b->tag) { - case T_IDENT: - case T_COMMENT: - DPUTD(d, &b->d); - DPUTC(d, 0); - break; - case T_DATE: - case T_EXPIRE: - DENSURE(d, 8); - if (b->t == KEXP_FOREVER) { - STORE32(d->buf + d->len, 0xffffffff); - STORE32(d->buf + d->len + 4, 0xffffffff); - } else { - STORE32(d->buf + d->len, ((b->t & ~MASK32) >> 16) >> 16); - STORE32(d->buf + d->len + 4, b->t); - } - d->len += 8; - break; - case T_KEYID: - DENSURE(d, 4); - STORE32(d->buf + d->len, b->k); - d->len += 4; - break; - case T_FILE: - case T_SIGNATURE: - DENSURE(d, 2); - STORE16(d->buf + d->len, b->b.len); - d->len += 2; - DPUTD(d, &b->b); - if (b->tag == T_FILE) { - DPUTD(d, &b->d); - DPUTC(d, 0); - } - break; - } -} - -/* --- @bwrite@ --- * - * - * Arguments: @block *b@ = pointer to block to write - * @FILE *fp@ = stream to write on - * - * Returns: --- - * - * Use: Writes a block on a stream in a textual format. - */ - -static void bwrite(block *b, FILE *fp) -{ - fputs(tagtab[b->tag], fp); - putc(' ', fp); - switch (b->tag) { - case T_IDENT: - case T_COMMENT: - putstring(fp, b->d.buf, 0); - break; - case T_DATE: - case T_EXPIRE: { - dstr d = DSTR_INIT; - timestring(b->t, &d); - putstring(fp, d.buf, 0); - dstr_destroy(&d); - } break; - case T_KEYID: - fprintf(fp, "%08lx", (unsigned long)b->k); - break; - case T_FILE: - case T_SIGNATURE: { - dstr d = DSTR_INIT; - base64_ctx b64; - base64_init(&b64); - b64.maxline = 0; - base64_encode(&b64, b->b.buf, b->b.len, &d); - base64_encode(&b64, 0, 0, &d); - dstr_write(&d, fp); - if (b->tag == T_FILE) { - putc(' ', fp); - putstring(fp, b->d.buf, 0); - } - } break; - } - putc('\n', fp); -} - -/* --- @bemit@ --- * - * - * Arguments: @block *b@ = pointer to block to write - * @FILE *fp@ = file to write on - * @ghash *h@ = pointer to hash function - * @unsigned bin@ = binary/text flag - * - * Returns: --- - * - * Use: Spits out a block properly. - */ - -static void bemit(block *b, FILE *fp, ghash *h, unsigned bin) -{ - if (h || (fp && bin)) { - dstr d = DSTR_INIT; - blob(b, &d); - if (h) - GH_HASH(h, d.buf, d.len); - if (fp && bin) - fwrite(d.buf, d.len, 1, fp); - } - if (fp && !bin) - bwrite(b, fp); -} - -/*----- Static variables --------------------------------------------------*/ - -static const char *keyring = "keyring"; - -/*----- Other shared functions --------------------------------------------*/ - -/* --- @fhex@ --- * - * - * Arguments: @FILE *fp@ = file to write on - * @const void *p@ = pointer to data to be written - * @size_t sz@ = size of the data to write - * - * Returns: --- - * - * Use: Emits a hex dump to a stream. - */ - -static void fhex(FILE *fp, const void *p, size_t sz) -{ - const octet *q = p; - if (!sz) - return; - for (;;) { - fprintf(fp, "%02x", *q++); - sz--; - if (!sz) - break; - } -} - -/*----- Signature generation ----------------------------------------------*/ - -static int sign(int argc, char *argv[]) -{ -#define f_bogus 1u -#define f_bin 2u -#define f_nocheck 4u - - unsigned f = 0; - const char *ki = "dsig"; - key_file kf; - key *k; - sig *s; - fhashstate fh; - time_t exp = KEXP_EXPIRE; - unsigned verb = 0; - const char *ifile = 0, *hfile = 0; - const char *ofile = 0; - const char *c = 0; - const char *err; - FILE *ifp, *ofp; - dstr d = DSTR_INIT; - hfpctx hfp; - block b; - int e, hf, n; - - for (;;) { - static struct option opts[] = { - { "null", 0, 0, '0' }, - { "binary", 0, 0, 'b' }, - { "verbose", 0, 0, 'v' }, - { "progress", 0, 0, 'p' }, - { "quiet", 0, 0, 'q' }, - { "comment", OPTF_ARGREQ, 0, 'c' }, - { "file", OPTF_ARGREQ, 0, 'f' }, - { "hashes", OPTF_ARGREQ, 0, 'h' }, - { "output", OPTF_ARGREQ, 0, 'o' }, - { "key", OPTF_ARGREQ, 0, 'k' }, - { "expire", OPTF_ARGREQ, 0, 'e' }, - { "nocheck", OPTF_ARGREQ, 0, 'C' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+0vpqbC" "c:" "f:h:o:" "k:e:", - opts, 0, 0, 0); - if (i < 0) - break; - switch (i) { - case '0': - f |= GSF_RAW; - break; - case 'b': - f |= f_bin; - break; - case 'v': - verb++; - break; - case 'p': - f |= FHF_PROGRESS; - break; - case 'q': - if (verb > 0) - verb--; - break; - case 'C': - f |= f_nocheck; - break; - case 'c': - c = optarg; - break; - case 'f': - ifile = optarg; - break; - case 'h': - hfile = optarg; - break; - case 'o': - ofile = optarg; - break; - case 'k': - ki = optarg; - break; - case 'e': - if (strcmp(optarg, "forever") == 0) - exp = KEXP_FOREVER; - else if ((exp = get_date(optarg, 0)) == -1) - die(EXIT_FAILURE, "bad expiry time"); - break; - default: - f |= f_bogus; - break; - } - } - if (optind != argc || (f & f_bogus)) - die(EXIT_FAILURE, "Usage: sign [-OPTIONS]"); - if (hfile && ifile) - die(EXIT_FAILURE, "Inconsistent options `-h' and `-f'"); - - /* --- Locate the signing key --- */ - - if (key_open(&kf, keyring, KOPEN_WRITE, key_moan, 0)) - die(EXIT_FAILURE, "couldn't open keyring `%s'", keyring); - if ((k = key_bytag(&kf, ki)) == 0) - die(EXIT_FAILURE, "couldn't find key `%s'", ki); - key_fulltag(k, &d); - if (exp == KEXP_FOREVER && k->exp != KEXP_FOREVER) { - die(EXIT_FAILURE, "key `%s' expires: can't create nonexpiring signature", - d.buf); - } - s = getsig(k, "dsig", 1); - - /* --- Check the key --- */ - - if (!(f & f_nocheck) && (err = s->ops->check(s)) != 0) - moan("key `%s' fails check: %s", d.buf, err); - - /* --- Open files --- */ - - if (hfile) ifile = hfile; - if (!ifile || strcmp(ifile, "-") == 0) - ifp = stdin; - else if ((ifp = fopen(ifile, (f & f_bin) ? "rb" : "r")) == 0) { - die(EXIT_FAILURE, "couldn't open input file `%s': %s", - ifile, strerror(errno)); - } - - if (!ofile || strcmp(ofile, "-") == 0) - ofp = stdout; - else if ((ofp = fopen(ofile, (f & f_bin) ? "wb" : "w")) == 0) { - die(EXIT_FAILURE, "couldn't open output file `%s': %s", - ofile, strerror(errno)); - } - - /* --- Emit the start of the output --- */ - - binit(&b); b.tag = T_IDENT; - dstr_putf(&b.d, "%s, Catacomb version " VERSION, QUIS); - bemit(&b, ofp, 0, f & f_bin); - - breset(&b); b.tag = T_KEYID; b.k = k->id; - bemit(&b, ofp, 0, f & f_bin); - - /* --- Start hashing, and emit the datestamps and things --- */ - - { - time_t now = time(0); - - breset(&b); b.tag = T_DATE; b.t = now; bemit(&b, ofp, s->h, f & f_bin); - if (exp == KEXP_EXPIRE) - exp = now + 86400 * 28; - breset(&b); b.tag = T_EXPIRE; b.t = exp; bemit(&b, ofp, s->h, f & f_bin); - if (c) { - breset(&b); b.tag = T_COMMENT; DPUTS(&b.d, c); - bemit(&b, ofp, s->h, f & f_bin); - } - - if (!(f & f_bin)) - putc('\n', ofp); - } - - /* --- Now hash the various files --- */ - - if (hfile) { - hfp.f = f; - hfp.fp = ifp; - hfp.ee = &encodingtab[ENC_HEX]; - hfp.gch = GH_CLASS(s->h); - hfp.dline = &d; - hfp.dfile = &b.d; - - n = 0; - for (;;) { - breset(&b); - DENSURE(&b.b, hfp.gch->hashsz); - hfp.hbuf = (octet *)b.b.buf; - if (ferror(ofp)) { f |= f_bogus; break; } - if ((hf = hfparse(&hfp)) == HF_EOF) break; - n++; - - switch (hf) { - case HF_HASH: - if (hfp.gch != GH_CLASS(s->h)) { - moan("%s:%d: incorrect hash function `%s' (should be `%s')", - hfile, n, hfp.gch->name, GH_CLASS(s->h)->name); - f |= f_bogus; - } - break; - case HF_BAD: - moan("%s:%d: invalid hash-file line", hfile, n); - f |= f_bogus; - break; - case HF_FILE: - b.tag = T_FILE; - b.b.len += hfp.gch->hashsz; - bemit(&b, ofp, s->h, f & f_bin); - break; - } - } - } else { - for (;;) { - - /* --- Stop on an output error --- */ - - if (ferror(ofp)) { - f |= f_bogus; - break; - } - - /* --- Read the next filename to hash --- */ - - fhash_init(&fh, GH_CLASS(s->h), f | FHF_BINARY); - breset(&b); - if (getstring(ifp, &b.d, GSF_FILE | f)) - break; - b.tag = T_FILE; - DENSURE(&b.b, GH_CLASS(s->h)->hashsz); - if (fhash(&fh, b.d.buf, b.b.buf)) { - moan("error reading `%s': %s", b.d.buf, strerror(errno)); - f |= f_bogus; - } else { - b.b.len += GH_CLASS(s->h)->hashsz; - if (verb) { - fhex(stderr, b.b.buf, b.b.len); - fprintf(stderr, " %s\n", b.d.buf); - } - bemit(&b, ofp, s->h, f & f_bin); - } - fhash_free(&fh); - } - } - - /* --- Create the signature --- */ - - if (!(f & f_bogus)) { - breset(&b); - b.tag = T_SIGNATURE; - if ((e = s->ops->doit(s, &b.b)) != 0) { - moan("error creating signature: %s", key_strerror(e)); - f |= f_bogus; - } - if (!(f & f_bogus)) { - bemit(&b, ofp, 0, f & f_bin); - key_used(&kf, k, exp); - } - } - - /* --- Tidy up at the end --- */ - - freesig(s); - bdestroy(&b); - if (ifile) - fclose(ifp); - if (ofile) { - if (fclose(ofp)) - f |= f_bogus; - } else { - if (fflush(ofp)) - f |= f_bogus; - } - if ((e = key_close(&kf)) != 0) { - switch (e) { - case KWRITE_FAIL: - die(EXIT_FAILURE, "couldn't write file `%s': %s", - keyring, strerror(errno)); - case KWRITE_BROKEN: - die(EXIT_FAILURE, "keyring file `%s' broken: %s (repair manually)", - keyring, strerror(errno)); - } - } - if (f & f_bogus) - die(EXIT_FAILURE, "error(s) occurred while creating signature"); - return (EXIT_SUCCESS); - -#undef f_bin -#undef f_bogus -#undef f_nocheck -} - -/*----- Signature verification --------------------------------------------*/ - -static int checkjunk(const char *path, const struct stat *st, void *p) -{ - if (!st) printf("JUNK (error %s) %s\n", strerror(errno), path); - else printf("JUNK %s %s\n", describefile(st), path); - return (0); -} - -static int verify(int argc, char *argv[]) -{ -#define f_bogus 1u -#define f_bin 2u -#define f_ok 4u -#define f_nocheck 8u - - unsigned f = 0; - unsigned verb = 1; - key_file kf; - key *k = 0; - sig *s; - dstr d = DSTR_INIT; - const char *err; - fhashstate fh; - FILE *fp; - block b; - int e; - - /* --- Parse the options --- */ - - for (;;) { - static struct option opts[] = { - { "verbose", 0, 0, 'v' }, - { "progress", 0, 0, 'p' }, - { "quiet", 0, 0, 'q' }, - { "nocheck", 0, 0, 'C' }, - { "junk", 0, 0, 'j' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+vpqCj", opts, 0, 0, 0); - if (i < 0) - break; - switch (i) { - case 'v': - verb++; - break; - case 'p': - f |= FHF_PROGRESS; - break; - case 'q': - if (verb) - verb--; - break; - case 'C': - f |= f_nocheck; - break; - case 'j': - f |= FHF_JUNK; - break; - default: - f |= f_bogus; - break; - } - } - argc -= optind; - argv += optind; - if ((f & f_bogus) || argc > 1) - die(EXIT_FAILURE, "Usage: verify [-qvC] [FILE]"); - - /* --- Open the key file, and start reading the input file --- */ - - if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0)) - die(EXIT_FAILURE, "couldn't open keyring `%s'\n", keyring); - if (argc < 1) - fp = stdin; - else { - if ((fp = fopen(argv[0], "rb")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s': %s\n", - argv[0], strerror(errno)); - } - if (getc(fp) == 0) { - ungetc(0, fp); - f |= f_bin; - } else { - fclose(fp); - if ((fp = fopen(argv[0], "r")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s': %s\n", - argv[0], strerror(errno)); - } - } - } - - /* --- Read the introductory matter --- */ - - binit(&b); - for (;;) { - breset(&b); - e = bget(&b, fp, f & f_bin); - if (e < 0) - die(EXIT_FAILURE, "error reading packet: %s", errtab[-e]); - if (e >= T_BEGIN) - break; - switch (e) { - case T_IDENT: - if (verb > 2) - printf("INFO ident: `%s'\n", b.d.buf); - break; - case T_KEYID: - if ((k = key_byid(&kf, b.k)) == 0) { - if (verb) - printf("FAIL key %08lx not found\n", (unsigned long)b.k); - exit(EXIT_FAILURE); - } - if (verb > 2) { - DRESET(&b.d); - key_fulltag(k, &b.d); - printf("INFO key: %s\n", b.d.buf); - } - break; - default: - die(EXIT_FAILURE, "(internal) unknown packet type\n"); - break; - } - } - - /* --- Initialize the hash function and start reading hashed packets --- */ - - if (!k) { - if (verb) - puts("FAIL no keyid packet found"); - exit(EXIT_FAILURE); - } - - s = getsig(k, "dsig", 0); - if (!(f & f_nocheck) && verb && (err = s->ops->check(s)) != 0) - printf("WARN public key fails check: %s", err); - - fhash_init(&fh, GH_CLASS(s->h), f | FHF_BINARY); - for (;;) { - switch (e) { - case T_COMMENT: - if (verb > 1) - printf("INFO comment: `%s'\n", b.d.buf); - bemit(&b, 0, s->h, 0); - break; - case T_DATE: - if (verb > 2) { - DRESET(&b.d); - timestring(b.t, &b.d); - printf("INFO date: %s\n", b.d.buf); - } - bemit(&b, 0, s->h, 0); - break; - case T_EXPIRE: { - time_t now = time(0); - if (b.t != KEXP_FOREVER && b.t < now) { - if (verb > 1) - puts("BAD signature has expired"); - f |= f_bogus; - } - if (verb > 2) { - DRESET(&b.d); - timestring(b.t, &b.d); - printf("INFO expires: %s\n", b.d.buf); - } - bemit(&b, 0, s->h, 0); - } break; - case T_FILE: - DRESET(&d); - DENSURE(&d, GH_CLASS(s->h)->hashsz); - if (fhash(&fh, b.d.buf, d.buf)) { - if (verb > 1) { - printf("BAD error reading file `%s': %s\n", - b.d.buf, strerror(errno)); - } - f |= f_bogus; - } else if (b.b.len != GH_CLASS(s->h)->hashsz || - memcmp(d.buf, b.b.buf, b.b.len) != 0) { - if (verb > 1) - printf("BAD file `%s' has incorrect hash\n", b.d.buf); - f |= f_bogus; - } else if (verb > 3) { - fputs("INFO hash: ", stdout); - fhex(stdout, b.b.buf, b.b.len); - printf(" %s\n", b.d.buf); - } - bemit(&b, 0, s->h, 0); - break; - case T_SIGNATURE: - if (s->ops->doit(s, &b.b)) { - if (verb > 1) - puts("BAD bad signature"); - f |= f_bogus; - } else if (verb > 2) - puts("INFO good signature"); - goto done; - default: - if (verb) - printf("FAIL invalid packet type %i\n", e); - exit(EXIT_FAILURE); - break; - } - breset(&b); - e = bget(&b, fp, f & f_bin); - if (e < 0) { - if (verb) - printf("FAIL error reading packet: %s\n", errtab[-e]); - exit(EXIT_FAILURE); - } - } -done: - if ((f & FHF_JUNK) && fhash_junk(&fh, checkjunk, 0)) - f |= f_bogus; - fhash_free(&fh); - bdestroy(&b); - dstr_destroy(&d); - freesig(s); - key_close(&kf); - if (fp != stdin) - fclose(fp); - if (verb) { - if (f & f_bogus) - puts("FAIL signature invalid"); - else - puts("OK signature verified"); - } - return (f & f_bogus ? EXIT_FAILURE : EXIT_SUCCESS); - -#undef f_bogus -#undef f_bin -#undef f_ok -#undef f_nocheck -} - -/*----- Main code ---------------------------------------------------------*/ - -#define LISTS(LI) \ - LI("Lists", list, \ - listtab[i].name, listtab[i].name) \ - LI("Signature schemes", sig, \ - sigtab[i].name, sigtab[i].name) \ - LI("Hash functions", hash, \ - ghashtab[i], ghashtab[i]->name) - -MAKELISTTAB(listtab, LISTS) - -int cmd_show(int argc, char *argv[]) -{ - return (displaylists(listtab, argv + 1)); -} - -static int cmd_help(int, char **); - -static cmd cmdtab[] = { - { "help", cmd_help, "help [COMMAND...]" }, - { "show", cmd_show, "show [ITEM...]" }, - { "sign", sign, - "sign [-0bpqvC] [-c COMMENT] [-k TAG] [-e EXPIRE]\n\t\ -[-f FILE] [-h FILE] [-o OUTPUT]", - "\ -Options:\n\ -\n\ --0, --null Read null-terminated filenames from stdin.\n\ --b, --binary Produce a binary output file.\n\ --q, --quiet Produce fewer messages while working.\n\ --v, --verbose Produce more messages while working.\n\ --p, --progress Show progress on large files.\n\ --C, --nocheck Don't check the private key.\n\ --c, --comment=COMMENT Include COMMENT in the output file.\n\ --f, --file=FILE Read filenames to hash from FILE.\n\ --h, --hashes=FILE Read precomputed hashes from FILE.\n\ --o, --output=FILE Write the signed result to FILE.\n\ --k, --key=TAG Use a key named by TAG.\n\ --e, --expire=TIME The signature should expire after TIME.\n\ -" }, - { "verify", verify, - "verify [-pqvC] [FILE]", "\ -Options:\n\ -\n\ --q, --quiet Produce fewer messages while working.\n\ --v, --verbose Produce more messages while working.\n\ --p, --progress Show progress on large files.\n\ --C, --nocheck Don't check the public key.\n\ -" }, - { 0, 0, 0 } -}; - -static int cmd_help(int argc, char **argv) -{ - sc_help(cmdtab, stdout, argv + 1); - return (0); -} - -void version(FILE *fp) -{ - pquis(fp, "$, Catacomb version " VERSION "\n"); -} - -static void usage(FILE *fp) -{ - pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n"); -} - -void help_global(FILE *fp) -{ - usage(fp); - fputs("\n\ -Create and verify signatures on lists of files.\n\ -\n\ -Global command-line options:\n\ -\n\ --h, --help [COMMAND...] Show this help message, or help for COMMANDs.\n\ --v, --version Show program version number.\n\ --u, --usage Show a terse usage message.\n\ -\n\ --k, --keyring=FILE Read keys from FILE.\n", - fp); -} - -/* --- @main@ --- * - * - * Arguments: @int argc@ = number of command line arguments - * @char *argv[]@ = vector of command line arguments - * - * Returns: Zero if successful, nonzero otherwise. - * - * Use: Signs or verifies signatures on lists of files. Useful for - * ensuring that a distribution is unmolested. - */ - -int main(int argc, char *argv[]) -{ - unsigned f = 0; - -#define f_bogus 1u - - /* --- Initialize the library --- */ - - ego(argv[0]); - sub_init(); - rand_noisesrc(RAND_GLOBAL, &noise_source); - rand_seed(RAND_GLOBAL, 160); - - /* --- Parse options --- */ - - for (;;) { - static struct option opts[] = { - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'v' }, - { "usage", 0, 0, 'u' }, - { "keyring", OPTF_ARGREQ, 0, 'k' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+hvu k:", opts, 0, 0, 0); - if (i < 0) - break; - switch (i) { - case 'h': - sc_help(cmdtab, stdout, argv + optind); - exit(0); - break; - case 'v': - version(stdout); - exit(0); - break; - case 'u': - usage(stdout); - exit(0); - case 'k': - keyring = optarg; - break; - default: - f |= f_bogus; - break; - } - } - - argc -= optind; - argv += optind; - optind = 0; - if (f & f_bogus || argc < 1) { - usage(stderr); - exit(EXIT_FAILURE); - } - - /* --- Dispatch to the correct subcommand handler --- */ - - return (findcmd(cmdtab, argv[0])->cmd(argc, argv)); - -#undef f_bogus -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/ec-bin.c b/ec-bin.c deleted file mode 100644 index 8ba7354..0000000 --- a/ec-bin.c +++ /dev/null @@ -1,447 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Arithmetic for elliptic curves over binary fields - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ec.h" -#include "ec-guts.h" - -/*----- Main code ---------------------------------------------------------*/ - -static const ec_ops ec_binops, ec_binprojops; - -static ec *ecneg(ec_curve *c, ec *d, const ec *p) -{ - EC_COPY(d, p); - if (d->x) - d->y = F_ADD(c->f, d->y, d->y, d->x); - return (d); -} - -static ec *ecprojneg(ec_curve *c, ec *d, const ec *p) -{ - EC_COPY(d, p); - if (d->x) { - mp *t = F_MUL(c->f, MP_NEW, d->x, d->z); - d->y = F_ADD(c->f, d->y, d->y, t); - MP_DROP(t); - } - return (d); -} - -static ec *ecfind(ec_curve *c, ec *d, mp *x) -{ - field *f = c->f; - mp *y, *u, *v; - - if (F_ZEROP(f, x)) - y = F_SQRT(f, MP_NEW, c->b); - else { - u = F_SQR(f, MP_NEW, x); /* %$x^2$% */ - y = F_MUL(f, MP_NEW, u, c->a); /* %$a x^2$% */ - y = F_ADD(f, y, y, c->b); /* %$a x^2 + b$% */ - v = F_MUL(f, MP_NEW, u, x); /* %$x^3$% */ - y = F_ADD(f, y, y, v); /* %$A = x^3 + a x^2 + b$% */ - if (!F_ZEROP(f, y)) { - u = F_INV(f, u, u); /* %$x^{-2}$% */ - v = F_MUL(f, v, u, y); /* %$B = A x^{-2} = x + a + b x^{-2}$% */ - y = F_QUADSOLVE(f, y, v); /* %$z^2 + z = B$% */ - if (y) y = F_MUL(f, y, y, x); /* %$y = z x$% */ - } - MP_DROP(u); - MP_DROP(v); - } - if (!y) return (0); - EC_DESTROY(d); - d->x = MP_COPY(x); - d->y = y; - d->z = MP_COPY(f->one); - return (d); -} - -static ec *ecdbl(ec_curve *c, ec *d, const ec *a) -{ - if (EC_ATINF(a) || F_ZEROP(c->f, a->x)) - EC_SETINF(d); - else { - field *f = c->f; - mp *lambda; - mp *dx, *dy; - - dx = F_INV(f, MP_NEW, a->x); /* %$x^{-1}$% */ - dy = F_MUL(f, MP_NEW, dx, a->y); /* %$y/x$% */ - lambda = F_ADD(f, dy, dy, a->x); /* %$\lambda = x + y/x$% */ - - dx = F_SQR(f, dx, lambda); /* %$\lambda^2$% */ - dx = F_ADD(f, dx, dx, lambda); /* %$\lambda^2 + \lambda$% */ - dx = F_ADD(f, dx, dx, c->a); /* %$x' = a + \lambda^2 + \lambda$% */ - - dy = F_ADD(f, MP_NEW, a->x, dx); /* %$ x + x' $% */ - dy = F_MUL(f, dy, dy, lambda); /* %$ (x + x') \lambda$% */ - dy = F_ADD(f, dy, dy, a->y); /* %$ (x + x') \lambda + y$% */ - dy = F_ADD(f, dy, dy, dx); /* %$ y' = (x + x') \lambda + y + x'$% */ - - EC_DESTROY(d); - d->x = dx; - d->y = dy; - d->z = 0; - MP_DROP(lambda); - } - return (d); -} - -static ec *ecprojdbl(ec_curve *c, ec *d, const ec *a) -{ - if (EC_ATINF(a) || F_ZEROP(c->f, a->x)) - EC_SETINF(d); - else { - field *f = c->f; - ecctx_bin *cc = (ecctx_bin *)c; - mp *dx, *dy, *dz, *u, *v; - - dy = F_SQR(f, MP_NEW, a->z); /* %$z^2$% */ - dx = F_MUL(f, MP_NEW, dy, cc->bb); /* %$c z^2$% */ - dx = F_ADD(f, dx, dx, a->x); /* %$x + c z^2$% */ - dz = F_SQR(f, MP_NEW, dx); /* %$(x + c z^2)^2$% */ - dx = F_SQR(f, dx, dz); /* %$x' = (x + c z^2)^4$% */ - - dz = F_MUL(f, dz, dy, a->x); /* %$z' = x z^2$% */ - - dy = F_SQR(f, dy, a->x); /* %$x^2$% */ - u = F_MUL(f, MP_NEW, a->y, a->z); /* %$y z$% */ - u = F_ADD(f, u, u, dz); /* %$z' + y z$% */ - u = F_ADD(f, u, u, dy); /* %$u = z' + x^2 + y z$% */ - - v = F_SQR(f, MP_NEW, dy); /* %$x^4$% */ - dy = F_MUL(f, dy, v, dz); /* %$x^4 z'$% */ - v = F_MUL(f, v, u, dx); /* %$u x'$% */ - dy = F_ADD(f, dy, dy, v); /* %$y' = x^4 z' + u x'$% */ - - EC_DESTROY(d); - d->x = dx; - d->y = dy; - d->z = dz; - MP_DROP(u); - MP_DROP(v); - } - return (d); -} - -static ec *ecadd(ec_curve *c, ec *d, const ec *a, const ec *b) -{ - if (a == b) - ecdbl(c, d, a); - else if (EC_ATINF(a)) - EC_COPY(d, b); - else if (EC_ATINF(b)) - EC_COPY(d, a); - else { - field *f = c->f; - mp *lambda; - mp *dx, *dy; - - if (!MP_EQ(a->x, b->x)) { - dx = F_ADD(f, MP_NEW, a->x, b->x); /* %$x_0 + x_1$% */ - dy = F_INV(f, MP_NEW, dx); /* %$(x_0 + x_1)^{-1}$% */ - dx = F_ADD(f, dx, a->y, b->y); /* %$y_0 + y_1$% */ - lambda = F_MUL(f, MP_NEW, dy, dx); - /* %$\lambda = (y_0 + y_1)/(x_0 + x_1)$% */ - - dx = F_SQR(f, dx, lambda); /* %$\lambda^2$% */ - dx = F_ADD(f, dx, dx, lambda); /* %$\lambda^2 + \lambda$% */ - dx = F_ADD(f, dx, dx, c->a); /* %$a + \lambda^2 + \lambda$% */ - dx = F_ADD(f, dx, dx, a->x); /* %$a + \lambda^2 + \lambda + x_0$% */ - dx = F_ADD(f, dx, dx, b->x); - /* %$x' = a + \lambda^2 + \lambda + x_0 + x_1$% */ - } else if (!MP_EQ(a->y, b->y) || F_ZEROP(f, a->x)) { - EC_SETINF(d); - return (d); - } else { - dx = F_INV(f, MP_NEW, a->x); /* %$x^{-1}$% */ - dy = F_MUL(f, MP_NEW, dx, a->y); /* %$y/x$% */ - lambda = F_ADD(f, dy, dy, a->x); /* %$\lambda = x + y/x$% */ - - dx = F_SQR(f, dx, lambda); /* %$\lambda^2$% */ - dx = F_ADD(f, dx, dx, lambda); /* %$\lambda^2 + \lambda$% */ - dx = F_ADD(f, dx, dx, c->a); /* %$x' = a + \lambda^2 + \lambda$% */ - dy = MP_NEW; - } - - dy = F_ADD(f, dy, a->x, dx); /* %$ x + x' $% */ - dy = F_MUL(f, dy, dy, lambda); /* %$ (x + x') \lambda$% */ - dy = F_ADD(f, dy, dy, a->y); /* %$ (x + x') \lambda + y$% */ - dy = F_ADD(f, dy, dy, dx); /* %$ y' = (x + x') \lambda + y + x'$% */ - - EC_DESTROY(d); - d->x = dx; - d->y = dy; - d->z = 0; - MP_DROP(lambda); - } - return (d); -} - -static ec *ecprojadd(ec_curve *c, ec *d, const ec *a, const ec *b) -{ - if (a == b) - c->ops->dbl(c, d, a); - else if (EC_ATINF(a)) - EC_COPY(d, b); - else if (EC_ATINF(b)) - EC_COPY(d, a); - else { - field *f = c->f; - mp *dx, *dy, *dz, *u, *uu, *v, *t, *s, *ss, *r, *w, *l; - - dz = F_SQR(f, MP_NEW, b->z); /* %$z_1^2$% */ - u = F_MUL(f, MP_NEW, dz, a->x); /* %$u_0 = x_0 z_1^2$% */ - t = F_MUL(f, MP_NEW, dz, b->z); /* %$z_1^3$% */ - s = F_MUL(f, MP_NEW, t, a->y); /* %$s_0 = y_0 z_1^3$% */ - - dz = F_SQR(f, dz, a->z); /* %$z_0^2$% */ - uu = F_MUL(f, MP_NEW, dz, b->x); /* %$u_1 = x_1 z_0^2$% */ - t = F_MUL(f, t, dz, a->z); /* %$z_0^3$% */ - ss = F_MUL(f, MP_NEW, t, b->y); /* %$s_1 = y_1 z_0^3$% */ - - w = F_ADD(f, u, u, uu); /* %$r = u_0 + u_1$% */ - r = F_ADD(f, s, s, ss); /* %$w = s_0 + s_1$% */ - if (F_ZEROP(f, w)) { - MP_DROP(w); - MP_DROP(uu); - MP_DROP(ss); - MP_DROP(t); - MP_DROP(dz); - if (F_ZEROP(f, r)) { - MP_DROP(r); - return (c->ops->dbl(c, d, a)); - } else { - MP_DROP(r); - EC_SETINF(d); - return (d); - } - } - - l = F_MUL(f, t, a->z, w); /* %$l = z_0 w$% */ - - dz = F_MUL(f, dz, l, b->z); /* %$z' = l z_1$% */ - - ss = F_MUL(f, ss, r, b->x); /* %$r x_1$% */ - t = F_MUL(f, uu, l, b->y); /* %$l y_1$% */ - v = F_ADD(f, ss, ss, t); /* %$v = r x_1 + l y_1$% */ - - t = F_ADD(f, t, r, dz); /* %$t = r + z'$% */ - - uu = F_SQR(f, MP_NEW, dz); /* %$z'^2$% */ - dx = F_MUL(f, MP_NEW, uu, c->a); /* %$a z'^2$% */ - uu = F_MUL(f, uu, t, r); /* %$t r$% */ - dx = F_ADD(f, dx, dx, uu); /* %$a z'^2 + t r$% */ - r = F_SQR(f, r, w); /* %$w^2$% */ - uu = F_MUL(f, uu, r, w); /* %$w^3$% */ - dx = F_ADD(f, dx, dx, uu); /* %$x' = a z'^2 + t r + w^3$% */ - - r = F_SQR(f, r, l); /* %$l^2$% */ - dy = F_MUL(f, uu, v, r); /* %$v l^2$% */ - l = F_MUL(f, l, t, dx); /* %$t x'$% */ - dy = F_ADD(f, dy, dy, l); /* %$y' = t x' + v l^2$% */ - - EC_DESTROY(d); - d->x = dx; - d->y = dy; - d->z = dz; - MP_DROP(l); - MP_DROP(r); - MP_DROP(w); - MP_DROP(t); - MP_DROP(v); - } - return (d); -} - -static int eccheck(ec_curve *c, const ec *p) -{ - field *f = c->f; - int rc; - mp *u, *v; - - if (EC_ATINF(p)) return (0); - v = F_SQR(f, MP_NEW, p->x); - u = F_MUL(f, MP_NEW, v, p->x); - v = F_MUL(f, v, v, c->a); - u = F_ADD(f, u, u, v); - u = F_ADD(f, u, u, c->b); - v = F_MUL(f, v, p->x, p->y); - u = F_ADD(f, u, u, v); - v = F_SQR(f, v, p->y); - u = F_ADD(f, u, u, v); - rc = F_ZEROP(f, u) ? 0 : -1; - mp_drop(u); - mp_drop(v); - return (rc); -} - -static int ecprojcheck(ec_curve *c, const ec *p) -{ - ec t = EC_INIT; - int rc; - - c->ops->fix(c, &t, p); - rc = eccheck(c, &t); - EC_DESTROY(&t); - return (rc); -} - -static void ecdestroy(ec_curve *c) -{ - ecctx_bin *cc = (ecctx_bin *)c; - MP_DROP(cc->c.a); - MP_DROP(cc->c.b); - if (cc->bb) MP_DROP(cc->bb); - DESTROY(cc); -} - -/* --- @ec_bin@, @ec_binproj@ --- * - * - * Arguments: @field *f@ = the underlying field for this elliptic curve - * @mp *a, *b@ = the coefficients for this curve - * - * Returns: A pointer to the curve, or null. - * - * Use: Creates a curve structure for an elliptic curve defined over - * a binary field. The @binproj@ variant uses projective - * coordinates, which can be a win. - */ - -ec_curve *ec_bin(field *f, mp *a, mp *b) -{ - ecctx_bin *cc = CREATE(ecctx_bin); - cc->c.ops = &ec_binops; - cc->c.f = f; - cc->c.a = F_IN(f, MP_NEW, a); - cc->c.b = F_IN(f, MP_NEW, b); - cc->bb = 0; - return (&cc->c); -} - -ec_curve *ec_binproj(field *f, mp *a, mp *b) -{ - ecctx_bin *cc = CREATE(ecctx_bin); - int i; - mp *c, *d; - - cc->c.ops = &ec_binprojops; - cc->c.f = f; - cc->c.a = F_IN(f, MP_NEW, a); - cc->c.b = F_IN(f, MP_NEW, b); - - c = MP_COPY(cc->c.b); - for (i = 0; i < f->nbits - 2; i++) - c = F_SQR(f, c, c); - d = F_SQR(f, MP_NEW, c); d = F_SQR(f, d, d); - if (!MP_EQ(d, cc->c.b)) { - MP_DROP(c); - MP_DROP(d); - MP_DROP(cc->c.a); - MP_DROP(cc->c.b); - DESTROY(cc); - return (0); - } - cc->bb = c; - MP_DROP(d); - return (&cc->c); -} - -static const ec_ops ec_binops = { - "bin", - ecdestroy, ec_stdsamep, ec_idin, ec_idout, ec_idfix, - ecfind, ecneg, ecadd, ec_stdsub, ecdbl, eccheck -}; - -static const ec_ops ec_binprojops = { - "binproj", - ecdestroy, ec_stdsamep, ec_projin, ec_projout, ec_projfix, - ecfind, ecprojneg, ecprojadd, ec_stdsub, ecprojdbl, ecprojcheck -}; - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#define MP(x) mp_readstring(MP_NEW, #x, 0, 0) - -int main(int argc, char *argv[]) -{ - field *f; - ec_curve *c; - ec g = EC_INIT, d = EC_INIT; - mp *p, *a, *b, *r, *beta; - int i, n = argc == 1 ? 1 : atoi(argv[1]); - - printf("ec-bin: "); - fflush(stdout); - a = MP(0x7ffffffffffffffffffffffffffffffffffffffff); - b = MP(0x6645f3cacf1638e139c6cd13ef61734fbc9e3d9fb); - p = MP(0x800000000000000000000000000000000000000c9); - beta = MP(0x715169c109c612e390d347c748342bcd3b02a0bef); - r = MP(0x040000000000000000000292fe77e70c12a4234c32); - - f = field_binnorm(p, beta); - c = ec_binproj(f, a, b); - g.x = MP(0x0311103c17167564ace77ccb09c681f886ba54ee8); - g.y = MP(0x333ac13c6447f2e67613bf7009daf98c87bb50c7f); - - for (i = 0; i < n; i++) { - ec_mul(c, &d, &g, r); - if (EC_ATINF(&d)) { - fprintf(stderr, "zero too early\n"); - return (1); - } - ec_add(c, &d, &d, &g); - if (!EC_ATINF(&d)) { - fprintf(stderr, "didn't reach zero\n"); - MP_EPRINTX("d.x", d.x); - MP_EPRINTX("d.y", d.y); - return (1); - } - ec_destroy(&d); - } - - ec_destroy(&g); - ec_destroycurve(c); - F_DESTROY(f); - MP_DROP(p); MP_DROP(a); MP_DROP(b); MP_DROP(r); MP_DROP(beta); - assert(!mparena_count(&mparena_global)); - printf("ok\n"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/ec-exp.c b/ec-exp.c deleted file mode 100644 index 2c9a800..0000000 --- a/ec-exp.c +++ /dev/null @@ -1,143 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Point multiplication for elliptic curves - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "ec.h" -#include "ec-exp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @ec_imul@, @ec_mul@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @const ec *p@ = pointer to the generator point - * @mp *n@ = integer multiplier - * - * Returns: The destination @d@. - * - * Use: Multiplies a point by a scalar, returning %$n p$%. The - * @imul@ variant uses internal representations for argument - * and result. - */ - -ec *ec_imul(ec_curve *c, ec *d, const ec *p, mp *n) -{ - ec t = EC_INIT; - - EC_COPY(&t, p); - if (t.x && (n->f & MP_BURN)) - t.x->f |= MP_BURN; - MP_SHRINK(n); - EC_SETINF(d); - if (MP_ZEROP(n)) - ; - else { - if (MP_NEGP(n)) - EC_NEG(c, &t, &t); - if (MP_LEN(n) < EXP_THRESH) - EXP_SIMPLE(*d, t, n); - else - EXP_WINDOW(*d, t, n); - } - EC_DESTROY(&t); - return (d); -} - -ec *ec_mul(ec_curve *c, ec *d, const ec *p, mp *n) -{ - EC_IN(c, d, p); - ec_imul(c, d, d, n); - return (EC_OUT(c, d, d)); -} - -/* --- @ec_mmul@, @ec_immul@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @const ec_mulfactor *f@ = pointer to vector of factors - * @size_t n@ = number of factors - * - * Returns: The destination @d@. - * - * Use: Does simultaneous point multiplication. The @immul@ variant - * uses internal representations for arguments and result. - */ - -#undef EXP_WINSZ -#define EXP_WINSZ 3 - -static ec *immul(ec_curve *c, ec *d, ec_mulfactor *f, size_t n) -{ - size_t i; - - for (i = 0; i < n; i++) { - MP_SHRINK(f[i].exp); - if (MP_NEGP(f[i].exp)) - EC_NEG(c, &f[i].base, &f[i].base); - if (f[i].base.x && f[i].exp->f & MP_BURN) - f[i].base.x->f |= MP_BURN; - } - EC_SETINF(d); - EXP_SIMUL(*d, f, n); - for (i = 0; i < n; i++) - EC_DESTROY(&f[i].base); - xfree(f); - return (d); -} - -ec *ec_immul(ec_curve *c, ec *d, const ec_mulfactor *f, size_t n) -{ - ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor)); - size_t i; - - for (i = 0; i < n; i++) { - EC_CREATE(&ff[i].base); - EC_COPY(&ff[i].base, &f[i].base); - ff[i].exp = f[i].exp; - } - return (immul(c, d, ff, n)); -} - -ec *ec_mmul(ec_curve *c, ec *d, const ec_mulfactor *f, size_t n) -{ - ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor)); - size_t i; - - for (i = 0; i < n; i++) { - EC_CREATE(&ff[i].base); - EC_IN(c, &ff[i].base, &f[i].base); - ff[i].exp = f[i].exp; - } - immul(c, d, ff, n); - return (EC_OUT(c, d, d)); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/ec-exp.h b/ec-exp.h deleted file mode 100644 index 8ee3154..0000000 --- a/ec-exp.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*-c-*- - * - * $Id: ec-exp.h,v 1.6 2004/04/08 01:36:15 mdw Exp $ - * - * Exponentiation operations for elliptic curves - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_EC_EXP_H -#define CATACOMB_EC_EXP_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Exponentation definitions -----------------------------------------*/ - -#define EXP_TYPE ec - -#define EXP_COPY(d, p) do { \ - (d).x = MP_COPY((p).x); \ - (d).y = MP_COPY((p).y); \ - (d).z = (p).z ? MP_COPY((p).z) : MP_NEW; \ -} while (0) -#define EXP_DROP(x) EC_DESTROY(&(x)) - -#define EXP_MUL(a, x) EC_ADD(c, &(a), &(a), &(x)) -#define EXP_SQR(a) EC_DBL(c, &(a), &(a)) -#define EXP_FIX(x) - -#define EXP_SETMUL(d, x, y) do { \ - EC_CREATE(&(d)); \ - EC_ADD(c, &(d), &(x), &(y)); \ -} while (0) -#define EXP_SETSQR(d, x) do { \ - EC_CREATE(&(d)); \ - EC_DBL(c, &(d), &(x)); \ -} while (0) - -#include "exp.h" - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/ec-fetch.c b/ec-fetch.c deleted file mode 100644 index 81bfb6c..0000000 --- a/ec-fetch.c +++ /dev/null @@ -1,91 +0,0 @@ -/* -*-c-*- - * - * $Id: ec-fetch.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Key fetching for elliptic curve public and private keys - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "ec-keys.h" -#include "key.h" - -/*----- Key fetching ------------------------------------------------------*/ - -const key_fetchdef ec_paramfetch[] = { - { "curve", offsetof(ec_pub, cstr), KENC_STRING, 0 }, - { 0, 0, 0, 0 } -}; - -const key_fetchdef ec_pubfetch[] = { - { "curve", offsetof(ec_pub, cstr), KENC_STRING, 0 }, - { "p", offsetof(ec_pub, p), KENC_EC, 0 }, - { 0, 0, 0, 0 } -}; - -static const key_fetchdef priv[] = { - { "x", offsetof(ec_priv, x), KENC_MP, 0 }, - { 0, 0, 0, 0 } -}; - -const key_fetchdef ec_privfetch[] = { - { "curve", offsetof(ec_pub, cstr), KENC_STRING, 0 }, - { "p", offsetof(ec_pub, p), KENC_EC, 0 }, - { "private", 0, KENC_STRUCT, priv }, - { 0, 0, 0, 0 } -}; - -/* --- @ec_paramfree@, @ec_pubfree@, @ec_privfree@ --- * - * - * Arguments: @ec_param *ep@, @ec_pub *ep@, @ec_priv *ep@ = pointer to - * key block to free - * - * Returns: --- - * - * Use: Frees an elliptic curve key block - */ - -void ec_paramfree(ec_param *ep) -{ - if (ep->ei.c) ec_freeinfo(&ep->ei); - xfree(ep->cstr); -} - -void ec_pubfree(ec_pub *ep) -{ - if (ep->ei.c) ec_freeinfo(&ep->ei); - xfree(ep->cstr); - EC_DESTROY(&ep->p); -} - -void ec_privfree(ec_priv *ep) -{ - if (ep->ei.c) ec_freeinfo(&ep->ei); - xfree(ep->cstr); - EC_DESTROY(&ep->p); - mp_drop(ep->x); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/ec-gentab.awk b/ec-gentab.awk deleted file mode 100755 index b00300c..0000000 --- a/ec-gentab.awk +++ /dev/null @@ -1,116 +0,0 @@ -#! /usr/bin/awk -f -# -# $Id: ec-gentab.awk,v 1.1 2004/04/01 21:28:41 mdw Exp $ - -function banner(name, s, i) -{ - s = "/*----- " name " "; - while (length(s) < 75) s = s "-"; - return (s "*/"); -} - -function fix(name) -{ - gsub(/[^0-9A-Za-z_]+/, "_", name); - return (name); -} - -BEGIN { - print "/* -*-c-*-"; - print " *"; - print " * Table of elliptic curves [generated]"; - print " */"; - print ""; - print "#include \"ectab.h\""; - print ""; - print "#define N(x) (sizeof(x)/sizeof(*x))"; - print "#define MP(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }"; - print "#define NOMP { 0, 0, 0, 0, 0 }"; - print ""; - print banner("Curve data"); - print ""; - - d_i = 0; - name = ""; -} - -function putmp(x, d) -{ - if (!(x in data)) { - print "curve " name ": missing " x >"/dev/stderr"; - exit 1; - } - d = data[x]; - if (!(d in cache)) { - n = "c_" fix(name) "_" x; - print "static mpw " n "[] = {"; - system("./mpdump " d); - print "};"; - print ""; - cache[d] = n; - } - mp[x] = cache[d]; -} - -function flush() -{ - if (name == "") return; - print "/* --- Curve " name " --- */"; - delete mp; - print ""; - putmp("p"); - if (type == "binnorm") putmp("beta"); - putmp("a"); - putmp("b"); - putmp("r"); - putmp("h"); - putmp("gx"); - putmp("gy"); - print "static ecdata c_" fix(name) " = {"; - print " FTAG_" toupper(type) ","; - print " MP(" mp["p"] ")," - if (type == "binnorm") - print " MP(" mp["beta"] "),"; - else - print " NOMP,"; - print " MP(" mp["a"] ")," - print " MP(" mp["b"] ")," - print " MP(" mp["r"] ")," - print " MP(" mp["h"] ")," - print " MP(" mp["gx"] ")," - print " MP(" mp["gy"] ")" - print "};"; - print ""; - dname[d_i++] = name; - d[name] = name; - r[name] = "c_" fix(name); - name = ""; -} - -/^[ \t]*(#|$)/ { next; } - -$1 == "alias" { flush(); dname[d_i++] = $2; d[$2] = $3; next; } - -$1 == "curve" { flush(); delete data; name = $2; type = $3; next; } - -{ data[$1] = $2; next; } - -END { - flush(); - print banner("Main table"); - print ""; - print "const ecentry ectab[] = {"; - for (i = 0; i < d_i; i++) { - name = dname[i]; - rname = d[name]; - if (!rname in r) { - print "curve " rname " not found (alias from " name ")" >"/dev/stderr"; - exit 1; - } - print " { \"" name "\", &" r[rname] " },"; - } - print " { 0, 0 }"; - print "};" - print ""; - print banner("That's all, folks"); -} diff --git a/ec-guts.h b/ec-guts.h deleted file mode 100644 index fb2b306..0000000 --- a/ec-guts.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Internal structures for built-in elliptic curve types - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_EC_GUTS_H -#define CATACOMB_EC_GUTS_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_EC_H -# include "ec.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct ecctx_bin { - ec_curve c; - mp *bb; -} ecctx_bin; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/ec-info.c b/ec-info.c deleted file mode 100644 index 6fcef88..0000000 --- a/ec-info.c +++ /dev/null @@ -1,781 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Elliptic curve information management - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ec.h" -#include "ectab.h" -#include "gf.h" -#include "keysz.h" -#include "mpbarrett.h" -#include "pgen.h" -#include "primeiter.h" -#include "mprand.h" -#include "mpint.h" -#include "rabin.h" - -/*----- Embedding degree checking -----------------------------------------* - * - * Let %$q = p^m$% be a prime power, and let %$E$% be an elliptic curve over - * %$\gf{q}$% with %$n = \#E(\gf{q}) = r h$% where %$r$% is prime. Then the - * Weil and Tate pairings can be used to map %$r$%-torsion points on - * %$E(\gf{q})$% onto the %$r$%-th roots of unity (i.e., the order-%$r$% - * subgroup) in an extension field %$\gf{p^k}$% of %$\gf{p}$% (%%\emph{not}%% - * of %$\gf{q}$% -- see [Hitt]). We call the smallest such %$k$% the - * %%\emph{embedding degree}%% of the curve %$E$%. The - * Menezes-Okamoto-Vanstone (MOV) attack solves the discrete log problem in - * %$E(\gf{q})$% by using the pairing and then applying index calculus to - * extract a discrete log in %$\gf{p^k}$%; obviously this only works if %$k$% - * is small enough. - * - * The usual check, suggested in, e.g., [P1363] or [SEC1], only covers - * extension fields %$\gf{q^\ell}$% of %$\gf{q}$%, which is fine when %$q$% - * is prime, but when we're dealing with binary fields it works less well. - * Indeed, as [Hitt] demonstrates, the embedding field can actually be - * %%\emph{smaller}%% than %$\gf{q}$%, and choosing %$m$% prime doesn't help - * (even though I previously thought it did). - * - * Define the %%\emph{embedding degree bound}%% %$B$% to be the smallest - * %$i$% such that discrete logs in %$\gf{p^i}$% are about as hard as in - * %$E(\gf{q})$%. - * - * The embedding group is a subgroup of the multiplicative group - * %$\gf{p^k}^*$% which contains %$p^k - 1$% elements; therefore we must have - * %$r \mid p^k - 1$%, or, equivalently, %$p^k \equiv 1 \pmod{r}$%. - * - * The recommended checking procedure, e.g., in [P1363], is just to check - * %$q^i \not\equiv 1 \pmod{r}$% for each %$0 < i < B$%. This is fast when - * you only consider extension fields of %$\gf{q}$%, since %$B$% is at most - * about 27. However, as noted above, this is inadequate when %$q$% is a - * prime power, and we must check all the extension fields of %$p$%. Now - * %$B$% can be about 15000, which is rather scarier -- we need a better - * algorithm. - * - * As noted, we must have %$p^k \equiv 1 \pmod{r}$%; but by minimality of - * %$k$%, we must have %$p^i \not\equiv 1 \pmod{r}$% for %$0 < i < k$%. - * Therefore %$p$% generates an order-%$k$% subgroup in %$\gf{r}^*$%, so we - * must have %$k \mid r - 1$%. - * - * Of course, factoring %$r - 1$% is a mug's game; but we're not interested - * in the complete factorization -- just the %$B$%-smooth portion. An - * algorithm suggests itself: - * - * 1. Extract the factors of %$r - 1$% which are less than %$B$%. - * - * 2. For each divisor %$d$% of %$r - 1$% less than %$B$% (which we can - * construct using this factorization), make sure that - * %$p^d \not\equiv 1 \pmod{r}$%. - * - * This takes a little while but not ever-so long. - * - * This is enough for cryptosystems based on the computational Diffie- - * Hellman problem to be secure. However, it's %%\emph{not}%% enough for the - * %%\emph{decisional}%% Diffie-Hellman problem to be hard; it appears we - * also need to hope that there aren't any suitable distortion maps with - * which one can solve the DDH problem. I don't know how to check for those - * at the moment. - * - * We'll take the subgroup order as indicative of the security level actually - * wanted. Then, to ensure security against the MOV attack, we must ensure - * that the embedding degree is sufficiently large that discrete logs in - * %$\gf{q^m}$% are at least as hard as discrete logs over the curve. - * - * We actually allow a small amount of slop in the conversions, in order to - * let people pick nice round numbers for their key lengths. - * - * References: - * - * [Hitt] L. Hitt, On an improved definition of embedding degree; - * http://eprint.iacr.org/2006/415 - * - * [P1363] IEEE 1363-2000: Standard Specifications for Public Key - * Cryptography; http://grouper.ieee.org/groups/1363/P1363/index.html - * - * [SEC1] SEC 1: Elliptic Curve Cryptography; - * http://www.secg.org/download/aid-385/sec1_final.pdf - */ - -/* --- @movcheck@ --- * - * - * Arguments: @mp *r@ = curve subgroup order - * @mp *p@ = field characteristic - * @unsigned long B@ = embedding degree bound - * - * Returns: Zero if OK, nonzero if an embedding was found. - * - * Use: Checks a curve for embeddings with degree less than the - * stated bound %$B$%. See above for explanation and a - * description of the algorithm. - */ - -static int movcheck(mp *r, mp *p, unsigned long B) -{ - mpmont mm; - mp *r1, *pp = MP_NEW, *t = MP_NEW, *u = MP_NEW, *v = MP_NEW, *tt; - struct factor { - unsigned long f; - unsigned c, e; - }; - DA_DECL(factor_v, struct factor); - factor_v fv = DA_INIT; - size_t nf; - struct factor *ff; - primeiter pi; - mp *BB; - unsigned long d, f; - unsigned i, j; - int rc = 0; - - /* --- Special case --- * - * - * If %$r = 2$% then (a) Montgomery reduction won't work, and (b) we have - * no security worth checking anyway. Otherwise we're guaranteed that - * %$r$% is a prime, so it must be odd. - */ - - if (MP_EQ(r, MP_TWO)) - return (0); - - /* --- First factor the %$B%-smooth portion of %$r - 1$% --- * - * - * We can generate prime numbers up to %$B$% efficiently, so trial division - * it is. - */ - - BB = mp_fromulong(MP_NEW, B); - r1 = mp_sub(MP_NEW, r, MP_ONE); - primeiter_create(&pi, 0); - for (;;) { - pp = primeiter_next(&pi, pp); - if (MP_CMP(pp, >, BB)) - break; - mp_div(&u, &v, r1, pp); - if (!MP_ZEROP(v)) - continue; - i = 0; - do { - tt = r1; r1 = u; u = tt; i++; - mp_div(&u, &v, r1, pp); - } while (MP_ZEROP(v)); - DA_ENSURE(&fv, 1); - DA_UNSAFE_EXTEND(&fv, 1); - DA_LAST(&fv).f = mp_toulong(pp); - DA_LAST(&fv).e = i; - DA_LAST(&fv).c = 0; - } - MP_DROP(BB); MP_DROP(pp); primeiter_destroy(&pi); - nf = DA_LEN(&fv); ff = DA(&fv); - - /* --- Now generate divisors of %$r - 1$% less than %$B$% --- * - * - * For each divisor %$d$%, check whether %$p^d \equiv 1 \pmod{r}$%. - */ - - mpmont_create(&mm, r); - u = mpmont_mul(&mm, u, p, mm.r2); - for (;;) { - - /* --- Construct the divisor --- */ - - d = 1; - for (i = 0; i < nf; i++) { - f = ff[i].f; j = ff[i].c; if (!j) continue; - for (;;) { - if (f >= (B + d - 1)/d) goto toobig; - if (j & 1) d *= f; - j >>= 1; if (!j) break; - f *= f; - } - } - v = mp_fromulong(v, d); - - /* --- Compute %$p^k \bmod r$% and check --- */ - - t = mpmont_expr(&mm, t, u, v); - if (MP_EQ(t, mm.r)) { - rc = -1; - break; - } - - /* --- Step the divisors along --- */ - - toobig: - for (i = 0; i < nf; i++) { - if (ff[i].c < ff[i].e) { - ff[i].c++; - goto more; - } - ff[i].c = 0; - } - break; - more:; - } - - /* --- Clear away the debris --- */ - - mpmont_destroy(&mm); - MP_DROP(t); MP_DROP(u); MP_DROP(v); MP_DROP(r1); - DA_DESTROY(&fv); - return (rc); -} - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @ec_curveparse@ --- * - * - * Arguments: @qd_parse *qd@ = parser context - * - * Returns: Elliptic curve pointer if OK, or null. - * - * Use: Parses an elliptic curve description, which has the form - * - * * a field description - * * an optional `;' - * * `prime', `primeproj', `bin', or `binproj' - * * an optional `:' - * * the %$a$% parameter - * * an optional `,' - * * the %$b$% parameter - */ - -ec_curve *ec_curveparse(qd_parse *qd) -{ - mp *a = MP_NEW, *b = MP_NEW; - ec_curve *c; - field *f; - - if ((f = field_parse(qd)) == 0) goto fail; - qd_delim(qd, ';'); - switch (qd_enum(qd, "prime,primeproj,bin,binproj")) { - case 0: - if (F_TYPE(f) != FTY_PRIME) { - qd->e = "field not prime"; - goto fail; - } - qd_delim(qd, ':'); - if ((a = qd_getmp(qd)) == 0) goto fail; - qd_delim(qd, ','); - if ((b = qd_getmp(qd)) == 0) goto fail; - c = ec_prime(f, a, b); - break; - case 1: - if (F_TYPE(f) != FTY_PRIME) { - qd->e = "field not prime"; - goto fail; - } - qd_delim(qd, ':'); - if ((a = qd_getmp(qd)) == 0) goto fail; - qd_delim(qd, ','); - if ((b = qd_getmp(qd)) == 0) goto fail; - c = ec_primeproj(f, a, b); - break; - case 2: - if (F_TYPE(f) != FTY_BINARY) { - qd->e = "field not binary"; - goto fail; - } - qd_delim(qd, ':'); - if ((a = qd_getmp(qd)) == 0) goto fail; - qd_delim(qd, ','); - if ((b = qd_getmp(qd)) == 0) goto fail; - c = ec_bin(f, a, b); - break; - case 3: - if (F_TYPE(f) != FTY_BINARY) { - qd->e = "field not binary"; - goto fail; - } - qd_delim(qd, ':'); - if ((a = qd_getmp(qd)) == 0) goto fail; - qd_delim(qd, ','); - if ((b = qd_getmp(qd)) == 0) goto fail; - c = ec_binproj(f, a, b); - break; - default: - goto fail; - } - if (!c) { - qd->e = "bad curve parameters"; - goto fail; - } - if (a) MP_DROP(a); - if (b) MP_DROP(b); - return (c); - -fail: - if (f) F_DESTROY(f); - if (a) MP_DROP(a); - if (b) MP_DROP(b); - return (0); -} - -/* --- @ec_ptparse@ --- * - * - * Arguments: @qd_parse *qd@ = parser context - * @ec *p@ = where to put the point - * - * Returns: The point address, or null. - * - * Use: Parses an elliptic curve point. This has the form - * - * * %$x$%-coordinate - * * optional `,' - * * %$y$%-coordinate - */ - -ec *ec_ptparse(qd_parse *qd, ec *p) -{ - mp *x = MP_NEW, *y = MP_NEW; - - if (qd_enum(qd, "inf") >= 0) { - EC_SETINF(p); - return (p); - } - if ((x = qd_getmp(qd)) == 0) goto fail; - qd_delim(qd, ','); - if ((y = qd_getmp(qd)) == 0) goto fail; - EC_DESTROY(p); - p->x = x; - p->y = y; - p->z = 0; - return (p); - -fail: - if (x) MP_DROP(x); - if (y) MP_DROP(y); - return (0); -} - -/* --- @ec_infofromdata@ --- * - * - * Arguments: @ec_info *ei@ = where to write the information - * @ecdata *ed@ = raw data - * - * Returns: --- - * - * Use: Loads elliptic curve information about one of the standard - * curves. - */ - -void ec_infofromdata(ec_info *ei, ecdata *ed) -{ - field *f; - - switch (ed->ftag) { - case FTAG_PRIME: - f = field_prime(&ed->p); - ei->c = ec_primeproj(f, &ed->a, &ed->b); - break; - case FTAG_NICEPRIME: - f = field_niceprime(&ed->p); - ei->c = ec_primeproj(f, &ed->a, &ed->b); - break; - case FTAG_BINPOLY: - f = field_binpoly(&ed->p); - ei->c = ec_binproj(f, &ed->a, &ed->b); - break; - case FTAG_BINNORM: - f = field_binnorm(&ed->p, &ed->beta); - ei->c = ec_binproj(f, &ed->a, &ed->b); - break; - default: - abort(); - } - - assert(f); assert(ei->c); - EC_CREATE(&ei->g); ei->g.x = &ed->gx; ei->g.y = &ed->gy; ei->g.z = 0; - ei->r = &ed->r; ei->h = &ed->h; -} - -/* --- @ec_infoparse@ --- * - * - * Arguments: @qd_parse *qd@ = parser context - * @ec_info *ei@ = curve information block, currently - * uninitialized - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Parses an elliptic curve information string, and stores the - * information in @ei@. This is either the name of a standard - * curve, or it has the form - * - * * elliptic curve description - * * optional `;' - * * common point - * * optional `:' - * * group order - * * optional `*' - * * cofactor - */ - -int ec_infoparse(qd_parse *qd, ec_info *ei) -{ - ec_curve *c = 0; - field *f; - ec g = EC_INIT; - const ecentry *ee; - mp *r = MP_NEW, *h = MP_NEW; - - for (ee = ectab; ee->name; ee++) { - if (qd_enum(qd, ee->name) >= 0) { - ec_infofromdata(ei, ee->data); - goto found; - } - } - - if ((c = ec_curveparse(qd)) == 0) goto fail; - qd_delim(qd, ';'); if (!ec_ptparse(qd, &g)) goto fail; - qd_delim(qd, ':'); if ((r = qd_getmp(qd)) == 0) goto fail; - qd_delim(qd, '*'); if ((h = qd_getmp(qd)) == 0) goto fail; - ei->c = c; ei->g = g; ei->r = r; ei->h = h; - -found: - return (0); - -fail: - EC_DESTROY(&g); - if (r) MP_DROP(r); - if (h) MP_DROP(h); - if (c) { f = c->f; ec_destroycurve(c); F_DESTROY(f); } - return (-1); -} - -/* --- @ec_getinfo@ --- * - * - * Arguments: @ec_info *ei@ = where to write the information - * @const char *p@ = string describing a curve - * - * Returns: Null on success, or a pointer to an error message. - * - * Use: Parses out information about a curve. The string is either a - * standard curve name, or a curve info string. - */ - -const char *ec_getinfo(ec_info *ei, const char *p) -{ - qd_parse qd; - - qd.p = p; - qd.e = 0; - if (ec_infoparse(&qd, ei)) - return (qd.e); - if (!qd_eofp(&qd)) { - ec_freeinfo(ei); - return ("junk found at end of string"); - } - return (0); -} - -/* --- @ec_sameinfop@ --- * - * - * Arguments: @ec_info *ei, *ej@ = two elliptic curve parameter sets - * - * Returns: Nonzero if the curves are identical (not just isomorphic). - * - * Use: Checks for sameness of curve parameters. - */ - -int ec_sameinfop(ec_info *ei, ec_info *ej) -{ - return (ec_samep(ei->c, ej->c) && - MP_EQ(ei->r, ej->r) && MP_EQ(ei->h, ej->h) && - EC_EQ(&ei->g, &ej->g)); -} - -/* --- @ec_freeinfo@ --- * - * - * Arguments: @ec_info *ei@ = elliptic curve information block to free - * - * Returns: --- - * - * Use: Frees the information block. - */ - -void ec_freeinfo(ec_info *ei) -{ - field *f; - - EC_DESTROY(&ei->g); - MP_DROP(ei->r); - MP_DROP(ei->h); - f = ei->c->f; ec_destroycurve(ei->c); F_DESTROY(f); -} - -/* --- @ec_checkinfo@ --- * - * - * Arguments: @const ec_info *ei@ = elliptic curve information block - * - * Returns: Null if OK, or pointer to error message. - * - * Use: Checks an elliptic curve according to the rules in SEC1. - */ - -static const char *gencheck(const ec_info *ei, grand *gr, mp *q, mp *ch) -{ - ec_curve *c = ei->c; - unsigned long qmbits, rbits, cbits, B; - mp *qq; - mp *nn; - mp *x, *y; - ec p; - int rc; - - /* --- Check curve isn't anomalous --- */ - - if (MP_EQ(ei->r, q)) return ("curve is anomalous"); - - /* --- Check %$G \in E \setminus \{ 0 \}$% --- */ - - if (EC_ATINF(&ei->g)) return ("generator at infinity"); - if (ec_check(c, &ei->g)) return ("generator not on curve"); - - /* --- Check %$r$% is prime --- */ - - if (!pgen_primep(ei->r, gr)) return ("generator order not prime"); - - /* --- Check that the cofactor is correct --- * - * - * Let %$q$% be the size of the field, and let %$n = h r = \#E(\gf{q})$% be - * the number of %$\gf{q}$%-rational points on our curve. Hasse's theorem - * tells us that - * - * %$|q + 1 - n| \le 2\sqrt{q}$% - * - * or, if we square both sides, - * - * %$(q + 1 - n)^2 \le 4 q$%. - * - * We'd like the cofactor to be uniquely determined by this equation, which - * is possible as long as it's not too big. (If it is, we have to mess - * about with Weil pairings, which is no fun.) For this, we need the - * following inequalities: - * - * * %$A = (q + 1 - n)^2 \le 4 q$% (both lower and upper bounds from - * Hasse's theorem); - * - * * %$B = (q + 1 - n - r)^2 > 4 q$% (check %$h - 1$% isn't possible); - * and - * - * * %$C = (q + 1 - n + r)^2 > 4 q$% (check %$h + 1$% isn't possible). - */ - - rc = 1; - qq = mp_add(MP_NEW, q, MP_ONE); - nn = mp_mul(MP_NEW, ei->r, ei->h); - nn = mp_sub(nn, qq, nn); - qq = mp_lsl(qq, q, 2); - - y = mp_sqr(MP_NEW, nn); - if (MP_CMP(y, >, qq)) rc = 0; - - x = mp_sub(MP_NEW, nn, ei->r); - y = mp_sqr(y, x); - if (MP_CMP(y, <=, qq)) rc = 0; - - x = mp_add(x, nn, ei->r); - y = mp_sqr(y, x); - if (MP_CMP(y, <=, qq)) rc = 0; - - MP_DROP(x); - MP_DROP(y); - MP_DROP(nn); - MP_DROP(qq); - if (!rc) return ("incorrect or ambiguous cofactor"); - - /* --- Check %$n G = 0$% --- */ - - EC_CREATE(&p); - ec_mul(c, &p, &ei->g, ei->r); - rc = EC_ATINF(&p); - EC_DESTROY(&p); - if (!rc) return ("incorrect group order"); - - /* --- Check the embedding degree --- */ - - rbits = mp_bits(ei->r); - cbits = mp_bits(ch); - qmbits = keysz_todl(keysz_fromec(rbits * 7/8)); - B = (qmbits + cbits - 1)/cbits; - if (movcheck(ei->r, ch, B)) - return("curve embedding degree too low"); - - /* --- Done --- */ - - return (0); -} - -static int primeeltp(mp *x, field *f) - { return (!MP_NEGP(x) && MP_CMP(x, <, f->m)); } - -static const char *primecheck(const ec_info *ei, grand *gr) -{ - ec_curve *c = ei->c; - field *f = c->f; - mp *x, *y; - int rc; - const char *err; - - /* --- Check %$p$% is an odd prime --- */ - - if (!pgen_primep(f->m, gr)) return ("p not prime"); - - /* --- Check %$a$%, %$b$%, %$G_x$% and %$G_y$% are in %$[0, p)$% --- */ - - if (!primeeltp(c->a, f)) return ("a out of range"); - if (!primeeltp(c->b, f)) return ("b out of range"); - if (!primeeltp(ei->g.x, f)) return ("G_x out of range"); - if (!primeeltp(ei->g.x, f)) return ("G_y out of range"); - - /* --- Check %$4 a^3 + 27 b^2 \not\equiv 0 \pmod{p}$% --- */ - - x = F_SQR(f, MP_NEW, c->a); - x = F_MUL(f, x, x, c->a); - x = F_QDL(f, x, x); - y = F_SQR(f, MP_NEW, c->b); - y = F_TPL(f, y, y); - y = F_TPL(f, y, y); - y = F_TPL(f, y, y); - x = F_ADD(f, x, x, y); - rc = F_ZEROP(f, x); - MP_DROP(x); - MP_DROP(y); - if (rc) return ("not an elliptic curve"); - - /* --- Now do the general checks --- */ - - err = gencheck(ei, gr, f->m, f->m); - return (err); -} - -static const char *bincheck(const ec_info *ei, grand *gr) -{ - ec_curve *c = ei->c; - field *f = c->f; - mp *x; - int rc; - const char *err; - - /* --- Check that %$m$% is prime --- */ - - x = mp_fromuint(MP_NEW, f->nbits); - rc = pfilt_smallfactor(x); - mp_drop(x); - if (rc != PGEN_DONE) return ("degree not prime"); - - /* --- Check that %$p$% is irreducible --- */ - - if (!gf_irreduciblep(f->m)) return ("p not irreducible"); - - /* --- Check that %$a, b, G_x, G_y$% have degree less than %$p$% --- */ - - if (mp_bits(c->a) > f->nbits) return ("a out of range"); - if (mp_bits(c->b) > f->nbits) return ("a out of range"); - if (mp_bits(ei->g.x) > f->nbits) return ("G_x out of range"); - if (mp_bits(ei->g.y) > f->nbits) return ("G_y out of range"); - - /* --- Check that %$b \ne 0$% --- */ - - if (F_ZEROP(f, c->b)) return ("b is zero"); - - /* --- Now do the general checks --- */ - - x = mp_lsl(MP_NEW, MP_ONE, f->nbits); - err = gencheck(ei, gr, x, MP_TWO); - mp_drop(x); - return (err); -} - -const char *ec_checkinfo(const ec_info *ei, grand *gr) -{ - switch (F_TYPE(ei->c->f)) { - case FTY_PRIME: return (primecheck(ei, gr)); break; - case FTY_BINARY: return (bincheck(ei, gr)); break; - } - return ("unknown curve type"); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include "fibrand.h" - -int main(int argc, char *argv[]) -{ - const ecentry *ee; - const char *e; - int ok = 1; - int i; - grand *gr; - - gr = fibrand_create(0); - if (argc > 1) { - for (i = 1; i < argc; i++) { - ec_info ei; - if ((e = ec_getinfo(&ei, argv[i])) != 0) - fprintf(stderr, "bad curve spec `%s': %s\n", argv[i], e); - else { - e = ec_checkinfo(&ei, gr); - ec_freeinfo(&ei); - if (!e) - printf("OK %s\n", argv[i]); - else { - printf("BAD %s: %s\n", argv[i], e); - ok = 0; - } - } - assert(mparena_count(MPARENA_GLOBAL) == 0); - } - } else { - fputs("checking standard curves:", stdout); - fflush(stdout); - for (ee = ectab; ee->name; ee++) { - ec_info ei; - ec_infofromdata(&ei, ee->data); - e = ec_checkinfo(&ei, gr); - ec_freeinfo(&ei); - if (e) { - printf(" [%s fails: %s]", ee->name, e); - ok = 0; - } else - printf(" %s", ee->name); - fflush(stdout); - assert(mparena_count(MPARENA_GLOBAL) == 0); - } - fputs(ok ? " ok\n" : " failed\n", stdout); - } - gr->ops->destroy(gr); - return (!ok); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/ec-keys.h b/ec-keys.h deleted file mode 100644 index 60db9ff..0000000 --- a/ec-keys.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -*-c-*- - * - * $Id: ec-keys.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Elliptic curve key-fetching - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_EC_KEYS_H -#define CATACOMB_EC_KEYS_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_EC_H -# include "ec.h" -#endif - -#ifndef CATACOMB_KEY_H -# include "key.h" -#endif - -/*----- Key structures ----------------------------------------------------*/ - -typedef struct ec_param { - ec_info ei; /* Curve information */ - char *cstr; /* Curve definition string */ -} ec_param; - -typedef struct ec_pub { - ec_info ei; /* Curve information */ - char *cstr; /* Curve definition string */ - ec p; /* Public point */ -} ec_pub; - -typedef struct ec_priv { - ec_info ei; /* Curve information */ - char *cstr; /* Curve definition string */ - ec p; /* Public point */ - mp *x; /* Secret exponent */ -} ec_priv; - -extern const key_fetchdef ec_paramfetch[]; -#define EC_PARAMFETCHSZ 3 - -extern const key_fetchdef ec_pubfetch[]; -#define EC_PUBFETCHSZ 4 - -extern const key_fetchdef ec_privfetch[]; -#define EC_PRIVFETCHSZ 7 - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @ec_paramfree@, @ec_pubfree@, @ec_privfree@ --- * - * - * Arguments: @ec_param *ep@, @ec_pub *ep@, @ec_priv *ep@ = pointer to - * key block to free - * - * Returns: --- - * - * Use: Frees an elliptic curve key block - */ - -extern void ec_paramfree(ec_param */*ep*/); -extern void ec_pubfree(ec_pub */*ep*/); -extern void ec_privfree(ec_priv */*ep*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/ec-prime.c b/ec-prime.c deleted file mode 100644 index 52815e4..0000000 --- a/ec-prime.c +++ /dev/null @@ -1,451 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Elliptic curves over prime fields - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ec.h" - -/*----- Simple prime curves -----------------------------------------------*/ - -static const ec_ops ec_primeops, ec_primeprojops, ec_primeprojxops; - -static ec *ecneg(ec_curve *c, ec *d, const ec *p) -{ - EC_COPY(d, p); - if (d->y) - d->y = F_NEG(c->f, d->y, d->y); - return (d); -} - -static ec *ecfind(ec_curve *c, ec *d, mp *x) -{ - mp *p, *q; - field *f = c->f; - - q = F_SQR(f, MP_NEW, x); - p = F_MUL(f, MP_NEW, x, q); - q = F_MUL(f, q, x, c->a); - p = F_ADD(f, p, p, q); - p = F_ADD(f, p, p, c->b); - MP_DROP(q); - p = F_SQRT(f, p, p); - if (!p) - return (0); - EC_DESTROY(d); - d->x = MP_COPY(x); - d->y = p; - d->z = MP_COPY(f->one); - return (d); -} - -static ec *ecdbl(ec_curve *c, ec *d, const ec *a) -{ - if (EC_ATINF(a) || F_ZEROP(c->f, a->y)) - EC_SETINF(d); - else { - field *f = c->f; - mp *lambda; - mp *dy, *dx; - - dx = F_SQR(f, MP_NEW, a->x); /* %$x^2$% */ - dy = F_DBL(f, MP_NEW, a->y); /* %$2 y$% */ - dx = F_TPL(f, dx, dx); /* %$3 x^2$% */ - dx = F_ADD(f, dx, dx, c->a); /* %$3 x^2 + A$% */ - dy = F_INV(f, dy, dy); /* %$(2 y)^{-1}$% */ - lambda = F_MUL(f, MP_NEW, dx, dy); /* %$\lambda = (3 x^2 + A)/(2 y)$% */ - - dx = F_SQR(f, dx, lambda); /* %$\lambda^2$% */ - dy = F_DBL(f, dy, a->x); /* %$2 x$% */ - dx = F_SUB(f, dx, dx, dy); /* %$x' = \lambda^2 - 2 x */ - dy = F_SUB(f, dy, a->x, dx); /* %$x - x'$% */ - dy = F_MUL(f, dy, lambda, dy); /* %$\lambda (x - x')$% */ - dy = F_SUB(f, dy, dy, a->y); /* %$y' = \lambda (x - x') - y$% */ - - EC_DESTROY(d); - d->x = dx; - d->y = dy; - d->z = 0; - MP_DROP(lambda); - } - return (d); -} - -static ec *ecprojdbl(ec_curve *c, ec *d, const ec *a) -{ - if (EC_ATINF(a) || F_ZEROP(c->f, a->y)) - EC_SETINF(d); - else { - field *f = c->f; - mp *p, *q, *m, *s, *dx, *dy, *dz; - - p = F_SQR(f, MP_NEW, a->z); /* %$z^2$% */ - q = F_SQR(f, MP_NEW, p); /* %$z^4$% */ - p = F_MUL(f, p, q, c->a); /* %$A z^4$% */ - m = F_SQR(f, MP_NEW, a->x); /* %$x^2$% */ - m = F_TPL(f, m, m); /* %$3 x^2$% */ - m = F_ADD(f, m, m, p); /* %$m = 3 x^2 + A z^4$% */ - - q = F_DBL(f, q, a->y); /* %$2 y$% */ - dz = F_MUL(f, MP_NEW, q, a->z); /* %$z' = 2 y z$% */ - - p = F_SQR(f, p, q); /* %$4 y^2$% */ - s = F_MUL(f, MP_NEW, p, a->x); /* %$s = 4 x y^2$% */ - q = F_SQR(f, q, p); /* %$16 y^4$% */ - q = F_HLV(f, q, q); /* %$t = 8 y^4$% */ - - p = F_DBL(f, p, s); /* %$2 s$% */ - dx = F_SQR(f, MP_NEW, m); /* %$m^2$% */ - dx = F_SUB(f, dx, dx, p); /* %$x' = m^2 - 2 s$% */ - - s = F_SUB(f, s, s, dx); /* %$s - x'$% */ - dy = F_MUL(f, p, m, s); /* %$m (s - x')$% */ - dy = F_SUB(f, dy, dy, q); /* %$y' = m (s - x') - t$% */ - - EC_DESTROY(d); - d->x = dx; - d->y = dy; - d->z = dz; - MP_DROP(m); - MP_DROP(q); - MP_DROP(s); - } - return (d); -} - -static ec *ecprojxdbl(ec_curve *c, ec *d, const ec *a) -{ - if (EC_ATINF(a) || F_ZEROP(c->f, a->y)) - EC_SETINF(d); - else { - field *f = c->f; - mp *p, *q, *m, *s, *dx, *dy, *dz; - - m = F_SQR(f, MP_NEW, a->z); /* %$z^2$% */ - p = F_SUB(f, MP_NEW, a->x, m); /* %$x - z^2$% */ - q = F_ADD(f, MP_NEW, a->x, m); /* %$x + z^2$% */ - m = F_MUL(f, m, p, q); /* %$x^2 - z^4$% */ - m = F_TPL(f, m, m); /* %$m = 3 x^2 - 3 z^4$% */ - - q = F_DBL(f, q, a->y); /* %$2 y$% */ - dz = F_MUL(f, MP_NEW, q, a->z); /* %$z' = 2 y z$% */ - - p = F_SQR(f, p, q); /* %$4 y^2$% */ - s = F_MUL(f, MP_NEW, p, a->x); /* %$s = 4 x y^2$% */ - q = F_SQR(f, q, p); /* %$16 y^4$% */ - q = F_HLV(f, q, q); /* %$t = 8 y^4$% */ - - p = F_DBL(f, p, s); /* %$2 s$% */ - dx = F_SQR(f, MP_NEW, m); /* %$m^2$% */ - dx = F_SUB(f, dx, dx, p); /* %$x' = m^2 - 2 s$% */ - - s = F_SUB(f, s, s, dx); /* %$s - x'$% */ - dy = F_MUL(f, p, m, s); /* %$m (s - x')$% */ - dy = F_SUB(f, dy, dy, q); /* %$y' = m (s - x') - t$% */ - - EC_DESTROY(d); - d->x = dx; - d->y = dy; - d->z = dz; - MP_DROP(m); - MP_DROP(q); - MP_DROP(s); - } - return (d); -} - -static ec *ecadd(ec_curve *c, ec *d, const ec *a, const ec *b) -{ - if (a == b) - ecdbl(c, d, a); - else if (EC_ATINF(a)) - EC_COPY(d, b); - else if (EC_ATINF(b)) - EC_COPY(d, a); - else { - field *f = c->f; - mp *lambda; - mp *dy, *dx; - - if (!MP_EQ(a->x, b->x)) { - dy = F_SUB(f, MP_NEW, a->y, b->y); /* %$y_0 - y_1$% */ - dx = F_SUB(f, MP_NEW, a->x, b->x); /* %$x_0 - x_1$% */ - dx = F_INV(f, dx, dx); /* %$(x_0 - x_1)^{-1}$% */ - lambda = F_MUL(f, MP_NEW, dy, dx); - /* %$\lambda = (y_0 - y1)/(x_0 - x_1)$% */ - } else if (F_ZEROP(c->f, a->y) || !MP_EQ(a->y, b->y)) { - EC_SETINF(d); - return (d); - } else { - dx = F_SQR(f, MP_NEW, a->x); /* %$x_0^2$% */ - dx = F_TPL(f, dx, dx); /* %$3 x_0^2$% */ - dx = F_ADD(f, dx, dx, c->a); /* %$3 x_0^2 + A$% */ - dy = F_DBL(f, MP_NEW, a->y); /* %$2 y_0$% */ - dy = F_INV(f, dy, dy); /* %$(2 y_0)^{-1}$% */ - lambda = F_MUL(f, MP_NEW, dx, dy); - /* %$\lambda = (3 x_0^2 + A)/(2 y_0)$% */ - } - - dx = F_SQR(f, dx, lambda); /* %$\lambda^2$% */ - dx = F_SUB(f, dx, dx, a->x); /* %$\lambda^2 - x_0$% */ - dx = F_SUB(f, dx, dx, b->x); /* %$x' = \lambda^2 - x_0 - x_1$% */ - dy = F_SUB(f, dy, b->x, dx); /* %$x_1 - x'$% */ - dy = F_MUL(f, dy, lambda, dy); /* %$\lambda (x_1 - x')$% */ - dy = F_SUB(f, dy, dy, b->y); /* %$y' = \lambda (x_1 - x') - y_1$% */ - - EC_DESTROY(d); - d->x = dx; - d->y = dy; - d->z = 0; - MP_DROP(lambda); - } - return (d); -} - -static ec *ecprojadd(ec_curve *c, ec *d, const ec *a, const ec *b) -{ - if (a == b) - c->ops->dbl(c, d, a); - else if (EC_ATINF(a)) - EC_COPY(d, b); - else if (EC_ATINF(b)) - EC_COPY(d, a); - else { - field *f = c->f; - mp *p, *q, *r, *w, *u, *uu, *s, *ss, *dx, *dy, *dz; - - q = F_SQR(f, MP_NEW, a->z); /* %$z_0^2$% */ - u = F_MUL(f, MP_NEW, q, b->x); /* %$u = x_1 z_0^2$% */ - p = F_MUL(f, MP_NEW, q, b->y); /* %$y_1 z_0^2$% */ - s = F_MUL(f, q, p, a->z); /* %$s = y_1 z_0^3$% */ - - q = F_SQR(f, MP_NEW, b->z); /* %$z_1^2$% */ - uu = F_MUL(f, MP_NEW, q, a->x); /* %$uu = x_0 z_1^2$%*/ - p = F_MUL(f, p, q, a->y); /* %$y_0 z_1^2$% */ - ss = F_MUL(f, q, p, b->z); /* %$ss = y_0 z_1^3$% */ - - w = F_SUB(f, p, uu, u); /* %$w = uu - u$% */ - r = F_SUB(f, MP_NEW, ss, s); /* %$r = ss - s$% */ - if (F_ZEROP(f, w)) { - MP_DROP(w); - MP_DROP(u); - MP_DROP(s); - MP_DROP(uu); - MP_DROP(ss); - if (F_ZEROP(f, r)) { - MP_DROP(r); - return (c->ops->dbl(c, d, a)); - } else { - MP_DROP(r); - EC_SETINF(d); - return (d); - } - } - u = F_ADD(f, u, u, uu); /* %$t = uu + u$% */ - s = F_ADD(f, s, s, ss); /* %$m = ss + r$% */ - - uu = F_MUL(f, uu, a->z, w); /* %$z_0 w$% */ - dz = F_MUL(f, ss, uu, b->z); /* %$z' = z_0 z_1 w$% */ - - p = F_SQR(f, uu, w); /* %$w^2$% */ - q = F_MUL(f, MP_NEW, p, u); /* %$t w^2$% */ - u = F_MUL(f, u, p, w); /* %$w^3$% */ - p = F_MUL(f, p, u, s); /* %$m w^3$% */ - - dx = F_SQR(f, u, r); /* %$r^2$% */ - dx = F_SUB(f, dx, dx, q); /* %$x' = r^2 - t w^2$% */ - - s = F_DBL(f, s, dx); /* %$2 x'$% */ - q = F_SUB(f, q, q, s); /* %$v = t w^2 - 2 x'$% */ - dy = F_MUL(f, s, q, r); /* %$v r$% */ - dy = F_SUB(f, dy, dy, p); /* %$v r - m w^3$% */ - dy = F_HLV(f, dy, dy); /* %$y' = (v r - m w^3)/2$% */ - - EC_DESTROY(d); - d->x = dx; - d->y = dy; - d->z = dz; - MP_DROP(p); - MP_DROP(q); - MP_DROP(r); - MP_DROP(w); - } - return (d); -} - -static int eccheck(ec_curve *c, const ec *p) -{ - field *f = c->f; - mp *l, *x, *r; - int rc; - if (EC_ATINF(p)) return (0); - l = F_SQR(f, MP_NEW, p->y); - x = F_SQR(f, MP_NEW, p->x); - r = F_MUL(f, MP_NEW, x, p->x); - x = F_MUL(f, x, c->a, p->x); - r = F_ADD(f, r, r, x); - r = F_ADD(f, r, r, c->b); - rc = MP_EQ(l, r) ? 0 : -1; - mp_drop(l); - mp_drop(x); - mp_drop(r); - return (rc); -} - -static int ecprojcheck(ec_curve *c, const ec *p) -{ - ec t = EC_INIT; - int rc; - - c->ops->fix(c, &t, p); - rc = eccheck(c, &t); - EC_DESTROY(&t); - return (rc); -} - -static void ecdestroy(ec_curve *c) -{ - MP_DROP(c->a); - MP_DROP(c->b); - DESTROY(c); -} - -/* --- @ec_prime@, @ec_primeproj@ --- * - * - * Arguments: @field *f@ = the underlying field for this elliptic curve - * @mp *a, *b@ = the coefficients for this curve - * - * Returns: A pointer to the curve, or null. - * - * Use: Creates a curve structure for an elliptic curve defined over - * a prime field. The @primeproj@ variant uses projective - * coordinates, which can be a win. - */ - -extern ec_curve *ec_prime(field *f, mp *a, mp *b) -{ - ec_curve *c = CREATE(ec_curve); - c->ops = &ec_primeops; - c->f = f; - c->a = F_IN(f, MP_NEW, a); - c->b = F_IN(f, MP_NEW, b); - return (c); -} - -extern ec_curve *ec_primeproj(field *f, mp *a, mp *b) -{ - ec_curve *c = CREATE(ec_curve); - mp *ax; - - ax = mp_add(MP_NEW, a, MP_THREE); - ax = F_IN(f, ax, ax); - if (F_ZEROP(f, ax)) - c->ops = &ec_primeprojxops; - else - c->ops = &ec_primeprojops; - MP_DROP(ax); - c->f = f; - c->a = F_IN(f, MP_NEW, a); - c->b = F_IN(f, MP_NEW, b); - return (c); -} - -static const ec_ops ec_primeops = { - "prime", - ecdestroy, ec_stdsamep, ec_idin, ec_idout, ec_idfix, - ecfind, ecneg, ecadd, ec_stdsub, ecdbl, eccheck -}; - -static const ec_ops ec_primeprojops = { - "primeproj", - ecdestroy, ec_stdsamep, ec_projin, ec_projout, ec_projfix, - ecfind, ecneg, ecprojadd, ec_stdsub, ecprojdbl, ecprojcheck -}; - -static const ec_ops ec_primeprojxops = { - "primeproj", - ecdestroy, ec_stdsamep, ec_projin, ec_projout, ec_projfix, - ecfind, ecneg, ecprojadd, ec_stdsub, ecprojxdbl, ecprojcheck -}; - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#define MP(x) mp_readstring(MP_NEW, #x, 0, 0) - -int main(int argc, char *argv[]) -{ - field *f; - ec_curve *c; - ec g = EC_INIT, d = EC_INIT; - mp *p, *a, *b, *r; - int i, n = argc == 1 ? 1 : atoi(argv[1]); - - printf("ec-prime: "); - fflush(stdout); - a = MP(-3); - b = MP(0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef); - p = MP(39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319); - r = MP(39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942642); - - f = field_niceprime(p); - c = ec_primeproj(f, a, b); - - g.x = MP(0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7); - g.y = MP(0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f); - - for (i = 0; i < n; i++) { - ec_mul(c, &d, &g, r); - if (EC_ATINF(&d)) { - fprintf(stderr, "zero too early\n"); - return (1); - } - ec_add(c, &d, &d, &g); - if (!EC_ATINF(&d)) { - fprintf(stderr, "didn't reach zero\n"); - MP_EPRINT("d.x", d.x); - MP_EPRINT("d.y", d.y); - return (1); - } - ec_destroy(&d); - } - ec_destroy(&g); - ec_destroycurve(c); - F_DESTROY(f); - MP_DROP(p); MP_DROP(a); MP_DROP(b); MP_DROP(r); - assert(!mparena_count(&mparena_global)); - printf("ok\n"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/ec-raw.c b/ec-raw.c deleted file mode 100644 index 738827f..0000000 --- a/ec-raw.c +++ /dev/null @@ -1,96 +0,0 @@ -/* -*-c-*- - * - * $Id: ec-raw.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Raw formatting of elliptic curve points - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "ec.h" -#include "ec-raw.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @ec_putraw@ --- * - * - * Arguments: @ec_curve *c@ = elliptic curve - * @buf *b@ = pointer to a buffer - * @const ec *p@ = an elliptic curve point - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Puts an elliptic curve point to the given buffer using the - * standard uncompressed format described in P1383 and SEC1. - * This requires at most @1 + 2 * c->f->noctets@ space in the - * buffer. We don't do point compression. - */ - -int ec_putraw(ec_curve *c, buf *b, const ec *p) -{ - octet *q; - size_t n; - - if (EC_ATINF(p)) return (buf_putbyte(b, 0)); - buf_putbyte(b, 4); - n = c->f->noctets; - if ((q = buf_get(b, n * 2)) == 0) return (-1); - mp_storeb(p->x, q, n); - mp_storeb(p->y, q + n, n); - return (0); -} - -/* --- @ec_getraw@ --- * - * - * Arguments: @ec_curve *c@ = elliptic curve - * @buf *b@ = pointer to a buffer - * @ec *d@ = an elliptic curve point - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Reads an elliptic curve point from the given buffer using the - * standard uncompressed format described in P1383 and SEC1. - * We don't do point compression. - */ - -int ec_getraw(ec_curve *c, buf *b, ec *d) -{ - const octet *q; - size_t n; - int u; - - if ((u = buf_getbyte(b)) < 0) return (-1); - if (!u) { EC_SETINF(d); return (0); } - if (!(u & 4)) return (-1); - n = c->f->noctets; - if ((q = buf_get(b, n * 2)) == 0) return (-1); - EC_DESTROY(d); - d->x = mp_loadb(MP_NEW, q, n); - d->y = mp_loadb(MP_NEW, q + n, n); - d->z = 0; - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/ec-raw.h b/ec-raw.h deleted file mode 100644 index 083ca93..0000000 --- a/ec-raw.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -*-c-*- - * - * $Id: ec-raw.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Raw formatting of elliptic curve points - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_EC_RAW_H -#define CATACOMB_EC_RAW_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_BUF_H -# include "buf.h" -#endif - -#ifndef CATACOMB_EC_H -# include "ec.h" -#endif - -/*----- Data formatting ---------------------------------------------------*/ - -/* --- @ec_putraw@ --- * - * - * Arguments: @ec_curve *c@ = elliptic curve - * @buf *b@ = pointer to a buffer - * @const ec *p@ = an elliptic curve point - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Puts an elliptic curve point to the given buffer using the - * standard uncompressed format described in P1383 and SEC1. - * We don't do point compression. - */ - -extern int ec_putraw(ec_curve */*c*/, buf */*b*/, const ec */*p*/); - -/* --- @ec_getraw@ --- * - * - * Arguments: @ec_curve *c@ = elliptic curve - * @buf *b@ = pointer to a buffer - * @ec *d@ = an elliptic curve point - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Reads an elliptic curve point from the given buffer using the - * standard uncompressed format described in P1383 and SEC1. - * We don't do point compression. - */ - -extern int ec_getraw(ec_curve */*c*/, buf */*b*/, ec */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/ec-test.c b/ec-test.c deleted file mode 100644 index ad2af90..0000000 --- a/ec-test.c +++ /dev/null @@ -1,347 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Code for testing elliptic-curve stuff - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ec.h" -#include "ec-test.h" - -/*----- Cardboard cut-out elliptic curve ----------------------------------*/ - -typedef struct ecctx { - ec_curve c; - unsigned long magic; - char *name; - ec_curve *real; -} ecctx; - -#define MAGIC 0x3a1f0b07 - -static void ecDESTROY(ec_curve *cc) -{ - ecctx *c = (ecctx *)cc; - xfree(c->name); - ec_destroycurve(c->real); - DESTROY(c); -} - -#define UNOP(OP) \ - static ec *ec##OP(ec_curve *cc, ec *d, const ec *p) { \ - ecctx *c = (ecctx *)cc; \ - return (EC_##OP(c->real, d, p)); \ - } - -#define BINOP(OP) \ - static ec *ec##OP(ec_curve *cc, ec *d, const ec *p, const ec *q) { \ - ecctx *c = (ecctx *)cc; \ - return (EC_##OP(c->real, d, p, q)); \ - } - -UNOP(IN) -UNOP(OUT) -UNOP(FIX) -UNOP(NEG) -UNOP(DBL) -BINOP(ADD) -BINOP(SUB) - -#undef UNOP -#undef BINOP - -static ec *ecFIND(ec_curve *cc, ec *d, mp *x) -{ - ecctx *c = (ecctx *)cc; - return (EC_FIND(c->real, d, x)); -} - -static int ecCHECK(ec_curve *cc, const ec *p) -{ - ecctx *c = (ecctx *)cc; - return (EC_CHECK(c->real, p)); -} - -static int ecSAMEP(ec_curve *cc, ec_curve *dd) -{ - ecctx *c = (ecctx *)cc, *d = (ecctx *)dd; - return (ec_samep(c->real, d->real)); -} - -static const ec_ops ecops = { - "cardboard", - ecDESTROY, ecSAMEP, ecIN, ecOUT, ecFIX, - ecFIND, ecNEG, ecADD, ecSUB, ecDBL, ecCHECK -}; - -static ec_curve *ec_cutout(ec_curve *real, const char *name) -{ - ecctx *c = CREATE(ecctx); - c->c.f = real->f; - c->c.ops = &ecops; - c->c.a = real->a; - c->c.b = real->b; - c->magic = MAGIC; - c->name = xstrdup(name); - c->real = real; - return (&c->c); -} - -static const char *ec_name(ec_curve *cc) -{ - ecctx *c = (ecctx *)cc; - assert(c->magic == MAGIC); - return (c->name); -} - -/*----- Test field types --------------------------------------------------*/ - -static void ecvcvt(const char *buf, dstr *d) -{ - ec_curve *v; - qd_parse qd; - - qd.p = buf; - qd.e = 0; - if ((v = ec_curveparse(&qd)) == 0) { - fprintf(stderr, "bad curve `%.*s|%s': %s\n", - qd.p - buf, buf, qd.p, qd.e); - exit(1); - } - dstr_ensure(d, sizeof(v)); - *(ec_curve **)d->buf = ec_cutout(v, buf); - d->len += sizeof(v); -} - -static void ecvdump(dstr *d, FILE *fp) -{ - ec_curve *v = *(ec_curve **)d->buf; - fprintf(fp, "%s", ec_name(v)); -} - -const test_type type_ecurve = { ecvcvt, ecvdump }; - -static void eccvt(const char *p, dstr *d) -{ - ec *a; - qd_parse qd; - - qd.p = p; - qd.e = 0; - dstr_ensure(d, sizeof(ec)); - a = (ec *)d->buf; - d->len += sizeof(ec); - ec_create(a); - if (!ec_ptparse(&qd, a)) { - fprintf(stderr, "bad point `%.*s|%s': %s\n", qd.p - p, p, qd.p, qd.e); - exit(1); - } -} - -static void ecdodump(ec *a, FILE *fp) -{ - if (EC_ATINF(a)) - fputs("inf", fp); - else { - fputs("0x", fp); - mp_writefile(a->x, fp, 16); - fputs(", 0x", fp); - mp_writefile(a->y, fp, 16); - } -} - -static void ecdump(dstr *d, FILE *fp) -{ - ec *a = (ec *)d->buf; - ecdodump(a, fp); -} - -const test_type type_ec = { eccvt, ecdump }; - -/*----- Testing elliptic curve functionality ------------------------------*/ - -#ifdef TEST_RIG - -static void ecdestroy(ec_curve *c) -{ - field *f = c->f; - ec_destroycurve(c); - F_DESTROY(f); -} - -#define UNOP(op) \ - static int v##op(dstr v[]) \ - { \ - ec_curve *e = *(ec_curve **)v[0].buf; \ - ec *a = (ec *)v[1].buf; \ - ec *r = (ec *)v[2].buf; \ - ec c = EC_INIT; \ - int ok = 1; \ - ec_##op(e, &c, a); \ - if (!EC_EQ(r, &c)) { \ - fprintf(stderr, #op "failed"); \ - fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); \ - fprintf(stderr, "\n a = "); ecdodump(a, stderr); \ - fprintf(stderr, "\n r = "); ecdodump(r, stderr); \ - fprintf(stderr, "\n c = "); ecdodump(&c, stderr); \ - fprintf(stderr, "\n"); \ - ok = 0; \ - } \ - EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); \ - ecdestroy(e); \ - return (ok); \ - } - -#define BINOP(op) \ - static int v##op(dstr v[]) \ - { \ - ec_curve *e = *(ec_curve **)v[0].buf; \ - ec *a = (ec *)v[1].buf; \ - ec *b = (ec *)v[2].buf; \ - ec *r = (ec *)v[3].buf; \ - ec c = EC_INIT; \ - int ok = 1; \ - ec_##op(e, &c, a, b); \ - if (!EC_EQ(r, &c)) { \ - fprintf(stderr, #op "failed"); \ - fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); \ - fprintf(stderr, "\n a = "); ecdodump(a, stderr); \ - fprintf(stderr, "\n b = "); ecdodump(b, stderr); \ - fprintf(stderr, "\n r = "); ecdodump(r, stderr); \ - fprintf(stderr, "\n c = "); ecdodump(&c, stderr); \ - fprintf(stderr, "\n"); \ - ok = 0; \ - } \ - EC_DESTROY(a); EC_DESTROY(b); EC_DESTROY(r); EC_DESTROY(&c); \ - ecdestroy(e); \ - return (ok); \ - } - -UNOP(neg) -UNOP(dbl) -BINOP(add) -BINOP(sub) - -static int vcheck(dstr v[]) -{ - ec_curve *e = *(ec_curve **)v[0].buf; - ec *a = (ec *)v[1].buf; - int r = *(int *)v[2].buf; - int c; - int ok = 1; - c = ec_check(e, a); - if (r != c) { - fprintf(stderr, "check failed"); - fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); - fprintf(stderr, "\n a = "); ecdodump(a, stderr); - fprintf(stderr, "\n r = %d", r); - fprintf(stderr, "\n c = %d", c); - fprintf(stderr, "\n"); - ok = 0; - } - EC_DESTROY(a); - ecdestroy(e); - return (ok); -} - -static int vmul(dstr v[]) -{ - ec_curve *e = *(ec_curve **)v[0].buf; - ec *a = (ec *)v[1].buf; - mp *n = *(mp **)v[2].buf; - ec *r = (ec *)v[3].buf; - ec c = EC_INIT; - int ok = 1; - ec_mul(e, &c, a, n); - if (!EC_EQ(r, &c)) { - fprintf(stderr, "mul failed"); - fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); - fprintf(stderr, "\n a = "); ecdodump(a, stderr); - fprintf(stderr, "\n n = "); mp_writefile(n, stderr, 10); - fprintf(stderr, "\n r = "); ecdodump(r, stderr); - fprintf(stderr, "\n c = "); ecdodump(&c, stderr); - fprintf(stderr, "\n"); - ok = 0; - } - EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); MP_DROP(n); - ecdestroy(e); - return (ok); -} - -static int vfind(dstr v[]) -{ - ec_curve *e = *(ec_curve **)v[0].buf; - mp *x = *(mp **)v[1].buf; - ec *r = (ec *)v[2].buf; - ec c = EC_INIT; - int ok = 1; - if (!ec_find(e, &c, x)) EC_SETINF(&c); - if (!EC_EQ(r, &c)) { - fprintf(stderr, "find failed"); - fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); - fprintf(stderr, "\n x = "); mp_writefile(x, stderr, 16); - fprintf(stderr, "\n r = "); ecdodump(r, stderr); - fprintf(stderr, "\n c = "); ecdodump(&c, stderr); - fprintf(stderr, "\n"); - ok = 0; - } - MP_DROP(x); EC_DESTROY(r); EC_DESTROY(&c); - ecdestroy(e); - return (ok); -} - -static test_chunk tests[] = { - { "neg", vneg, { &type_ecurve, &type_ec, &type_ec } }, - { "dbl", vdbl, { &type_ecurve, &type_ec, &type_ec } }, - { "add", vadd, { &type_ecurve, &type_ec, &type_ec, &type_ec } }, - { "sub", vsub, { &type_ecurve, &type_ec, &type_ec, &type_ec } }, - { "mul", vmul, { &type_ecurve, &type_ec, &type_mp, &type_ec } }, - { "check", vcheck, { &type_ecurve, &type_ec, &type_int } }, - { "find", vfind, { &type_ecurve, &type_mp, &type_ec } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/ec"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/ec-test.h b/ec-test.h deleted file mode 100644 index 18e4b25..0000000 --- a/ec-test.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*-c-*- - * - * $Id: ec-test.h,v 1.3 2004/04/08 16:17:32 mdw Exp $ - * - * Elliptic curve test functions - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_EC_TEST_H -#define CATACOMB_EC_TEST_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_EC_H -# include "ec.h" -#endif - -/*----- Test vector types -------------------------------------------------*/ - -extern const test_type type_ecurve, type_ec; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/ec.c b/ec.c deleted file mode 100644 index cad7a56..0000000 --- a/ec.c +++ /dev/null @@ -1,424 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Elliptic curve definitions - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "ec.h" - -/*----- Trivial wrappers --------------------------------------------------*/ - -/* --- @ec_samep@ --- * - * - * Arguments: @ec_curve *c, *d@ = two elliptic curves - * - * Returns: Nonzero if the curves are identical (not just isomorphic). - * - * Use: Checks for sameness of curves. This function does the full - * check, not just the curve-type-specific check done by the - * @sampep@ field operation. - */ - -int ec_samep(ec_curve *c, ec_curve *d) -{ - return (c == d || (field_samep(c->f, d->f) && - c->ops == d->ops && EC_SAMEP(c, d))); -} - -/* --- @ec_create@ --- * - * - * Arguments: @ec *p@ = pointer to an elliptic-curve point - * - * Returns: The argument @p@. - * - * Use: Initializes a new point. The initial value is the additive - * identity (which is universal for all curves). - */ - -ec *ec_create(ec *p) { EC_CREATE(p); return (p); } - -/* --- @ec_destroy@ --- * - * - * Arguments: @ec *p@ = pointer to an elliptic-curve point - * - * Returns: --- - * - * Use: Destroys a point, making it invalid. - */ - -void ec_destroy(ec *p) { EC_DESTROY(p); } - -/* --- @ec_atinf@ --- * - * - * Arguments: @const ec *p@ = pointer to a point - * - * Returns: Nonzero if %$p = O$% is the point at infinity, zero - * otherwise. - */ - -int ec_atinf(const ec *p) { return (EC_ATINF(p)); } - -/* --- @ec_setinf@ --- * - * - * Arguments: @ec *p@ = pointer to a point - * - * Returns: The argument @p@. - * - * Use: Sets the given point to be the point %$O$% at infinity. - */ - -ec *ec_setinf(ec *p) { EC_SETINF(p); return (p); } - -/* --- @ec_copy@ --- * - * - * Arguments: @ec *d@ = pointer to destination point - * @const ec *p@ = pointer to source point - * - * Returns: The destination @d@. - * - * Use: Creates a copy of an elliptic curve point. - */ - -ec *ec_copy(ec *d, const ec *p) { EC_COPY(d, p); return (d); } - -/* --- @ec_eq@ --- * - * - * Arguments: @const ec *p, *q@ = two points - * - * Returns: Nonzero if the points are equal. Compares external-format - * points. - */ - -int ec_eq(const ec *p, const ec *q) { return (EC_EQ(p, q)); } - -/*----- Standard curve operations -----------------------------------------*/ - -/* --- @ec_stdsamep@ --- * - * - * Arguments: @ec_curve *c, *d@ = two elliptic curves - * - * Returns: Nonzero if the curves are identical (not just isomorphic). - * - * Use: Simple sameness check on @a@ and @b@ curve members. - */ - -int ec_stdsamep(ec_curve *c, ec_curve *d) - { return (MP_EQ(c->a, d->a) && MP_EQ(c->b, d->b)); } - -/* --- @ec_idin@, @ec_idout@, @ec_idfix@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination - * @const ec *p@ = pointer to a source point - * - * Returns: The destination @d@. - * - * Use: An identity operation if your curve has no internal - * representation. (The field internal representation is still - * used.) - */ - -ec *ec_idin(ec_curve *c, ec *d, const ec *p) -{ - if (EC_ATINF(p)) - EC_SETINF(d); - else { - field *f = c->f; - d->x = F_IN(f, d->x, p->x); - d->y = F_IN(f, d->y, p->y); - mp_drop(d->z); d->z = 0; - } - return (d); -} - -ec *ec_idout(ec_curve *c, ec *d, const ec *p) -{ - if (EC_ATINF(p)) - EC_SETINF(d); - else { - field *f = c->f; - d->x = F_OUT(f, d->x, p->x); - d->y = F_OUT(f, d->y, p->y); - mp_drop(d->z); d->z = 0; - } - return (d); -} - -ec *ec_idfix(ec_curve *c, ec *d, const ec *p) - { EC_COPY(d, p); return (d); } - -/* --- @ec_projin@, @ec_projout@, @ec_projfix@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination - * @const ec *p@ = pointer to a source point - * - * Returns: The destination @d@. - * - * Use: Conversion functions if your curve operations use a - * projective representation. - */ - -ec *ec_projin(ec_curve *c, ec *d, const ec *p) -{ - if (EC_ATINF(p)) - EC_SETINF(d); - else { - field *f = c->f; - d->x = F_IN(f, d->x, p->x); - d->y = F_IN(f, d->y, p->y); - mp_drop(d->z); d->z = MP_COPY(f->one); - } - return (d); -} - -ec *ec_projout(ec_curve *c, ec *d, const ec *p) -{ - if (EC_ATINF(p)) - EC_SETINF(d); - else { - mp *x, *y, *z, *zz; - field *f = c->f; - if (p->z == f->one) { - d->x = F_OUT(f, d->x, p->x); - d->y = F_OUT(f, d->y, p->y); - } else { - z = F_INV(f, MP_NEW, p->z); - zz = F_SQR(f, MP_NEW, z); - z = F_MUL(f, z, zz, z); - x = F_MUL(f, d->x, p->x, zz); - y = F_MUL(f, d->y, p->y, z); - mp_drop(z); - mp_drop(zz); - d->x = F_OUT(f, x, x); - d->y = F_OUT(f, y, y); - } - mp_drop(d->z); - d->z = 0; - } - return (d); -} - -ec *ec_projfix(ec_curve *c, ec *d, const ec *p) -{ - if (EC_ATINF(p)) - EC_SETINF(d); - else if (p->z == c->f->one) - EC_COPY(d, p); - else { - mp *z, *zz; - field *f = c->f; - z = F_INV(f, MP_NEW, p->z); - zz = F_SQR(f, MP_NEW, z); - z = F_MUL(f, z, zz, z); - d->x = F_MUL(f, d->x, p->x, zz); - d->y = F_MUL(f, d->y, p->y, z); - mp_drop(z); - mp_drop(zz); - mp_drop(d->z); - d->z = MP_COPY(f->one); - } - return (d); -} - -/* --- @ec_stdsub@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination - * @const ec *p, *q@ = the operand points - * - * Returns: The destination @d@. - * - * Use: Standard point subtraction operation, in terms of negation - * and addition. This isn't as efficient as a ready-made - * subtraction operator. - */ - -ec *ec_stdsub(ec_curve *c, ec *d, const ec *p, const ec *q) -{ - ec t = EC_INIT; - EC_NEG(c, &t, q); - EC_FIX(c, &t, &t); - EC_ADD(c, d, p, &t); - EC_DESTROY(&t); - return (d); -} - -/*----- Creating curves ---------------------------------------------------*/ - -/* --- @ec_destroycurve@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an ellptic curve - * - * Returns: --- - * - * Use: Destroys a description of an elliptic curve. - */ - -void ec_destroycurve(ec_curve *c) { c->ops->destroy(c); } - -/*----- Real arithmetic ---------------------------------------------------*/ - -/* --- @ec_find@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @mp *x@ = a possible x-coordinate - * - * Returns: Zero if OK, nonzero if there isn't a point there. - * - * Use: Finds a point on an elliptic curve with a given x-coordinate. - */ - -ec *ec_find(ec_curve *c, ec *d, mp *x) -{ - x = F_IN(c->f, MP_NEW, x); - if ((d = EC_FIND(c, d, x)) != 0) - EC_OUT(c, d, d); - MP_DROP(x); - return (d); -} - -/* --- @ec_neg@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @const ec *p@ = pointer to the operand point - * - * Returns: The destination point. - * - * Use: Computes the negation of the given point. - */ - -ec *ec_neg(ec_curve *c, ec *d, const ec *p) - { EC_IN(c, d, p); EC_NEG(c, d, d); return (EC_OUT(c, d, d)); } - -/* --- @ec_add@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @const ec *p, *q@ = pointers to the operand points - * - * Returns: --- - * - * Use: Adds two points on an elliptic curve. - */ - -ec *ec_add(ec_curve *c, ec *d, const ec *p, const ec *q) -{ - ec pp = EC_INIT, qq = EC_INIT; - EC_IN(c, &pp, p); - EC_IN(c, &qq, q); - EC_ADD(c, d, &pp, &qq); - EC_OUT(c, d, d); - EC_DESTROY(&pp); - EC_DESTROY(&qq); - return (d); -} - -/* --- @ec_sub@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @const ec *p, *q@ = pointers to the operand points - * - * Returns: The destination @d@. - * - * Use: Subtracts one point from another on an elliptic curve. - */ - -ec *ec_sub(ec_curve *c, ec *d, const ec *p, const ec *q) -{ - ec pp = EC_INIT, qq = EC_INIT; - EC_IN(c, &pp, p); - EC_IN(c, &qq, q); - EC_SUB(c, d, &pp, &qq); - EC_OUT(c, d, d); - EC_DESTROY(&pp); - EC_DESTROY(&qq); - return (d); -} - -/* --- @ec_dbl@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @const ec *p@ = pointer to the operand point - * - * Returns: --- - * - * Use: Doubles a point on an elliptic curve. - */ - -ec *ec_dbl(ec_curve *c, ec *d, const ec *p) - { EC_IN(c, d, p); EC_DBL(c, d, d); return (EC_OUT(c, d, d)); } - -/* --- @ec_check@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @const ec *p@ = pointer to the point - * - * Returns: Zero if OK, nonzero if this is an invalid point. - * - * Use: Checks that a point is actually on an elliptic curve. - */ - -int ec_check(ec_curve *c, const ec *p) -{ - ec t = EC_INIT; - int rc; - - if (EC_ATINF(p)) - return (0); - EC_IN(c, &t, p); - rc = EC_CHECK(c, &t); - EC_DESTROY(&t); - return (rc); -} - -/* --- @ec_rand@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @grand *r@ = random number source - * - * Returns: The destination @d@. - * - * Use: Finds a random point on the given curve. - */ - -ec *ec_rand(ec_curve *c, ec *d, grand *r) -{ - mp *x = MP_NEW; - do x = F_RAND(c->f, x, r); while (!EC_FIND(c, d, x)); - mp_drop(x); - if (grand_range(r, 2)) EC_NEG(c, d, d); - return (EC_OUT(c, d, d)); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/ec.h b/ec.h deleted file mode 100644 index ac0b8fc..0000000 --- a/ec.h +++ /dev/null @@ -1,618 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Elliptic curve definitions - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_EC_H -#define CATACOMB_EC_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_FIELD_H -# include "field.h" -#endif - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_QDPARSE_H -# include "qdparse.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- An elliptic curve representation --- */ - -typedef struct ec_curve { - const struct ec_ops *ops; /* Curve operations */ - field *f; /* Underlying field structure */ - mp *a, *b; /* Standard params (internal form) */ -} ec_curve; - -/* --- An elliptic curve point --- */ - -typedef struct ec { - mp *x, *y; /* Point coordinates */ - mp *z; /* Common denominator (or null) */ -} ec; - -/* --- A factor for simultaneous multiplication --- */ - -typedef struct ec_mulfactor { - ec base; /* The point */ - mp *exp; /* The exponent */ -} ec_mulfactor; - -/* --- Elliptic curve operations --- * - * - * All operations (apart from @destroy@ and @in@) are guaranteed to be - * performed on internal representations of points. - * - * (Historical note. We used to guarantee that the second to @add@ and @mul@ - * was the output of @in@ or @fix@, but this canonification turned out to - * make the precomputation in @ec_exp@ too slow. Projective implementations - * must therefore cope with a pair of arbitrary points.) - */ - -typedef struct ec_ops { - const char *name; - void (*destroy)(ec_curve */*c*/); - int (*samep)(ec_curve */*c*/, ec_curve */*d*/); - ec *(*in)(ec_curve */*c*/, ec */*d*/, const ec */*p*/); - ec *(*out)(ec_curve */*c*/, ec */*d*/, const ec */*p*/); - ec *(*fix)(ec_curve */*c*/, ec */*d*/, const ec */*p*/); - ec *(*find)(ec_curve */*c*/, ec */*d*/, mp */*x*/); - ec *(*neg)(ec_curve */*c*/, ec */*d*/, const ec */*p*/); - ec *(*add)(ec_curve */*c*/, ec */*d*/, const ec */*p*/, const ec */*q*/); - ec *(*sub)(ec_curve */*c*/, ec */*d*/, const ec */*p*/, const ec */*q*/); - ec *(*dbl)(ec_curve */*c*/, ec */*d*/, const ec */*p*/); - int (*check)(ec_curve */*c*/, const ec */*p*/); -} ec_ops; - -#define EC_NAME(c) (c)->ops->name - -#define EC_SAMEP(c, d) (c)->ops->samep((c), (d)) -#define EC_IN(c, d, p) (c)->ops->in((c), (d), (p)) -#define EC_OUT(c, d, p) (c)->ops->out((c), (d), (p)) -#define EC_FIX(c, d, p) (c)->ops->fix((c), (d), (p)) - -#define EC_FIND(c, d, x) (c)->ops->find((c), (d), (x)) -#define EC_NEG(c, d, x) (c)->ops->neg((c), (d), (x)) -#define EC_ADD(c, d, p, q) (c)->ops->add((c), (d), (p), (q)) -#define EC_SUB(c, d, p, q) (c)->ops->sub((c), (d), (p), (q)) -#define EC_DBL(c, d, p) (c)->ops->dbl((c), (d), (p)) -#define EC_CHECK(c, p) (c)->ops->check((c), (p)) - -/* --- Elliptic curve parameters --- */ - -typedef struct ec_info { - ec_curve *c; /* The actual curve */ - ec g; /* The common point */ - mp *r; /* Order of %$g$% */ - mp *h; /* Cofactor %$h = \#E/r$% */ -} ec_info; - -/*----- Simple memory management things -----------------------------------*/ - -/* --- @ec_create@ --- * - * - * Arguments: @ec *p@ = pointer to an elliptic-curve point - * - * Returns: The argument @p@. - * - * Use: Initializes a new point. The initial value is the additive - * identity (which is universal for all curves). - */ - -#define EC_INIT { MP_NEW, MP_NEW, MP_NEW } - -#define EC_CREATE(p) do { \ - ec *_p = (p); \ - _p->x = _p->y = _p->z = MP_NEW; \ -} while (0) - -extern ec *ec_create(ec */*p*/); - -/* --- @ec_destroy@ --- * - * - * Arguments: @ec *p@ = pointer to an elliptic-curve point - * - * Returns: --- - * - * Use: Destroys a point, making it invalid. - */ - -#define EC_DESTROY(p) do { \ - ec *_p = (p); \ - if (!EC_ATINF(_p)) { \ - MP_DROP(_p->x); \ - MP_DROP(_p->y); \ - if (_p->z) MP_DROP(_p->z); \ - } \ -} while (0) - -extern void ec_destroy(ec */*p*/); - -/* --- @ec_atinf@ --- * - * - * Arguments: @const ec *p@ = pointer to a point - * - * Returns: Nonzero if %$p = O$% is the point at infinity, zero - * otherwise. - */ - -#define EC_ATINF(p) ((p)->x == MP_NEW || (p)->x == MP_NEWSEC) - -extern int ec_atinf(const ec */*p*/); - -/* --- @ec_setinf@ --- * - * - * Arguments: @ec *p@ = pointer to a point - * - * Returns: The argument @p@. - * - * Use: Sets the given point to be the point %$O$% at infinity. - */ - -#define EC_SETINF(p) do { \ - ec *_p = (p); \ - if (!EC_ATINF(_p)) { \ - MP_DROP(_p->x); \ - MP_DROP(_p->y); \ - if (_p->z) MP_DROP(_p->z); \ - _p->x = _p->y = _p->z = MP_NEW; \ - _p->y = MP_NEW; \ - _p->z = MP_NEW; \ - } \ -} while (0) - -extern ec *ec_setinf(ec */*p*/); - -/* --- @ec_copy@ --- * - * - * Arguments: @ec *d@ = pointer to destination point - * @const ec *p@ = pointer to source point - * - * Returns: The destination @d@. - * - * Use: Creates a copy of an elliptic curve point. - */ - -#define EC_COPY(d, p) do { \ - ec *_d = (d); \ - const ec *_p = (p); \ - if (d != p) { \ - EC_DESTROY(d); \ - if (EC_ATINF(p)) \ - _d->x = _d->y = _d->z = MP_NEW; \ - else { \ - _d->x = MP_COPY(_p->x); \ - _d->y = MP_COPY(_p->y); \ - _d->z = _p->z ? MP_COPY(_p->z) : MP_NEW; \ - } \ - } \ -} while (0) - -extern ec *ec_copy(ec */*d*/, const ec */*p*/); - -/* --- @ec_eq@ --- * - * - * Arguments: @const ec *p, *q@ = two points - * - * Returns: Nonzero if the points are equal. Compares external-format - * points. - */ - -#define EC_EQ(p, q) \ - ((EC_ATINF(p) && EC_ATINF(q)) || \ - (!EC_ATINF(p) && !EC_ATINF(q) && \ - MP_EQ((p)->x, (q)->x) && \ - MP_EQ((p)->y, (q)->y))) - -extern int ec_eq(const ec *p, const ec *q); - -/*----- Interesting arithmetic --------------------------------------------*/ - -/* --- @ec_samep@ --- * - * - * Arguments: @ec_curve *c, *d@ = two elliptic curves - * - * Returns: Nonzero if the curves are identical (not just isomorphic). - * - * Use: Checks for sameness of curves. This function does the full - * check, not just the curve-type-specific check done by the - * @sampep@ field operation. - */ - -extern int ec_samep(ec_curve */*c*/, ec_curve */*d*/); - -/* --- @ec_find@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @mp *x@ = a possible x-coordinate - * - * Returns: The destination if OK, or null if no point was found. - * - * Use: Finds a point on an elliptic curve with a given - * x-coordinate. If there is no point with the given - * %$x$%-coordinate, a null pointer is returned and the - * destination is left invalid. - */ - -extern ec *ec_find(ec_curve */*c*/, ec */*d*/, mp */*x*/); - -/* --- @ec_rand@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @grand *r@ = random number source - * - * Returns: The destination @d@. - * - * Use: Finds a random point on the given curve. - */ - -extern ec *ec_rand(ec_curve */*c*/, ec */*d*/, grand */*r*/); - -/* --- @ec_neg@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @const ec *p@ = pointer to the operand point - * - * Returns: The destination point. - * - * Use: Computes the negation of the given point. - */ - -extern ec *ec_neg(ec_curve */*c*/, ec */*d*/, const ec */*p*/); - -/* --- @ec_add@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @const ec *p, *q@ = pointers to the operand points - * - * Returns: The destination @d@. - * - * Use: Adds two points on an elliptic curve. - */ - -extern ec *ec_add(ec_curve */*c*/, ec */*d*/, - const ec */*p*/, const ec */*q*/); - -/* --- @ec_sub@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @const ec *p, *q@ = pointers to the operand points - * - * Returns: The destination @d@. - * - * Use: Subtracts one point from another on an elliptic curve. - */ - -extern ec *ec_sub(ec_curve */*c*/, ec */*d*/, - const ec */*p*/, const ec */*q*/); - -/* --- @ec_dbl@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @const ec *p@ = pointer to the operand point - * - * Returns: The destination @d@. - * - * Use: Doubles a point on an elliptic curve. - */ - -extern ec *ec_dbl(ec_curve */*c*/, ec */*d*/, const ec */*p*/); - -/* --- @ec_check@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @const ec *p@ = pointer to the point - * - * Returns: Zero if OK, nonzero if this is an invalid point. - * - * Use: Checks that a point is actually on an elliptic curve. - */ - -extern int ec_check(ec_curve */*c*/, const ec */*p*/); - -/* --- @ec_mul@, @ec_imul@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @const ec *p@ = pointer to the generator point - * @mp *n@ = integer multiplier - * - * Returns: The destination @d@. - * - * Use: Multiplies a point by a scalar, returning %$n p$%. The - * @imul@ variant uses internal representations for argument - * and result. - */ - -extern ec *ec_mul(ec_curve */*c*/, ec */*d*/, const ec */*p*/, mp */*n*/); -extern ec *ec_imul(ec_curve */*c*/, ec */*d*/, const ec */*p*/, mp */*n*/); - -/* --- @ec_mmul@, @ec_immul@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination point - * @const ec_mulfactor *f@ = pointer to vector of factors - * @size_t n@ = number of factors - * - * Returns: The destination @d@. - * - * Use: Does simultaneous point multiplication. The @immul@ variant - * uses internal representations for arguments and result. - */ - -extern ec *ec_mmul(ec_curve */*c*/, ec */*d*/, - const ec_mulfactor */*f*/, size_t /*n*/); -extern ec *ec_immul(ec_curve */*c*/, ec */*d*/, - const ec_mulfactor */*f*/, size_t /*n*/); - -/*----- Standard curve operations -----------------------------------------*/ - -/* --- @ec_stdsamep@ --- * - * - * Arguments: @ec_curve *c, *d@ = two elliptic curves - * - * Returns: Nonzero if the curves are identical (not just isomorphic). - * - * Use: Simple sameness check on @a@ and @b@ curve members. - */ - -extern int ec_stdsamep(ec_curve */*c*/, ec_curve */*d*/); - -/* --- @ec_idin@, @ec_idout@, @ec_idfix@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination - * @const ec *p@ = pointer to a source point - * - * Returns: The destination @d@. - * - * Use: An identity operation if your curve has no internal - * representation. (The field internal representation is still - * used.) - */ - -extern ec *ec_idin(ec_curve */*c*/, ec */*d*/, const ec */*p*/); -extern ec *ec_idout(ec_curve */*c*/, ec */*d*/, const ec */*p*/); -extern ec *ec_idfix(ec_curve */*c*/, ec */*d*/, const ec */*p*/); - -/* --- @ec_projin@, @ec_projout@, @ec_projfix@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination - * @const ec *p@ = pointer to a source point - * - * Returns: The destination @d@. - * - * Use: Conversion functions if your curve operations use a - * projective representation. - */ - -extern ec *ec_projin(ec_curve */*c*/, ec */*d*/, const ec */*p*/); -extern ec *ec_projout(ec_curve */*c*/, ec */*d*/, const ec */*p*/); -extern ec *ec_projfix(ec_curve */*c*/, ec */*d*/, const ec */*p*/); - -/* --- @ec_stdsub@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an elliptic curve - * @ec *d@ = pointer to the destination - * @const ec *p, *q@ = the operand points - * - * Returns: The destination @d@. - * - * Use: Standard point subtraction operation, in terms of negation - * and addition. This isn't as efficient as a ready-made - * subtraction operator. - */ - -extern ec *ec_stdsub(ec_curve */*c*/, ec */*d*/, - const ec */*p*/, const ec */*q*/); - -/*----- Creating curves ---------------------------------------------------*/ - -/* --- @ec_destroycurve@ --- * - * - * Arguments: @ec_curve *c@ = pointer to an ellptic curve - * - * Returns: --- - * - * Use: Destroys a description of an elliptic curve. - */ - -extern void ec_destroycurve(ec_curve */*c*/); - -/* --- @ec_prime@, @ec_primeproj@ --- * - * - * Arguments: @field *f@ = the underlying field for this elliptic curve - * @mp *a, *b@ = the coefficients for this curve - * - * Returns: A pointer to the curve, or null. - * - * Use: Creates a curve structure for an elliptic curve defined over - * a prime field. The @primeproj@ variant uses projective - * coordinates, which can be a win. - */ - -extern ec_curve *ec_prime(field */*f*/, mp */*a*/, mp */*b*/); -extern ec_curve *ec_primeproj(field */*f*/, mp */*a*/, mp */*b*/); - -/* --- @ec_bin@, @ec_binproj@ --- * - * - * Arguments: @field *f@ = the underlying field for this elliptic curve - * @mp *a, *b@ = the coefficients for this curve - * - * Returns: A pointer to the curve, or null. - * - * Use: Creates a curve structure for an elliptic curve defined over - * a binary field. The @binproj@ variant uses projective - * coordinates, which can be a win. - */ - -extern ec_curve *ec_bin(field */*f*/, mp */*a*/, mp */*b*/); -extern ec_curve *ec_binproj(field */*f*/, mp */*a*/, mp */*b*/); - -/*----- Curve parameter sets ----------------------------------------------*/ - -/* --- @ec_curveparse@ --- * - * - * Arguments: @qd_parse *qd@ = parser context - * - * Returns: Elliptic curve pointer if OK, or null. - * - * Use: Parses an elliptic curve description, which has the form - * - * * a field description - * * an optional `;' - * * `prime', `primeproj', `bin', or `binproj' - * * an optional `:' - * * the %$a$% parameter - * * an optional `,' - * * the %$b$% parameter - */ - -extern ec_curve *ec_curveparse(qd_parse */*qd*/); - -/* --- @ec_ptparse@ --- * - * - * Arguments: @qd_parse *qd@ = parser context - * @ec *p@ = where to put the point - * - * Returns: The point address, or null. - * - * Use: Parses an elliptic curve point. This has the form - * - * * %$x$%-coordinate - * * optional `,' - * * %$y$%-coordinate - */ - -extern ec *ec_ptparse(qd_parse */*qd*/, ec */*p*/); - -/* --- @ec_infoparse@ --- * - * - * Arguments: @qd_parse *qd@ = parser context - * @ec_info *ei@ = curve information block, currently - * uninitialized - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Parses an elliptic curve information string, and stores the - * information in @ei@. This has the form - * - * * elliptic curve description - * * optional `;' - * * common point - * * optional `:' - * * group order - * * optional `*' - * * cofactor - */ - -extern int ec_infoparse(qd_parse */*qd*/, ec_info */*ei*/); - -/* --- @ec_infofromdata@ --- * - * - * Arguments: @ec_info *ei@ = where to write the information - * @ecdata *ed@ = raw data - * - * Returns: --- - * - * Use: Loads elliptic curve information about one of the standard - * curves. - */ - -struct ecdata; -extern void ec_infofromdata(ec_info */*ei*/, struct ecdata */*ed*/); - -/* --- @ec_getinfo@ --- * - * - * Arguments: @ec_info *ei@ = where to write the information - * @const char *p@ = string describing a curve - * - * Returns: Null on success, or a pointer to an error message. - * - * Use: Parses out information about a curve. The string is either a - * standard curve name, or a curve info string. - */ - -extern const char *ec_getinfo(ec_info */*ei*/, const char */*p*/); - -/* --- @ec_sameinfop@ --- * - * - * Arguments: @ec_info *ei, *ej@ = two elliptic curve parameter sets - * - * Returns: Nonzero if the curves are identical (not just isomorphic). - * - * Use: Checks for sameness of curve parameters. - */ - -extern int ec_sameinfop(ec_info */*ei*/, ec_info */*ej*/); - -/* --- @ec_freeinfo@ --- * - * - * Arguments: @ec_info *ei@ = elliptic curve information block to free - * - * Returns: --- - * - * Use: Frees the information block. - */ - -extern void ec_freeinfo(ec_info */*ei*/); - -/* --- @ec_checkinfo@ --- * - * - * Arguments: @const ec_info *ei@ = elliptic curve information block - * - * Returns: Null if OK, or pointer to error message. - * - * Use: Checks an elliptic curve according to the rules in SEC1. - */ - -extern const char *ec_checkinfo(const ec_info */*ei*/, grand */*gr*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/ecb-def.h b/ecb-def.h deleted file mode 100644 index 08a25f6..0000000 --- a/ecb-def.h +++ /dev/null @@ -1,473 +0,0 @@ -/* -*-c-*- - * - * $Id: ecb-def.h,v 1.4 2004/04/17 09:58:37 mdw Exp $ - * - * Definitions electronic code book mode - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_ECB_DEF_H -#define CATACOMB_ECB_DEF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include -#include - -#ifndef CATACOMB_ARENA_H -# include "arena.h" -#endif - -#ifndef CATACOMB_BLKC_H -# include "blkc.h" -#endif - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -#ifndef CATACOMB_PARANOIA_H -# include "paranoia.h" -#endif - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @ECB_DEF@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher - * - * Use: Creates an implementation for ECB stealing mode. - */ - -#define ECB_DEF(PRE, pre) \ - \ -/* --- @pre_ecbsetkey@ --- * \ - * \ - * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \ - * @const pre_ctx *k@ = pointer to cipher context \ - * \ - * Returns: --- \ - * \ - * Use: Sets the ECB context to use a different cipher key. \ - */ \ - \ -void pre##_ecbsetkey(pre##_ecbctx *ctx, const pre##_ctx *k) \ -{ \ - ctx->ctx = *k; \ -} \ - \ -/* --- @pre_ecbinit@ --- * \ - * \ - * Arguments: @pre_ecbctx *ctx@ = pointer to cipher context \ - * @const void *key@ = pointer to the key buffer \ - * @size_t sz@ = size of the key \ - * @const void *iv@ = pointer to initialization vector \ - * \ - * Returns: --- \ - * \ - * Use: Initializes an ECB context ready for use. This is \ - * equivalent to calls to @pre_init@ and @pre_setkey@. \ - */ \ - \ -void pre##_ecbinit(pre##_ecbctx *ctx, \ - const void *key, size_t sz, \ - const void *iv) \ -{ \ - pre##_init(&ctx->ctx, key, sz); \ -} \ - \ -/* --- @pre_ecbencrypt@ --- * \ - * \ - * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Encrypts a block with a block cipher in ECB mode, with \ - * ciphertext stealing and other clever tricks. \ - * Essentially, data can be encrypted in arbitrary sized \ - * chunks, although decryption must use the same chunks. \ - */ \ - \ -void pre##_ecbencrypt(pre##_ecbctx *ctx, \ - const void *src, void *dest, \ - size_t sz) \ -{ \ - const octet *s = src; \ - octet *d = dest; \ - \ - /* --- Empty blocks are trivial --- */ \ - \ - if (!sz) \ - return; \ - \ - /* --- Short blocks aren't allowed in ECB --- * \ - * \ - * There's absolutely nothing secure I can do with them. \ - */ \ - \ - assert(((void)"ECB must have at least one whole block to work with", \ - sz >= PRE##_BLKSZ)); \ - \ - /* --- Do the main chunk of encryption --- * \ - * \ - * This will do the whole lot if it's a whole number of blocks. Just \ - * give each block to the cipher in turn. This is trivial. \ - * Hopefully... \ - */ \ - \ - while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \ - uint32 x[PRE##_BLKSZ / 4]; \ - if (!s) \ - BLKC_ZERO(PRE, x); \ - else { \ - BLKC_LOAD(PRE, x, s); \ - s += PRE##_BLKSZ; \ - } \ - pre##_eblk(&ctx->ctx, x, x); \ - if (d) { \ - BLKC_STORE(PRE, d, x); \ - d += PRE##_BLKSZ; \ - } \ - sz -= PRE##_BLKSZ; \ - } \ - \ - /* --- Do the tail-end block and bit-left-over --- * \ - * \ - * This isn't very efficient. That shouldn't matter much. \ - */ \ - \ - if (sz) { \ - uint32 x[PRE##_BLKSZ / 4]; \ - octet b[PRE##_BLKSZ]; \ - unsigned i; \ - \ - /* --- Let @sz@ be the size of the partial block --- */ \ - \ - sz -= PRE##_BLKSZ; \ - \ - /* --- First stage --- * \ - * \ - * Read in the current block, and encrypt it. The first part of \ - * the result is the partial ciphertext block. Don't write that \ - * out yet, because I've not read the partial plaintext block. \ - */ \ - \ - if (!s) \ - BLKC_ZERO(PRE, x); \ - else { \ - BLKC_LOAD(PRE, x, s); \ - s += PRE##_BLKSZ; \ - } \ - pre##_eblk(&ctx->ctx, x, x); \ - BLKC_STORE(PRE, b, x); \ - \ - /* --- Second stage --- * \ - * \ - * Now move in the partial plaintext block, writing out the \ - * ciphertext as I go. Then encrypt, and write the complete \ - * ciphertext block. \ - */ \ - \ - if (d) d += PRE##_BLKSZ; \ - for (i = 0; i < sz; i++) { \ - register octet y = b[i]; \ - b[i] = s[i]; \ - if (d) d[i] = y; \ - } \ - BLKC_LOAD(PRE, x, b); \ - pre##_eblk(&ctx->ctx, x, x); \ - if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, x); \ - } \ - \ - /* --- Done --- */ \ - \ - return; \ -} \ - \ -/* --- @pre_ecbdecrypt@ --- * \ - * \ - * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Decrypts a block with a block cipher in ECB mode, with \ - * ciphertext stealing and other clever tricks. \ - * Essentially, data can be encrypted in arbitrary sized \ - * chunks, although decryption must use the same chunks. \ - */ \ - \ -void pre##_ecbdecrypt(pre##_ecbctx *ctx, \ - const void *src, void *dest, \ - size_t sz) \ -{ \ - const octet *s = src; \ - octet *d = dest; \ - \ - /* --- Empty blocks are trivial --- */ \ - \ - if (!sz) \ - return; \ - \ - /* --- Short blocks aren't allowed in ECB --- * \ - * \ - * There's absolutely nothing secure I can do with them. \ - */ \ - \ - assert(((void)"ECB must have at least one whole block to work with", \ - sz >= PRE##_BLKSZ)); \ - \ - /* --- Do the main chunk of decryption --- * \ - * \ - * This will do the whole lot if it's a whole number of blocks. \ - * Each block is just handed to the block cipher in turn. \ - */ \ - \ - while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \ - uint32 x[PRE##_BLKSZ / 4]; \ - BLKC_LOAD(PRE, x, s); \ - pre##_dblk(&ctx->ctx, x, x); \ - BLKC_STORE(PRE, d, x); \ - s += PRE##_BLKSZ; \ - d += PRE##_BLKSZ; \ - sz -= PRE##_BLKSZ; \ - } \ - \ - /* --- Do the tail-end block and bit-left-over --- * \ - * \ - * This isn't very efficient. That shouldn't matter much. \ - */ \ - \ - if (sz) { \ - uint32 x[PRE##_BLKSZ / 4]; \ - octet b[PRE##_BLKSZ]; \ - unsigned i; \ - \ - /* --- Let @sz@ be the size of the partial block --- */ \ - \ - sz -= PRE##_BLKSZ; \ - \ - /* --- First stage --- * \ - * \ - * Take the complete ciphertext block, and decrypt it. This block \ - * is carried over for the next encryption operation. \ - */ \ - \ - BLKC_LOAD(PRE, x, s); \ - pre##_dblk(&ctx->ctx, x, x); \ - BLKC_STORE(PRE, b, x); \ - \ - /* --- Second stage --- * \ - * \ - * The first few bytes are the partial plaintext block. Write that \ - * and replace with the partial ciphertext block. Then decrypt \ - * what's left as the complete plaintext. \ - */ \ - \ - s += PRE##_BLKSZ; \ - d += PRE##_BLKSZ; \ - for (i = 0; i < sz; i++) { \ - register octet y = s[i]; \ - d[i] = b[i]; \ - b[i] = y; \ - } \ - BLKC_LOAD(PRE, x, b); \ - pre##_dblk(&ctx->ctx, x, x); \ - BLKC_STORE(PRE, d - PRE##_BLKSZ, x); \ - } \ - \ - /* --- Done --- */ \ - \ - return; \ -} \ - \ -/* --- Generic cipher interface --- */ \ - \ -static const gcipher_ops gops; \ - \ -typedef struct gctx { \ - gcipher c; \ - pre##_ecbctx k; \ -} gctx; \ - \ -static gcipher *ginit(const void *k, size_t sz) \ -{ \ - gctx *g = S_CREATE(gctx); \ - g->c.ops = &gops; \ - pre##_ecbinit(&g->k, k, sz, 0); \ - return (&g->c); \ -} \ - \ -static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_ecbencrypt(&g->k, s, t, sz); \ -} \ - \ -static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_ecbdecrypt(&g->k, s, t, sz); \ -} \ - \ -static void gdestroy(gcipher *c) \ -{ \ - gctx *g = (gctx *)c; \ - BURN(*g); \ - S_DESTROY(g); \ -} \ - \ -static const gcipher_ops gops = { \ - &pre##_ecb, \ - gencrypt, gdecrypt, gdestroy, 0, 0 \ -}; \ - \ -const gccipher pre##_ecb = { \ - #pre "-ecb", pre##_keysz, PRE##_BLKSZ, \ - ginit \ -}; \ - \ -ECB_TEST(PRE, pre) - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#include "daftstory.h" - -/* --- @ECB_TEST@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions - * - * Use: Standard test rig for ECB functions. - */ - -#define ECB_TEST(PRE, pre) \ - \ -/* --- Initial plaintext for the test --- */ \ - \ -static const octet text[] = TEXT; \ - \ -/* --- Key and IV to use --- */ \ - \ -static const octet key[] = KEY; \ -static const octet iv[] = IV; \ - \ -/* --- Buffers for encryption and decryption output --- */ \ - \ -static octet ct[sizeof(text)]; \ -static octet pt[sizeof(text)]; \ - \ -static void hexdump(const octet *p, size_t sz) \ -{ \ - const octet *q = p + sz; \ - for (sz = 0; p < q; p++, sz++) { \ - printf("%02x", *p); \ - if ((sz + 1) % PRE##_BLKSZ == 0) \ - putchar(':'); \ - } \ -} \ - \ -int main(void) \ -{ \ - size_t sz = 0, rest; \ - pre##_ecbctx ctx; \ - int status = 0; \ - int done = 0; \ - \ - size_t keysz = PRE##_KEYSZ ? \ - PRE##_KEYSZ : strlen((const char *)key); \ - \ - fputs(#pre "-ecb: ", stdout); \ - \ - pre##_ecbinit(&ctx, key, keysz, iv); \ - \ - while (sz <= sizeof(text)) { \ - rest = sizeof(text) - sz; \ - if ((sz != 0 && sz < PRE##_BLKSZ) || \ - (rest != 0 && rest < PRE##_BLKSZ)) \ - goto next; \ - memcpy(ct, text, sizeof(text)); \ - pre##_ecbencrypt(&ctx, ct, ct, sz); \ - pre##_ecbencrypt(&ctx, ct + sz, ct + sz, rest); \ - memcpy(pt, ct, sizeof(text)); \ - pre##_ecbdecrypt(&ctx, pt, pt, sz); \ - pre##_ecbdecrypt(&ctx, pt + sz, pt + sz, rest); \ - if (memcmp(pt, text, sizeof(text)) == 0) { \ - done++; \ - if (sizeof(text) < 40 || done % 8 == 0) \ - fputc('.', stdout); \ - if (done % 480 == 0) \ - fputs("\n\t", stdout); \ - fflush(stdout); \ - } else { \ - printf("\nError (sz = %lu)\n", (unsigned long)sz); \ - status = 1; \ - printf("\tplaintext = "); hexdump(text, sz); \ - printf(", "); hexdump(text + sz, rest); \ - fputc('\n', stdout); \ - printf("\tciphertext = "); hexdump(ct, sz); \ - printf(", "); hexdump(ct + sz, rest); \ - fputc('\n', stdout); \ - printf("\trecovered text = "); hexdump(pt, sz); \ - printf(", "); hexdump(pt + sz, rest); \ - fputc('\n', stdout); \ - fputc('\n', stdout); \ - } \ - next: \ - if (sz < 63) \ - sz++; \ - else \ - sz += 9; \ - } \ - \ - fputs(status ? " failed\n" : " ok\n", stdout); \ - return (status); \ -} - -#else -# define ECB_TEST(PRE, pre) -#endif - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/ecb.h b/ecb.h deleted file mode 100644 index ed39310..0000000 --- a/ecb.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -*-c-*- - * - * $Id: ecb.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Electronic code book for block ciphers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_ECB_H -#define CATACOMB_ECB_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @ECB_DECL@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher - * - * Use: Creates declarations for ECB stealing mode. - */ - -#define ECB_DECL(PRE, pre) \ - \ -/* --- Electronic codebook context --- */ \ - \ -typedef struct pre##_ecbctx { \ - pre##_ctx ctx; /* Underlying cipher context */ \ -} pre##_ecbctx; \ - \ -/* --- @pre_ecbsetkey@ --- * \ - * \ - * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \ - * @const pre_ctx *k@ = pointer to cipher context \ - * \ - * Returns: --- \ - * \ - * Use: Sets the ECB context to use a different cipher key. \ - */ \ - \ -extern void pre##_ecbsetkey(pre##_ecbctx */*ctx*/, \ - const pre##_ctx */*k*/); \ - \ -/* --- @pre_ecbinit@ --- * \ - * \ - * Arguments: @pre_ecbctx *ctx@ = pointer to cipher context \ - * @const void *key@ = pointer to the key buffer \ - * @size_t sz@ = size of the key \ - * @const void *iv@ = pointer to initialization vector \ - * \ - * Returns: --- \ - * \ - * Use: Initializes an ECB context ready for use. This is \ - * equivalent to calls to @pre_init@ and @pre_setkey@. \ - */ \ - \ -extern void pre##_ecbinit(pre##_ecbctx */*ctx*/, \ - const void */*key*/, size_t /*sz*/, \ - const void */*iv*/); \ - \ -/* --- @pre_ecbencrypt@ --- * \ - * \ - * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Encrypts a block with a block cipher in ECB mode, with \ - * ciphertext stealing and other clever tricks. \ - * Essentially, data can be encrypted in arbitrary sized \ - * chunks, although decryption must use the same chunks. \ - */ \ - \ -extern void pre##_ecbencrypt(pre##_ecbctx */*ctx*/, \ - const void */*src*/, void */*dest*/, \ - size_t /*sz*/); \ - \ -/* --- @pre_ecbdecrypt@ --- * \ - * \ - * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Decrypts a block with a block cipher in ECB mode, with \ - * ciphertext stealing and other clever tricks. \ - * Essentially, data can be encrypted in arbitrary sized \ - * chunks, although decryption must use the same chunks. \ - */ \ - \ -extern void pre##_ecbdecrypt(pre##_ecbctx */*ctx*/, \ - const void */*src*/, void */*dest*/, \ - size_t /*sz*/); \ - \ -/* --- Generic cipher interface --- */ \ - \ -extern const gccipher pre##_ecb; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/ectab.h b/ectab.h deleted file mode 100644 index 7e6161c..0000000 --- a/ectab.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*-c-*- - * - * $Id: ectab.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Table of standard elliptic curves - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_ECTAB_H -#define CATACOMB_ECTAB_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include "ec.h" - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct ecdata { - unsigned ftag; /* The kind of curve this is */ - mp p, beta; /* Modulus, and conversion magic */ - mp a, b; /* Elliptic curve parameters */ - mp r; /* Order of common point %$g$% */ - mp h; /* Cofactor %$h = \#E/r$% */ - mp gx, gy; /* Common point */ -} ecdata; - -enum { - FTAG_PRIME, /* Prime but not nice */ - FTAG_NICEPRIME, /* Nice prime field */ - FTAG_BINPOLY, /* Binary field, poly basis */ - FTAG_BINNORM /* Binary field, normal basis */ -}; - -typedef struct ecentry { - const char *name; - ecdata *data; -} ecentry; - -/*----- Global variables --------------------------------------------------*/ - -extern const ecentry ectab[]; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/ectab.in b/ectab.in deleted file mode 100644 index 238accb..0000000 --- a/ectab.in +++ /dev/null @@ -1,636 +0,0 @@ -# $Id$ -# -# Standard ellipic curves - -#----- Curves from SEC2 ----------------------------------------------------- - -curve secp112r1 prime - p 0xdb7c2abf62e35e668076bead208b - a 0xdb7c2abf62e35e668076bead2088 - b 0x659ef8ba043916eede8911702b22 - r 0xdb7c2abf62e35e7628dfac6561c5 - h 1 - gx 0x09487239995a5ee76b55f9c2f098 - gy 0xa89ce5af8724c0a23e0e0ff77500 -curve secp112r2 prime - p 0xdb7c2abf62e35e668076bead208b - a 0x6127c24c05f38a0aaaf65c0ef02c - b 0x51def1815db5ed74fcc34c85d709 - r 0x36df0aafd8b8d7597ca10520d04b - h 4 - gx 0x4ba30ab5e892b4e1649dd0928643 - gy 0xadcd46f5882e3747def36e956e97 - -curve secp128r1 niceprime - p 0xfffffffdffffffffffffffffffffffff - a 0xfffffffdfffffffffffffffffffffffc - b 0xe87579c11079f43dd824993c2cee5ed3 - r 0xfffffffe0000000075a30d1b9038a115 - h 1 - gx 0x161ff7528b899b2d0c28607ca52c5b86 - gy 0xcf5ac8395bafeb13c02da292dded7a83 -curve secp128r2 niceprime - p 0xfffffffdffffffffffffffffffffffff - a 0xd6031998d1b3bbfebf59cc9bbff9aee1 - b 0x5eeefca380d02919dc2c6558bb6d8a5d - r 0x3fffffff7fffffffbe0024720613b5a3 - h 4 - gx 0x7b6aa5d85e572983e6fb32a7cdebc140 - gy 0x27b6916a894d3aee7106fe805fc34b44 - -curve secp160k1 niceprime - p 0xfffffffffffffffffffffffffffffffeffffac73 - a 0 - b 7 - r 0x0100000000000000000001b8fa16dfab9aca16b6b3 - h 1 - gx 0x3b4c382ce37aa192a4019e763036f4f5dd4d7ebb - gy 0x938cf935318fdced6bc28286531733c3f03c4fee -curve secp160r1 niceprime - p 0xffffffffffffffffffffffffffffffff7fffffff - a 0xffffffffffffffffffffffffffffffff7ffffffc - b 0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45 - r 0x0100000000000000000001f4c8f927aed3ca752257 - h 1 - gx 0x4a96b5688ef573284664698968c38bb913cbfc82 - gy 0x23a628553168947d59dcc912042351377ac5fb32 -curve secp160r2 niceprime - p 0xfffffffffffffffffffffffffffffffeffffac73 - a 0xfffffffffffffffffffffffffffffffeffffac70 - b 0xb4e134d3fb59eb8bab57274904664d5af50388ba - r 0x0100000000000000000000351ee786a818f3a1a16b - h 1 - gx 0x52dcb034293a117e1f4ff11b30f7199d3144ce6d - gy 0xfeaffef2e331f296e071fa0df9982cfea7d43f2e - -curve secp192k1 niceprime - p 0xfffffffffffffffffffffffffffffffffffffffeffffee37 - a 0 - b 3 - r 0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d - h 1 - gx 0xdb4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d - gy 0x9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d -curve secp192r1 niceprime - p 0xfffffffffffffffffffffffffffffffeffffffffffffffff - a 0xfffffffffffffffffffffffffffffffefffffffffffffffc - b 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1 - r 0xffffffffffffffffffffffff99def836146bc9b1b4d22831 - h 1 - gx 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012 - gy 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811 - -curve secp224k1 niceprime - p 0xfffffffffffffffffffffffffffffffffffffffffffffffeffffe56d - a 0 - b 5 - r 0x010000000000000000000000000001dce8d2ec6184caf0a971769fb1f7 - h 1 - gx 0xa1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c - gy 0x7e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5 -curve secp224r1 niceprime - p 0xffffffffffffffffffffffffffffffff000000000000000000000001 - a 0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe - b 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4 - r 0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d - h 1 - gx 0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21 - gy 0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34 - -curve secp256k1 niceprime - p 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f - a 0 - b 7 - r 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 - h 1 - gx 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 - gy 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 -curve secp256r1 niceprime - p 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff - a 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc - b 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b - r 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 - h 1 - gx 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296 - gy 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 - -curve secp384r1 niceprime - p 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff - a 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc - b 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef - r 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973 - h 1 - gx 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7 - gy 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f - -curve secp521r1 niceprime - p 0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - a 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc - b 0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00 - r 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409 - h 1 - gx 0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66 - gy 0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650 - -curve sect113r1 binpoly - p 0x20000000000000000000000000201 - a 0x003088250ca6e7c7fe649ce85820f7 - b 0x00e8bee4d3e2260744188be0e9c723 - r 0x0100000000000000d9ccec8a39e56f - h 2 - gx 0x009d73616f35f4ab1407d73562c10f - gy 0x00a52830277958ee84d1315ed31886 -curve sect113r2 binpoly - p 0x20000000000000000000000000201 - a 0x00689918dbec7e5a0dd6dfc0aa55c7 - b 0x0095e9a9ec9b297bd4bf36e059184f - r 0x010000000000000108789b2496af93 - h 2 - gx 0x01a57a6a7b26ca5ef52fcdb8164797 - gy 0x00b3adc94ed1fe674c06e695baba1d - -curve sect131r1 binpoly - p 0x80000000000000000000000000000010d - a 0x07a11b09a76b562144418ff3ff8c2570b8 - b 0x0217c05610884b63b9c6c7291678f9d341 - r 0x0400000000000000023123953a9464b54d - h 2 - gx 0x0081baf91fdf9833c40f9c181343638399 - gy 0x078c6e7ea38c001f73c8134b1b4ef9e150 -curve sect131r2 binpoly - p 0x80000000000000000000000000000010d - a 0x03e5a88919d7cafcbf415f07c2176573b2 - b 0x04b8266a46c55657ac734ce38f018f2192 - r 0x0400000000000000016954a233049ba98f - h 2 - gx 0x0356dcd8f2f95031ad652d23951bb366a8 - gy 0x0648f06d867940a5366d9e265de9eb240f - -curve sect163k1 binpoly - p 0x800000000000000000000000000000000000000c9 - a 1 - b 1 - r 0x04000000000000000000020108a2e0cc0d99f8a5ef - h 2 - gx 0x02fe13c0537bbc11acaa07d793de4e6d5e5c94eee8 - gy 0x0289070fb05d38ff58321f2e800536d538ccdaa3d9 -curve sect163r1 binpoly - p 0x800000000000000000000000000000000000000c9 - a 0x07b6882caaefa84f9554ff8428bd88e246d2782ae2 - b 0x0713612dcddcb40aab946bda29ca91f73af958afd9 - r 0x03ffffffffffffffffffff48aab689c29ca710279b - h 2 - gx 0x0369979697ab43897789566789567f787a7876a654 - gy 0x00435edb42efafb2989d51fefce3c80988f41ff883 -curve sect163r2 binpoly - p 0x800000000000000000000000000000000000000c9 - a 1 - b 0x020a601907b8c953ca1481eb10512f78744a3205fd - r 0x040000000000000000000292fe77e70c12a4234c33 - h 2 - gx 0x03f0eba16286a2d57ea0991168d4994637e8343e36 - gy 0x00d51fbc6c71a0094fa2cdd545b11c5c0c797324f1 - -curve sect193r1 binpoly - p 0x2000000000000000000000000000000000000000000008001 - a 0x0017858feb7a98975169e171f77b4087de098ac8a911df7b01 - b 0x00fdfb49bfe6c3a89facadaa7a1e5bbc7cc1c2e5d831478814 - r 0x01000000000000000000000000c7f34a778f443acc920eba49 - h 2 - gx 0x01f481bc5f0ff84a74ad6cdf6fdef4bf6179625372d8c0c5e1 - gy 0x0025e399f2903712ccf3ea9e3a1ad17fb0b3201b6af7ce1b05 -curve sect193r2 binpoly - p 0x2000000000000000000000000000000000000000000008001 - a 0x0163f35a5137c2ce3ea6ed8667190b0bc43ecd69977702709b - b 0x00c9bb9e8927d4d64c377e2ab2856a5b16e3efb7f61d4316ae - r 0x010000000000000000000000015aab561b005413ccd4ee99d5 - h 2 - gx 0x00d9b67d192e0367c803f39e1a7e82ca14a651350aae617e8f - gy 0x01ce94335607c304ac29e7defbd9ca01f596f927224cdecf6c - -curve sect233k1 binpoly - p 0x20000000000000000000000000000000000000004000000000000000001 - a 0 - b 1 - r 0x8000000000000000000000000000069d5bb915bcd46efb1ad5f173abdf - h 4 - gx 0x017232ba853a7e731af129f22ff4149563a419c26bf50a4c9d6eefad6126 - gy 0x01db537dece819b7f70f555a67c427a8cd9bf18aeb9b56e0c11056fae6a3 -curve sect233r1 binpoly - p 0x20000000000000000000000000000000000000004000000000000000001 - a 1 - b 0x0066647ede6c332c7f8c0923bb58213b333b20e9ce4281fe115f7d8f90ad - r 0x01000000000000000000000000000013e974e72f8a6922031d2603cfe0d7 - h 2 - gx 0x00fac9dfcbac8313bb2139f1bb755fef65bc391f8b36f8f8eb7371fd558b - gy 0x01006a08a41903350678e58528bebf8a0beff867a7ca36716f7e01f81052 - -curve sect239k1 binpoly - p 0x800000000000000000004000000000000000000000000000000000000001 - a 0 - b 1 - r 0x2000000000000000000000000000005a79fec67cb6e91f1c1da800e478a5 - h 4 - gx 0x29a0b6a887a983e9730988a68727a8b2d126c44cc2cc7b2a6555193035dc - gy 0x76310804f12e549bdb011c103089e73510acb275fc312a5dc6b76553f0ca - -curve sect283k1 binpoly - p 0x800000000000000000000000000000000000000000000000000000000000000000010a1 - a 0 - b 1 - r 0x01ffffffffffffffffffffffffffffffffffe9ae2ed07577265dff7f94451e061e163c61 - h 4 - gx 0x0503213f78ca44883f1a3b8162f188e553cd265f23c1567a16876913b0c2ac2458492836 - gy 0x01ccda380f1c9e318d90f95d07e5426fe87e45c0e8184698e45962364e34116177dd2259 -curve sect283r1 binpoly - p 0x800000000000000000000000000000000000000000000000000000000000000000010a1 - a 1 - b 0x027b680ac8b8596da5a4af8a19a0303fca97fd7645309fa2a581485af6263e313b79a2f5 - r 0x03ffffffffffffffffffffffffffffffffffef90399660fc938a90165b042a7cefadb307 - h 2 - gx 0x05f939258db7dd90e1934f8c70b0dfec2eed25b8557eac9c80e2e198f8cdbecd86b12053 - gy 0x03676854fe24141cb98fe6d4b20d02b4516ff702350eddb0826779c813f0df45be8112f4 - -curve sect409k1 binpoly - p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001 - a 0 - b 1 - r 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffe5f83b2d4ea20400ec4557d5ed3e3e7ca5b4b5c83b8e01e5fcf - h 4 - gx 0x0060f05f658f49c1ad3ab1890f7184210efd0987e307c84c27accfb8f9f67cc2c460189eb5aaaa62ee222eb1b35540cfe9023746 - gy 0x01e369050b7c4e42acba1dacbf04299c3460782f918ea427e6325165e9ea10e3da5f6c42e9c55215aa9ca27a5863ec48d8e0286b -curve sect409r1 binpoly - p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001 - a 1 - b 0x0021a5c2c8ee9feb5c4b9a753b7b476b7fd6422ef1f3dd674761fa99d6ac27c8a9a197b272822f6cd57a55aa4f50ae317b13545f - r 0x010000000000000000000000000000000000000000000000000001e2aad6a612f33307be5fa47c3c9e052f838164cd37d9a21173 - h 2 - gx 0x015d4860d088ddb3496b0c6064756260441cde4af1771d4db01ffe5b34e59703dc255a868a1180515603aeab60794e54bb7996a7 - gy 0x0061b1cfab6be5f32bbfa78324ed106a7636b9c5a7bd198d0158aa4f5488d08f38514f1fdf4b4f40d2181b3681c364ba0273c706 - -curve sect571k1 binpoly - p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425 - a 0 - b 1 - r 0x020000000000000000000000000000000000000000000000000000000000000000000000131850e1f19a63e4b391a8db917f4138b630d84be5d639381e91deb45cfe778f637c1001 - h 4 - gx 0x026eb7a859923fbc82189631f8103fe4ac9ca2970012d5d46024804801841ca44370958493b205e647da304db4ceb08cbbd1ba39494776fb988b47174dca88c7e2945283a01c8972 - gy 0x0349dc807f4fbf374f4aeade3bca95314dd58cec9f307a54ffc61efc006d8a2c9d4979c0ac44aea74fbebbb9f772aedcb620b01a7ba7af1b320430c8591984f601cd4c143ef1c7a3 -curve sect571r1 binpoly - p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425 - a 1 - b 0x02f40e7e2221f295de297117b7f3d62f5c6a97ffcb8ceff1cd6ba8ce4a9a18ad84ffabbd8efa59332be7ad6756a66e294afd185a78ff12aa520e4de739baca0c7ffeff7f2955727a - r 0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47 - h 2 - gx 0x0303001d34b856296c16c0d40d3cd7750a93d1d2955fa80aa5f40fc8db7b2abdbde53950f4c0d293cdd711a35b67fb1499ae60038614f1394abfa3b4c850d927e1e7769c8eec2d19 - gy 0x037bf27342da639b6dccfffeb73d69d78c6c27a6009cbbca1980f8533921e8a684423e43bab08a576291af8f461bb2a8b3531d2f0485c19b16e2f1516e23dd3c1a4827af1b8ac15b - -#----- Curves from ANSI X9.62 ----------------------------------------------- -# -# The conversion factors for the normal basis representations were generated -# because none were given in the document. - -curve ansi-c2pnb163v1 binpoly - p 0x080000000000000000000000000000000000000107 - a 0x072546b5435234a422e0789675f432c89435de5242 - b 0x00c9517d06d5240d3cff38c74b20b6cd4d6f9dd4d9 - r 0x0400000000000000000001e60fc8821cc74daeafc1 - h 2 - gx 0x07af69989546103d79329fcc3d74880f33bbe803cb - gy 0x01ec23211b5966adea1d3f87f7ea5848aef0b7ca9f -curve ansi-c2pnb163v2 binpoly - p 0x080000000000000000000000000000000000000107 - a 0x0108b39e77c4b108bed981ed0e890e117c511cf072 - b 0x0667aceb38af4e488c407433ffae4f1c811638df20 - r 0x03fffffffffffffffffffdf64de1151adbb78f10a7 - h 2 - gx 0x0024266e4eb5106d0a964d92c4860e2671db9b6cc5 - gy 0x079f684ddf6684c5cd258b3890021b2386dfd19fc5 -curve ansi-c2pnb163v3 binpoly - p 0x080000000000000000000000000000000000000107 - a 0x07a526c63d3e25a256a007699f5447e32ae456b50e - b 0x03f7061798eb99e238fd6f1bf95b48feeb4854252b - r 0x03fffffffffffffffffffe1aee140f110aff961309 - h 2 - gx 0x02f9f87b7c574d0bdecf8a22e6524775f98cdebdcb - gy 0x05b935590c155e17ea48eb3ff3718b893df59a05d0 - -curve ansi-c2tnb191v1 binpoly - p 0x800000000000000000000000000000000000000000000201 - a 0x2866537b676752636a68f56554e12640276b649ef7526267 - b 0x2e45ef571f00786f67b0081b9495a3d95462f5de0aa185ec - r 0x40000000000000000000000004a20e90c39067c893bbb9a5 - h 2 - gx 0x36b3daf8a23206f9c4f299d7b21a9c369137f2c84ae1aa0d - gy 0x765be73433b3f95e332932e70ea245ca2418ea0ef98018fb -curve ansi-c2tnb191v2 binpoly - p 0x800000000000000000000000000000000000000000000201 - a 0x401028774d7777c7b7666d1366ea432071274f89ff01e718 - b 0x0620048d28bcbd03b6249c99182b7c8cd19700c362c46a01 - r 0x20000000000000000000000050508cb89f652824e06b8173 - h 4 - gx 0x3809b2b7cc1b28cc5a87926aad83fd28789e81e2c9e3bf10 - gy 0x17434386626d14f3dbf01760d9213a3e1cf37aec437d668a -curve ansi-c2tnb191v3 binpoly - p 0x800000000000000000000000000000000000000000000201 - a 0x6c01074756099122221056911c77d77e77a777e7e7e77fcb - b 0x71fe1af926cf847989efef8db459f66394d90f32ad3f15e8 - r 0x155555555555555555555555610c0b196812bfb6288a3ea3 - h 6 - gx 0x375d4ce24fde434489de8746e71786015009e66e38a926dd - gy 0x545a39176196575d985999366e6ad34ce0a77cd7127b06be -curve ansi-c2onb191v1 binnorm - p 0x800000000000000000000000000000000000000000000201 - beta 0x19c409a7f85383bf0ef72b097a5c7398013a2dba6269292d - a 0x65903e04e1e4924253e26a3c9ac28c758bd8184a3fb680e8 - b 0x54678621b190cfce282ade219d5b3a065e3f4b3ffdebb29b - r 0x4000000000000000000000009cf2d6e3901dac4c32eec65d - h 2 - gx 0x5a2c69a32e8638e51ccefaad05350a978457cb5fb6df994a - gy 0x0f32fe0fa0e902f19b17d363c269f4f5cfe8087618569954 -curve ansi-c2onb191v2 binnorm - p 0x800000000000000000000000000000000000000000000201 - beta 0x19c409a7f85383bf0ef72b097a5c7398013a2dba6269292d - a 0x25f8d06c97c822536d469cd5170cdd7bb9f500bd6db110fb - b 0x75ff570e35ca94fb3780c2619d081c17aa59fbd5e591c1c4 - r 0x0fffffffffffffffffffffffeeb354b7270b2992b7818627 - h 8 - gx 0x2a16910e8f6c4b199be24213857abc9c992edfb2471f3c68 - gy 0x1592dbfebeb81a7c071b744d5e2f9e242ea65b81138a3468 - -curve ansi-c2tnb239v1 binpoly - p 0x800000000000000000000000000000000000000000000000001000000001 - a 0x32010857077c5431123a46b808906756f543423e8d27877578125778ac76 - b 0x790408f2eedaf392b012edefb3392f30f4327c0ca3f31fc383c422aa8c16 - r 0x2000000000000000000000000000000f4d42ffe1492a4993f1cad666e447 - h 4 - gx 0x57927098fa932e7c0a96d3fd5b706ef7e5f5c156e16b7e7c86038552e91d - gy 0x61d8ee5077c33fecf6f1a16b268de469c3c7744ea9a971649fc7a9616305 -curve ansi-c2tnb239v2 binpoly - p 0x800000000000000000000000000000000000000000000000001000000001 - a 0x4230017757a767fae42398569b746325d45313af0766266479b75654e65f - b 0x5037ea654196cff0cd82b2c14a2fcf2e3ff8775285b545722f03eacdb74b - r 0x1555555555555555555555555555553c6f2885259c31e3fcdf154624522d - h 6 - gx 0x28f9d04e900069c8dc47a08534fe76d2b900b7d7ef31f5709f200c4ca205 - gy 0x5667334c45aff3b5a03bad9dd75e2c71a99362567d5453f7fa6e227ec833 -curve ansi-c2tnb239v3 binpoly - p 0x800000000000000000000000000000000000000000000000001000000001 - a 0x01238774666a67766d6676f778e676b66999176666e687666d8766c66a9f - b 0x6a941977ba9f6a435199acfc51067ed587f519c5ecb541b8e44111de1d40 - r 0x0cccccccccccccccccccccccccccccac4912d2d9df903ef9888b8a0e4cff - h 10 - gx 0x70f6e9d04d289c4e89913ce3530bfde903977d42b146d539bf1bde4e9c92 - gy 0x2e5a0eaf6e5e1305b9004dce5c0ed7fe59a35608f33837c816d80b79f461 -curve ansi-c2onb239v1 binnorm - p 0x800000000000000000000000000000000000000000000000001000000001 - beta 0x3b5ce9846911b248f9347018a7ac8cce3662cee952ba45becd02d4b903ec - a 0x182dd45f5d470239b8983fea47b8b292641c57f9bf84baecde8bb3adce30 - b 0x147a9c1d4c2ce9be5d34ec02797f76667ebad5a3f93fa2a524bfde91ef28 - r 0x200000000000000000000000000000474f7e69f42fe430931d0b455aae8b - h 4 - gx 0x4912ad657f1d1c6b32edb9942c95e226b06fb012cd40fdea0d72197c8104 - gy 0x01f1fbc3d21168fd3f66c441c2b5c6cfdcd9ed3e13646b7a4db9a3b0c286 -curve ansi-c2onb239v2 binnorm - p 0x800000000000000000000000000000000000000000000000001000000001 - beta 0x3b5ce9846911b248f9347018a7ac8cce3662cee952ba45becd02d4b903ec - a 0x1ecf1b9d28d8017505e17475d3df2982e243ca5cb5e9f94a3f36124a486e - b 0x3ee257250d1a2e66cef23aa0f25b12388de8a10ff9554f90afbaa9a08b6d - r 0x1555555555555555555555555555558cf77a5d0589d2a9340d963b7ad703 - h 6 - gx 0x5f949ccb694f26b96d191e8925205a719929e93c37174cb6c7f659a37b85 - gy 0x2d788d605ac81069e9964fd6edbae8bbf582a5c409a1078cf487a147ceb2 - ## The spec seems bogus: the suggested base point G isn't in the - ## subgroup! The point above is h G. - ##gx 0x193279fc543e9f5f7119189785b9c60b249be4820baf6c24bdfa2813f8b8 - ##gy 0x5da021e5af77604051fc5c38da8293c1eeeaa00f046eeb93b6c8b774bb9b - -curve ansi-c2tnb359v1 binpoly - p 0x800000000000000000000000000000000000000000000000000000000000000000000000100000000000000001 - a 0x5667676a654b20754f356ea92017d946567c46675556f19556a04616b567d223a5e05656fb549016a96656a557 - b 0x2472e2d0197c49363f1fe7f5b6db075d52b6947d135d8ca445805d39bc345626089687742b6329e70680231988 - r 0x01af286bca1af286bca1af286bca1af286bca1af286bc9fb8f6b85c556892c20a7eb964fe7719e74f490758d3b - h 76 - gx 0x3c258ef3047767e7ede0f1fdaa79daee3841366a132e163aced4ed2401df9c6bdcde98e8e707c07a2239b1b097 - gy 0x53d7e08529547048121e9c95f3791dd804963948f34fae7bf44ea82365dc7868fe57e4ae2de211305a407104bd - -curve ansi-c2tnb431v1 binpoly - p 0x800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001 - a 0x1a827ef00dd6fc0e234caf046c6a5d8a85395b236cc4ad2cf32a0cadbdc9ddf620b0eb9906d0957f6c6feacd615468df104de296cd8f - b 0x10d9b4a3d9047d8b154359abfb1b7f5485b04ceb868237ddc9deda982a679a5a919b626d4e50a8dd731b107a9962381fb5d807bf2618 - r 0x000340340340340340340340340340340340340340340340340340340323c313fab50589703b5ec68d3587fec60d161cc149c1ad4a91 - h 10080 - gx 0x120fc05d3c67a99de161d2f4092622feca701be4f50f4758714e8a87bbf2a658ef8c21e7c5efe965361f6c2999c0c247b0dbd70ce6b7 - gy 0x20d0af8903a96f8d5fa2c255745d3c451b302c9346d9b7e485e7bce41f6b591f3e8f6addcbb0bc4c2f947a7de1a89b625d6a598b3760 - -# These curves aren't included because their degree isn't prime (so they -# may be vulnerable to Weil descent) -# ansi-c2pnb176w1 is bad: 176 isn't prime -# ansi-c2pnb208v1 is bad: 208 isn't prime -# ansi-c2pnb272w1 is bad: 272 isn't prime -# ansi-c2pnb304w1 is bad: 304 isn't prime -# ansi-c2pnb368w1 is bad: 368 isn't prime - -alias ansi-prime192v1 secp192r1 -curve ansi-prime192v2 niceprime - p 0xfffffffffffffffffffffffffffffffeffffffffffffffff - a 0xfffffffffffffffffffffffffffffffefffffffffffffffc - b 0xcc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953 - r 0xfffffffffffffffffffffffe5fb1a724dc80418648d8dd31 - h 1 - gx 0xeea2bae7e1497842f2de7769cfe9c989c072ad696f48034a - gy 0x6574d11d69b6ec7a672bb82a083df2f2b0847de970b2de15 -curve ansi-prime192v3 niceprime - p 0xfffffffffffffffffffffffffffffffeffffffffffffffff - a 0xfffffffffffffffffffffffffffffffefffffffffffffffc - b 0x22123dc2395a05caa7423daeccc94760a7d462256bd56916 - r 0xffffffffffffffffffffffff7a62d031c83f4294f640ec13 - h 1 - gx 0x7d29778100c65a1da1783716588dce2b8b4aee8e228f1896 - gy 0x38a90f22637337334b49dcb66a6dc8f9978aca7648a943b0 - -curve ansi-prime239v1 niceprime - p 0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff - a 0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc - b 0x6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a - r 0x7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b - h 1 - gx 0x0ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf - gy 0x7debe8e4e90a5dae6e4054ca530ba04654b36818ce226b39fccb7b02f1ae -curve ansi-prime239v2 niceprime - p 0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff - a 0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc - b 0x617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c - r 0x7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063 - h 1 - gx 0x38af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7 - gy 0x5b0125e4dbea0ec7206da0fc01d9b081329fb555de6ef460237dff8be4ba -curve ansi-prime239v3 niceprime - p 0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff - a 0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc - b 0x255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e - r 0x7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551 - h 1 - gx 0x6768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a - gy 0x1607e6898f390c06bc1d552bad226f3b6fcfe48b6e818499af18e3ed6cf3 - -alias ansi-prime256v1 secp256r1 - -#----- Curves from ANSI X9.63 ----------------------------------------------- -# -# These are just duplicates of the SEC curves. - -alias ansit163k1 sect163k1 -alias ansit163r1 sect163r1 -alias ansit163r2 sect163r2 -alias ansit193r1 sect193r1 -alias ansit193r2 sect193r2 -alias ansit233k1 sect233k1 -alias ansit233r1 sect233r1 -alias ansit239k1 sect239k1 -alias ansit283k1 sect283k1 -alias ansit283r1 sect283r1 -alias ansit409k1 sect409k1 -alias ansit409r1 sect409r1 -alias ansit571k1 sect571k1 -alias ansit571r1 sect571r1 - -alias ansip160k1 secp160k1 -alias ansip160r1 secp160r1 -alias ansip160r2 secp160r2 -alias ansip192k1 secp192k1 -alias ansip192r1 secp192r1 -alias ansip224k1 secp224k1 -alias ansip224r1 secp224r1 -alias ansip256k1 secp256k1 -alias ansip256r1 secp256r1 -alias ansip384r1 secp384r1 -alias ansip521r1 secp521r1 - -#----- Curves from RFC2414 (Oakley) ----------------------------------------- -# -# The Oakley curves are not good: -# oakley155 has too large a cofactor -# oakley185's field has composite degree -# Hence, we include neither here. - -#----- NIST curves from FIPS186-2 ------------------------------------------- -# -# These are duplicates of SEC2 curves. However, the normal basis -# representations aren't in SEC, so we give them here. (Conversion factors -# from FIPS186-2. - -alias nist-p192 secp192r1 -alias nist-p224 secp224r1 -alias nist-p256 secp256r1 -alias nist-p384 secp384r1 -alias nist-p521 secp521r1 - -alias nist-k163 sect163k1 -alias nist-k233 sect233k1 -alias nist-k283 sect283k1 -alias nist-k409 sect409k1 -alias nist-k571 sect571k1 - -alias nist-b163 sect163r2 -alias nist-b233 sect233r1 -alias nist-b283 sect283r1 -alias nist-b409 sect409r1 -alias nist-b571 sect571r1 - -curve nist-k163n binnorm - p 0x800000000000000000000000000000000000000c9 - beta 0x715169c109c612e390d347c748342bcd3b02a0bef - a 0x7ffffffffffffffffffffffffffffffffffffffff - b 0x7ffffffffffffffffffffffffffffffffffffffff - r 0x04000000000000000000020108a2e0cc0d99f8a5ef - h 2 - gx 0x05679b353caa46825fea2d3713ba450da0c2a4541 - gy 0x235b7c6710050689906bac3d9dec76a835591edb2 -curve nist-b163n binnorm - p 0x800000000000000000000000000000000000000c9 - beta 0x715169c109c612e390d347c748342bcd3b02a0bef - a 0x7ffffffffffffffffffffffffffffffffffffffff - b 0x6645f3cacf1638e139c6cd13ef61734fbc9e3d9fb - r 0x040000000000000000000292fe77e70c12a4234c33 - h 2 - gx 0x0311103c17167564ace77ccb09c681f886ba54ee8 - gy 0x333ac13c6447f2e67613bf7009daf98c87bb50c7f - -curve nist-k233n binnorm - p 0x20000000000000000000000000000000000000004000000000000000001 - beta 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9 - a 0 - b 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - r 0x8000000000000000000000000000069d5bb915bcd46efb1ad5f173abdf - h 4 - gx 0x0fde76d9dcd26e643ac26f1aa901aa129784b71fc0722b2d05614d650b3 - gy 0x0643e317633155c9e0447ba8020a3c43177450ee036d633501434cac978 -curve nist-b233n binnorm - p 0x20000000000000000000000000000000000000004000000000000000001 - beta 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9 - a 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - b 0x1a003e0962d4f9a8e407c904a9538163adb825212600c7752ad52233279 - r 0x01000000000000000000000000000013e974e72f8a6922031d2603cfe0d7 - h 2 - gx 0x18b863524b3cdfefb94f2784e0b116faac54404bc9162a363bab84a14c5 - gy 0x04925df77bd8b8ff1a5ff519417822bfedf2bbd752644292c98c7af6e02 - -curve nist-k283n binnorm - p 0x800000000000000000000000000000000000000000000000000000000000000000010a1 - beta 0x31e0ed791c3282dc5624a720818049d053e8c7ab8663792bc1d792eba9867fc7b317a99 - a 0 - b 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - r 0x01ffffffffffffffffffffffffffffffffffe9ae2ed07577265dff7f94451e061e163c61 - h 4 - gx 0x3ab9593f8db09fc188f1d7c4ac9fcc3e57fcd3bdb15024b212c70229de5fcd92eb0ea60 - gy 0x2118c4755e7345cd8f603ef93b98b106fe8854ffeb9a3b304634cc83a0e759f0c2686b1 -curve nist-b283n binnorm - p 0x800000000000000000000000000000000000000000000000000000000000000000010a1 - beta 0x31e0ed791c3282dc5624a720818049d053e8c7ab8663792bc1d792eba9867fc7b317a99 - a 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - b 0x157261b894739fb5a13503f55f0b3f10c5601166633102201138cc180c0206bdafbc951 - r 0x03ffffffffffffffffffffffffffffffffffef90399660fc938a90165b042a7cefadb307 - h 2 - gx 0x749468e464ee468634b21f7f61cb700701817e6bc36a2364cb8906e940948eaa463c35d - gy 0x62968bd3b489ac5c9b859da68475c315bafcdc4ccd0dc905b70f62446f49c052f49c08c - -curve nist-k409n binnorm - p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001 - beta 0x0dfa06be206aa97b7a41fffb9b0c55f8f048062fbe8381b4248adf92912ccc8e3f91a24e1cfb3950532b988971c23042e85708d - a 0 - b 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - r 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffe5f83b2d4ea20400ec4557d5ed3e3e7ca5b4b5c83b8e01e5fcf - h 4 - gx 0x1b559c7cba2422e3affe13343e808b55e012d726ca0b7e6a63aeafbc1e3a98e10ca0fcf98350c3b7f89a9754a8e1dc0713cec4a - gy 0x16d8c42052f07e7713e7490eff318ba1abd6fef8a5433c894b24f5c817aeb79852496fbee803a47bc8a203878ebf1c499afd7d6 -curve nist-b409n binnorm - p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001 - beta 0x0dfa06be206aa97b7a41fffb9b0c55f8f048062fbe8381b4248adf92912ccc8e3f91a24e1cfb3950532b988971c23042e85708d - a 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - b 0x124d0651c3d3772f7f5a1fe6e715559e2129bdfa04d52f7b6ac7c532cf0ed06f610072d88ad2fdcc50c6fde72843670f8b3742a - r 0x010000000000000000000000000000000000000000000000000001e2aad6a612f33307be5fa47c3c9e052f838164cd37d9a21173 - h 2 - gx 0x0ceacbc9f475767d8e69f3b5dfab39813685262bcacf22b84c7b6dd981899e7318c96f0761f77c602c016ced7c548de830d708f - gy 0x199d64ba8f089c6db0e0b61e80bb95934afd0caf2e8be76d1c5e9affc7476df49142691ad30390288aa09bcc59c1573aa3c009a - -curve nist-k571n binnorm - p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425 - beta 0x452186bbf5840a0bcf8c9f02a54efa04e813b43c3d4149606c4d27b487bf107393c8907f79d9778beb35ee87467d3288274caebda6ce05aeb4ca5cf3c3044bd4372232f2c1a27c4 - a 0 - b 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - r 0x020000000000000000000000000000000000000000000000000000000000000000000000131850e1f19a63e4b391a8db917f4138b630d84be5d639381e91deb45cfe778f637c1001 - h 4 - gx 0x04bb2dba418d0db107adae003427e5d7cc139acb465e5934f0bea2ab2f3622bc29b3d5b9aa7a1fdfd5d8be66057c1008e71e484bcd98f22bf8476423767367429ef2ec5bc3ebcf7 - gy 0x44cbb57de20788d2c952d7b56cf39bd3e89b18984bd124e751ceff4369dd8dac6a59e6e745df44d8220ce22aa2c852cfcbbef49ebaa98bd2483e33180e04286feaa253050caff60 -curve nist-b571n binnorm - p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425 - beta 0x452186bbf5840a0bcf8c9f02a54efa04e813b43c3d4149606c4d27b487bf107393c8907f79d9778beb35ee87467d3288274caebda6ce05aeb4ca5cf3c3044bd4372232f2c1a27c4 - a 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - b 0x3762d0d47116006179da35688eeaccf591a5cdea75000118d9608c59132d43426101a1dfb3774115f586623f75f00001ce611983c1275fa31f5bc9f4be1a0f467f01ca885c74777 - r 0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47 - h 2 - gx 0x0735e035def5925cc33173eb2a8ce7767522b466d278b650a2916127dfea9d2d361089f0a7a0247a184e1c70d417866e0fe0feb0ff8f2f3f9176418f97d117e624e2015df1662a8 - gy 0x04a36420572616cdf7e606fccadaecfc3b76dab0eb1248dd03fbdfc9cd3242c4726be579855e812de7ec5c500b4576a24628048b6a72d880062eed0dd34b1096d3acbb6b01a4a97 - -#----- That's all, folks----------------------------------------------------- diff --git a/exp.c b/exp.c deleted file mode 100644 index 4327129..0000000 --- a/exp.c +++ /dev/null @@ -1,71 +0,0 @@ -/* -*-c-*- - * - * $Id: exp.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Generalized exponentiation - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define EXP_TYPE /* Hack */ -#include "exp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @exp_simulnext@ --- * - * - * Arguments: @exp_simul *e@ = pointer to state structure - * @size_t x@ = a current accumulator - * - * Returns: The next column of bits. - * - * Use: Scans the next column of bits for a simultaneous - * exponentiation. - */ - -size_t exp_simulnext(exp_simul *e, size_t x) -{ - size_t i; - - /* --- Move to the next word along --- */ - - if (!e->b) { - e->o--; - for (i = 0; i < e->n; i++) - e->s[i].w = e->o < e->s[i].len ? e->s[i].v[e->o] : 0; - e->b = MPW_BITS; - } - - /* --- Scan out a column of bits --- */ - - for (i = 0; i < e->n; i++) { - x = (x << 1) | ((e->s[i].w >> (MPW_BITS - 1)) & 1u); - e->s[i].w <<= 1; - } - e->b--; - return (x); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/exp.h b/exp.h deleted file mode 100644 index 9ff6a24..0000000 --- a/exp.h +++ /dev/null @@ -1,422 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Generalized exponentiation - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifdef CATACOMB_EXP_H -# error "Multiple inclusion of " -#endif - -#define CATACOMB_EXP_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct exp_simulscan { - mpw w; - size_t len; - const mpw *v; -} exp_simulscan; - -typedef struct exp_simul { - unsigned b; - size_t o, n; - exp_simulscan *s; -} exp_simul; - -/*----- Macros provided ---------------------------------------------------*/ - -/* --- Parameters --- */ - -#ifndef EXP_WINSZ /* Sliding window size */ -# define EXP_WINSZ 4 /* Predefine if you need to */ -#endif - -/* --- These are determined from the window size --- * - * - * Given a %$k$%-bit exponent, I expect to do %$k/2$% multiplies if I use the - * simple way. If I use an n-bit sliding window, then I do %$2^n$% - * multiplies up front, but I only do %$(2^n - 1)/2^n k/n$% multiplies for - * the exponentiation. This is a win when - * - * %$k \ge \frac{n 2^{n+1}}{n - 2}$% - */ - -#define EXP_TABSZ (1 << EXP_WINSZ) -#define EXP_THRESH \ - ((EXP_WINSZ * (2 << EXP_WINSZ))/((EXP_WINSZ - 2) * MPW_BITS)) - -/* --- Required operations --- * - * - * The macros here are independent of the underlying group elements. You - * must provide the necessary group operations and other definitions. The - * group operation is assumed to be written multiplicatively. - * - * @EXP_TYPE@ The type of a group element, e.g., @mp *@. - * - * @EXP_COPY(d, x)@ Makes @d@ be a copy of @x@. - * - * @EXP_DROP(x)@ Discards the element @x@, reclaiming any - * memory it used. - * - * @EXP_MUL(a, x)@ Multiplies @a@ by @x@ (writing the result - * back to @a@). - * - * @EXP_FIX(x)@ Makes @x@ be a canonical representation of - * its value. All multiplications have the - * right argument canonical. - * - * @EXP_SQR(a)@ Multiplies @a@ by itself. - * - * @EXP_SETMUL(d, x, y)@ Sets @d@ to be the product of @x@ and @y@. - * The value @d@ has not been initialized. - * - * @EXP_SETSQR(d, x)@ Sets @d@ to be the square of @x@. - * - * Only @EXP_TYPE@, @EXP_MUL@ and @EXP_SQR@ are required for simple - * exponentation. Sliding window and simultaneous exponentation require all - * of the operations. - */ - -#ifndef EXP_TYPE -# error "EXP_TYPE not defined for " -#endif - -/* --- @EXP_SIMPLE@ --- * - * - * Arguments: @a@ = the result object, initially a multiplicative identity - * @g@ = the object to exponentiate - * @x@ = the exponent, as a multiprecision integer - * - * Use: Performs a simple left-to-right exponentiation. At the end - * of the code, the answer is left in @a@; @g@ and @x@ are - * unchanged. - */ - -#define EXP_SIMPLE(a, g, x) do { \ - mpscan sc; \ - unsigned sq = 0; \ - \ - /* --- Begin scanning --- */ \ - \ - mp_rscan(&sc, x); \ - if (!MP_RSTEP(&sc)) \ - goto exp_simple_exit; \ - while (!MP_RBIT(&sc)) \ - MP_RSTEP(&sc); \ - \ - /* --- Do the main body of the work --- */ \ - \ - EXP_FIX(g); \ - for (;;) { \ - EXP_MUL(a, g); \ - sq = 0; \ - for (;;) { \ - if (!MP_RSTEP(&sc)) \ - goto exp_simple_done; \ - sq++; \ - if (MP_RBIT(&sc)) \ - break; \ - } \ - while (sq--) EXP_SQR(a); \ - } \ - \ - /* --- Do a final round of squaring --- */ \ - \ -exp_simple_done: \ - while (sq--) EXP_SQR(a); \ -exp_simple_exit:; \ -} while (0) - -/* --- @EXP_WINDOW@ --- * - * - * Arguments: @a@ = the result object, initially a multiplicative identity - * @g@ = the object to exponentiate - * @x@ = the exponent, as a multiprecision integer - * - * Use: Performs a sliding-window exponentiation. At the end of the - * code, the answer is left in @a@; @g@ and @x@ are unchanged. - */ - -#define EXP_WINDOW(a, g, x) do { \ - EXP_TYPE *v; \ - EXP_TYPE g2; \ - unsigned i, sq = 0; \ - mpscan sc; \ - \ - /* --- Get going --- */ \ - \ - mp_rscan(&sc, x); \ - if (!MP_RSTEP(&sc)) \ - goto exp_window_exit; \ - \ - /* --- Do the precomputation --- */ \ - \ - EXP_FIX(g); \ - EXP_SETSQR(g2, g); \ - EXP_FIX(g2); \ - v = xmalloc(EXP_TABSZ * sizeof(EXP_TYPE)); \ - EXP_COPY(v[0], g); \ - for (i = 1; i < EXP_TABSZ; i++) { \ - EXP_SETMUL(v[i], v[i - 1], g2); \ - EXP_FIX(v[i]); \ - } \ - EXP_DROP(g2); \ - \ - /* --- Skip top-end zero bits --- * \ - * \ - * If the initial step worked, there must be a set bit somewhere, so \ - * keep stepping until I find it. \ - */ \ - \ - while (!MP_RBIT(&sc)) \ - MP_RSTEP(&sc); \ - \ - /* --- Now for the main work --- */ \ - \ - for (;;) { \ - unsigned l = 1; \ - unsigned z = 0; \ - \ - /* --- The next bit is set, so read a window index --- * \ - * \ - * Reset @i@ to zero and increment @sq@. Then, until either I read \ - * @WINSZ@ bits or I run out of bits, scan in a bit: if it's clear, \ - * bump the @z@ counter; if it's set, push a set bit into @i@, \ - * shift it over by @z@ bits, bump @sq@ by @z + 1@ and clear @z@. \ - * By the end of this palaver, @i@ is an index to the precomputed \ - * value in @v@. \ - */ \ - \ - i = 0; \ - sq++; \ - while (l < EXP_WINSZ && MP_RSTEP(&sc)) { \ - l++; \ - if (!MP_RBIT(&sc)) \ - z++; \ - else { \ - i = ((i << 1) | 1) << z; \ - sq += z + 1; \ - z = 0; \ - } \ - } \ - \ - /* --- Do the squaring --- * \ - * \ - * Remember that @sq@ carries over from the zero-skipping stuff \ - * below. \ - */ \ - \ - while (sq--) EXP_SQR(a); \ - \ - /* --- Do the multiply --- */ \ - \ - EXP_MUL(a, v[i]); \ - \ - /* --- Now grind along through the rest of the bits --- */ \ - \ - sq = z; \ - for (;;) { \ - if (!MP_RSTEP(&sc)) \ - goto exp_window_done; \ - if (MP_RBIT(&sc)) \ - break; \ - sq++; \ - } \ - } \ - \ - /* --- Do a final round of squaring --- */ \ - \ -exp_window_done: \ - while (sq--) EXP_SQR(a); \ - for (i = 0; i < EXP_TABSZ; i++) \ - EXP_DROP(v[i]); \ - xfree(v); \ -exp_window_exit:; \ -} while (0) - -/* --- @EXP_SIMUL@ --- * - * - * Arguments: @a@ = the result object, initially a multiplicative identity - * @f@ = pointer to a vector of base/exp pairs - * @n@ = the number of base/exp pairs - * - * Use: Performs a simultaneous sliding-window exponentiation. The - * @f@ table is an array of structures containing members @base@ - * of type @EXP_TYPE@, and @exp@ of type @mp *@. - */ - -#define EXP_SIMUL(a, f, n) do { \ - size_t i, j, jj, k; \ - size_t vn = 1 << (EXP_WINSZ * n), m = (1 << n) - 1; \ - EXP_TYPE *v = xmalloc(vn * sizeof(EXP_TYPE)); \ - exp_simul e; \ - unsigned sq = 0; \ - \ - /* --- Fill in the precomputed table --- */ \ - \ - j = 1; \ - for (i = 0; i < n; i++) { \ - EXP_COPY(v[j], f[n - 1 - i].base); \ - EXP_FIX(v[j]); \ - j <<= 1; \ - } \ - k = n * EXP_WINSZ; \ - jj = 1; \ - for (; i < k; i++) { \ - EXP_SETSQR(v[j], v[jj]); \ - EXP_FIX(v[j]); \ - j <<= 1; jj <<= 1; \ - } \ - for (i = 1; i < vn; i <<= 1) { \ - for (j = 1; j < i; j++) { \ - EXP_SETMUL(v[j + i], v[j], v[i]); \ - EXP_FIX(v[j + i]); \ - } \ - } \ - \ - /* --- Set up the bitscanners --- * \ - * \ - * Got to use custom scanners, to keep them all in sync. \ - */ \ - \ - e.n = n; \ - e.b = 0; \ - e.s = xmalloc(n * sizeof(*e.s)); \ - e.o = 0; \ - for (i = 0; i < n; i++) { \ - MP_SHRINK(f[i].exp); \ - e.s[i].len = MP_LEN(f[i].exp); \ - e.s[i].v = f[i].exp->v; \ - if (e.s[i].len > e.o) \ - e.o = e.s[i].len; \ - } \ - \ - /* --- Skip as far as a nonzero column in the exponent matrix --- */ \ - \ - do { \ - if (!e.o && !e.b) \ - goto exp_simul_done; \ - i = exp_simulnext(&e, 0); \ - } while (!(i & m)); \ - \ - /* --- Now for the main work --- */ \ - \ - for (;;) { \ - unsigned l = 1; \ - unsigned z = 0; \ - \ - /* --- Just read a nonzero column, so read a window index --- * \ - * \ - * Clear high bits of @i@ and increment @sq@. Then, until either I \ - * read @WINSZ@ columns or I run out, scan in a column and append \ - * it to @i@. If it's zero, bump the @z@ counter; if it's nonzero, \ - * bump @sq@ by @z + 1@ and clear @z@. By the end of this palaver, \ - * @i@ is an index to the precomputed value in @v@, followed by \ - * @n * z@ zero bits. \ - */ \ - \ - sq++; \ - while (l < EXP_WINSZ && (e.o || e.b)) { \ - l++; \ - i = exp_simulnext(&e, i); \ - if (!(i & m)) \ - z++; \ - else { \ - sq += z + 1; \ - z = 0; \ - } \ - } \ - \ - /* --- Do the squaring --- * \ - * \ - * Remember that @sq@ carries over from the zero-skipping stuff \ - * below. \ - */ \ - \ - while (sq--) EXP_SQR(a); \ - \ - /* --- Do the multiply --- */ \ - \ - i >>= (z * n); \ - EXP_MUL(a, v[i]); \ - \ - /* --- Now grind along through the rest of the bits --- */ \ - \ - sq = z; \ - for (;;) { \ - if (!e.o && !e.b) \ - goto exp_simul_done; \ - if ((i = exp_simulnext(&e, 0)) != 0) \ - break; \ - sq++; \ - } \ - } \ - \ - /* --- Do a final round of squaring --- */ \ - \ -exp_simul_done: \ - while (sq--) EXP_SQR(a); \ - for (i = 1; i < vn; i++) \ - EXP_DROP(v[i]); \ - xfree(v); \ - xfree(e.s); \ -} while (0) - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @exp_simulnext@ --- * - * - * Arguments: @exp_simul *e@ = pointer to state structure - * @size_t x@ = a current accumulator - * - * Returns: The next column of bits. - * - * Use: Scans the next column of bits for a simultaneous - * exponentiation. - */ - -extern size_t exp_simulnext(exp_simul */*e*/, size_t /*x*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif diff --git a/f-binpoly.c b/f-binpoly.c deleted file mode 100644 index 5f6a527..0000000 --- a/f-binpoly.c +++ /dev/null @@ -1,184 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Binary fields with polynomial basis representation - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "field.h" -#include "field-guts.h" -#include "mprand.h" - -/*----- Polynomial basis --------------------------------------------------*/ - -/* --- Field operations --- */ - -static void fdestroy(field *ff) { - fctx_binpoly *f = (fctx_binpoly *)ff; - gfreduce_destroy(&f->r); MP_DROP(f->f.q); - DESTROY(f); -} - -static mp *frand(field *f, mp *d, grand *r) { - return (mprand(d, f->nbits, r, 0)); -} - -static int fzerop(field *ff, mp *x) { return (MP_ZEROP(x)); } - -static mp *fadd(field *ff, mp *d, mp *x, mp *y) { return (gf_add(d, x, y)); } - -static mp *fmul(field *ff, mp *d, mp *x, mp *y) { - fctx_binpoly *f = (fctx_binpoly *)ff; d = gf_mul(d, x, y); - return (gfreduce_do(&f->r, d, d)); -} - -static mp *fsqr(field *ff, mp *d, mp *x) { - fctx_binpoly *f = (fctx_binpoly *)ff; d = gf_sqr(d, x); - return (gfreduce_do(&f->r, d, d)); -} - -static mp *finv(field *ff, mp *d, mp *x) { - fctx_binpoly *f = (fctx_binpoly *)ff; - d = gf_modinv(d, x, f->r.p); - return (d); -} - -static mp *freduce(field *ff, mp *d, mp *x) { - fctx_binpoly *f = (fctx_binpoly *)ff; - return (gfreduce_do(&f->r, d, x)); -} - -static mp *fsqrt(field *ff, mp *d, mp *x) { - fctx_binpoly *f = (fctx_binpoly *)ff; - return (gfreduce_sqrt(&f->r, d, x)); -} - -static mp *fquadsolve(field *ff, mp *d, mp *x) { - fctx_binpoly *f = (fctx_binpoly *)ff; - return (gfreduce_quadsolve(&f->r, d, x)); -} - -/* --- Field operations table --- */ - -static const field_ops fops = { - FTY_BINARY, "binpoly", - fdestroy, frand, field_stdsamep, - freduce, field_id, - fzerop, field_id, fadd, fadd, fmul, fsqr, finv, freduce, fsqrt, - fquadsolve, - 0, 0, 0, 0 -}; - -/* --- @field_binpoly@ --- * - * - * Arguments: @mp *p@ = the reduction polynomial - * - * Returns: A pointer to the field. - * - * Use: Creates a field structure for a binary field mod @p@. - */ - -field *field_binpoly(mp *p) -{ - fctx_binpoly *f = CREATE(fctx_binpoly); - f->f.ops = &fops; - f->f.zero = MP_ZERO; - f->f.one = MP_ONE; - f->f.nbits = mp_bits(p) - 1; - f->f.noctets = (f->f.nbits + 7) >> 3; - gfreduce_create(&f->r, p); - f->f.m = f->r.p; - f->f.q = mp_lsl(MP_NEW, MP_ONE, f->f.nbits); - return (&f->f); -} - -/*----- Normal basis ------------------------------------------------------*/ - -/* --- Field operations --- */ - -static void fndestroy(field *ff) { - fctx_binnorm *f = (fctx_binnorm *)ff; gfreduce_destroy(&f->f.r); - gfn_destroy(&f->ntop); gfn_destroy(&f->pton); MP_DROP(f->f.f.q); - DESTROY(f); -} - -static int fnsamep(field *ff, field *gg) { - fctx_binnorm *f = (fctx_binnorm *)ff, *g = (fctx_binnorm *)gg; - return (MP_EQ(f->ntop.r[0], g->ntop.r[0]) && field_stdsamep(ff, gg)); -} - -static mp *fnin(field *ff, mp *d, mp *x) { - fctx_binnorm *f = (fctx_binnorm *)ff; - return (gfn_transform(&f->ntop, d, x)); -} - -static mp *fnout(field *ff, mp *d, mp *x) { - fctx_binnorm *f = (fctx_binnorm *)ff; - return (gfn_transform(&f->pton, d, x)); -} - -/* --- Field operations table --- */ - -static const field_ops fnops = { - FTY_BINARY, "binnorm", - fndestroy, frand, fnsamep, - fnin, fnout, - fzerop, field_id, fadd, fadd, fmul, fsqr, finv, freduce, fsqrt, - fquadsolve, - 0, 0, 0, 0 -}; - -/* --- @field_binnorm@ --- * - * - * Arguments: @mp *p@ = the reduction polynomial - * @mp *beta@ = representation of normal point - * - * Returns: A pointer to the field. - * - * Use: Creates a field structure for a binary field mod @p@ which - * uses a normal basis representation externally. Computations - * are still done on a polynomial-basis representation. - */ - -field *field_binnorm(mp *p, mp *beta) -{ - fctx_binnorm *f = CREATE(fctx_binnorm); - f->f.f.ops = &fnops; - f->f.f.zero = MP_ZERO; - f->f.f.one = MP_ONE; - f->f.f.nbits = mp_bits(p) - 1; - f->f.f.noctets = (f->f.f.nbits + 7) >> 3; - gfreduce_create(&f->f.r, p); - f->f.f.m = f->f.r.p; - f->f.f.q = mp_lsl(MP_NEW, MP_ONE, f->f.f.nbits); - gfn_create(p, beta, &f->ntop, &f->pton); - return (&f->f.f); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/f-niceprime.c b/f-niceprime.c deleted file mode 100644 index 83b9ca5..0000000 --- a/f-niceprime.c +++ /dev/null @@ -1,164 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Prime fields with efficient reduction for special-form primes - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "field.h" -#include "field-guts.h" -#include "mprand.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Field operations --- */ - -static void fdestroy(field *ff) { - fctx_niceprime *f = (fctx_niceprime *)ff; - mpreduce_destroy(&f->r); - DESTROY(f); -} - -static mp *frand(field *ff, mp *d, grand *r) { - fctx_niceprime *f = (fctx_niceprime *)ff; - return (mprand_range(d, f->r.p, r, 0)); -} - -static int fzerop(field *ff, mp *x) { return (MP_ZEROP(x)); } - -static mp *fneg(field *ff, mp *d, mp *x) { - fctx_niceprime *f = (fctx_niceprime *)ff; - return (mp_sub(d, f->r.p, x)); -} - -static mp *fadd(field *ff, mp *d, mp *x, mp *y) { - fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_add(d, x, y); - if (MP_NEGP(d)) d = mp_add(d, d, f->r.p); - else if (MP_CMP(d, >, f->r.p)) d = mp_sub(d, d, f->r.p); - return (d); -} - -static mp *fsub(field *ff, mp *d, mp *x, mp *y) { - fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_sub(d, x, y); - if (MP_NEGP(d)) d = mp_add(d, d, f->r.p); - else if (MP_CMP(d, >, f->r.p)) d = mp_sub(d, d, f->r.p); - return (d); -} - -static mp *fmul(field *ff, mp *d, mp *x, mp *y) { - fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_mul(d, x, y); - return (mpreduce_do(&f->r, d, d)); -} - -static mp *fsqr(field *ff, mp *d, mp *x) { - fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_sqr(d, x); - return (mpreduce_do(&f->r, d, d)); -} - -static mp *finv(field *ff, mp *d, mp *x) { - fctx_niceprime *f = (fctx_niceprime *)ff; - d = mp_modinv(d, x, f->r.p); - return (d); -} - -static mp *freduce(field *ff, mp *d, mp *x) { - fctx_niceprime *f = (fctx_niceprime *)ff; - return (mpreduce_do(&f->r, d, x)); -} - -static mp *fsqrt(field *ff, mp *d, mp *x) { - fctx_niceprime *f = (fctx_niceprime *)ff; - return (mp_modsqrt(d, x, f->r.p)); -} - -static mp *fdbl(field *ff, mp *d, mp *x) { - fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_lsl(d, x, 1); - if (MP_CMP(d, >=, f->r.p)) d = mp_sub(d, d, f->r.p); - return (d); -} - -static mp *ftpl(field *ff, mp *d, mp *x) { - fctx_niceprime *f = (fctx_niceprime *)ff; MP_DEST(d, MP_LEN(x) + 1, x->f); - MPX_UMULN(d->v, d->vl, x->v, x->vl, 3); d->f &= ~MP_UNDEF; - while (MP_CMP(d, >=, f->r.p)) d = mp_sub(d, d, f->r.p); - return (d); -} - -static mp *fqdl(field *ff, mp *d, mp *x) { - fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_lsl(d, x, 2); - while (MP_CMP(d, >=, f->r.p)) d = mp_sub(d, d, f->r.p); - return (d); -} - -static mp *fhlv(field *ff, mp *d, mp *x) { - fctx_niceprime *f = (fctx_niceprime *)ff; - if (MP_ZEROP(x)) { MP_COPY(x); MP_DROP(d); return (x); } - if (x->v[0] & 1) { d = mp_add(d, x, f->r.p); x = d; } - return (mp_lsr(d, x, 1)); -} - -/* --- Field operations table --- */ - -static const field_ops fops = { - FTY_PRIME, "niceprime", - fdestroy, frand, field_stdsamep, - freduce, field_id, - fzerop, fneg, fadd, fsub, fmul, fsqr, finv, freduce, fsqrt, - 0, - fdbl, ftpl, fqdl, fhlv -}; - -/* --- @field_niceprime@ --- * - * - * Arguments: @mp *p@ = the characteristic of the field - * - * Returns: A pointer to the field, or null. - * - * Use: Creates a field structure for a prime field of size %$p$%, - * using efficient reduction for nice primes. - */ - -field *field_niceprime(mp *p) -{ - fctx_niceprime *f = CREATE(fctx_niceprime); - f->f.ops = &fops; - f->f.zero = MP_ZERO; - f->f.one = MP_ONE; - f->f.nbits = mp_bits(p); - f->f.noctets = (f->f.nbits + 7) >> 3; - if (mpreduce_create(&f->r, p)) { - DESTROY(f); - return (0); - } - f->f.m = f->r.p; - f->f.q = f->r.p; - return (&f->f); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/f-prime.c b/f-prime.c deleted file mode 100644 index 31638f5..0000000 --- a/f-prime.c +++ /dev/null @@ -1,178 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Prime fields with Montgomery arithmetic - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "field.h" -#include "mprand.h" -#include "field-guts.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Field operations --- */ - -static void fdestroy(field *ff) { - fctx_prime *f = (fctx_prime *)ff; - mpmont_destroy(&f->mm); - DESTROY(f); -} - -static mp *frand(field *ff, mp *d, grand *r) { - fctx_prime *f = (fctx_prime *)ff; - return (mprand_range(d, f->mm.m, r, 0)); -} - -static mp *fin(field *ff, mp *d, mp *x) { - fctx_prime *f = (fctx_prime *)ff; - mp_div(0, &d, x, f->mm.m); - return (mpmont_mul(&f->mm, d, d, f->mm.r2)); -} - -static mp *fout(field *ff, mp *d, mp *x) { - fctx_prime *f = (fctx_prime *)ff; - return (mpmont_reduce(&f->mm, d, x)); -} - -static int fzerop(field *ff, mp *x) { return (MP_ZEROP(x)); } - -static mp *fneg(field *ff, mp *d, mp *x) { - fctx_prime *f = (fctx_prime *)ff; - return (mp_sub(d, f->mm.m, x)); -} - -static mp *fadd(field *ff, mp *d, mp *x, mp *y) { - fctx_prime *f = (fctx_prime *)ff; d = mp_add(d, x, y); - if (MP_NEGP(d)) d = mp_add(d, d, f->mm.m); - else if (MP_CMP(d, >, f->mm.m)) d = mp_sub(d, d, f->mm.m); - return (d); -} - -static mp *fsub(field *ff, mp *d, mp *x, mp *y) { - fctx_prime *f = (fctx_prime *)ff; d = mp_sub(d, x, y); - if (MP_NEGP(d)) d = mp_add(d, d, f->mm.m); - else if (MP_CMP(d, >, f->mm.m)) d = mp_sub(d, d, f->mm.m); - return (d); -} - -static mp *fmul(field *ff, mp *d, mp *x, mp *y) { - fctx_prime *f = (fctx_prime *)ff; - return (mpmont_mul(&f->mm, d, x, y)); -} - -static mp *fsqr(field *ff, mp *d, mp *x) { - fctx_prime *f = (fctx_prime *)ff; d = mp_sqr(d, x); - return (mpmont_reduce(&f->mm, d, d)); -} - -static mp *finv(field *ff, mp *d, mp *x) { - fctx_prime *f = (fctx_prime *)ff; d = mpmont_reduce(&f->mm, d, x); - d = mp_modinv(d, d, f->mm.m); return (mpmont_mul(&f->mm, d, d, f->mm.r2)); -} - -static mp *freduce(field *ff, mp *d, mp *x) { - fctx_prime *f = (fctx_prime *)ff; - mp_div(0, &d, x, f->mm.m); - return (d); -} - -static mp *fsqrt(field *ff, mp *d, mp *x) { - fctx_prime *f = (fctx_prime *)ff; d = mpmont_reduce(&f->mm, d, x); - d = mp_modsqrt(d, d, f->mm.m); if (!d) return (d); - return (mpmont_mul(&f->mm, d, d, f->mm.r2)); -} - -static mp *fdbl(field *ff, mp *d, mp *x) { - fctx_prime *f = (fctx_prime *)ff; d = mp_lsl(d, x, 1); - if (MP_CMP(d, >=, f->mm.m)) d = mp_sub(d, d, f->mm.m); - return (d); -} - -static mp *ftpl(field *ff, mp *d, mp *x) { - fctx_prime *f = (fctx_prime *)ff; MP_DEST(d, MP_LEN(x) + 1, x->f); - MPX_UMULN(d->v, d->vl, x->v, x->vl, 3); d->f &= ~MP_UNDEF; - while (MP_CMP(d, >=, f->mm.m)) d = mp_sub(d, d, f->mm.m); - return (d); -} - -static mp *fqdl(field *ff, mp *d, mp *x) { - fctx_prime *f = (fctx_prime *)ff; d = mp_lsl(d, x, 2); - while (MP_CMP(d, >=, f->mm.m)) d = mp_sub(d, d, f->mm.m); - return (d); -} - -static mp *fhlv(field *ff, mp *d, mp *x) { - fctx_prime *f = (fctx_prime *)ff; - if (MP_ZEROP(x)) { MP_COPY(x); MP_DROP(d); return (x); } - if (x->v[0] & 1) { d = mp_add(d, x, f->mm.m); x = d; } - return (mp_lsr(d, x, 1)); -} - -/* --- Field operations table --- */ - -static const field_ops fops = { - FTY_PRIME, "prime", - fdestroy, frand, field_stdsamep, - fin, fout, - fzerop, fneg, fadd, fsub, fmul, fsqr, finv, freduce, fsqrt, - 0, - fdbl, ftpl, fqdl, fhlv -}; - -/* --- @field_prime@ --- * - * - * Arguments: @mp *p@ = the characteristic of the field - * - * Returns: A pointer to the field or null. - * - * Use: Creates a field structure for a prime field of size %$p$%, - * using Montgomery reduction for arithmetic. - */ - -field *field_prime(mp *p) -{ - fctx_prime *f; - - f = CREATE(fctx_prime); - f->f.ops = &fops; - if (mpmont_create(&f->mm, p)) { - DESTROY(f); - return (0); - } - f->f.zero = MP_ZERO; - f->f.one = f->mm.r; - f->f.m = f->mm.m; - f->f.nbits = mp_bits(p); - f->f.noctets = (f->f.nbits + 7) >> 3; - f->f.q = f->mm.m; - return (&f->f); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/factorial.c b/factorial.c deleted file mode 100644 index 31316a7..0000000 --- a/factorial.c +++ /dev/null @@ -1,152 +0,0 @@ -/* -*-c-*- - * - * $Id: factorial.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Example factorial computation - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "config.h" - -#include -#include -#include -#include - -#include -#include -#include - -#include "mpint.h" -#include "mpmul.h" -#include "mptext.h" - -/*----- Main code ---------------------------------------------------------*/ - -static void usage(FILE *fp) -{ - pquis(fp, "Usage: $ [-r RADIX] INTEGER\n"); -} - -static void version(FILE *fp) -{ - pquis(fp, "$, Catacomb version " VERSION "\n"); -} - -static void help(FILE *fp) -{ - version(fp); - putc('\n', fp); - usage(fp); - fputs("\n\ -Prints the factorial of the given integer on its output. Input may be\n\ -in decimal (the default), octal with preceding zero, hex with preceding\n\ -`0x', or any base N between 2 and 62 inclusive with preceding `N_'.\n\ -Output may be in any base between 2 and 62; the default is base 10. For\n\ -bases between 11 and 36 inclusive, lowercase letters of either case are\n\ -used as additional digits with values 10 upwards; lowercase is always\n\ -used for output. For bases between 37 and 62 inclusive, lowercase letters\n\ -have lower value than uppercase; hence `a' has the value 10, while `A' has\n\ -the value 36.\n\ -\n\ -Options provided:\n\ -\n\ --h, --help Display this help message.\n\ --v, --version Display the version number.\n\ --u, --usage Display a usage message.\n\ -\n\ --r, --radix=N Write output in base N.\n\ -", fp); -} - -int main(int argc, char *argv[]) -{ - unsigned long x; - int r = 10; - char *p; - mp *f, *ulmax, *xx; - unsigned fl = 0; - -#define f_bogus 1u - - ego(argv[0]); - - for (;;) { - static const struct option opt[] = { - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'v' }, - { "usage", 0, 0, 'u' }, - { "radix", OPTF_ARGREQ, 0, 'r' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "hvur:", opt, 0, 0, 0); - if (i < 0) - break; - switch (i) { - case 'h': - help(stdout); - exit(0); - case 'v': - version(stdout); - exit(0); - case 'u': - usage(stdout); - exit(0); - case 'r': - r = atoi(optarg); - if (r < 2 || r > 62) - die(EXIT_FAILURE, "bad radix `%s'", optarg); - break; - default: - fl |= f_bogus; - break; - } - } - - if (optind + 1 != argc || (fl & f_bogus)) { - usage(stderr); - exit(EXIT_FAILURE); - } - ulmax = mp_fromulong(MP_NEW, ULONG_MAX); - p = argv[optind]; - while (isspace((unsigned char)*p)) - p++; - xx = mp_readstring(MP_NEW, argv[optind], &p, 0); - while (isspace((unsigned char)*p)) - p++; - if (!xx || *p || MP_CMP(xx, >, ulmax)) - die(EXIT_FAILURE, "bad integer `%s'", argv[optind]); - x = mp_toulong(xx); - mp_drop(xx); - mp_drop(ulmax); - f = mp_factorial(x); - mp_writefile(f, stdout, r); - fputc('\n', stdout); - mp_drop(f); - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/fibrand.c b/fibrand.c deleted file mode 100644 index c926a1a..0000000 --- a/fibrand.c +++ /dev/null @@ -1,249 +0,0 @@ -/* -*-c-*- - * - * $Id: fibrand.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Fibonacci generator - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include -#include - -#include "fibrand.h" -#include "grand.h" -#include "lcrand.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @fibrand_step@ --- * - * - * Arguments: @fibrand *f@ = pointer to Fibonacci generator context - * - * Returns: Next output from generator. - * - * Use: Steps the generator. Returns - * %$x_{i - 24} + x_{i - 55} \bmod 2^{32}$%. - */ - -uint32 fibrand_step(fibrand *f) -{ - unsigned i = f->i; - unsigned j = i + (FIB_SZ - FIB_TAP); - uint32 x; - if (j >= FIB_SZ) - j -= FIB_SZ; - x = f->x[i] = U32(f->x[i] + f->x[j]); - i++; - if (i >= FIB_SZ) - i = 0; - f->i = i; - return (x); -} - -/* --- @fibrand_seed@ --- * - * - * Arguments: @fibrand *f@ = pointer to Fibonacci generator context - * @grand *r@ = random number generator to extract words from - * - * Returns: --- - * - * Use: Initializes a Fibonacci generator using word outputs from the - * given random number source @r@. - */ - -void fibrand_seed(fibrand *f, grand *r) -{ - int i; - unsigned p = 0; - - for (i = 0; i < FIB_SZ; i++) - p |= f->x[i] = r->ops->word(r); - if (!(p & 1)) { - i = r->ops->range(r, FIB_SZ); - f->x[i] |= 1; - } - f->i = 0; -} - -/* --- @fibrand_lcseed@ --- * - * - * Arguments: @fibrand *f@ = pointer to Fibonacci generator context - * @uint32 seed@ = seed value - * - * Returns: --- - * - * Use: Initializes a Fibonacci generator using outputs from the - * @lcrand@ generator seeded from @seed@. This is faster than - * using a generic @lcrand@-based generator and @fibrand_rseed@ - * because it uses raw outputs rather than uniformly distributed - * 32-bit words. - */ - -void fibrand_lcseed(fibrand *f, uint32 seed) -{ - int i; - unsigned p = 0; - - for (i = 0; i < FIB_SZ; i++) - p |= f->x[i] = seed = lcrand(seed); - if (!(p & 1)) { - i = lcrand_range(&seed, FIB_SZ); - f->x[i] |= 1; - } - f->i = 0; -} - -/* --- @fibrand_range@ --- * - * - * Arguments: @fibrand *f@ = pointer to Fibonacci generator context - * @uint32 m@ = limit - * - * Returns: A uniformly distributed pseudorandom integer in the interval - * %$[0, m)$%. - */ - -uint32 fibrand_range(fibrand *f, uint32 m) -{ - uint32 r = 0xffffffff - (0xffffffff % m); - uint32 x; - - /* --- Now generate numbers until a good one comes along --- */ - - do x = fibrand_step(f); while (x >= r); - return (x % m); -} - -/*----- Generic interface -------------------------------------------------*/ - -typedef struct gctx { - grand r; - fibrand f; -} gctx; - -static void gdestroy(grand *r) -{ - gctx *g = (gctx *)r; - DESTROY(g); -} - -static int gmisc(grand *r, unsigned op, ...) -{ - gctx *g = (gctx *)r; - va_list ap; - int rc = 0; - va_start(ap, op); - - switch (op) { - case GRAND_CHECK: - switch (va_arg(ap, unsigned)) { - case GRAND_CHECK: - case GRAND_SEEDINT: - case GRAND_SEEDUINT32: - case GRAND_SEEDRAND: - rc = 1; - break; - default: - rc = 0; - break; - } - break; - case GRAND_SEEDINT: - fibrand_lcseed(&g->f, va_arg(ap, unsigned)); - break; - case GRAND_SEEDUINT32: - fibrand_lcseed(&g->f, va_arg(ap, uint32)); - break; - case GRAND_SEEDRAND: - fibrand_seed(&g->f, va_arg(ap, grand *)); - break; - default: - GRAND_BADOP; - break; - } - - va_end(ap); - return (rc); -} - -static octet gbyte(grand *r) -{ - gctx *g = (gctx *)r; - return (U8(fibrand_step(&g->f))); -} - -static uint32 gword(grand *r) -{ - gctx *g = (gctx *)r; - return (fibrand_step(&g->f)); -} - -static uint32 grange(grand *r, uint32 l) -{ - gctx *g = (gctx *)r; - return (fibrand_range(&g->f, l)); -} - -static void gfill(grand *r, void *p, size_t sz) -{ - gctx *g = (gctx *)r; - octet *q = p; - while (sz) { - *q++ = U8(fibrand_step(&g->f)); - sz--; - } -} - -static const grand_ops gops = { - "fibrand", - 0, 0, - gmisc, gdestroy, - gword, gbyte, gword, grange, gfill -}; - -/* --- @fibrand_create@ --- * - * - * Arguments: @uint32 seed@ = initial seed - * - * Returns: Pointer to a generic generator. - * - * Use: Constructs a generic generator interface over a Fibonacci - * generator. The generator is seeded using @fibrand_lcseed@. - */ - -grand *fibrand_create(uint32 seed) -{ - gctx *g = CREATE(gctx); - g->r.ops = &gops; - fibrand_lcseed(&g->f, seed); - return (&g->r); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/fibrand.h b/fibrand.h deleted file mode 100644 index 14d2aec..0000000 --- a/fibrand.h +++ /dev/null @@ -1,139 +0,0 @@ -/* -*-c-*- - * - * $Id: fibrand.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Fibonacci generator - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the Fibonacci generator ----------------------------------* - * - * The generator was originally suggested by G. J. Mitchell and D. P. Moore - * in 1957, and publicized by D. E. Knuth as Algorithm 3.2.2A in volume 2 of - * his work `The Art of Computer Programming'. The generator is simple: at - * each stage it emits %$x_n = (x_{n - 55} + x_{n - 24}) \bmod 2^{32}$%. The - * period is proven to be greater than %$2^{55}$%, and statistical properties - * appear to be good. - */ - -#ifndef CATACOMB_FIBRAND_H -#define CATACOMB_FIBRAND_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -/*----- Magic constants ---------------------------------------------------*/ - -#define FIB_SZ 55 -#define FIB_TAP 24 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct fibrand { - unsigned i; - uint32 x[FIB_SZ]; -} fibrand; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @fibrand_step@ --- * - * - * Arguments: @fibrand *f@ = pointer to Fibonacci generator context - * - * Returns: Next output from generator. - * - * Use: Steps the generator. Returns - * %$x_{i - 24} + x_{i - 55} \bmod 2^{32}$%. - */ - -extern uint32 fibrand_step(fibrand */*f*/); - -/* --- @fibrand_seed@ --- * - * - * Arguments: @fibrand *f@ = pointer to Fibonacci generator context - * @grand *r@ = random number generator to extract words from - * - * Returns: --- - * - * Use: Initializes a Fibonacci generator using word outputs from the - * given random number source @r@. - */ - -extern void fibrand_seed(fibrand */*f*/, grand */*r*/); - -/* --- @fibrand_lcseed@ --- * - * - * Arguments: @fibrand *f@ = pointer to Fibonacci generator context - * @uint32 seed@ = seed value - * - * Returns: --- - * - * Use: Initializes a Fibonacci generator using outputs from the - * @lcrand@ generator seeded from @seed@. This is faster than - * using a generic @lcrand@-based generator and @fibrand_rseed@ - * because it uses raw outputs rather than uniformly distributed - * 32-bit words. - */ - -extern void fibrand_lcseed(fibrand */*f*/, uint32 /*seed*/); - -/* --- @fibrand_range@ --- * - * - * Arguments: @fibrand *f@ = pointer to Fibonacci generator context - * @uint32 m@ = limit - * - * Returns: A uniformly distributed pseudorandom integer in the interval - * %$[0, m)$%. - */ - -extern uint32 fibrand_range(fibrand */*f*/, uint32 /*m*/); - -/* --- @fibrand_create@ --- * - * - * Arguments: @uint32 seed@ = initial seed - * - * Returns: Pointer to a generic generator. - * - * Use: Constructs a generic generator interface over a Fibonacci - * generator. The generator is seeded using @fibrand_lcseed@. - */ - -extern grand *fibrand_create(uint32 /*seed*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/field-exp.c b/field-exp.c deleted file mode 100644 index 628fa49..0000000 --- a/field-exp.c +++ /dev/null @@ -1,73 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Exponentiation in finite fields - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "field.h" -#include "field-exp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @field_exp@ --- * - * - * Arguments: @field *f@ = pointer to field - * @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e$%. - * - * Use: Exponentiation in a finite field. Note that all quantities - * are in internal format. - */ - -mp *field_exp(field *f, mp *d, mp *a, mp *e) -{ - mp *x = MP_COPY(f->one); - mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; - - MP_COPY(a); - MP_SHRINK(e); - if (MP_ZEROP(e)) - ; - else { - if (MP_NEGP(e)) - a = F_INV(f, a, a); - if (MP_LEN(e) < EXP_THRESH) - EXP_SIMPLE(x, a, e); - else - EXP_WINDOW(x, a, e); - } - mp_drop(d); - mp_drop(spare); - mp_drop(a); - return (x); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/field-exp.h b/field-exp.h deleted file mode 100644 index 928a893..0000000 --- a/field-exp.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Exponentiation in finite fields - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_FIELD_EXP_H -#define CATACOMB_FIELD_EXP_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Exponentiation definitions ----------------------------------------*/ - -#define EXP_TYPE mp * - -#define EXP_COPY(d, x) d = MP_COPY(x) -#define EXP_DROP(x) MP_DROP(x) - -#define EXP_MUL(a, x) a = F_MUL(f, a, a, x) -#define EXP_SQR(a) a = F_SQR(f, a, a) -#define EXP_FIX(x) - -#define EXP_SETMUL(d, x, y) d = F_MUL(f, MP_NEW, x, y) -#define EXP_SETSQR(d, x) d = F_SQR(f, MP_NEW, x) - -#include "exp.h" - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/field-guts.h b/field-guts.h deleted file mode 100644 index fc7ce50..0000000 --- a/field-guts.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Internal structures for built-in fields - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_FIELD_GUTS_H -#define CATACOMB_FIELD_GUTS_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_EC_H -# include "ec.h" -#endif - -#ifndef CATACOMB_MPMONT_H -# include "mpmont.h" -#endif - -#ifndef CATACOMB_MPREDUCE_H -# include "mpreduce.h" -#endif - -#ifndef CATACOMB_GF_H -# include "gf.h" -#endif - -#ifndef CATACOMB_GFN_H -# include "gfn.h" -#endif - -#ifndef CATACOMB_GFREDUCE_H -# include "gfreduce.h" -#endif - -#ifndef CATACOMB_FIELD_H -# include "field.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct fctx_prime { - field f; - mpmont mm; -} fctx_prime; - -typedef struct fctx_niceprime { - field f; - mpreduce r; -} fctx_niceprime; - -typedef struct fctx_binpoly { - field f; - gfreduce r; -} fctx_binpoly; - -typedef struct fctx_binnorm { - fctx_binpoly f; - gfn ntop, pton; -} fctx_binnorm; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/field-parse.c b/field-parse.c deleted file mode 100644 index cbbd246..0000000 --- a/field-parse.c +++ /dev/null @@ -1,87 +0,0 @@ -/* -*-c-*- - * - * $Id: field-parse.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Parse field descriptions - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "field.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @field_parse@ --- * - * - * Arguments: @qd_parse *qd@ = parser context - * - * Returns: Field pointer if OK, or null. - * - * Use: Parses a field description, which has the form - * - * * `prime', `niceprime' or `binpoly' - * * an optional `:' - * * the field modulus - */ - -field *field_parse(qd_parse *qd) -{ - field *f = 0; - mp *m = MP_NEW, *b = MP_NEW; - - switch (qd_enum(qd, "prime,niceprime,binpoly,binnorm")) { - case 0: - qd_delim(qd, ':'); - if ((m = qd_getmp(qd)) == 0) goto done; - f = field_prime(m); - break; - case 1: - qd_delim(qd, ':'); - if ((m = qd_getmp(qd)) == 0) goto done; - f = field_niceprime(m); - break; - case 2: - qd_delim(qd, ':'); - if ((m = qd_getmp(qd)) == 0) goto done; - f = field_binpoly(m); - break; - case 3: - qd_delim(qd, ':'); - if ((m = qd_getmp(qd)) == 0) goto done; - qd_delim(qd, ','); - if ((b = qd_getmp(qd)) == 0) goto done; - f = field_binnorm(m, b); - break; - default: - goto done; - } - if (!f) qd->e = "bad field parameters"; -done: - mp_drop(m); - mp_drop(b); - return (f); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/field.c b/field.c deleted file mode 100644 index 8fb1ad6..0000000 --- a/field.c +++ /dev/null @@ -1,78 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Abstract field operations - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "field.h" -#include "mp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @field_id@ --- * - * - * Arguments: @field *f@ = pointer to a field - * @mp *d@ = a destination element - * @mp *x@ = a source element - * - * Returns: The result element. - * - * Use: An identity operation which can be used if your field has no - * internal representation. - */ - -mp *field_id(field *f, mp *d, mp *x) - { x = MP_COPY(x); if (d) MP_DROP(d); return (x); } - -/* --- @field_samep@ --- * - * - * Arguments: @field *f, *g@ = two fields - * - * Returns: Nonzero if the fields are identical (not just isomorphic). - * - * Use: Checks for sameness of fields. This function does the full - * check, not just the field-type-specific check done by the - * @sampep@ field operation. - */ - -int field_samep(field *f, field *g) - { return (f == g || (f->ops == g->ops && F_SAMEP(f, g))); } - -/* --- @field_stdsamep@ --- * - * - * Arguments: @field *f, *g@ = two fields - * - * Returns: Nonzero if the fields are identical (not just isomorphic). - * - * Use: Standard sameness check, based on equality of the @m@ - * member. - */ - -int field_stdsamep(field *f, field *g) { return (MP_EQ(f->m, g->m)); } - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/field.h b/field.h deleted file mode 100644 index 6085716..0000000 --- a/field.h +++ /dev/null @@ -1,267 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Definitions for field arithmetic - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_FIELD_H -#define CATACOMB_FIELD_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_QDPARSE_H -# include "qdparse.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct field { - const struct field_ops *ops; /* Field operations */ - mp *zero, *one; /* Identities in the field */ - mp *m; /* Modulus (prime and binary) */ - unsigned long nbits; /* Length of field element in bits */ - size_t noctets; /* Length of element in octets */ - mp *q; /* Number of elements in field */ -} field; - -enum { - FTY_PRIME, - FTY_BINARY -}; - -typedef struct field_ops { - - /* --- General information --- */ - - unsigned ty; /* What kind of field this is */ - const char *name; /* Human-readable name string */ - - /* --- Universal operations --- */ - - void (*destroy)(field */*f*/); - mp *(*rand)(field */*f*/, mp */*d*/, grand */*r*/); - int (*samep)(field */*f*/, field */*g*/); - - mp *(*in)(field */*f*/, mp */*d*/, mp */*x*/); - mp *(*out)(field */*f*/, mp */*d*/, mp */*x*/); - - int (*zerop)(field */*f*/, mp */*x*/); - mp *(*neg)(field */*f*/, mp */*d*/, mp */*x*/); - mp *(*add)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/); - mp *(*sub)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/); - mp *(*mul)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/); - mp *(*sqr)(field */*f*/, mp */*d*/, mp */*x*/); - mp *(*inv)(field */*f*/, mp */*d*/, mp */*x*/); - mp *(*reduce)(field */*f*/, mp */*d*/, mp */*x*/); - mp *(*sqrt)(field */*f*/, mp */*d*/, mp */*x*/); - - /* --- Operations for binary fields only --- */ - - mp *(*quadsolve)(field */*f*/, mp */*d*/, mp */*x*/); - - /* --- Operations for prime fields only --- */ - - mp *(*dbl)(field */*f*/, mp */*d*/, mp */*x*/); - mp *(*tpl)(field */*f*/, mp */*d*/, mp */*x*/); - mp *(*qdl)(field */*f*/, mp */*d*/, mp */*x*/); - mp *(*hlv)(field */*f*/, mp */*d*/, mp */*x*/); - -} field_ops; - -#define F_TYPE(f) (f)->ops->ty -#define F_NAME(f) (f)->ops->name - -#define F_DESTROY(f) (f)->ops->destroy((f)) -#define F_RAND(f, d, r) (f)->ops->rand((f), (d), (r)) -#define F_SAMEP(f, g) (f)->ops->samep((f), (g)) - -#define F_IN(f, d, x) (f)->ops->in((f), (d), (x)) -#define F_OUT(f, d, x) (f)->ops->out((f), (d), (x)) - -#define F_ZEROP(f, x) (f)->ops->zerop((f), (x)) -#define F_NEG(f, d, x) (f)->ops->neg((f), (d), (x)) -#define F_ADD(f, d, x, y) (f)->ops->add((f), (d), (x), (y)) -#define F_SUB(f, d, x, y) (f)->ops->sub((f), (d), (x), (y)) -#define F_MUL(f, d, x, y) (f)->ops->mul((f), (d), (x), (y)) -#define F_SQR(f, d, x) (f)->ops->sqr((f), (d), (x)) -#define F_INV(f, d, x) (f)->ops->inv((f), (d), (x)) -#define F_REDUCE(f, d, x) (f)->ops->reduce((f), (d), (x)) -#define F_SQRT(f, d, x) (f)->ops->sqrt((f), (d), (x)) - -#define F_QUADSOLVE(f, d, x) (f)->ops->quadsolve((f), (d), (x)) - -#define F_DBL(f, d, x) (f)->ops->dbl((f), (d), (x)) -#define F_TPL(f, d, x) (f)->ops->tpl((f), (d), (x)) -#define F_QDL(f, d, x) (f)->ops->qdl((f), (d), (x)) -#define F_HLV(f, d, x) (f)->ops->hlv((f), (d), (x)) - -/*----- Helpful field operations ------------------------------------------*/ - -/* --- @field_id@ --- * - * - * Arguments: @field *f@ = pointer to a field - * @mp *d@ = a destination element - * @mp *x@ = a source element - * - * Returns: The result element. - * - * Use: An identity operation which can be used if your field has no - * internal representation. - */ - -extern mp *field_id(field */*f*/, mp */*d*/, mp */*x*/); - -/* --- @field_samep@ --- * - * - * Arguments: @field *f, *g@ = two fields - * - * Returns: Nonzero if the fields are identical (not just isomorphic). - * - * Use: Checks for sameness of fields. This function does the full - * check, not just the field-type-specific check done by the - * @sampep@ field operation. - */ - -extern int field_samep(field */*f*/, field */*g*/); - -/* --- @field_stdsamep@ --- * - * - * Arguments: @field *f, *g@ = two fields - * - * Returns: Nonzero if the fields are identical (not just isomorphic). - * - * Use: Standard sameness check, based on equality of the @m@ - * member. - */ - -extern int field_stdsamep(field */*f*/, field */*g*/); - -/*----- Arithmetic --------------------------------------------------------*/ - -/* --- @field_exp@ --- * - * - * Arguments: @field *f@ = pointer to field - * @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e$%. - * - * Use: Exponentiation in a finite field. Note that all quantities - * are in internal format. This is a generic implementation - * suitable for use with all fields and is not intended to be - * optimal. - */ - -extern mp *field_exp(field */*f*/, mp */*d*/, mp */*a*/, mp */*e*/); - -/*----- Creating fields ---------------------------------------------------*/ - -/* --- @field_prime@ --- * - * - * Arguments: @mp *p@ = the characteristic of the field - * - * Returns: A pointer to the field. - * - * Use: Creates a field structure for a prime field of size %$p$%, - * using Montgomery reduction for arithmetic. - */ - -extern field *field_prime(mp */*p*/); - -/* --- @field_niceprime@ --- * - * - * Arguments: @mp *p@ = the characteristic of the field - * - * Returns: A pointer to the field, or null. - * - * Use: Creates a field structure for a prime field of size %$p$%, - * using efficient reduction for nice primes. - */ - -extern field *field_niceprime(mp */*p*/); - -/* --- @field_binpoly@ --- * - * - * Arguments: @mp *p@ = an irreducible polynomial over %$\gf{2}$% - * - * Returns: A pointer to the field. - * - * Use: Creates a field structure for a binary field using naive - * arithmetic. - */ - -extern field *field_binpoly(mp */*p*/); - -/* --- @field_binnorm@ --- * - * - * Arguments: @mp *p@ = the reduction polynomial - * @mp *beta@ = representation of normal point - * - * Returns: A pointer to the field. - * - * Use: Creates a field structure for a binary field mod @p@ which - * uses a normal basis representation externally. Computations - * are still done on a polynomial-basis representation. - */ - -extern field *field_binnorm(mp */*p*/, mp */*beta*/); - -/* --- @field_parse@ --- * - * - * Arguments: @qd_parse *qd@ = parser context - * - * Returns: Field pointer if OK, or null. - * - * Use: Parses a field description, which has the form - * - * * `prime', `niceprime', `binpoly', or `binnorm' - * * an optional `:' - * * the field modulus - * * for `binnorm', an optional `,' and the beta value - */ - -extern field *field_parse(qd_parse */*qd*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/fipstest.c b/fipstest.c deleted file mode 100644 index 4563882..0000000 --- a/fipstest.c +++ /dev/null @@ -1,191 +0,0 @@ -/* -*-c-*- - * - * $Id: fipstest.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * FIPS140 randomness tests - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "fipstest.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @monobit@ --- * - * - * Arguments: @const octet *p@ = pointer to buffer - * - * Returns: Zero if OK, @FIPSTEST_MONOBIT@ on failure. - * - * Use: Performs the monobit test on a buffer of data. If %$n_1$% is - * the number of 1 bits in the buffer, then the monobit test is - * passed when %$9654 < n_1 < 10346$%. - */ - -static unsigned monobit(const octet *p) -{ - unsigned n1 = 0; - unsigned i, j; - - for (i = 0; i < FIPSTEST_BUFSZ; i++) { - octet x = p[i]; - for (j = 0; j < 8; j++) { - if (x & 1) - n1++; - x >>= 1; - } - } - - if (9725 >= n1 || n1 >= 10275) - return (FIPSTEST_MONOBIT); - return (0); -} - -/* --- @poker@ --- * - * - * Arguments: @const octet *p@ = pointer to buffer - * - * Returns: Zero if OK, @FIPSTEST_POKER@ on failure. - * - * Use: Performs the poker test on a buffer of data. The buffer is - * divided into 4-bit nibbles %$x_i$%. If - * %$f(x) = \sum_{x_i = x} 1$% is the frequency of each nibble, - * then the test is passed if - * %$2.16 < 16/5000 \sum_i f(i)^2 - 5000 < 46.17$%. - */ - -static unsigned poker(const octet *p) -{ - unsigned long f[16] = { 0 }; - unsigned i; - unsigned long q = 0; - - /* --- Compute the frequencies --- */ - - for (i = 0; i < FIPSTEST_BUFSZ; i++) { - octet x = p[i]; - f[x & 0xf]++; - f[(x >> 4) & 0xf]++; - } - - /* --- Now do the comparison --- * - * - * This can be simplified. Multiply through the inequality by 5000 and - * we get %$5150 < 16 \sum_i f(i)^2 - 5000^2 < 287000$%. - */ - - for (i = 0; i < 16; i++) - q += f[i] * f[i]; - q <<= 4; - q -= 5000ul * 5000ul; - - if (10800 >= q || q >= 230850) - return (FIPSTEST_POKER); - return (0); -} - -/* --- @runs@ --- * - * - * Arguments: @const octet *p@ = pointer to buffer - * - * Returns: Zero for success, @FIPSTEST_RUNS@ or @FIPSTEST_LONGRUNS@ on - * failure. - * - * Use: Performs the runs and long runs tests. The frequency of each - * `run', or sequence of equal bits, is counted and tested. - */ - -static unsigned runs(const octet *p) -{ - unsigned rc = 0; - unsigned i, j; - unsigned r = 0; - unsigned bb = 0; - unsigned f[2][6] = { { 0 } }; - - /* --- Count the run lengths --- */ - - for (i = 0; i < FIPSTEST_BUFSZ; i++) { - octet x = p[i]; - for (j = 0; j < 8; j++) { - unsigned b = x & 1; - x >>= 1; - if (b == bb) - r++; - else { - if (r) { - if (r >= 34) - rc |= FIPSTEST_LONGRUNS; - if (r > 6) - r = 6; - f[bb][r - 1]++; - } - r = 1; - bb = b; - } - } - } - - if (r >= 26) - rc |= FIPSTEST_LONGRUNS; - if (r > 6) - r = 6; - f[bb][r - 1]++; - - /* --- Check the results --- */ - - if (2343 > f[0][0] || f[0][0] > 2657 || 2343 > f[1][0] || f[1][0] > 2657 || - 1135 > f[0][1] || f[0][1] > 1365 || 1135 > f[1][1] || f[1][1] > 1365 || - 542 > f[0][2] || f[0][2] > 708 || 542 > f[1][2] || f[1][2] > 708 || - 251 > f[0][3] || f[0][3] > 373 || 251 > f[1][3] || f[1][3] > 373 || - 111 > f[0][4] || f[0][4] > 201 || 111 > f[1][4] || f[1][4] > 201 || - 111 > f[0][5] || f[0][5] > 201 || 111 > f[1][5] || f[1][5] > 201) - rc |= FIPSTEST_RUNS; - - return (rc); -} - -/* --- @fipstest@ --- * - * - * Arguments: @const octet *p@ = pointer to a buffer of @FIPSTEST_BUFSZ@ - * bytes - * - * Returns: Zero if OK, or a bitmask of failed tests. - * - * Use: Performs the FIPS140 randomness tests on a block of data. - */ - -unsigned fipstest(const octet *p) -{ - unsigned rc = 0; - rc |= monobit(p); - rc |= poker(p); - rc |= runs(p); - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/fipstest.h b/fipstest.h deleted file mode 100644 index 1db305c..0000000 --- a/fipstest.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -*-c-*- - * - * $Id: fipstest.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * FIPS140 randomness tests - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_FIPSTEST_H -#define CATACOMB_FIPSTEST_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -/*----- Magic numbers -----------------------------------------------------*/ - -#define FIPSTEST_BUFSZ 2500 - -#define FIPSTEST_OK 0u -#define FIPSTEST_MONOBIT 1u -#define FIPSTEST_POKER 2u -#define FIPSTEST_RUNS 4u -#define FIPSTEST_LONGRUNS 8u - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @fipstest@ --- * - * - * Arguments: @const octet *p@ = pointer to a buffer of @FIPSTEST_BUFSZ@ - * bytes - * - * Returns: Zero if OK, or a bitmask of failed tests. - * - * Use: Performs the FIPS140 randomness tests on a block of data. - */ - -extern unsigned fipstest(const octet */*p*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/g-bin.c b/g-bin.c deleted file mode 100644 index bdae80a..0000000 --- a/g-bin.c +++ /dev/null @@ -1,179 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Abstraction for prime groups - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "mpmont.h" -#include "pgen.h" - -#define ge mp * -#include "group.h" -#include "group-guts.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Group operations --- */ - -static void gdestroygroup(group *gg) { - gctx_bin *g = (gctx_bin *)gg; - mp_drop(g->gen); mp_drop(g->g.r); mp_drop(g->g.h); - gfreduce_destroy(&g->r); - DESTROY(g); -} - -static mp **gcreate(group *gg) - { mp **x = CREATE(mp *); *x = MP_COPY(*gg->i); return (x); } - -static void gcopy(group *gg, mp **d, mp **x) - { mp *t = MP_COPY(*x); MP_DROP(*d); *d = t; } - -static void gburn(group *gg, mp **x) { (*x)->f |= MP_BURN; } - -static void gdestroy(group *gg, mp **x) { MP_DROP(*x); DESTROY(x); } - -static int gsamep(group *gg, group *hh) { - gctx_bin *g = (gctx_bin *)gg, *h = (gctx_bin *)hh; - return (MP_EQ(g->r.p, h->r.p)); -} - -static int geq(group *gg, mp **x, mp **y) { return (MP_EQ(*x, *y)); } - -static const char *gcheck(group *gg, grand *gr) { - gctx_bin *g = (gctx_bin *)gg; int rc; mp *t, *tt; - if (!gf_irreduciblep(g->r.p)) return ("p is not irreducible"); - t = mp_mul(MP_NEW, g->g.r, g->g.h); t = mp_add(t, t, MP_ONE); - tt = mp_lsl(MP_NEW, MP_ONE, g->g.nbits); - rc = MP_EQ(t, tt); MP_DROP(t); MP_DROP(tt); - if (!rc) return ("not a subgroup"); - return (group_stdcheck(gg, gr)); -} - -static void gmul(group *gg, mp **d, mp **x, mp **y) { - gctx_bin *g = (gctx_bin *)gg; mp *r = gf_mul(*d, *x, *y); - *d = gfreduce_do(&g->r, r, r); -} - -static void gsqr(group *gg, mp **d, mp **x) { - gctx_bin *g = (gctx_bin *)gg; mp *r = gf_sqr(*d, *x); - *d = gfreduce_do(&g->r, r, r); -} - -static void ginv(group *gg, mp **d, mp **x) - { gctx_bin *g = (gctx_bin *)gg; *d = gf_modinv(*d, *x, g->r.p); } - -static void gexp(group *gg, mp **d, mp **x, mp *n) - { gctx_bin *g = (gctx_bin *)gg; *d = gfreduce_exp(&g->r, *d, *x, n); } - -static int gread(group *gg, mp **d, const mptext_ops *ops, void *p) { - mp *t; if ((t = mp_read(MP_NEW, 0, ops, p)) == 0) return (-1); - mp_drop(*d); *d = t; return (0); -} - -static int gwrite(group *gg, mp **x, const mptext_ops *ops, void *p) { - int rc = -1; - if (!ops->put("0x", 2, p) && !mp_write(*x, 16, ops, p)) rc = 0; - return (rc); -} - -static mp *gtoint(group *gg, mp *d, mp **x) { return MP_COPY(*x); } - -static int gfromint(group *gg, mp **d, mp *x) { *d = MP_COPY(x); return 0; } - -static int gtobuf(group *gg, buf *b, mp **x) - { int rc = buf_putmp(b, *x); return (rc); } - -static int gfrombuf(group *gg, buf *b, mp **d) { - gctx_bin *g = (gctx_bin *)gg; mp *x; - if ((x = buf_getmp(b)) == 0) return (-1); - MP_DROP(*d); *d = gfreduce_do(&g->r, x, x); - return (0); -} - -static int gtoraw(group *gg, buf *b, mp **x) { - gctx_bin * g = (gctx_bin *)gg; octet *q; - if ((q = buf_get(b, g->g.noctets)) == 0) return (-1); - mp_storeb(*x, q, g->g.noctets); return (0); -} - -static int gfromraw(group *gg, buf *b, mp **d) { - gctx_bin * g = (gctx_bin *)gg; mp *x; octet *q; - if ((q = buf_get(b, g->g.noctets)) == 0) return (-1); - x = mp_loadb(MP_NEW, q, g->g.noctets); - MP_DROP(*d); *d = gfreduce_do(&g->r, x, x); - return (0); -} - -/* --- @group_binary@ --- * - * - * Arguments: @const gbin_param *gb@ = group parameters - * - * Returns: A pointer to the group, or null. - * - * Use: Constructs an abstract group interface for a subgroup of a - * prime field. Group elements are @mp *@ pointers. - */ - -static const group_ops gops = { - GTY_BINARY, "bin", - gdestroygroup, gcreate, gcopy, gburn, gdestroy, - gsamep, geq, group_stdidentp, - gcheck, - gmul, gsqr, ginv, group_stddiv, gexp, group_stdmexp, - gread, gwrite, - gtoint, gfromint, group_stdtoec, group_stdfromec, gtobuf, gfrombuf, - gtoraw, gfromraw -}; - -group *group_binary(const gbin_param *gb) -{ - gctx_bin *g; - mp *t; - - if (!MP_POSP(gb->p)) - return (0); - g = CREATE(gctx_bin); - g->g.ops = &gops; - g->g.nbits = mp_bits(gb->p) - 1; - g->g.noctets = (g->g.nbits + 7) >> 3; - gfreduce_create(&g->r, gb->p); - g->one = MP_ONE; - g->g.i = &g->one; - g->gen = MP_COPY(gb->g); - g->g.g = &g->gen; - g->g.r = MP_COPY(gb->q); - t = mp_lsl(MP_NEW, MP_ONE, g->g.nbits); - t = mp_sub(t, t, MP_ONE); - g->g.h = MP_NEW; mp_div(&g->g.h, 0, t, gb->q); - MP_DROP(t); - return (&g->g); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/g-ec.c b/g-ec.c deleted file mode 100644 index 4679742..0000000 --- a/g-ec.c +++ /dev/null @@ -1,218 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Abstraction for elliptic curve groups - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#define ge ec -#include "group.h" -#include "ec-raw.h" -#include "group-guts.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Group operations --- */ - -static void gdestroygroup(group *gg) { - gctx_ec *g = (gctx_ec *)gg; - EC_DESTROY(&g->gen); - ec_freeinfo(&g->ei); - DESTROY(g); -} - -static ec *gcreate(group *gg) - { ec *x = CREATE(ec); EC_CREATE(x); return (x); } - -static void gcopy(group *gg, ec *d, ec *x) { EC_COPY(d, x); } - -static void gburn(group *gg, ec *x) { if (x->x) (x->x)->f |= MP_BURN; } - -static void gdestroy(group *gg, ec *x) { EC_DESTROY(x); DESTROY(x); } - -static int gsamep(group *gg, group *hh) { - gctx_ec *g = (gctx_ec *)gg, *h = (gctx_ec *)hh; - return (ec_sameinfop(&g->ei, &h->ei)); -} - -static int geq(group *gg, ec *x, ec *y) { - gctx_ec *g = (gctx_ec *)gg; EC_FIX(g->ei.c, x, x); EC_FIX(g->ei.c, y, y); - return (EC_EQ(x, y)); -} - -static int gidentp(group *gg, ec *x) { return (EC_ATINF(x)); } - -static const char *gcheck(group *gg, grand *gr) - { gctx_ec *g = (gctx_ec *)gg; return (ec_checkinfo(&g->ei, gr)); } - -static void gmul(group *gg, ec *d, ec *x, ec *y) - { gctx_ec *g = (gctx_ec *)gg; EC_ADD(g->ei.c, d, x, y); } - -static void gsqr(group *gg, ec *d, ec *x) - { gctx_ec *g = (gctx_ec *)gg; EC_DBL(g->ei.c, d, x); } - -static void ginv(group *gg, ec *d, ec *x) - { gctx_ec *g = (gctx_ec *)gg; EC_NEG(g->ei.c, d, x); } - -static void gdiv(group *gg, ec *d, ec *x, ec *y) - { gctx_ec *g = (gctx_ec *)gg; EC_SUB(g->ei.c, d, x, y); } - -static void gexp(group *gg, ec *d, ec *x, mp *n) - { gctx_ec *g = (gctx_ec *)gg; ec_imul(g->ei.c, d, x, n); } - -static void gmexp(group *gg, ec *d, const group_expfactor *f, size_t n) { - gctx_ec *g = (gctx_ec *)gg; size_t i; - ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor)); - for (i = 0; i < n; i++) { ff[i].base = *f[i].base; ff[i].exp = f[i].exp; } - ec_immul(g->ei.c, d, ff, n); xfree(ff); -} - -static int gread(group *gg, ec *d, const mptext_ops *ops, void *p) { - gctx_ec *g = (gctx_ec *)gg; - ec t = EC_INIT; - int rc = -1; - int ch; - - ch = ops->get(p); - if (tolower(ch) == 'i') { - if (tolower(ops->get(p)) != 'n' || tolower(ops->get(p)) != 'f') - return (-1); - EC_SETINF(d); - return (0); - } - ops->unget(ch, p); - if ((t.x = mp_read(MP_NEW, 0, ops, p)) == 0) goto done; - do ch = ops->get(p); while (ch == ',' || isspace(ch)); ops->unget(ch, p); - if ((t.y = mp_read(MP_NEW, 0, ops, p)) == 0) goto done; - EC_IN(g->ei.c, &t, &t); - if (EC_CHECK(g->ei.c, &t)) goto done; - EC_COPY(d, &t); rc = 0; - EC_DESTROY(&t); -done: - return (rc); -} - -static int gwrite(group *gg, ec *x, const mptext_ops *ops, void *p) { - gctx_ec *g = (gctx_ec *)gg; int rc = -1; ec t = EC_INIT; - EC_OUT(g->ei.c, &t, x); if (EC_ATINF(&t)) rc = ops->put("inf", 3, p); - else if (!ops->put("0x", 2, p) && !mp_write(t.x, 16, ops, p) && - !ops->put(", 0x", 4, p) && !mp_write(t.y, 16, ops, p)) rc = 0; - EC_DESTROY(&t); return (rc); -} - -static mp *gtoint(group *gg, mp *d, ec *x) { - gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; mp *i; if (EC_ATINF(x)) i = 0; - else { EC_OUT(g->ei.c, &t, x); i = MP_COPY(t.x); EC_DESTROY(&t); } - mp_drop(d); return (i); -} - -static int gfromint(group *gg, ec *d, mp *x) { - gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; - if (!ec_find(g->ei.c, &t, x)) return (-1); - EC_IN(g->ei.c, d, &t); EC_DESTROY(&t); return (0); -} - -static int gtoec(group *gg, ec *d, ec *x) - { gctx_ec *g = (gctx_ec *)gg; EC_OUT(g->ei.c, d, x); return (0); } - -static int gfromec(group *gg, ec *d, const ec *x) { - gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; EC_IN(g->ei.c, &t, x); - rc = EC_CHECK(g->ei.c, &t); if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); - return (rc); -} - -static int gtobuf(group *gg, buf *b, ec *x) { - gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; - EC_OUT(g->ei.c, &t, x); rc = buf_putec(b, &t); EC_DESTROY(&t); return (rc); -} - -static int gfrombuf(group *gg, buf *b, ec *d) { - gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; - if (buf_getec(b, &t)) return (-1); - EC_IN(g->ei.c, &t, &t); rc = EC_CHECK(g->ei.c, &t); - if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); return (rc); -} - -static int gtoraw(group *gg, buf *b, ec *x) { - gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; - EC_OUT(g->ei.c, &t, x); rc = ec_putraw(g->ei.c, b, &t); - EC_DESTROY(&t); return (rc); -} - -static int gfromraw(group *gg, buf *b, ec *d) { - gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; - if (ec_getraw(g->ei.c, b, &t)) return (-1); - EC_IN(g->ei.c, &t, &t); rc = EC_CHECK(g->ei.c, &t); - if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); return (rc); -} - -/* --- @group_ec@ --- * - * - * Arguments: @const ec_info *ei@ = elliptic curve parameters - * - * Returns: A pointer to the group. - * - * Use: Constructs an abstract group interface for an elliptic curve - * group. Group elements are @ec@ structures. The contents of - * the @ec_info@ structure becomes the property of the @group@ - * object; you can (and should) free the structure itself, but - * calling @ec_freeinfo@ on it is not allowed. - */ - -static const group_ops gops = { - GTY_EC, "ec", - gdestroygroup, gcreate, gcopy, gburn, gdestroy, - gsamep, geq, gidentp, - gcheck, - gmul, gsqr, ginv, gdiv, gexp, gmexp, - gread, gwrite, - gtoint, gfromint, gtoec, gfromec, gtobuf, gfrombuf, gtoraw, gfromraw -}; - -group *group_ec(const ec_info *ei) -{ - gctx_ec *g = CREATE(gctx_ec); - - g->g.ops = &gops; - g->g.nbits = ei->c->f->nbits * 2; - g->g.noctets = ei->c->f->noctets * 2 + 1; - g->ei = *ei; - EC_CREATE(&g->id); - g->g.i = &g->id; - EC_CREATE(&g->gen); - g->g.g = &g->gen; - EC_IN(g->ei.c, &g->gen, &ei->g); - g->g.r = ei->r; - g->g.h = ei->h; - return (&g->g); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/g-prime.c b/g-prime.c deleted file mode 100644 index 5230111..0000000 --- a/g-prime.c +++ /dev/null @@ -1,190 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Abstraction for prime groups - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "mpmont.h" -#include "pgen.h" - -#define ge mp * -#include "group.h" -#include "group-guts.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Group operations --- */ - -static void gdestroygroup(group *gg) { - gctx_prime *g = (gctx_prime *)gg; - mp_drop(g->gen); mp_drop(g->g.r); mp_drop(g->g.h); - mpmont_destroy(&g->mm); - DESTROY(g); -} - -static mp **gcreate(group *gg) - { mp **x = CREATE(mp *); *x = MP_COPY(*gg->i); return (x); } - -static void gcopy(group *gg, mp **d, mp **x) - { mp *t = MP_COPY(*x); MP_DROP(*d); *d = t; } - -static void gburn(group *gg, mp **x) { (*x)->f |= MP_BURN; } - -static void gdestroy(group *gg, mp **x) { MP_DROP(*x); DESTROY(x); } - -static int gsamep(group *gg, group *hh) { - gctx_prime *g = (gctx_prime *)gg, *h = (gctx_prime *)hh; - return (MP_EQ(g->mm.m, h->mm.m)); -} - -static int geq(group *gg, mp **x, mp **y) { return (MP_EQ(*x, *y)); } - -static const char *gcheck(group *gg, grand *gr) { - gctx_prime *g = (gctx_prime *)gg; int rc; mp *t; - if (!pgen_primep(g->mm.m, gr)) return ("p is not prime"); - t = mp_mul(MP_NEW, g->g.r, g->g.h); t = mp_add(t, t, MP_ONE); - rc = MP_EQ(t, g->mm.m); MP_DROP(t); if (!rc) return ("not a subgroup"); - return (group_stdcheck(gg, gr)); -} - -static void gmul(group *gg, mp **d, mp **x, mp **y) - { gctx_prime *g = (gctx_prime *)gg; *d = mpmont_mul(&g->mm, *d, *x, *y); } - -static void gsqr(group *gg, mp **d, mp **x) { - gctx_prime *g = (gctx_prime *)gg; mp *r = mp_sqr(*d, *x); - *d = mpmont_reduce(&g->mm, r, r); -} - -static void ginv(group *gg, mp **d, mp **x) { - gctx_prime *g = (gctx_prime *)gg; mp *r = mpmont_reduce(&g->mm, *d, *x); - r = mp_modinv(r, r, g->mm.m); *d = mpmont_mul(&g->mm, r, r, g->mm.r2); -} - -static void gexp(group *gg, mp **d, mp **x, mp *n) - { gctx_prime *g = (gctx_prime *)gg; *d = mpmont_expr(&g->mm, *d, *x, n); } - -static void gmexp(group *gg, mp **d, const group_expfactor *f, size_t n) { - gctx_prime *g = (gctx_prime *)gg; size_t i; - mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor)); - for (i = 0; i < n; i++) { ff[i].base = *f[i].base; ff[i].exp = f[i].exp; } - *d = mpmont_mexpr(&g->mm, *d, ff, n); xfree(ff); -} - -static int gread(group *gg, mp **d, const mptext_ops *ops, void *p) { - gctx_prime *g = (gctx_prime *)gg; mp *t; - if ((t = mp_read(MP_NEW, 0, ops, p)) == 0) return (-1); - mp_drop(*d); *d = mpmont_mul(&g->mm, t, t, g->mm.r2); return (0); -} - -static int gwrite(group *gg, mp **x, const mptext_ops *ops, void *p) { - gctx_prime *g = (gctx_prime *)gg; - mp *t = mpmont_reduce(&g->mm, MP_NEW, *x); - int rc = mp_write(t, 10, ops, p); MP_DROP(t); return (rc); -} - -static mp *gtoint(group *gg, mp *d, mp **x) { - gctx_prime *g = (gctx_prime *)gg; - return (mpmont_reduce(&g->mm, d, *x)); -} - -static int gfromint(group *gg, mp **d, mp *x) { - gctx_prime *g = (gctx_prime *)gg; mp_div(0, d, x, g->mm.m); - *d = mpmont_mul(&g->mm, *d, *d, g->mm.r2); return (0); -} - -static int gtobuf(group *gg, buf *b, mp **x) { - gctx_prime *g = (gctx_prime *)gg; - mp *t = mpmont_reduce(&g->mm, MP_NEW, *x); - int rc = buf_putmp(b, t); MP_DROP(t); return (rc); -} - -static int gfrombuf(group *gg, buf *b, mp **d) { - gctx_prime * g = (gctx_prime *)gg; mp *x; - if ((x = buf_getmp(b)) == 0) return (-1); - mp_div(0, &x, x, g->mm.m); mp_drop(*d); - *d = mpmont_mul(&g->mm, x, x, g->mm.r2); return(0); -} - -static int gtoraw(group *gg, buf *b, mp **x) { - gctx_prime *g = (gctx_prime *)gg; octet *q; - mp *t = mpmont_reduce(&g->mm, MP_NEW, *x); - if ((q = buf_get(b, g->g.noctets)) == 0) { MP_DROP(t); return (-1); } - mp_storeb(t, q, g->g.noctets); MP_DROP(t); return (0); -} - -static int gfromraw(group *gg, buf *b, mp **d) { - gctx_prime * g = (gctx_prime *)gg; mp *x; octet *q; - if ((q = buf_get(b, g->g.noctets)) == 0) return (-1); - x = mp_loadb(MP_NEW, q, g->g.noctets); - mp_div(0, &x, x, g->mm.m); mp_drop(*d); - *d = mpmont_mul(&g->mm, x, x, g->mm.r2); return(0); -} - -/* --- @group_prime@ --- * - * - * Arguments: @const gprime_param *gp@ = group parameters - * - * Returns: A pointer to the group, or null. - * - * Use: Constructs an abstract group interface for a subgroup of a - * prime field. Group elements are @mp *@ pointers. - */ - -static const group_ops gops = { - GTY_PRIME, "prime", - gdestroygroup, gcreate, gcopy, gburn, gdestroy, - gsamep, geq, group_stdidentp, - gcheck, - gmul, gsqr, ginv, group_stddiv, gexp, gmexp, - gread, gwrite, - gtoint, gfromint, group_stdtoec, group_stdfromec, gtobuf, gfrombuf, - gtoraw, gfromraw -}; - -group *group_prime(const gprime_param *gp) -{ - gctx_prime *g; - - if (!MP_POSP(gp->p) || !MP_ODDP(gp->p)) - return (0); - g = CREATE(gctx_prime); - g->g.ops = &gops; - g->g.nbits = mp_bits(gp->p); - g->g.noctets = (g->g.nbits + 7) >> 3; - mpmont_create(&g->mm, gp->p); - g->g.i = &g->mm.r; - g->gen = mpmont_mul(&g->mm, MP_NEW, gp->g, g->mm.r2); - g->g.g = &g->gen; - g->g.r = MP_COPY(gp->q); - g->g.h = MP_NEW; mp_div(&g->g.h, 0, gp->p, gp->q); - return (&g->g); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gcipher.h b/gcipher.h deleted file mode 100644 index 5682738..0000000 --- a/gcipher.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -*-c-*- - * - * $Id: gcipher.h,v 1.5 2004/04/21 00:37:32 mdw Exp $ - * - * Generic symmetric cipher interface - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GCIPHER_H -#define CATACOMB_GCIPHER_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#ifndef CATACOMB_KEYSZ_H -# include "keysz.h" -#endif - -/*----- Generic symmetric cipher interface --------------------------------*/ - -typedef struct gcipher { - const struct gcipher_ops *ops; /* Pointer to cipher operations */ -} gcipher; - -typedef struct gcipher_ops { - const struct gccipher *c; /* Pointer to cipher class */ - void (*encrypt)(gcipher */*c*/, const void */*s*/, - void */*t*/, size_t /*sz*/); - void (*decrypt)(gcipher */*c*/, const void */*s*/, - void */*t*/, size_t /*sz*/); - void (*destroy)(gcipher */*c*/); - void (*setiv)(gcipher */*c*/, const void */*iv*/); - void (*bdry)(gcipher */*c*/); -} gcipher_ops; - -typedef struct gccipher { - const char *name; /* Cipher name */ - const octet *keysz; /* Preferred key size table */ - size_t blksz; /* Block size or zero if none */ - gcipher *(*init)(const void */*k*/, size_t /*sz*/); -} gccipher; - -#define GC_INIT(cc, k, sz) (cc)->init((k), (sz)) -#define GC_CLASS(cc) (cc)->ops->c -#define GC_ENCRYPT(c, s, t, sz) (c)->ops->encrypt((c), (s), (t), (sz)) -#define GC_DECRYPT(c, s, t, sz) (c)->ops->decrypt((c), (s), (t), (sz)) -#define GC_DESTROY(c) (c)->ops->destroy((c)) -#define GC_SETIV(c, iv) (c)->ops->setiv((c), (iv)) -#define GC_BDRY(c) (c)->ops->bdry((c)) - -/*----- Tables ------------------------------------------------------------*/ - -extern const gccipher *const gciphertab[]; - -/* --- @gcipher_byname@ --- * - * - * Arguments: @const char *p@ = pointer to name string - * - * Returns: The named cipher class, or null. - */ - -extern const gccipher *gcipher_byname(const char */*p*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/gdsa.c b/gdsa.c deleted file mode 100644 index 1f5dac7..0000000 --- a/gdsa.c +++ /dev/null @@ -1,257 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Generalized version of DSA - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "dsa.h" -#include "gdsa.h" -#include "group.h" -#include "ghash.h" -#include "mpbarrett.h" -#include "mprand.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @gdsa_beginhash@ --- * - * - * Arguments: @const gdsa *c@ = pointer to the context structure - * - * Returns: A hashing context for you to hash the message. - * - * Use: Initializes a hash function correctly for you to hash a - * message. Requires @h@. - */ - -ghash *gdsa_beginhash(const gdsa *c) { return (GH_INIT(c->h)); } - -/* --- @gdsa_endhash@ --- * - * - * Arguments: @const gdsa *c@ = pointer to the context structure - * @ghash *h@ = the hashing context - * - * Returns: --- - * - * Use: Does any final thing that DSA wants to do when hashing a - * message. (Actually, there's nothing.) The hashing context - * isn't finalized. - */ - -void gdsa_endhash(const gdsa *c, ghash *h) { ; } - -/* --- @gdsa_sign@ --- * - * - * Arguments: @const gdsa *c@ = my context structure - * @gdsa_sig *s@ = where to put the signature (initialized) - * @const void *m@ = pointer to message hash - * @mp *k@ = random exponent for this message or null - * - * Returns: --- - * - * Use: Signs a message. Requires @g@, @u@, @h@, and @r@ if @k@ is - * null. This is a better idea than inventing @k@ yourself. - */ - -void gdsa_sign(const gdsa *c, gdsa_sig *s, const void *m, mp *k) -{ - group *g = c->g; - mp *mr = dsa_h2n(MP_NEW, g->r, m, c->h->hashsz); - ge *z = G_CREATE(g); - mp *sr = s->r, *ss = s->s; - mpbarrett b; - - if (k) { MP_COPY(k); goto have_k; } -new_k: - k = mprand_range(k, g->r, c->r, 0); -have_k: - if (MP_ZEROP(k)) goto new_k; - G_EXP(g, z, g->g, k); - sr = G_TOINT(g, sr, z); assert(sr); - if (MP_ZEROP(sr)) goto new_k; - - mp_div(0, &sr, sr, g->r); - mpbarrett_create(&b, g->r); - ss = mp_mul(ss, sr, c->u); ss = mpbarrett_reduce(&b, ss, ss); - ss = mp_add(ss, ss, mr); mp_div(0, &ss, ss, g->r); - k = mp_modinv(k, k, g->r); - ss = mp_mul(ss, ss, k); ss = mpbarrett_reduce(&b, ss, ss); - s->r = sr; s->s = ss; - mp_drop(k); mp_drop(mr); mpbarrett_destroy(&b); G_DESTROY(g, z); -} - -/* --- @gdsa_verify@ --- * - * - * Arguments: @const gdsa *c@ = my context structure - * @const gdsa_sig *s@ = the signature to verify - * @const void *m@ = pointer to message hash - * - * Returns: Zero if OK, negative on failure. - * - * Use: Checks a signature on a message, Requires @g@, @p@ and @h@. - */ - -int gdsa_verify(const gdsa *c, const gdsa_sig *s, const void *m) -{ - group *g = c->g; - group_expfactor e[2]; - mpbarrett b; - mp *h, *t; - ge *w; - int rc = -1; - - if (MP_CMP(s->r, <, MP_ONE) || MP_CMP(s->r, >=, g->r) || - MP_CMP(s->s, <, MP_ONE) || MP_CMP(s->s, >=, g->r)) - return (-1); - mpbarrett_create(&b, g->r); h = mp_modinv(MP_NEW, s->s, g->r); - e[0].base = g->g; e[1].base = c->p; - t = dsa_h2n(MP_NEW, g->r, m, c->h->hashsz); mp_div(0, &t, t, g->r); - t = mp_mul(t, t, h); e[0].exp = t = mpbarrett_reduce(&b, t, t); - h = mp_mul(h, s->r, h); e[1].exp = h = mpbarrett_reduce(&b, h, h); - w = G_CREATE(g); G_MEXP(g, w, e, 2); - t = G_TOINT(g, t, w); if (!t) goto done; - mp_div(0, &t, t, g->r); if (MP_EQ(t, s->r)) rc = 0; -done: - G_DESTROY(g, w); mp_drop(t); mp_drop(h); mpbarrett_destroy(&b); - return (rc); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static group *getgroup(const char *p) { - group *g; qd_parse qd; - qd.p = p; qd.e = 0; g = group_parse(&qd); - if (g && !qd_eofp(&qd)) { G_DESTROYGROUP(g); g = 0; qd.e = "junk at eof"; } - if (!g) { fprintf(stderr, "bad group string `%.*s|%s': %s\n", qd.p - p, - p, qd.p, qd.e); exit(1); } - return (g); -} - -static ge *getge(group *g, const char *p) { - ge *x = G_CREATE(g); - if (group_readstring(g, x, p, 0)) { - fprintf(stderr, "bad group element `%s'\n", p); - exit(1); - } - return (x); -} - -static void showge(group *g, const char *p, ge *x) { - fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr); - putc('\n', stderr); -} - -static void showmp(const char *p, mp *x, int r) { - fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r); - putc('\n', stderr); -} - -static int tsign(dstr *v) -{ - gdsa c; - gdsa_sig s, ss = GDSA_SIG_INIT; - ghash *h; - mp *k; - int ok = 1; - - c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf); - c.u = *(mp **)v[2].buf; k = *(mp **)v[4].buf; - s.r = *(mp **)v[5].buf; s.s = *(mp **)v[6].buf; - - h = gdsa_beginhash(&c); - GH_HASH(h, v[3].buf, v[3].len); - gdsa_endhash(&c, h); - gdsa_sign(&c, &ss, GH_DONE(h, 0), k); - if (!MP_EQ(s.r, ss.r) || !MP_EQ(s.s, ss.s)) { - ok = 0; - fprintf(stderr, "*** sign failed!\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - fprintf(stderr, "*** hash: %s\n", c.h->name); - showmp("private key", c.u, 16); - fprintf(stderr, "*** message: `%s'\n", v[3].buf); - showmp("computed r", ss.r, 16); showmp("computed s", ss.s, 16); - showmp("expected r", s.r, 16); showmp("expected s", s.s, 16); - } - mp_drop(s.r); mp_drop(s.s); mp_drop(ss.r); mp_drop(ss.s); - mp_drop(k); mp_drop(c.u); G_DESTROYGROUP(c.g); GH_DESTROY(h); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tverify(dstr *v) -{ - gdsa c; - gdsa_sig s; - ghash *h; - int rc, erc; - int ok = 1; - - c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf); - c.p = getge(c.g, v[2].buf); - s.r = *(mp **)v[4].buf; s.s = *(mp **)v[5].buf; - erc = *(int *)v[6].buf; - - h = gdsa_beginhash(&c); - GH_HASH(h, v[3].buf, v[3].len); - gdsa_endhash(&c, h); - rc = gdsa_verify(&c, &s, GH_DONE(h, 0)); - if (!rc != !erc) { - ok = 0; - fprintf(stderr, "*** verify failed!\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - fprintf(stderr, "*** hash: %s\n", c.h->name); - showge(c.g, "public key", c.p); - fprintf(stderr, "*** message: `%s'\n", v[3].buf); - showmp("sig r", s.r, 16); showmp("sig s", s.s, 16); - fprintf(stderr, "*** expected %s\n", !erc ? "pass" : "fail"); - } - mp_drop(s.r); mp_drop(s.s); G_DESTROY(c.g, c.p); G_DESTROYGROUP(c.g); - GH_DESTROY(h); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static const test_chunk tests[] = { - { "sign", tsign, { &type_string, &type_string, &type_mp, &type_string, - &type_mp, &type_mp, &type_mp } }, - { "verify", tverify, { &type_string, &type_string, &type_string, - &type_string, &type_mp, &type_mp, &type_int } }, - { 0 } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/gdsa"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gdsa.h b/gdsa.h deleted file mode 100644 index f673b70..0000000 --- a/gdsa.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Generalized version of DSA - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GDSA_H -#define CATACOMB_GDSA_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -#ifndef CATACOMB_GROUP_H -# include "group.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- GDSA context --- * - * - * You don't need to fill in all of this stuff. See the description of the - * function you want to use to find out what members are needed. - */ - -typedef struct gdsa { - group *g; /* The group we work in */ - mp *u; /* Private key, for signing */ - ge *p; /* Public key, for verifying */ - grand *r; /* Random number source */ - const gchash *h; /* Hash function */ -} gdsa; - -/* --- GDSA signatures --- */ - -typedef struct gdsa_sig { mp *r, *s; } gdsa_sig; -#define GDSA_SIG_INIT { MP_NEW, MP_NEW } - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @gdsa_beginhash@ --- * - * - * Arguments: @const gdsa *c@ = pointer to the context structure - * - * Returns: A hashing context for you to hash the message. - * - * Use: Initializes a hash function correctly for you to hash a - * message. Requires @h@. - */ - -extern ghash *gdsa_beginhash(const gdsa */*c*/); - -/* --- @gdsa_endhash@ --- * - * - * Arguments: @const gdsa *c@ = pointer to the context structure - * @ghash *h@ = the hashing context - * - * Returns: --- - * - * Use: Does any final thing that DSA wants to do when hashing a - * message. (Actually, there's nothing.) The hashing context - * isn't finalized. - */ - -extern void gdsa_endhash(const gdsa */*c*/, ghash */*h*/); - -/* --- @gdsa_sign@ --- * - * - * Arguments: @const gdsa *c@ = my context structure - * @gdsa_sig *s@ = where to put the signature (initialized) - * @const void *m@ = pointer to message hash - * @mp *k@ = random exponent for this message or null - * - * Returns: --- - * - * Use: Signs a message. Requires @g@, @u@, @h@, and @r@ if @k@ is - * null. This is a better idea than inventing @k@ yourself. - */ - -extern void gdsa_sign(const gdsa */*c*/, gdsa_sig */*s*/, - const void */*m*/, mp */*k*/); - -/* --- @gdsa_verify@ --- * - * - * Arguments: @const gdsa *c@ = my context structure - * @const gdsa_sig *s@ = the signature to verify - * @const void *m@ = pointer to message hash - * - * Returns: Zero if OK, negative on failure. - * - * Use: Checks a signature on a message, Requires @g@, @p@, @h@. - */ - -extern int gdsa_verify(const gdsa */*c*/, const gdsa_sig */*s*/, - const void */*m*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/genlimits.c b/genlimits.c deleted file mode 100644 index 6bd0e98..0000000 --- a/genlimits.c +++ /dev/null @@ -1,282 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Generate limit MPs for C types - * - * (c) 2006 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _GNU_SOURCE -#include -#include -#include -#include - -#if __STDC_VERSION__ >= 199900l -# include -# include -#endif - -#include "mp.h" -#include "mpint.h" - -/*----- Data types --------------------------------------------------------*/ - -/* --- Hack for GCC --- * - * - * WG14 in their infinite wisdom decided not to use the GCC constant name. - */ - -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91) -# define EXT __extension__ -#else -# define EXT -#endif - -#if defined(LONG_LONG_MIN) && !defined(LLONG_MIN) -# define LLONG_MIN EXT LONG_LONG_MIN -#endif - -#if defined(LONG_LONG_MAX) && !defined(LLONG_MAX) -# define LLONG_MAX EXT LONG_LONG_MAX -#endif - -#if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX) -# define ULLONG_MAX EXT ULONG_LONG_MAX -#endif - -/* --- Choose the largest integer type --- */ - -#if defined(INTMAX_MAX) - typedef intmax_t imax; -#elif defined(LLONG_MAX) - EXT typedef long long imax; -#else - typedef long imax; -#endif - -#if defined(UINTMAX_MAX) - typedef uintmax_t umax; -#elif defined(ULLONG_MAX) - EXT typedef unsigned long long umax; -#else - typedef unsigned long umax; -#endif - -/*----- Main code ---------------------------------------------------------*/ - -#define TABSZ 64 - -enum { NEG, POS, NSIGN }; - -umax cmap[TABSZ]; -int gmap[TABSZ][NSIGN]; -struct { int g, s; } qmap[TABSZ]; -int dumpp = 0; - -static int n, q; - -static void dump(mp *x) -{ - int i, w, n; - - fputs(" ", stdout); - w = (MPW_BITS + 3)/4; - n = 1; - while (2 + 2 * n * (4 + w) < 72) n <<= 1; - i = 0; - for (;;) { - printf("0x%0*x", w, x->v[i]); - i++; - if (i >= MP_LEN(x)) break; - fputs(",", stdout); - if (i % n) fputs(" ", stdout); else fputs("\n ", stdout); - } - fputs("\n", stdout); -} - -static void doemit(umax c, int s, int *gg, int *qq) -{ - int i; - mp *x = MP_NEW; - - for (i = 0; i < n; i++) { - if (cmap[i] == c) - goto found; - } - - assert(i < TABSZ); - n = i + 1; - cmap[i] = c; - gmap[i][POS] = gmap[i][NEG] = -1; - if (dumpp) { - MP_FROMINT(x, umax, c); - printf("static mpw guts_%d[] = {\n", q); - dump(x); - fputs("};\n\n", stdout); - MP_DROP(x); - } - -found: - *gg = i; - if (gmap[i][s] < 0) { - assert(q < TABSZ); - gmap[i][s] = q; - qmap[q].g = i; - qmap[q].s = s; - q++; - } - *qq = gmap[i][s]; -} - -static void emit(imax c, int *gg, int *qq) -{ - umax uc; - int s; - - if (c >= 0) { uc = c; s = POS; } - else { uc = -c; s = NEG; } - doemit(uc, s, gg, qq); -} - -static void uemit(umax c, int *gg, int *qq) { doemit(c, POS, gg, qq); } - -struct { - const char *name; - imax min; - umax max; - int gmin, gmax; - int qmin, qmax; -} tab[] = { - { "SCHAR", SCHAR_MIN, SCHAR_MAX }, - { "CHAR", CHAR_MIN, CHAR_MAX }, - { "UCHAR", 0, UCHAR_MAX }, - { "UINT8", 0, 0xff }, - { "SHRT", SHRT_MIN, SHRT_MAX }, - { "USHRT", 0, USHRT_MAX }, - { "UINT16", 0, 0xffff }, - { "INT", INT_MIN, INT_MAX }, - { "UINT", 0, UINT_MAX }, - { "LONG", LONG_MIN, LONG_MAX }, - { "ULONG", 0, ULONG_MAX }, - { "UINT32", 0, 0xffffffff }, -#ifdef LLONG_MAX - { "LLONG", LLONG_MIN, LLONG_MAX }, - { "ULLONG", 0, ULLONG_MAX }, -#endif - { "SIZET", 0, ~(size_t)0 }, - { 0 } -}; - -static void dogen(void) -{ - int i; - - for (i = 0; tab[i].name; i++) { - if (tab[i].min) - emit(tab[i].min, &tab[i].gmin, &tab[i].qmin); - uemit(tab[i].max, &tab[i].gmax, &tab[i].qmax); - } -} - -static void cgen(void) -{ - int i; - - fputs("\ -/* -*-c-*-\n\ - *\n\ - * C integer limits [generated]\n\ - */\n\ -\n\ -#include \"mplimits.h\"\n\ -\n\ -#define N(x) (sizeof(x)/sizeof(*x))\n\ -#define MPpos(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }\n\ -#define MPneg(x) { x, x + N(x), N(x), 0, MP_CONST|MP_NEG, 0 }\n\ -\n", - stdout); - dumpp = 1; - dogen(); - - fputs("mp mp_limits[] = {\n", stdout); - for (i = 0; i < q; i++) - printf(" MP%s(guts_%d),\n", qmap[i].s ? "pos" : "neg", qmap[i].g); - fputs("};\n", stdout); -} - -static void hgen(void) -{ - int i; - - fputs("\ -/* -*-c-*-\n\ - *\n\ - * C integer limits [generated]\n\ - */\n\ -\n\ -#ifndef CATACOMB_MPLIMITS_H\n\ -#define CATACOMB_MPLIMITS_H\n\ -\n\ -#ifndef CATACOMB_MP_H\n\ -# include \"mp.h\"\n\ -#endif\n\ -\n\ -extern mp mp_limits[];\n\ -\n", - stdout); - dogen(); - - for (i = 0; tab[i].name; i++) { - if (tab[i].min) { - printf("#define MP_%s_MIN (&mp_limits[%d])\n", - tab[i].name, gmap[tab[i].qmin][NEG]); - } - printf("#define MP_%s_MAX (&mp_limits[%d])\n", - tab[i].name, gmap[tab[i].qmax][POS]); - } - fputs("\n#endif\n", stdout); -} - -int main(int argc, char *argv[]) -{ - const char *what = argc == 2 ? argv[1] : ""; - - switch (what[0]) { - case 'c': cgen(); break; - case 'h': hgen(); break; - default: - fprintf(stderr, "unknown action `%s'\n", what); - exit(1); - } - if (fflush(stdout) || fclose(stdout)) { - fprintf(stderr, "error writing output: %s\n", strerror(errno)); - exit(1); - } - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/genprimes.c b/genprimes.c deleted file mode 100644 index 2d80d07..0000000 --- a/genprimes.c +++ /dev/null @@ -1,193 +0,0 @@ -/* -*-c-*- - * - * $Id: genprimes.c,v 1.7 2004/04/08 01:36:15 mdw Exp $ - * - * Generate prime number table - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/*----- Data structures ---------------------------------------------------*/ - -DA_DECL(intv, int); - -/*----- Main code ---------------------------------------------------------*/ - -int main(int argc, char *argv[]) -{ - int p_max = 0, p_n = 0; - char *type = "unsigned int"; - char *header = "primetab.h"; - char *source = "primetab.c"; - char *name = "primetab"; - char *sym = 0; - intv p = DA_INIT; - int i; - - ego(argv[0]); - - for (;;) { - int i = getopt(argc, argv, "h:c:i:n:m:t:s:"); - if (i < 0) - break; - switch (i) { - case 'h': - header = optarg; - break; - case 'c': - source = optarg; - break; - case 'i': - name = optarg; - break; - case 'n': - p_max = 0; - p_n = atoi(optarg); - break; - case 'm': - p_n = 0; - p_max = atoi(optarg); - break; - case 't': - type = optarg; - break; - case 's': - sym = optarg; - break; - default: - pquis(stderr, "Usage: $ [-n nprimes] [-m maxprime] [-t type]\n"); - exit(EXIT_FAILURE); - } - } - - if (!p_max && !p_n) - die(EXIT_FAILURE, "bad arguments to `-n' or `-m'"); - - if (p_n || p_max >= 2) - DA_PUSH(&p, 2); - for (i = 3; (!p_max && !p_n) || - (p_n && DA_LEN(&p) < p_n) || - (p_max && i <= p_max); - i += 2) { - int j; - for (j = 0; j < DA_LEN(&p); j++) { - if (i % DA(&p)[j] == 0) - goto composite; - } - DA_PUSH(&p, i); - composite:; - } - - { - FILE *fp = fopen(header, "w"); - dstr d = DSTR_INIT; - char *q; - if (!fp) - die(EXIT_FAILURE, "couldn't write `%s': %s", header, strerror(errno)); - if (!sym) { - for (q = header; *q; q++) { - int ch = (unsigned char)*q; - if (isalnum(ch)) - ch = toupper(ch); - else - ch = '_'; - DPUTC(&d, ch); - } - DPUTZ(&d); - sym = d.buf; - } - fprintf(fp, "\ -/* -*-c-*-\n\ - *\n\ - * Table of small prime numbers [generated]\n\ - */\n\ -\n\ -#ifndef %s\n\ -#define %s\n\ -\n\ -#define NPRIME %luu\n\ -#define MAXPRIME %uu\n\ -\n\ -typedef %s smallprime;\n\ -extern const smallprime %s[];\n\ -\n\ -#endif\n\ -", - sym, sym, - (unsigned long)DA_LEN(&p), - DA_LAST(&p), - type, name); - dstr_destroy(&d); - if (fclose(fp) == EOF) { - remove(header); - die(EXIT_FAILURE, "error writing `%s': %s", header, strerror(errno)); - } - } - - { - FILE *fp = fopen(source, "w"); - int i; - if (!fp) - die(EXIT_FAILURE, "couldn't write `%s': %s", source, strerror(errno)); - fprintf(fp, "\ -/* -*-c-*-\n\ - *\n\ - * Table of small prime numbers [generated]\n\ - */\n\ -\n\ -#include \"%s\"\n\ -\n\ -const %s %s[] = {", - header, type, name); - for (i = 0; i < DA_LEN(&p); i++) { - if (i % 8 == 0) - fputs("\n ", fp); - fprintf(fp, "%5i, ", DA(&p)[i]); - } - fputs("\n\ -};\n\ -", fp); - if (fclose(fp) == EOF) { - remove(source); - die(EXIT_FAILURE, "error writing `%s': %s", source, strerror(errno)); - } - } - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gf-arith.c b/gf-arith.c deleted file mode 100644 index 5a7b3f2..0000000 --- a/gf-arith.c +++ /dev/null @@ -1,309 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Basic arithmetic on binary polynomials - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "gf.h" - -/*----- Macros ------------------------------------------------------------*/ - -#define MAX(x, y) ((x) >= (y) ? (x) : (y)) - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @gf_add@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: Result, @a@ added to @b@. - */ - -mp *gf_add(mp *d, mp *a, mp *b) -{ - MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)), (a->f | b->f) & MP_BURN); - gfx_add(d->v, d->vl, a->v, a->vl, b->v, b->vl); - d->f = (a->f | b->f) & MP_BURN; - MP_SHRINK(d); - return (d); -} - -/* --- @gf_mul@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: Result, @a@ multiplied by @b@. - */ - -mp *gf_mul(mp *d, mp *a, mp *b) -{ - a = MP_COPY(a); - b = MP_COPY(b); - - if (MP_LEN(a) <= MPK_THRESH || MP_LEN(b) <= GFK_THRESH) { - MP_DEST(d, MP_LEN(a) + MP_LEN(b), a->f | b->f | MP_UNDEF); - gfx_mul(d->v, d->vl, a->v, a->vl, b->v, b->vl); - } else { - size_t m = MAX(MP_LEN(a), MP_LEN(b)); - mpw *s; - MP_DEST(d, 2 * m, a->f | b->f | MP_UNDEF); - s = mpalloc(d->a, 3 * m); - gfx_kmul(d->v, d->vl, a->v, a->vl, b->v, b->vl, s, s + 3 * m); - mpfree(d->a, s); - } - - d->f = (a->f | b->f) & MP_BURN; - MP_SHRINK(d); - MP_DROP(a); - MP_DROP(b); - return (d); -} - -/* --- @gf_sqr@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = source - * - * Returns: Result, @a@ squared. - */ - -mp *gf_sqr(mp *d, mp *a) -{ - MP_COPY(a); - MP_DEST(d, 2 * MP_LEN(a), a->f & MP_BURN); - gfx_sqr(d->v, d->vl, a->v, a->vl); - d->f = a->f & MP_BURN; - MP_SHRINK(d); - MP_DROP(a); - return (d); -} - -/* --- @gf_div@ --- * - * - * Arguments: @mp **qq, **rr@ = destination, quotient and remainder - * @mp *a, *b@ = sources - * - * Use: Calculates the quotient and remainder when @a@ is divided by - * @b@. The destinations @*qq@ and @*rr@ must be distinct. - * Either of @qq@ or @rr@ may be null to indicate that the - * result is irrelevant. (Discarding both results is silly.) - * There is a performance advantage if @a == *rr@. - */ - -void gf_div(mp **qq, mp **rr, mp *a, mp *b) - { - mp *r = rr ? *rr : MP_NEW; - mp *q = qq ? *qq : MP_NEW; - - /* --- Set the remainder up right --- */ - - b = MP_COPY(b); - a = MP_COPY(a); - if (r) - MP_DROP(r); - r = a; - MP_DEST(r, MP_LEN(b) + 2, a->f | b->f); - - /* --- Fix up the quotient too --- */ - - r = MP_COPY(r); - MP_DEST(q, MP_LEN(r), r->f | MP_UNDEF); - MP_DROP(r); - - /* --- Perform the calculation --- */ - - gfx_div(q->v, q->vl, r->v, r->vl, b->v, b->vl); - - /* --- Sort out the sign of the results --- * - * - * If the signs of the arguments differ, and the remainder is nonzero, I - * must add one to the absolute value of the quotient and subtract the - * remainder from @b@. - */ - - q->f = (r->f | b->f) & MP_BURN; - r->f = (r->f | b->f) & MP_BURN; - - /* --- Store the return values --- */ - - MP_DROP(b); - - if (!qq) - MP_DROP(q); - else { - MP_SHRINK(q); - *qq = q; - } - - if (!rr) - MP_DROP(r); - else { - MP_SHRINK(r); - *rr = r; - } -} - -/* --- @gf_irreduciblep@ --- * - * - * Arguments: @mp *f@ = a polynomial - * - * Returns: Nonzero if the polynomial is irreducible; otherwise zero. - */ - -int gf_irreduciblep(mp *f) -{ - unsigned long m; - mp *u = MP_TWO; - mp *v = MP_NEW; - - if (MP_ZEROP(f)) - return (0); - else if (MP_LEN(f) == 1) { - if (f->v[0] < 2) return (0); - if (f->v[0] < 4) return (1); - } - m = (mp_bits(f) - 1)/2; - while (m) { - u = gf_sqr(u, u); - gf_div(0, &u, u, f); - v = gf_add(v, u, MP_TWO); - gf_gcd(&v, 0, 0, v, f); - if (!MP_EQ(v, MP_ONE)) break; - m--; - } - MP_DROP(u); - MP_DROP(v); - return (!m); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int verify(const char *op, mp *expect, mp *result, mp *a, mp *b) -{ - if (!MP_EQ(expect, result)) { - fprintf(stderr, "\n*** %s failed", op); - fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 16); - fputs("\n*** b = ", stderr); mp_writefile(b, stderr, 16); - fputs("\n*** result = ", stderr); mp_writefile(result, stderr, 16); - fputs("\n*** expect = ", stderr); mp_writefile(expect, stderr, 16); - fputc('\n', stderr); - return (0); - } - return (1); -} - -#define RIG(name, op) \ - static int t##name(dstr *v) \ - { \ - mp *a = *(mp **)v[0].buf; \ - mp *b = *(mp **)v[1].buf; \ - mp *r = *(mp **)v[2].buf; \ - mp *c = op(MP_NEW, a, b); \ - int ok = verify(#name, r, c, a, b); \ - mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(r); \ - assert(mparena_count(MPARENA_GLOBAL) == 0); \ - return (ok); \ - } - -RIG(add, gf_add) -RIG(mul, gf_mul) -RIG(exp, gf_exp) - -#undef RIG - -static int tsqr(dstr *v) -{ - mp *a = *(mp **)v[0].buf; - mp *r = *(mp **)v[1].buf; - mp *c = MP_NEW; - int ok = 1; - c = gf_sqr(MP_NEW, a); - ok &= verify("sqr", r, c, a, MP_ZERO); - mp_drop(a); mp_drop(r); mp_drop(c); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tdiv(dstr *v) -{ - mp *a = *(mp **)v[0].buf; - mp *b = *(mp **)v[1].buf; - mp *q = *(mp **)v[2].buf; - mp *r = *(mp **)v[3].buf; - mp *c = MP_NEW, *d = MP_NEW; - int ok = 1; - gf_div(&c, &d, a, b); - ok &= verify("div(quotient)", q, c, a, b); - ok &= verify("div(remainder)", r, d, a, b); - mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(d); mp_drop(r); mp_drop(q); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tirred(dstr *v) -{ - mp *a = *(mp **)v[0].buf; - int r = *(int *)v[1].buf; - int c = gf_irreduciblep(a); - int ok = 1; - if (r != c) { - ok = 0; - fprintf(stderr, "\n*** irred failed"); - fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 16); - fprintf(stderr, "\n*** r = %d\n", r); - fprintf(stderr, "*** c = %d\n", c); - } - mp_drop(a); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "add", tadd, { &type_mp, &type_mp, &type_mp, 0 } }, - { "mul", tmul, { &type_mp, &type_mp, &type_mp, 0 } }, - { "sqr", tsqr, { &type_mp, &type_mp, 0 } }, - { "div", tdiv, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, - { "exp", texp, { &type_mp, &type_mp, &type_mp, 0 } }, - { "irred", tirred, { &type_mp, &type_int, 0 } }, - { 0, 0, { 0 } }, -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/gf"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gf-exp.c b/gf-exp.c deleted file mode 100644 index 92c151f..0000000 --- a/gf-exp.c +++ /dev/null @@ -1,67 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Exponentiation for binary polynomials - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "gf.h" -#include "gf-exp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @gf_exp@ --- * - * - * Arguments: @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e$%. - */ - -mp *gf_exp(mp *d, mp *a, mp *e) -{ - mp *x = MP_ONE; - mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; - assert(!MP_NEGP(e)); - - MP_COPY(a); - if (MP_ZEROP(e)) - ; - else if (MP_LEN(e) < EXP_THRESH) - EXP_SIMPLE(x, a, e); - else - EXP_WINDOW(x, a, e); - mp_drop(d); - mp_drop(spare); - mp_drop(a); - return (x); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gf-exp.h b/gf-exp.h deleted file mode 100644 index 85090c7..0000000 --- a/gf-exp.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Exponentiation for binary polynomials - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GF_EXP_H -#define CATACOMB_GF_EXP_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Exponentiation ----------------------------------------------------*/ - -#define EXP_TYPE mp * - -#define EXP_COPY(d, x) d = MP_COPY(x) -#define EXP_DROP(x) MP_DROP(x) - -#define EXP_MUL(a, x) do { \ - mp *t = gf_mul(spare, a, x); \ - spare = a; \ - a = t; \ -} while (0) - -#define EXP_SQR(a) do { \ - mp *t = gf_sqr(spare, a); \ - spare = a; \ - a = t; \ -} while (0) - -#define EXP_FIX(x) - -#define EXP_SETMUL(d, x, y) d = gf_mul(MP_NEW, x, y) -#define EXP_SETSQR(d, x) d = gf_sqr(MP_NEW, x) - -#include "exp.h" - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/gf-gcd.c b/gf-gcd.c deleted file mode 100644 index 03cee47..0000000 --- a/gf-gcd.c +++ /dev/null @@ -1,263 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Euclidian algorithm on binary polynomials - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "gf.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @gf_gcd@ --- * - * - * Arguments: @mp **gcd, **xx, **yy@ = where to write the results - * @mp *a, *b@ = sources (must be nonzero) - * - * - * Returns: --- - * - * Use: Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that - * @ax + by = gcd(a, b)@. This is useful for computing modular - * inverses. - */ - -void gf_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b) -{ - mp *x = MP_ONE, *X = MP_ZERO; - mp *y = MP_ZERO, *Y = MP_ONE; - mp *u, *v; - mp *q = MP_NEW, *t, *spare = MP_NEW; - unsigned f = 0; - -#define f_swap 1u -#define f_ext 2u - - /* --- Sort out some initial flags --- */ - - if (xx || yy) - f |= f_ext; - - /* --- Ensure that @a@ is larger than @b@ --- * - * - * If they're the same length we don't care which order they're in, so this - * unsigned comparison is fine. - */ - - if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) { - t = a; a = b; b = t; - f |= f_swap; - } - - /* --- Check for zeroness --- */ - - if (MP_EQ(b, MP_ZERO)) { - - /* --- Store %$|a|$% as the GCD --- */ - - if (gcd) { - if (*gcd) MP_DROP(*gcd); - a = MP_COPY(a); - *gcd = a; - } - - /* --- Store %$1$% and %$0$% in the appropriate bins --- */ - - if (f & f_ext) { - if (f & f_swap) { - mp **t = xx; xx = yy; yy = t; - } - if (xx) { - if (*xx) MP_DROP(*xx); - if (MP_EQ(a, MP_ZERO)) - *xx = MP_ZERO; - else - *xx = MP_ONE; - } - if (yy) { - if (*yy) MP_DROP(*yy); - *yy = MP_ZERO; - } - } - return; - } - - /* --- Main extended Euclidean algorithm --- */ - - u = MP_COPY(a); - v = MP_COPY(b); - - while (!MP_ZEROP(v)) { - gf_div(&q, &u, u, v); - if (f & f_ext) { - t = gf_mul(spare, X, q); - t = gf_add(t, t, x); - spare = x; x = X; X = t; - t = gf_mul(spare, Y, q); - t = gf_add(t, t, y); - spare = y; y = Y; Y = t; - } - t = u; u = v; v = t; - } - - MP_DROP(q); if (spare) MP_DROP(spare); - if (!gcd) - MP_DROP(u); - else { - if (*gcd) MP_DROP(*gcd); - u->f &= ~MP_NEG; - *gcd = u; - } - - /* --- Perform a little normalization --- */ - - if (f & f_ext) { - - /* --- If @a@ and @b@ got swapped, swap the coefficients back --- */ - - if (f & f_swap) { - t = x; x = y; y = t; - t = a; a = b; b = t; - } - - /* --- Store the results --- */ - - if (!xx) - MP_DROP(x); - else { - if (*xx) MP_DROP(*xx); - *xx = x; - } - - if (!yy) - MP_DROP(y); - else { - if (*yy) MP_DROP(*yy); - *yy = y; - } - } - - MP_DROP(v); - MP_DROP(X); MP_DROP(Y); -} - -/* -- @gf_modinv@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *x@ = argument - * @mp *p@ = modulus - * - * Returns: The inverse %$x^{-1} \bmod p$%. - * - * Use: Computes a modular inverse, the catch being that the - * arguments and results are binary polynomials. An assertion - * fails if %$p$% has no inverse. - */ - -mp *gf_modinv(mp *d, mp *x, mp *p) -{ - mp *g = MP_NEW; - gf_gcd(&g, 0, &d, p, x); - assert(MP_EQ(g, MP_ONE)); - mp_drop(g); - return (d); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int gcd(dstr *v) -{ - int ok = 1; - mp *a = *(mp **)v[0].buf; - mp *b = *(mp **)v[1].buf; - mp *g = *(mp **)v[2].buf; - mp *x = *(mp **)v[3].buf; - mp *y = *(mp **)v[4].buf; - - mp *gg = MP_NEW, *xx = MP_NEW, *yy = MP_NEW; - gf_gcd(&gg, &xx, &yy, a, b); - if (!MP_EQ(x, xx)) { - fputs("\n*** gf_gcd(x) failed", stderr); - fputs("\na = ", stderr); mp_writefile(a, stderr, 16); - fputs("\nb = ", stderr); mp_writefile(b, stderr, 16); - fputs("\nexpect = ", stderr); mp_writefile(x, stderr, 16); - fputs("\nresult = ", stderr); mp_writefile(xx, stderr, 16); - fputc('\n', stderr); - ok = 0; - } - if (!MP_EQ(y, yy)) { - fputs("\n*** gf_gcd(y) failed", stderr); - fputs("\na = ", stderr); mp_writefile(a, stderr, 16); - fputs("\nb = ", stderr); mp_writefile(b, stderr, 16); - fputs("\nexpect = ", stderr); mp_writefile(y, stderr, 16); - fputs("\nresult = ", stderr); mp_writefile(yy, stderr, 16); - fputc('\n', stderr); - ok = 0; - } - - if (!ok) { - mp *ax = gf_mul(MP_NEW, a, xx); - mp *by = gf_mul(MP_NEW, b, yy); - ax = gf_add(ax, ax, by); - if (MP_EQ(ax, gg)) - fputs("\n*** (Alternative result found.)\n", stderr); - MP_DROP(ax); - MP_DROP(by); - } - - if (!MP_EQ(g, gg)) { - fputs("\n*** gf_gcd(gcd) failed", stderr); - fputs("\na = ", stderr); mp_writefile(a, stderr, 16); - fputs("\nb = ", stderr); mp_writefile(b, stderr, 16); - fputs("\nexpect = ", stderr); mp_writefile(g, stderr, 16); - fputs("\nresult = ", stderr); mp_writefile(gg, stderr, 16); - fputc('\n', stderr); - ok = 0; - } - MP_DROP(a); MP_DROP(b); MP_DROP(g); MP_DROP(x); MP_DROP(y); - MP_DROP(gg); MP_DROP(xx); MP_DROP(yy); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "gcd", gcd, { &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/gf"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gf.h b/gf.h deleted file mode 100644 index 8de8231..0000000 --- a/gf.h +++ /dev/null @@ -1,151 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Arithmetic on binary polynomials - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GF_H -#define CATACOMB_GF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_GFX_H -# include "gfx.h" -#endif - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @gf_add@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: Result, @a@ added to @b@. - */ - -extern mp *gf_add(mp */*d*/, mp */*a*/, mp */*b*/); -#define gf_sub gf_add - -/* --- @gf_mul@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: Result, @a@ multiplied by @b@. - */ - -extern mp *gf_mul(mp */*d*/, mp */*a*/, mp */*b*/); - -/* --- @gf_sqr@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = source - * - * Returns: Result, @a@ squared. - */ - -extern mp *gf_sqr(mp */*d*/, mp */*a*/); - -/* --- @gf_div@ --- * - * - * Arguments: @mp **qq, **rr@ = destination, quotient and remainder - * @mp *a, *b@ = sources - * - * Use: Calculates the quotient and remainder when @a@ is divided by - * @b@. The destinations @*qq@ and @*rr@ must be distinct. - * Either of @qq@ or @rr@ may be null to indicate that the - * result is irrelevant. (Discarding both results is silly.) - * There is a performance advantage if @a == *rr@. - */ - -extern void gf_div(mp **/*qq*/, mp **/*rr*/, mp */*a*/, mp */*b*/); - -/* --- @gf_exp@ --- * - * - * Arguments: @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e$%. - */ - -extern mp *gf_exp(mp */*d*/, mp */*a*/, mp */*e*/); - -/* --- @gf_irreduciblep@ --- * - * - * Arguments: @mp *f@ = a polynomial - * - * Returns: Nonzero if the polynomial is irreducible; otherwise zero. - */ - -extern int gf_irreduciblep(mp */*f*/); - -/* --- @gf_gcd@ --- * - * - * Arguments: @mp **gcd, **xx, **yy@ = where to write the results - * @mp *a, *b@ = sources (must be nonzero) - * - * - * Returns: --- - * - * Use: Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that - * @ax + by = gcd(a, b)@. This is useful for computing modular - * inverses. - */ - -extern void gf_gcd(mp **/*gcd*/, mp **/*xx*/, mp **/*yy*/, - mp */*a*/, mp */*b*/); - -/* -- @gf_modinv@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *x@ = argument - * @mp *p@ = modulus - * - * Returns: The inverse %$x^{-1} \bmod p$%. - * - * Use: Computes a modular inverse, the catch being that the - * arguments and results are binary polynomials. An assertion - * fails if %$p$% has no inverse. - */ - -extern mp *gf_modinv(mp */*d*/, mp */*x*/, mp */*p*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/gfn.c b/gfn.c deleted file mode 100644 index 8bfc441..0000000 --- a/gfn.c +++ /dev/null @@ -1,274 +0,0 @@ -/* -*-c-*- - * - * $Id: gfn.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Normal-basis translation for binary fields - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "gfreduce.h" -#include "gfn.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @gfn_copy@ --- * - * - * Arguments: @gfn *d@ = where to put the copy - * @const gfn *s@ = where the source is - * - * Returns: --- - * - * Use: Makes a copy of a translation matrix. - */ - -void gfn_copy(gfn *d, const gfn *s) -{ - size_t i; - - d->n = s->n; - d->r = xmalloc(s->n * sizeof(mp *)); - for (i = 0; i < s->n; i++) - d->r[i] = MP_COPY(s->r[i]); -} - -/* --- @gfn_destroy@ --- * - * - * Arguments: @gfn *m@ = a transformation matrix to free - * - * Returns: --- - * - * Use: Frees up a transformation matrix when it's no longer wanted. - */ - -void gfn_destroy(gfn *m) - { size_t i; for (i = 0; i < m->n; i++) MP_DROP(m->r[i]); xfree(m->r); } - -/* --- @gfn_identity@ --- * - * - * Arguments: @gfn *m@ = where to put the matrix - * @size_t n@ = size of the matrix - * - * Returns: --- - * - * Use: Fills @m@ with an identity matrix. - */ - -void gfn_identity(gfn *m, size_t n) -{ - size_t i; - - m->n = n; - m->r = xmalloc(n * sizeof(mp *)); - m->r[0] = MP_ONE; - for (i = 1; i < n; i++) - m->r[i] = mp_lsl(MP_NEW, m->r[i - 1], 1); -} - -/* --- @gfn_invert@ --- * - * - * Arguments: @gfn *m@ = a transformation matrix - * - * Returns: Zero if successful, nonzero if the matrix was singular. - * - * Use: Inverts a transformation matrix. - */ - -int gfn_invert(gfn *m) -{ - size_t i, j; - gfn mm; - mp *t; - int rc = -1; - - mm = *m; - gfn_identity(m, mm.n); - for (i = 0; i < mm.n; i++) { - if (!mp_testbit(mm.r[i], i)) { - for (j = i + 1; j < mm.n; j++) { - if (mp_testbit(mm.r[j], i)) - goto found_set; - } - goto fail; - found_set: - t = mm.r[i]; mm.r[i] = mm.r[j]; mm.r[j] = t; - t = m->r[i]; m->r[i] = m->r[j]; m->r[j] = t; - } - for (j = 0; j < mm.n; j++) { - if (j == i) continue; - if (mp_testbit(mm.r[j], i)) { - mm.r[j] = mp_xor(mm.r[j], mm.r[j], mm.r[i]); - m->r[j] = mp_xor(m->r[j], m->r[j], m->r[i]); - } - } - } - rc = 0; -fail: - gfn_destroy(&mm); - return (rc); -} - -/* --- @gfn_transform@ --- * - * - * Arguments: @gfn *m@ = conversion matrix to apply - * @mp *d@ = destination pointer - * @mp *x@ = input value - * - * Returns: The transformed element. - * - * Use: Transforms a field element according to the given matrix. - */ - -mp *gfn_transform(gfn *m, mp *d, mp *x) -{ - mp *y = MP_ZERO; - size_t i; - mpscan sc; - - for (i = 0, mp_scan(&sc, x); i < m->n && mp_step(&sc); i++) - if (mp_bit(&sc)) y = mp_xor(y, y, m->r[i]); - mp_drop(d); - return (y); -} - -/* --- @gfn_create@ --- * - * - * Arguments: @mp *p@ = modulus for polynomial basis - * @mp *beta@ = the generator of the normal basis, expressed - * relative to the polynomial basis - * @gfn *ntop@ = output normal-to-polynomail conversion matrix - * @gfn *pton@ = output polynomial-to-normal conversion matrix - * - * Returns: Zero if it worked, nonzero otherwise (e.g., if %$\beta$% - * doesn't generate a proper basis). - * - * Use: Constructs conversion matrices between polynomial and normal - * basis representations of binary field elements. - */ - -int gfn_create(mp *p, mp *beta, gfn *ntop, gfn *pton) -{ - size_t m = mp_bits(p) - 1; - size_t i; - gfreduce gr; - gfn *np, tmp; - - /* --- We start by building the the @ntop@ matrix --- * - * - * For mad reasons, the string representation of normal-basis elements is - * backwards. - */ - - gfreduce_create(&gr, p); - np = ntop ? ntop : &tmp; - np->n = m; - np->r = xmalloc(m * sizeof(mp *)); - np->r[m - 1] = MP_COPY(beta); - for (i = m - 1; i--; ) { - mp *x = gf_sqr(MP_NEW, np->r[i + 1]); - np->r[i] = gfreduce_do(&gr, x, x); - } - gfreduce_destroy(&gr); - - /* --- That was easy -- now invert it --- */ - - if (pton) { - if (ntop) gfn_copy(pton, np); else *pton = *np; - if (gfn_invert(pton)) { - gfn_destroy(pton); - if (ntop) gfn_destroy(ntop); - return (-1); - } - } - - /* --- And we're done --- */ - - return (0); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int check(dstr *v) -{ - mp *p = *(mp **)v[0].buf; - mp *beta = *(mp **)v[1].buf; - mp *xp = *(mp **)v[2].buf; - mp *xn = *(mp **)v[3].buf; - mp *y = MP_NEW; - gfn pton, ntop, ii; - size_t i; - int ok = 1; - - gfn_create(p, beta, &ntop, &pton); - gfn_identity(&ii, pton.n); - for (i = 0; i < pton.n; i++) { - y = gfn_transform(&ntop, y, pton.r[i]); - if (!MP_EQ(y, ii.r[i])) { - ok = 0; - fprintf(stderr, "*** inverse pton->ntop check failed (row %lu)\n", - (unsigned long)i); - MP_EPRINTX("*** p", p); MP_EPRINTX("*** beta", beta); - MP_EPRINTX("*** computed", y); - } - } - gfn_destroy(&ii); - y = gfn_transform(&pton, y, xp); - if (!MP_EQ(y, xn)) { - ok = 0; - fprintf(stderr, "*** pton failed\n"); - MP_EPRINTX("*** p", p); MP_EPRINTX("*** beta", beta); - MP_EPRINTX("*** xp", xp); MP_EPRINTX("*** xn", xn); - MP_EPRINTX("*** computed", y); - } - y = gfn_transform(&ntop, y, xn); - if (!MP_EQ(y, xp)) { - ok = 0; - fprintf(stderr, "*** ntop failed\n"); - MP_EPRINTX("*** p", p); MP_EPRINTX("*** beta", beta); - MP_EPRINTX("*** xp", xp); MP_EPRINTX("*** xn", xn); - MP_EPRINTX("*** computed", y); - } - gfn_destroy(&pton); gfn_destroy(&ntop); - mp_drop(p); mp_drop(beta); mp_drop(xp); mp_drop(xn); mp_drop(y); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "gfn", check, { &type_mp, &type_mp, &type_mp, &type_mp } }, - { 0 } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, tests, SRCDIR "/tests/gfn"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gfn.h b/gfn.h deleted file mode 100644 index dcb0db0..0000000 --- a/gfn.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -*-c-*- - * - * $Id: gfn.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Normal-basis translation for binary fields - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GFN_H -#define CATACOMB_GFN_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include "gf.h" - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct gfn { - size_t n; /* Number of rows */ - mp **r; /* Array of the rows */ -} gfn; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @gfn_copy@ --- * - * - * Arguments: @gfn *d@ = where to put the copy - * @const gfn *s@ = where the source is - * - * Returns: --- - * - * Use: Makes a copy of a translation matrix. - */ - -extern void gfn_copy(gfn */*d*/, const gfn */*s*/); - -/* --- @gfn_destroy@ --- * - * - * Arguments: @gfn *m@ = a transformation matrix to free - * - * Returns: --- - * - * Use: Frees up a transformation matrix when it's no longer wanted. - */ - -extern void gfn_destroy(gfn */*m*/); - -/* --- @gfn_identity@ --- * - * - * Arguments: @gfn *m@ = where to put the matrix - * @size_t n@ = size of the matrix - * - * Returns: --- - * - * Use: Fills @m@ with an identity matrix. - */ - -extern void gfn_identity(gfn */*m*/, size_t /*n*/); - -/* --- @gfn_invert@ --- * - * - * Arguments: @gfn *m@ = a transformation matrix - * - * Returns: Zero if successful, nonzero if the matrix was singular. - * - * Use: Inverts a transformation matrix. - */ - -extern int gfn_invert(gfn */*m*/); - -/* --- @gfn_transform@ --- * - * - * Arguments: @gfn *m@ = conversion matrix to apply - * @mp *d@ = destination pointer - * @mp *x@ = input value - * - * Returns: The transformed element. - * - * Use: Transforms a field element according to the given matrix. - */ - -extern mp *gfn_transform(gfn */*m*/, mp */*d*/, mp */*x*/); - -/* --- @gfn_create@ --- * - * - * Arguments: @mp *p@ = modulus for polynomial basis - * @mp *beta@ = the generator of the normal basis, expressed - * relative to the polynomial basis - * @gfn *ntop@ = output normal-to-polynomail conversion matrix - * @gfn *pton@ = output polynomial-to-normal conversion matrix - * - * Returns: Zero if it worked, nonzero otherwise (e.g., if %$\beta$% - * doesn't generate a proper basis). - * - * Use: Constructs conversion matrices between polynomial and normal - * basis representations of binary field elements. - */ - -extern int gfn_create(mp */*p*/, mp */*beta*/, gfn */*ntop*/, gfn */*pton*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/gfreduce-exp.h b/gfreduce-exp.h deleted file mode 100644 index d4aaf0a..0000000 --- a/gfreduce-exp.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*-c-*- - * - * $Id: gfreduce-exp.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Exponentiation operations for binary field reduction - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GFREDUCE_EXP_H -#define CATACOMB_GFREDUCE_EXP_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Exponentiation definitions ----------------------------------------*/ - -#define EXP_TYPE mp * - -#define EXP_COPY(d, x) d = MP_COPY(x) -#define EXP_DROP(x) MP_DROP(x) - -#define EXP_MUL(a, x) do { \ - mp *t = gf_mul(spare, a, x); \ - spare = a; \ - a = gfreduce_do(gr, t, t); \ -} while (0) - -#define EXP_SQR(a) do { \ - mp *t = gf_sqr(spare, a); \ - spare = a; \ - a = gfreduce_do(gr, t, t); \ -} while (0) - -#define EXP_FIX(x) - -#define EXP_SETMUL(d, x, y) do { \ - d = gf_mul(MP_NEW, x, y); \ - d = gfreduce_do(gr, d, d); \ -} while (0) - -#define EXP_SETSQR(d, x) do { \ - d = gf_sqr(MP_NEW, x); \ - d = gfreduce_do(gr, d, d); \ -} while (0) - -#include "exp.h" - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/gfreduce.c b/gfreduce.c deleted file mode 100644 index f9b92c8..0000000 --- a/gfreduce.c +++ /dev/null @@ -1,652 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Efficient reduction modulo sparse binary polynomials - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include "gf.h" -#include "gfreduce.h" -#include "gfreduce-exp.h" -#include "fibrand.h" -#include "mprand.h" - -/*----- Data structures ---------------------------------------------------*/ - -DA_DECL(instr_v, gfreduce_instr); - -/*----- Main code ---------------------------------------------------------*/ - -/* --- What's going on here? --- * - * - * Let's face it, @gfx_div@ sucks. It works (I hope), but it's not in any - * sense fast. Here, we do efficient reduction modulo sparse polynomials. - * - * Suppose we have a polynomial @X@ we're trying to reduce mod @P@. If we - * take the topmost nonzero word of @X@, call it @w@, then we can eliminate - * it by subtracting off @w P x^{k}@ for an appropriate value of @k@. The - * trick is in observing that if @P@ is sparse we can do this multiplication - * and subtraction efficiently, just by XORing appropriate shifts of @w@ into - * @X@. - * - * The first tricky bit is in working out when to stop. I'll use eight-bit - * words to demonstrate what I'm talking about. - * - * xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx - * 001ppppp pppppppp pppppppp pppppppp - * || - * |<------------ bp ------------->| - * |<------------ nw --------------->| - * - * The trick of taking whole words off of @X@ stops working when there are - * only @nw@ words left. Then we have to mask off the bottom bits of @w@ - * before continuing. - */ - -/* --- @gfreduce_create@ --- * - * - * Arguments: @gfreduce *r@ = structure to fill in - * @mp *x@ = a (hopefully sparse) polynomial - * - * Returns: --- - * - * Use: Initializes a context structure for reduction. - */ - -void gfreduce_create(gfreduce *r, mp *p) -{ - instr_v iv = DA_INIT; - unsigned long d; - unsigned dw; - mpscan sc; - unsigned long i; - gfreduce_instr *ip; - unsigned f = 0; - size_t w, ww, wi, wl, ll, bb; - - /* --- Sort out the easy stuff --- */ - - d = mp_bits(p); assert(d); d--; - r->lim = d/MPW_BITS; - dw = d%MPW_BITS; - if (!dw) - r->mask = 0; - else { - r->mask = MPW(((mpw)-1) << dw); - r->lim++; - } - r->p = mp_copy(p); - - /* --- Stash a new instruction --- */ - -#define INSTR(op_, arg_) do { \ - DA_ENSURE(&iv, 1); \ - DA(&iv)[DA_LEN(&iv)].op = (op_); \ - DA(&iv)[DA_LEN(&iv)].arg = (arg_); \ - DA_EXTEND(&iv, 1); \ -} while (0) - -#define f_lsr 1u - - w = (d + MPW_BITS - 1)/MPW_BITS; - INSTR(GFRI_LOAD, w); - wi = DA_LEN(&iv); - f = 0; - ll = 0; - bb = MPW_BITS - dw; - for (i = 0, mp_scan(&sc, p); mp_step(&sc) && i < d; i++) { - if (!mp_bit(&sc)) - continue; - ww = (d - i + MPW_BITS - 1)/MPW_BITS; - if (ww != w) { - wl = DA_LEN(&iv); - INSTR(GFRI_STORE, w); - if (!ll) - ll = DA_LEN(&iv); - if (!(f & f_lsr)) - INSTR(GFRI_LOAD, ww); - else { - INSTR(GFRI_LOAD, w - 1); - for (; wi < wl; wi++) { - ip = &DA(&iv)[wi]; - assert(ip->op == GFRI_LSL); - if (ip->arg) - INSTR(GFRI_LSR, MPW_BITS - ip->arg); - } - if (w - 1 != ww) { - INSTR(GFRI_STORE, w - 1); - INSTR(GFRI_LOAD, ww); - } - f &= ~f_lsr; - } - w = ww; - wi = DA_LEN(&iv); - } - INSTR(GFRI_LSL, (bb + i)%MPW_BITS); - if ((bb + i)%MPW_BITS) - f |= f_lsr; - } - wl = DA_LEN(&iv); - INSTR(GFRI_STORE, w); - if (!ll) - ll = DA_LEN(&iv); - if (f & f_lsr) { - INSTR(GFRI_LOAD, w - 1); - for (; wi < wl; wi++) { - ip = &DA(&iv)[wi]; - assert(ip->op == GFRI_LSL); - if (ip->arg) - INSTR(GFRI_LSR, MPW_BITS - ip->arg); - } - INSTR(GFRI_STORE, w - 1); - } - -#undef INSTR - - r->in = DA_LEN(&iv); - r->iv = xmalloc(r->in * sizeof(gfreduce_instr)); - r->liv = r->iv + ll; - memcpy(r->iv, DA(&iv), r->in * sizeof(gfreduce_instr)); - DA_DESTROY(&iv); -} - -/* --- @gfreduce_destroy@ --- * - * - * Arguments: @gfreduce *r@ = structure to free - * - * Returns: --- - * - * Use: Reclaims the resources from a reduction context. - */ - -void gfreduce_destroy(gfreduce *r) -{ - mp_drop(r->p); - xfree(r->iv); -} - -/* --- @gfreduce_dump@ --- * - * - * Arguments: @gfreduce *r@ = structure to dump - * @FILE *fp@ = file to dump on - * - * Returns: --- - * - * Use: Dumps a reduction context. - */ - -void gfreduce_dump(gfreduce *r, FILE *fp) -{ - size_t i; - - fprintf(fp, "poly = "); mp_writefile(r->p, fp, 16); - fprintf(fp, "\n lim = %lu; mask = %lx\n", - (unsigned long)r->lim, (unsigned long)r->mask); - for (i = 0; i < r->in; i++) { - static const char *opname[] = { "load", "lsl", "lsr", "store" }; - assert(r->iv[i].op < N(opname)); - fprintf(fp, " %s %lu\n", - opname[r->iv[i].op], - (unsigned long)r->iv[i].arg); - } -} - -/* --- @gfreduce_do@ --- * - * - * Arguments: @gfreduce *r@ = reduction context - * @mp *d@ = destination - * @mp *x@ = source - * - * Returns: Destination, @x@ reduced modulo the reduction poly. - */ - -static void run(const gfreduce_instr *i, const gfreduce_instr *il, - mpw *v, mpw z) -{ - mpw w = 0; - - for (; i < il; i++) { - switch (i->op) { - case GFRI_LOAD: w = *(v - i->arg); break; - case GFRI_LSL: w ^= z << i->arg; break; - case GFRI_LSR: w ^= z >> i->arg; break; - case GFRI_STORE: *(v - i->arg) = MPW(w); break; - default: abort(); - } - } -} - -mp *gfreduce_do(gfreduce *r, mp *d, mp *x) -{ - mpw *v, *vl; - const gfreduce_instr *il; - mpw z; - - /* --- Try to reuse the source's space --- */ - - MP_COPY(x); - if (d) MP_DROP(d); - MP_DEST(x, MP_LEN(x), x->f); - - /* --- Do the reduction --- */ - - il = r->iv + r->in; - if (MP_LEN(x) >= r->lim) { - v = x->v + r->lim; - vl = x->vl; - while (vl-- > v) { - while (*vl) { - z = *vl; - *vl = 0; - run(r->iv, il, vl, z); - } - } - if (r->mask) { - while (*vl & r->mask) { - z = *vl & r->mask; - *vl &= ~r->mask; - run(r->iv, il, vl, z); - } - } - } - - /* --- Done --- */ - - MP_SHRINK(x); - return (x); -} - -/* --- @gfreduce_sqrt@ --- * - * - * Arguments: @gfreduce *r@ = pointer to reduction context - * @mp *d@ = destination - * @mp *x@ = some polynomial - * - * Returns: The square root of @x@ modulo @r->p@, or null. - */ - -mp *gfreduce_sqrt(gfreduce *r, mp *d, mp *x) -{ - mp *y = MP_COPY(x); - mp *z, *spare = MP_NEW; - unsigned long m = mp_bits(r->p) - 1; - unsigned long i; - - for (i = 0; i < m - 1; i++) { - mp *t = gf_sqr(spare, y); - spare = y; - y = gfreduce_do(r, t, t); - } - z = gf_sqr(spare, y); - z = gfreduce_do(r, z, z); - if (!MP_EQ(x, z)) { - mp_drop(y); - y = 0; - } - mp_drop(z); - mp_drop(d); - return (y); -} - -/* --- @gfreduce_trace@ --- * - * - * Arguments: @gfreduce *r@ = pointer to reduction context - * @mp *x@ = some polynomial - * - * Returns: The trace of @x@. (%$\Tr(x)=x + x^2 + \cdots + x^{2^{m-1}}$% - * if %$x \in \gf{2^m}$%). - */ - -int gfreduce_trace(gfreduce *r, mp *x) -{ - mp *y = MP_COPY(x); - mp *spare = MP_NEW; - unsigned long m = mp_bits(r->p) - 1; - unsigned long i; - int rc; - - for (i = 0; i < m - 1; i++) { - mp *t = gf_sqr(spare, y); - spare = y; - y = gfreduce_do(r, t, t); - y = gf_add(y, y, x); - } - rc = !MP_ZEROP(y); - mp_drop(spare); - mp_drop(y); - return (rc); -} - -/* --- @gfreduce_halftrace@ --- * - * - * Arguments: @gfreduce *r@ = pointer to reduction context - * @mp *d@ = destination - * @mp *x@ = some polynomial - * - * Returns: The half-trace of @x@. - * (%$\HfTr(x)= x + x^{2^2} + \cdots + x^{2^{m-1}}$% - * if %$x \in \gf{2^m}$% with %$m$% odd). - */ - -mp *gfreduce_halftrace(gfreduce *r, mp *d, mp *x) -{ - mp *y = MP_COPY(x); - mp *spare = MP_NEW; - unsigned long m = mp_bits(r->p) - 1; - unsigned long i; - - mp_drop(d); - for (i = 0; i < m - 1; i += 2) { - mp *t = gf_sqr(spare, y); - spare = y; - y = gfreduce_do(r, t, t); - t = gf_sqr(spare, y); - spare = y; - y = gfreduce_do(r, t, t); - y = gf_add(y, y, x); - } - mp_drop(spare); - return (y); -} - -/* --- @gfreduce_quadsolve@ --- * - * - * Arguments: @gfreduce *r@ = pointer to reduction context - * @mp *d@ = destination - * @mp *x@ = some polynomial - * - * Returns: A polynomial @y@ such that %$y^2 + y = x$%, or null. - */ - -mp *gfreduce_quadsolve(gfreduce *r, mp *d, mp *x) -{ - unsigned long m = mp_bits(r->p) - 1; - mp *t; - - MP_COPY(x); - if (m & 1) - d = gfreduce_halftrace(r, d, x); - else { - mp *z, *w, *rho = MP_NEW; - mp *spare = MP_NEW; - grand *fr = fibrand_create(0); - unsigned long i; - - for (;;) { - rho = mprand(rho, m, fr, 0); - z = MP_ZERO; - w = MP_COPY(rho); - for (i = 0; i < m - 1; i++) { - t = gf_sqr(spare, z); spare = z; z = gfreduce_do(r, t, t); - t = gf_sqr(spare, w); spare = w; w = gfreduce_do(r, t, t); - t = gf_mul(spare, w, x); t = gfreduce_do(r, t, t); spare = t; - z = gf_add(z, z, t); - w = gf_add(w, w, rho); - } - if (!MP_ZEROP(w)) - break; - MP_DROP(z); - MP_DROP(w); - } - if (d) MP_DROP(d); - MP_DROP(w); - MP_DROP(spare); - MP_DROP(rho); - fr->ops->destroy(fr); - d = z; - } - - t = gf_sqr(MP_NEW, d); t = gfreduce_do(r, t, t); t = gf_add(t, t, d); - if (!MP_EQ(t, x)) { - MP_DROP(d); - d = 0; - } - MP_DROP(t); - MP_DROP(x); - if (d) d->v[0] &= ~(mpw)1; - return (d); -} - -/* --- @gfreduce_exp@ --- * - * - * Arguments: @gfreduce *gr@ = pointer to reduction context - * @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e \bmod m$%. - */ - -mp *gfreduce_exp(gfreduce *gr, mp *d, mp *a, mp *e) -{ - mp *x = MP_ONE; - mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; - - MP_SHRINK(e); - MP_COPY(a); - if (MP_ZEROP(e)) - ; - else { - if (MP_NEGP(e)) - a = gf_modinv(a, a, gr->p); - if (MP_LEN(e) < EXP_THRESH) - EXP_SIMPLE(x, a, e); - else - EXP_WINDOW(x, a, e); - } - mp_drop(d); - mp_drop(a); - mp_drop(spare); - return (x); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#define MP(x) mp_readstring(MP_NEW, #x, 0, 0) - -static int vreduce(dstr *v) -{ - mp *d = *(mp **)v[0].buf; - mp *n = *(mp **)v[1].buf; - mp *r = *(mp **)v[2].buf; - mp *c; - int ok = 1; - gfreduce rr; - - gfreduce_create(&rr, d); - c = gfreduce_do(&rr, MP_NEW, n); - if (!MP_EQ(c, r)) { - fprintf(stderr, "\n*** reduction failed\n*** "); - gfreduce_dump(&rr, stderr); - fprintf(stderr, "\n*** n = "); mp_writefile(n, stderr, 16); - fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16); - fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16); - fprintf(stderr, "\n"); - ok = 0; - } - gfreduce_destroy(&rr); - mp_drop(n); mp_drop(d); mp_drop(r); mp_drop(c); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vmodexp(dstr *v) -{ - mp *p = *(mp **)v[0].buf; - mp *g = *(mp **)v[1].buf; - mp *x = *(mp **)v[2].buf; - mp *r = *(mp **)v[3].buf; - mp *c; - int ok = 1; - gfreduce rr; - - gfreduce_create(&rr, p); - c = gfreduce_exp(&rr, MP_NEW, g, x); - if (!MP_EQ(c, r)) { - fprintf(stderr, "\n*** modexp failed\n*** "); - fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16); - fprintf(stderr, "\n*** g = "); mp_writefile(g, stderr, 16); - fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16); - fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16); - fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16); - fprintf(stderr, "\n"); - ok = 0; - } - gfreduce_destroy(&rr); - mp_drop(p); mp_drop(g); mp_drop(r); mp_drop(x); mp_drop(c); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vsqrt(dstr *v) -{ - mp *p = *(mp **)v[0].buf; - mp *x = *(mp **)v[1].buf; - mp *r = *(mp **)v[2].buf; - mp *c; - int ok = 1; - gfreduce rr; - - gfreduce_create(&rr, p); - c = gfreduce_sqrt(&rr, MP_NEW, x); - if (!MP_EQ(c, r)) { - fprintf(stderr, "\n*** sqrt failed\n*** "); - fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16); - fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16); - fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16); - fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16); - fprintf(stderr, "\n"); - ok = 0; - } - gfreduce_destroy(&rr); - mp_drop(p); mp_drop(r); mp_drop(x); mp_drop(c); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vtr(dstr *v) -{ - mp *p = *(mp **)v[0].buf; - mp *x = *(mp **)v[1].buf; - int r = *(int *)v[2].buf, c; - int ok = 1; - gfreduce rr; - - gfreduce_create(&rr, p); - c = gfreduce_trace(&rr, x); - if (c != r) { - fprintf(stderr, "\n*** trace failed\n*** "); - fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16); - fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16); - fprintf(stderr, "\n*** c = %d", c); - fprintf(stderr, "\n*** r = %d", r); - fprintf(stderr, "\n"); - ok = 0; - } - gfreduce_destroy(&rr); - mp_drop(p); mp_drop(x); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vhftr(dstr *v) -{ - mp *p = *(mp **)v[0].buf; - mp *x = *(mp **)v[1].buf; - mp *r = *(mp **)v[2].buf; - mp *c; - int ok = 1; - gfreduce rr; - - gfreduce_create(&rr, p); - c = gfreduce_halftrace(&rr, MP_NEW, x); - if (!MP_EQ(c, r)) { - fprintf(stderr, "\n*** halftrace failed\n*** "); - fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16); - fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16); - fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16); - fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16); - fprintf(stderr, "\n"); - ok = 0; - } - gfreduce_destroy(&rr); - mp_drop(p); mp_drop(r); mp_drop(x); mp_drop(c); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vquad(dstr *v) -{ - mp *p = *(mp **)v[0].buf; - mp *x = *(mp **)v[1].buf; - mp *r = *(mp **)v[2].buf; - mp *c; - int ok = 1; - gfreduce rr; - - gfreduce_create(&rr, p); - c = gfreduce_quadsolve(&rr, MP_NEW, x); - if (!MP_EQ(c, r)) { - fprintf(stderr, "\n*** quadsolve failed\n*** "); - fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16); - fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16); - fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16); - fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16); - fprintf(stderr, "\n"); - ok = 0; - } - gfreduce_destroy(&rr); - mp_drop(p); mp_drop(r); mp_drop(x); mp_drop(c); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk defs[] = { - { "reduce", vreduce, { &type_mp, &type_mp, &type_mp, 0 } }, - { "modexp", vmodexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, - { "sqrt", vsqrt, { &type_mp, &type_mp, &type_mp, 0 } }, - { "trace", vtr, { &type_mp, &type_mp, &type_int, 0 } }, - { "halftrace", vhftr, { &type_mp, &type_mp, &type_mp, 0 } }, - { "quadsolve", vquad, { &type_mp, &type_mp, &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, defs, SRCDIR"/tests/gfreduce"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gfreduce.h b/gfreduce.h deleted file mode 100644 index 1a5685c..0000000 --- a/gfreduce.h +++ /dev/null @@ -1,178 +0,0 @@ -/* -*-c-*- - * - * $Id: gfreduce.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Reduction modulo sparse binary polynomials - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GFREDUCE_H -#define CATACOMB_GFREDUCE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GF_H -# include "gf.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct gfreduce_instr { - unsigned op; /* Instruction opcode */ - size_t arg; /* Immediate argument */ -} gfreduce_instr; - -enum { - GFRI_LOAD, /* Load @p[arg]@ */ - GFRI_LSL, /* XOR with @w << arg@ */ - GFRI_LSR, /* XOR with @w >> arg@ */ - GFRI_STORE, /* Store @p[arg]@ */ - GFRI_MAX -}; - -typedef struct gfreduce { - size_t lim; /* Word of degree bit */ - mpw mask; /* Mask for degree word */ - mp *p; /* Copy of the polynomial */ - size_t in; /* Number of instruction words */ - gfreduce_instr *iv, *liv; /* Vector of instructions */ -} gfreduce; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @gfreduce_create@ --- * - * - * Arguments: @gfreduce *r@ = structure to fill in - * @mp *x@ = a (hopefully sparse) polynomial - * - * Returns: --- - * - * Use: Initializes a context structure for reduction. - */ - -extern void gfreduce_create(gfreduce */*r*/, mp */*p*/); - -/* --- @gfreduce_destroy@ --- * - * - * Arguments: @gfreduce *r@ = structure to free - * - * Returns: --- - * - * Use: Reclaims the resources from a reduction context. - */ - -extern void gfreduce_destroy(gfreduce */*r*/); - -/* --- @gfreduce_dump@ --- * - * - * Arguments: @gfreduce *r@ = structure to dump - * @FILE *fp@ = file to dump on - * - * Returns: --- - * - * Use: Dumps a reduction context. - */ - -extern void gfreduce_dump(gfreduce */*r*/, FILE */*fp*/); - -/* --- @gfreduce_do@ --- * - * - * Arguments: @gfreduce *r@ = reduction context - * @mp *d@ = destination - * @mp *x@ = source - * - * Returns: Destination, @x@ reduced modulo the reduction poly. - */ - -extern mp *gfreduce_do(gfreduce */*r*/, mp */*d*/, mp */*x*/); - -/* --- @gfreduce_sqrt@ --- * - * - * Arguments: @gfreduce *r@ = pointer to reduction context - * @mp *d@ = destination - * @mp *x@ = some polynomial - * - * Returns: The square root of @x@ modulo @r->p@, or null. - */ - -extern mp *gfreduce_sqrt(gfreduce */*r*/, mp */*d*/, mp */*x*/); - -/* --- @gfreduce_trace@ --- * - * - * Arguments: @gfreduce *r@ = pointer to reduction context - * @mp *x@ = some polynomial - * - * Returns: The trace of @x@. (%$\Tr(x)=x + x^2 + \cdots + x^{2^{m-1}}$% - * if %$x \in \gf{2^m}$%). - */ - -extern int gfreduce_trace(gfreduce */*r*/, mp */*x*/); - -/* --- @gfreduce_halftrace@ --- * - * - * Arguments: @gfreduce *r@ = pointer to reduction context - * @mp *d@ = destination - * @mp *x@ = some polynomial - * - * Returns: The half-trace of @x@. - * (%$\HfTr(x)= x + x^{2^2} + \cdots + x^{2^{m-1}}$% - * if %$x \in \gf{2^m}$% with %$m$% odd). - */ - -extern mp *gfreduce_halftrace(gfreduce */*r*/, mp */*d*/, mp */*x*/); - -/* --- @gfreduce_quadsolve@ --- * - * - * Arguments: @gfreduce *r@ = pointer to reduction context - * @mp *d@ = destination - * @mp *x@ = some polynomial - * - * Returns: A polynomial @y@ such that %$y^2 + y = x$%, or null. - */ - -extern mp *gfreduce_quadsolve(gfreduce */*r*/, mp */*d*/, mp */*x*/); - -/* --- @gfreduce_exp@ --- * - * - * Arguments: @gfreduce *gr@ = pointer to reduction context - * @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e \bmod m$%. - */ - -extern mp *gfreduce_exp(gfreduce */*gr*/, mp */*d*/, mp */*a*/, mp */*e*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/gfshare-mktab.c b/gfshare-mktab.c deleted file mode 100644 index 4cf5727..0000000 --- a/gfshare-mktab.c +++ /dev/null @@ -1,108 +0,0 @@ -/* -*-c-*- - * - * $Id: gfshare-mktab.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Generate tables for %$\gf{2^8}$% multiplication - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -/*----- Magic numbers -----------------------------------------------------*/ - -#define MOD 0x11d - -/*----- Main code ---------------------------------------------------------*/ - -int main(int argc, char *argv[]) -{ - octet log[256], alog[256]; - unsigned x; - unsigned i; - - x = 1; - for (i = 0; i < 255; i++) { - alog[i] = x; - log[x] = i; - x <<= 1; - if (x & 0x100) - x ^= MOD; - } - log[0] = 0; - alog[255] = 1; - - fputs("\ -/* -*-c-*-\n\ - *\n\ - * Log tables for secret sharing in %$\\gf{2^8}$% [generated]\n\ - */\n\ -\n\ -#ifndef GFSHARE_TAB_H\n\ -#define GFSHARE_TAB_H\n\ -\n\ -#define GFSHARE_LOG { \\\n\ - ", stdout); - - for (i = 0; i < 256; i++) { - printf("0x%02x", log[i]); - if (i == 255) - puts(" \\\n}\n"); - else if (i % 8 == 7) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - fputs("\ -#define GFSHARE_EXP { \\\n\ - ", stdout); - - for (i = 0; i < 510; i++) { - printf("0x%02x", alog[i % 255]); - if (i == 509) - puts(" \\\n}\n"); - else if (i % 8 == 7) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - /* --- Done --- */ - - fputs("#endif\n", stdout); - - if (fclose(stdout)) { - fprintf(stderr, "error writing data\n"); - exit(EXIT_FAILURE); - } - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gfshare.c b/gfshare.c deleted file mode 100644 index 99b1223..0000000 --- a/gfshare.c +++ /dev/null @@ -1,341 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Secret sharing over %$\gf{2^8}$% - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include -#include - -#include "arena.h" -#include "gfshare.h" -#include "gfshare-tab.h" -#include "grand.h" - -/*----- Static variables --------------------------------------------------*/ - -static const octet gflog[] = GFSHARE_LOG, gfexp[] = GFSHARE_EXP; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @gfshare_create@ --- * - * - * Arguments: @gfshare *s@ = pointer to share context to initialize - * @unsigned t@ = threshold for the system - * @size_t sz@ = size of the secret - * - * Returns: --- - * - * Use: Initializes a sharing context. - */ - -void gfshare_create(gfshare *s, unsigned t, size_t sz) -{ - s->t = t; - s->i = 0; - s->sz = sz; - s->v = 0; -} - -/* --- @gfshare_destroy@ --- * - * - * Arguments: @gfshare *s@ = pointer to share context to destroy - * - * Returns: --- - * - * Use: Disposes of a sharing context. The allocations for the - * individual shares and the vector @v@ are freed; the secret is - * left alone. - */ - -void gfshare_destroy(gfshare *s) -{ - if (s->v) - XS_FREE(s->v); -} - -/* --- @gfshare_mkshares@ --- * - * - * Arguments: @gfshare *s@ = pointer to share context to fill in - * @grand *r@ = pointer to random number source - * @const void *buf@ = pointer to the secret to share - * - * Returns: --- - * - * Use: Initializes a sharing context to be able to create shares. - * The context structure is expected to be mostly filled in. In - * particular, @t@ must be initialized. If @v@ is zero, a - * vector of appropriate size is allocated. You should use the - * macro @GFSHARE_INIT@ or @gfshare_create@ to construct sharing - * contexts. - */ - -void gfshare_mkshares(gfshare *s, grand *r, const void *buf) -{ - s->v = XS_ALLOC(s->sz * s->t); - r->ops->fill(r, s->v, s->sz * (s->t - 1)); - memcpy(s->v + s->sz * (s->t - 1), buf, s->sz); -} - -/* --- @gfshare_get@ --- * - * - * Arguments: @gfshare *s@ = pointer to share conext - * @unsigned x@ = share index to fetch - * @void *buf@ = pointer to output buffer - * - * Returns: --- - * - * Use: Extracts a share from the system. You may extract up to 255 - * shares from the system. Shares are indexed from 0. - */ - -void gfshare_get(gfshare *s, unsigned x, void *buf) -{ - unsigned i; - const octet *p = s->v; - unsigned ilog = gflog[x + 1]; - - /* --- Evaluate the polynomial at %$x = i + 1$% --- */ - - memcpy(buf, p, s->sz); - p += s->sz; - - for (i = 1; i < s->t; i++) { - octet *q = buf; - unsigned k; - for (k = 0; k < s->sz; k++) { - unsigned qq = *q; - if (qq) - qq = gfexp[ilog + gflog[qq]]; - *q++ = qq ^ *p++; - } - } -} - -/* --- @gfshare_addedp@ --- * - * - * Arguments: @gfshare *s@ = pointer to sharing context - * @unsigned x@ = which share number to check - * - * Returns: Nonzero if share @x@ has been added already, zero if it - * hasn't. - */ - -int gfshare_addedp(gfshare *s, unsigned x) -{ - unsigned i; - - for (i = 0; i < s->i; i++) { - if (GFSHARE_INDEX(s, i) == x + 1) - return (1); - } - return (0); -} - -/* --- @gfshare_add@ --- * - * - * Arguments: @gfshare *s@ = pointer to sharing context - * @unsigned x@ = which share number this is - * @const void *y@ = the share value - * - * Returns: Number of shares required before recovery may be performed. - * - * Use: Adds a share to the context. The context must have been - * initialized with the correct threshold @t@. - */ - -unsigned gfshare_add(gfshare *s, unsigned x, const void *y) -{ - octet *p; - - assert(((void)"Share context is full", s->i < s->t)); - assert(((void)"Share already present", !gfshare_addedp(s, x))); - - /* --- If no vector has been allocated, create one --- */ - - if (!s->v) { - s->v = XS_ALLOC(s->t * (s->sz + 1)); - s->i = 0; - } - - /* --- Store the share in the vector --- */ - - p = &GFSHARE_INDEX(s, s->i); - *p++ = x + 1; - memcpy(p, y, s->sz); - s->i++; - - /* --- Done --- */ - - return (s->t - s->i); -} - -/* --- @gfshare_combine@ --- * - * - * Arguments: @gfshare *s@ = pointer to share context - * @void *buf@ = pointer to output buffer for the secret - * - * Returns: --- - * - * Use: Reconstructs a secret, given enough shares. - */ - -void gfshare_combine(gfshare *s, void *buf) -{ - unsigned i, j; - unsigned xi, xj; - - /* --- Sanity checking --- */ - - assert(((void)"Not enough shares yet", s->i == s->t)); - - /* --- Grind through the shares --- */ - - memset(buf, 0, s->sz); - - for (i = 0; i < s->t; i++) { - octet *p = buf; - octet *q = &GFSHARE_INDEX(s, i); - unsigned c = 0, ci = 0; - - /* --- Compute the magic coefficient --- */ - - xi = *q++; - for (j = 0; j < s->t; j++) { - if (i == j) - continue; - xj = GFSHARE_INDEX(s, j); - c += gflog[xj]; - if (c >= 0xff) - c -= 0xff; - ci += gflog[xi ^ xj]; - if (ci >= 0xff) - ci -= 0xff; - } - if (ci > c) - c += 0xff; - c -= ci; - - /* --- Work out another layer of the secret --- */ - - p = buf; - for (j = 0; j < s->sz; j++) { - if (*q) - *p ^= gfexp[c + gflog[*q]]; - p++, q++; - } - } -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include "fibrand.h" - -static int verify(grand *r) -{ - unsigned n = r->ops->range(r, 16) + 8; - unsigned t = r->ops->range(r, n - 1) + 1; - unsigned len = r->ops->range(r, 32) + 1; - - octet *v = xmalloc(t * len); - unsigned *p = xmalloc(n * sizeof(unsigned)); - octet *sec = xmalloc(len), *sbuf = xmalloc(len); - gfshare s; - unsigned i; - - int ok = 1; - - for (i = 0; i < n; i++) - p[i] = i; - for (i = 0; i < t; i++) { - unsigned long j = r->ops->range(r, n - i); - unsigned x = p[i]; - p[i] = p[i + j]; - p[i + j] = x; - } - - r->ops->fill(r, sec, len); - - gfshare_create(&s, t, len); - - gfshare_mkshares(&s, r, sec); - for (i = 0; i < t; i++) - gfshare_get(&s, p[i], v + (i * len)); - gfshare_destroy(&s); - - gfshare_create(&s, t, len); - for (i = 0; i < t; i++) - gfshare_add(&s, p[i], v + (i * len)); - gfshare_combine(&s, sbuf); - gfshare_destroy(&s); - - if (memcmp(sec, sbuf, len) != 0) { - ok = 0; - fprintf(stderr, "\nbad recombination of shares\n"); - }; - - xfree(sec); - xfree(sbuf); - - xfree(v); - xfree(p); - - return (ok); -} - -int main(void) -{ - grand *r = fibrand_create(0); - unsigned i; - int ok = 1; - - fputs("gfshare: ", stdout); - for (i = 0; i < 40; i++) { - if (!verify(r)) - ok = 0; - fputc('.', stdout); - fflush(stdout); - } - - if (ok) - fputs(" ok\n", stdout); - else - fputs(" failed\n", stdout); - return (ok ? EXIT_SUCCESS : EXIT_FAILURE); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gfshare.h b/gfshare.h deleted file mode 100644 index 9826758..0000000 --- a/gfshare.h +++ /dev/null @@ -1,182 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Secret sharing over %$\gf{2^8}$% - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the system -----------------------------------------------* - * - * This uses a variant of Shamir's secret sharing system. Shamir's original - * system used polynomials modulo a large prime. This implementation instead - * uses the field %$\gf{2^8}$%, represented by - * - * %$\gf{2}[x]/(x^8 + x^4 + x^3 + x^2 + 1)$% - * - * and shares each byte of the secret independently. It is therefore limited - * to 255 players, although this probably isn't a serious limitation in - * practice. - * - * Share creation and reconstruction is extremely efficient. Contrast the - * performance of the straightforward implementation based on multiprecision - * arithmetic. - */ - -#ifndef CATACOMB_GFSHARE_H -#define CATACOMB_GFSHARE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- A secret sharing context --- */ - -typedef struct gfshare { - unsigned t; /* Threshold */ - unsigned i; /* Next free slot in vector */ - size_t sz; /* Size of the secret and shares */ - octet *v; /* Vector of share information */ -} gfshare; - -#define GFSHARE_INIT(t, sz) { t, 0, sz, 0 } - -#define GFSHARE_INDEX(s, i) ((s)->v[(i) * ((s)->sz + 1)]) - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @gfshare_create@ --- * - * - * Arguments: @gfshare *s@ = pointer to share context to initialize - * @unsigned t@ = threshold for the system - * @size_t sz@ = size of the secret - * - * Returns: --- - * - * Use: Initializes a sharing context. - */ - -extern void gfshare_create(gfshare */*s*/, unsigned /*t*/, size_t /*sz*/); - -/* --- @gfshare_destroy@ --- * - * - * Arguments: @gfshare *s@ = pointer to share context to destroy - * - * Returns: --- - * - * Use: Disposes of a sharing context. The allocations for the - * individual shares and the vector @v@ are freed; the secret is - * left alone. - */ - -extern void gfshare_destroy(gfshare */*s*/); - -/* --- @gfshare_mkshares@ --- * - * - * Arguments: @gfshare *s@ = pointer to share context to fill in - * @grand *r@ = pointer to random number source - * @const void *buf@ = pointer to the secret to share - * - * Returns: --- - * - * Use: Initializes a sharing context to be able to create shares. - * The context structure is expected to be mostly filled in. In - * particular, @t@ must be initialized. If @v@ is zero, a - * vector of appropriate size is allocated. You should use the - * macro @GFSHARE_INIT@ or @gfshare_create@ to construct sharing - * contexts. - */ - -extern void gfshare_mkshares(gfshare */*s*/, grand */*r*/, - const void */*buf*/); - -/* --- @gfshare_get@ --- * - * - * Arguments: @gfshare *s@ = pointer to share conext - * @unsigned x@ = share index to fetch - * @void *buf@ = pointer to output buffer - * - * Returns: --- - * - * Use: Extracts a share from the system. You may extract up to 255 - * shares from the system. Shares are indexed from 0. - */ - -extern void gfshare_get(gfshare */*s*/, unsigned /*x*/, void */*buf*/); - -/* --- @gfshare_addedp@ --- * - * - * Arguments: @gfshare *s@ = pointer to sharing context - * @unsigned x@ = which share number to check - * - * Returns: Nonzero if share @x@ has been added already, zero if it - * hasn't. - */ - -extern int gfshare_addedp(gfshare */*s*/, unsigned /*x*/); - -/* --- @gfshare_add@ --- * - * - * Arguments: @gfshare *s@ = pointer to sharing context - * @unsigned x@ = which share number this is - * @const void *y@ = the share value - * - * Returns: Number of shares required before recovery may be performed. - * - * Use: Adds a share to the context. The context must have been - * initialized with the correct threshold @t@. - */ - -extern unsigned gfshare_add(gfshare */*s*/, - unsigned /*x*/, const void */*y*/); - -/* --- @gfshare_combine@ --- * - * - * Arguments: @gfshare *s@ = pointer to share context - * @void *buf@ = pointer to output buffer for the secret - * - * Returns: --- - * - * Use: Reconstructs a secret, given enough shares. - */ - -extern void gfshare_combine(gfshare */*s*/, void */*buf*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/gfx-kmul.c b/gfx-kmul.c deleted file mode 100644 index ec2bd6d..0000000 --- a/gfx-kmul.c +++ /dev/null @@ -1,249 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Karatsuba's multiplication algorithm on binary polynomials - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include "gfx.h" -#include "karatsuba.h" - -/*----- Tweakables --------------------------------------------------------*/ - -#ifdef TEST_RIG -# undef GFK_THRESH -# define GFK_THRESH 1 -#endif - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @gfx_kmul@ --- * - * - * Arguments: @mpw *dv, *dvl@ = pointer to destination buffer - * @const mpw *av, *avl@ = pointer to first argument - * @const mpw *bv, *bvl@ = pointer to second argument - * @mpw *sv, *svl@ = pointer to scratch workspace - * - * Returns: --- - * - * Use: Multiplies two binary polynomials using Karatsuba's - * algorithm. This is rather faster than traditional long - * multiplication (e.g., @gfx_umul@) on polynomials with large - * degree, although more expensive on small ones. - * - * The destination must be twice as large as the larger - * argument. The scratch space must be twice as large as the - * larger argument. - */ - -void gfx_kmul(mpw *dv, mpw *dvl, - const mpw *av, const mpw *avl, - const mpw *bv, const mpw *bvl, - mpw *sv, mpw *svl) -{ - const mpw *avm, *bvm; - size_t m; - - /* --- Dispose of easy cases to @mpx_umul@ --- * - * - * Karatsuba is only a win on large numbers, because of all the - * recursiveness and bookkeeping. The recursive calls make a quick check - * to see whether to bottom out to @gfx_umul@ which should help quite a - * lot, but sometimes the only way to know is to make sure... - */ - - MPX_SHRINK(av, avl); - MPX_SHRINK(bv, bvl); - - if (avl - av <= GFK_THRESH || bvl - bv <= GFK_THRESH) { - gfx_mul(dv, dvl, av, avl, bv, bvl); - return; - } - - /* --- How the algorithm works --- * - * - * Let %$A = xb + y$% and %$B = ub + v$%. Then, simply by expanding, - * %$AB = x u b^2 + b(x v + y u) + y v$%. That's not helped any, because - * I've got four multiplications, each four times easier than the one I - * started with. However, note that I can rewrite the coefficient of %$b$% - * as %$xv + yu = (x + y)(u + v) - xu - yv$%. The terms %$xu$% and %$yv$% - * I've already calculated, and that leaves only one more multiplication to - * do. So now I have three multiplications, each four times easier, and - * that's a win. - */ - - /* --- First things --- * - * - * Sort out where to break the factors in half. I'll choose the midpoint - * of the larger one, since this minimizes the amount of work I have to do - * most effectively. - */ - - if (avl - av > bvl - bv) { - m = (avl - av + 1) >> 1; - avm = av + m; - if (bvl - bv > m) - bvm = bv + m; - else - bvm = bvl; - } else { - m = (bvl - bv + 1) >> 1; - bvm = bv + m; - if (avl - av > m) - avm = av + m; - else - avm = avl; - } - - /* --- Sort out the middle term --- */ - - { - mpw *bsv = sv + m, *ssv = bsv + m; - mpw *rdv = dv + m, *rdvl = rdv + 2 * m; - - assert(rdvl <= dvl); - assert(ssv <= svl); - UXOR2(sv, bsv, av, avm, avm, avl); - UXOR2(bsv, ssv, bv, bvm, bvm, bvl); - if (m > GFK_THRESH) - gfx_kmul(rdv, rdvl, sv, bsv, bsv, ssv, ssv, svl); - else - gfx_mul(rdv, rdvl, sv, bsv, bsv, ssv); - } - - /* --- Sort out the other two terms --- */ - - { - mpw *svm = sv + m, *ssv = svm + m; - mpw *tdv = dv + m; - mpw *rdv = tdv + m; - - if (avl == avm || bvl == bvm) - MPX_ZERO(rdv + m, dvl); - else { - if (m > GFK_THRESH) - gfx_kmul(sv, ssv, avm, avl, bvm, bvl, ssv, svl); - else - gfx_mul(sv, ssv, avm, avl, bvm, bvl); - MPX_COPY(rdv + m, dvl, svm, ssv); - UXOR(rdv, sv, svm); - UXOR(tdv, sv, ssv); - } - - if (m > GFK_THRESH) - gfx_kmul(sv, ssv, av, avm, bv, bvm, ssv, svl); - else - gfx_mul(sv, ssv, av, avm, bv, bvm); - MPX_COPY(dv, tdv, sv, svm); - UXOR(tdv, sv, ssv); - UXOR(tdv, svm, ssv); - } -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include -#include - -#define ALLOC(v, vl, sz) do { \ - size_t _sz = (sz); \ - mpw *_vv = xmalloc(MPWS(_sz)); \ - mpw *_vvl = _vv + _sz; \ - (v) = _vv; \ - (vl) = _vvl; \ -} while (0) - -#define LOAD(v, vl, d) do { \ - const dstr *_d = (d); \ - mpw *_v, *_vl; \ - ALLOC(_v, _vl, MPW_RQ(_d->len)); \ - mpx_loadb(_v, _vl, _d->buf, _d->len); \ - (v) = _v; \ - (vl) = _vl; \ -} while (0) - -#define MAX(x, y) ((x) > (y) ? (x) : (y)) - -static void dumpmp(const char *msg, const mpw *v, const mpw *vl) -{ - fputs(msg, stderr); - MPX_SHRINK(v, vl); - while (v < vl) - fprintf(stderr, " %08lx", (unsigned long)*--vl); - fputc('\n', stderr); -} - -static int mul(dstr *v) -{ - mpw *a, *al; - mpw *b, *bl; - mpw *c, *cl; - mpw *d, *dl; - mpw *s, *sl; - size_t m; - int ok = 1; - - LOAD(a, al, &v[0]); - LOAD(b, bl, &v[1]); - LOAD(c, cl, &v[2]); - m = MAX(al - a, bl - b) + 1; - ALLOC(d, dl, 2 * m); - ALLOC(s, sl, 2 * m); - - gfx_kmul(d, dl, a, al, b, bl, s, sl); - if (!mpx_ueq(d, dl, c, cl)) { - fprintf(stderr, "\n*** mul failed\n"); - dumpmp(" a", a, al); - dumpmp(" b", b, bl); - dumpmp("expected", c, cl); - dumpmp(" result", d, dl); - ok = 0; - } - - xfree(a); xfree(b); xfree(c); xfree(d); xfree(s); - return (ok); -} - -static test_chunk defs[] = { - { "mul", mul, { &type_hex, &type_hex, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, defs, SRCDIR"/tests/gfx"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gfx-sqr-mktab.c b/gfx-sqr-mktab.c deleted file mode 100644 index c0a0b36..0000000 --- a/gfx-sqr-mktab.c +++ /dev/null @@ -1,91 +0,0 @@ -/* -*-c-*- - * - * $Id: gfx-sqr-mktab.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Build table for squaring of binary polynomials - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -/*----- Main code ---------------------------------------------------------*/ - -static void mktab(uint16 *t) -{ - unsigned i, j, x; - - for (i = 0; i < 256; i++) { - x = 0; - for (j = 0; j < 8; j++) { - if (i & (1 << j)) - x |= 1 << (2 * j); - } - t[i] = x; - } -} - -int main(void) -{ - uint16 t[256]; - unsigned i; - - mktab(t); -fputs("\ -/* -*-c-*-\n\ - *\n\ - * Bit spacing table for binary polynomial squaring\n\ - */\n\ -\n\ -#ifndef GFX_SQR_TAB_H\n\ -#define GFX_SQR_TAB_H\n\ -\n\ -#define GFX_SQRTAB { \\\n\ - ", stdout); - - for (i = 0; i < 256; i++) { - printf("0x%04x", t[i]); - if (i == 255) - puts(" \\\n}\n"); - else if (i % 8 == 7) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - fputs("#endif\n", stdout); - - if (fclose(stdout)) { - fprintf(stderr, "error writing data\n"); - exit(EXIT_FAILURE); - } - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gfx-sqr.c b/gfx-sqr.c deleted file mode 100644 index ef54cf1..0000000 --- a/gfx-sqr.c +++ /dev/null @@ -1,214 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Sqaring binary polynomials - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mpx.h" -#include "gfx.h" -#include "gfx-sqr-tab.h" - -/*----- Static variables --------------------------------------------------*/ - -static const uint16 tab[256] = GFX_SQRTAB; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @gfx_sqr@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = argument vector base and limit - * - * Returns: --- - * - * Use: Performs squaring of binary polynomials. - */ - -void gfx_sqr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl) -{ - mpd a = 0, aa = 0; - unsigned b = 0, bb = 0; - - /* --- Simple stuff --- */ - - if (dv >= dvl) - return; - MPX_SHRINK(av, avl); - - /* --- The main algorithm --- * - * - * Our method depends on the fact that, in a field of characteristic 2, we - * have that %$(a + b)^2 = a^2 + b^2$%. Thus, to square a polynomial, it's - * sufficient just to put a zero bit between each of the bits of the - * original argument. We use a precomputed table for this, and work on - * entire octets at a time. Life is more complicated because we've got to - * be careful of bizarre architectures which don't have words with a - * multiple of 8 bits in them. - */ - - for (;;) { - - /* --- Input buffering --- */ - - if (b < 8) { - if (av >= avl) - break; - a |= *av++ << b; - b += MPW_BITS; - } - - /* --- Do the work in the middle --- */ - - aa |= (mpd)(tab[U8(a)]) << bb; - bb += 16; - a >>= 8; - b -= 8; - - /* --- Output buffering --- */ - - if (bb >= MPW_BITS) { - *dv++ = MPW(aa); - if (dv >= dvl) - return; - aa >>= MPW_BITS; - bb -= MPW_BITS; - } - } - - /* --- Flush the input buffer --- */ - - if (b) for (;;) { - aa |= (mpd)(tab[U8(a)]) << bb; - bb += 16; - if (bb > MPW_BITS) { - *dv++ = MPW(aa); - if (dv >= dvl) - return; - aa >>= MPW_BITS; - bb -= MPW_BITS; - } - a >>= 8; - if (b <= 8) - break; - else - b -= 8; - } - - /* --- Flush the output buffer --- */ - - if (bb) for (;;) { - *dv++ = MPW(aa); - if (dv >= dvl) - return; - aa >>= MPW_BITS; - if (bb <= MPW_BITS) - break; - else - bb -= MPW_BITS; - } - - /* --- Zero the rest of everything --- */ - - MPX_ZERO(dv, dvl); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include -#include -#include -#include - -#define ALLOC(v, vl, sz) do { \ - size_t _sz = (sz); \ - mpw *_vv = xmalloc(MPWS(_sz)); \ - mpw *_vvl = _vv + _sz; \ - (v) = _vv; \ - (vl) = _vvl; \ -} while (0) - -#define LOAD(v, vl, d) do { \ - const dstr *_d = (d); \ - mpw *_v, *_vl; \ - ALLOC(_v, _vl, MPW_RQ(_d->len)); \ - mpx_loadb(_v, _vl, _d->buf, _d->len); \ - (v) = _v; \ - (vl) = _vl; \ -} while (0) - -#define MAX(x, y) ((x) > (y) ? (x) : (y)) - -static void dumpmp(const char *msg, const mpw *v, const mpw *vl) -{ - fputs(msg, stderr); - MPX_SHRINK(v, vl); - while (v < vl) - fprintf(stderr, " %08lx", (unsigned long)*--vl); - fputc('\n', stderr); -} - -static int vsqr(dstr *v) -{ - mpw *a, *al; - mpw *b, *bl; - mpw *d, *dl; - int ok = 1; - - LOAD(a, al, &v[0]); - LOAD(b, bl, &v[1]); - ALLOC(d, dl, 2 * (al - a)); - - gfx_sqr(d, dl, a, al); - if (!mpx_ueq(d, dl, b, bl)) { - fprintf(stderr, "\n*** vsqr failed\n"); - dumpmp(" a", a, al); - dumpmp("expected", b, bl); - dumpmp(" result", d, dl); - ok = 0; - } - - xfree(a); xfree(b); xfree(d); - return (ok); -} - -static test_chunk defs[] = { - { "sqr", vsqr, { &type_hex, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, defs, SRCDIR"/tests/gfx"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gfx.c b/gfx.c deleted file mode 100644 index b1bdd51..0000000 --- a/gfx.c +++ /dev/null @@ -1,389 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Low-level arithmetic on binary polynomials - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "mpx.h" -#include "mpscan.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @gfx_add@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = first addend vector base and limit - * @const mpw *bv, *bvl@ = second addend vector base and limit - * - * Returns: --- - * - * Use: Adds two %$\gf{2}$% polynomials. This is the same as - * subtraction. - */ - -void gfx_add(mpw *dv, mpw *dvl, - const mpw *av, const mpw *avl, - const mpw *bv, const mpw *bvl) -{ - MPX_SHRINK(av, avl); - MPX_SHRINK(bv, bvl); - - while (av < avl || bv < bvl) { - mpw a, b; - if (dv >= dvl) - return; - a = (av < avl) ? *av++ : 0; - b = (bv < bvl) ? *bv++ : 0; - *dv++ = a ^ b; - } - if (dv < dvl) - MPX_ZERO(dv, dvl); -} - -/* --- @gfx_acc@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = addend vector base and limit - * - * Returns: --- - * - * Use: Adds the addend into the destination. This is considerably - * faster than the three-address add call. - */ - -void gfx_acc(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl) -{ - size_t dlen, alen; - - MPX_SHRINK(av, avl); - dlen = dvl - dv; - alen = avl - av; - if (dlen < alen) - avl = av + dlen; - while (av < avl) - *dv++ ^= *av++; -} - -/* --- @gfx_accshift@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = addend vector base and limit - * @size_t n@ = number of bits to shift - * - * Returns: --- - * - * Use: Shifts the argument left by %$n$% places and adds it to the - * destination. This is a primitive used by multiplication and - * division. - */ - -void gfx_accshift(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n) -{ - size_t c = n / MPW_BITS; - mpw x = 0, y; - size_t dlen, alen; - - /* --- Sort out the shift amounts --- */ - - if (dvl - dv < c) - return; - dv += c; - n %= MPW_BITS; - if (!n) { - gfx_acc(dv, dvl, av, avl); - return; - } - c = MPW_BITS - n; - - /* --- Sort out vector lengths --- */ - - MPX_SHRINK(av, avl); - dlen = dvl - dv; - alen = avl - av; - if (dlen < alen) - avl = av + dlen; - - /* --- Now do the hard work --- */ - - while (av < avl) { - y = *av++; - *dv++ ^= MPW((y << n) | (x >> c)); - x = y; - } - if (dv < dvl) - *dv++ ^= x >> c; -} - -/* --- @gfx_mul@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = first argument vector base and limit - * @const mpw *bv, *bvl@ = second argument vector base and limit - * - * Returns: --- - * - * Use: Does multiplication of polynomials over %$\gf{2}$%. - */ - -void gfx_mul(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, - const mpw *bv, const mpw *bvl) -{ - mpscan sc; - const mpw *v; - mpw *vv; - mpw z; - mpd x, y; - - MPX_SHRINK(av, avl); - MPX_SHRINK(bv, bvl); - MPSCAN_INITX(&sc, av, avl); - MPX_ZERO(dv, dvl); - - while (bv < bvl && dv < dvl) { - x = 0; - for (v = av, vv = dv++; v < avl && vv < dvl; v++) { - z = *bv; y = *v; - while (z) { - if (z & 1u) x ^= y; - z >>= 1; y <<= 1; - } - *vv++ ^= MPW(x); - x >>= MPW_BITS; - } - if (vv < dvl) - *vv++ = MPW(x); - bv++; - } -} - -/* --- @gfx_div@ --- * - * - * Arguments: @mpw *qv, *qvl@ = quotient vector base and limit - * @mpw *rv, *rvl@ = dividend/remainder vector base and limit - * @const mpw *dv, *dvl@ = divisor vector base and limit - * - * Returns: --- - * - * Use: Performs division on polynomials over %$\gf{2}$%. - */ - -void gfx_div(mpw *qv, mpw *qvl, mpw *rv, mpw *rvl, - const mpw *dv, const mpw *dvl) -{ - size_t dlen, rlen, qlen; - size_t dbits; - mpw *rvv, *rvd; - unsigned rvm, n, qi; - mpw q; - - MPX_SHRINK(rv, rvl); - MPX_SHRINK(dv, dvl); - assert(((void)"division by zero in gfx_div", dv < dvl)); - MPX_BITS(dbits, dv, dvl); - dlen = dvl - dv; - rlen = rvl - rv; - qlen = qvl - qv; - - MPX_ZERO(qv, qvl); - if (dlen > rlen) - return; - rvd = rvl - dlen; - rvv = rvl - 1; - rvm = 1 << (MPW_BITS - 1); - n = MPW_BITS - (dbits % MPW_BITS); - if (n == MPW_BITS) - n = 0; - q = 0; - qi = rvd - rv; - - for (;;) { - q <<= 1; - if (*rvv & rvm) { - q |= 1; - gfx_accshift(rvd, rvl, dv, dvl, n); - } - rvm >>= 1; - if (!rvm) { - rvm = 1 << (MPW_BITS - 1); - rvv--; - } - if (n) - n--; - else { - if (qi < qlen) - qv[qi] = q; - q = 0; - qi--; - if (rvd == rv) - break; - n = MPW_BITS - 1; - rvd--; - } - } -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include -#include -#include -#include - -#define ALLOC(v, vl, sz) do { \ - size_t _sz = (sz); \ - mpw *_vv = xmalloc(MPWS(_sz)); \ - mpw *_vvl = _vv + _sz; \ - (v) = _vv; \ - (vl) = _vvl; \ -} while (0) - -#define LOAD(v, vl, d) do { \ - const dstr *_d = (d); \ - mpw *_v, *_vl; \ - ALLOC(_v, _vl, MPW_RQ(_d->len)); \ - mpx_loadb(_v, _vl, _d->buf, _d->len); \ - (v) = _v; \ - (vl) = _vl; \ -} while (0) - -#define MAX(x, y) ((x) > (y) ? (x) : (y)) - -static void dumpmp(const char *msg, const mpw *v, const mpw *vl) -{ - fputs(msg, stderr); - MPX_SHRINK(v, vl); - while (v < vl) - fprintf(stderr, " %08lx", (unsigned long)*--vl); - fputc('\n', stderr); -} - -static int vadd(dstr *v) -{ - mpw *a, *al; - mpw *b, *bl; - mpw *c, *cl; - mpw *d, *dl; - int ok = 1; - - LOAD(a, al, &v[0]); - LOAD(b, bl, &v[1]); - LOAD(c, cl, &v[2]); - ALLOC(d, dl, MAX(al - a, bl - b) + 1); - - gfx_add(d, dl, a, al, b, bl); - if (!mpx_ueq(d, dl, c, cl)) { - fprintf(stderr, "\n*** vadd failed\n"); - dumpmp(" a", a, al); - dumpmp(" b", b, bl); - dumpmp("expected", c, cl); - dumpmp(" result", d, dl); - ok = 0; - } - - xfree(a); xfree(b); xfree(c); xfree(d); - return (ok); -} - -static int vmul(dstr *v) -{ - mpw *a, *al; - mpw *b, *bl; - mpw *c, *cl; - mpw *d, *dl; - int ok = 1; - - LOAD(a, al, &v[0]); - LOAD(b, bl, &v[1]); - LOAD(c, cl, &v[2]); - ALLOC(d, dl, (al - a) + (bl - b)); - - gfx_mul(d, dl, a, al, b, bl); - if (!mpx_ueq(d, dl, c, cl)) { - fprintf(stderr, "\n*** vmul failed\n"); - dumpmp(" a", a, al); - dumpmp(" b", b, bl); - dumpmp("expected", c, cl); - dumpmp(" result", d, dl); - ok = 0; - } - - xfree(a); xfree(b); xfree(c); xfree(d); - return (ok); -} - -static int vdiv(dstr *v) -{ - mpw *a, *al; - mpw *b, *bl; - mpw *q, *ql; - mpw *r, *rl; - mpw *qq, *qql; - int ok = 1; - - ALLOC(a, al, MPW_RQ(v[0].len) + 2); mpx_loadb(a, al, v[0].buf, v[0].len); - LOAD(b, bl, &v[1]); - LOAD(q, ql, &v[2]); - LOAD(r, rl, &v[3]); - ALLOC(qq, qql, al - a); - - gfx_div(qq, qql, a, al, b, bl); - if (!mpx_ueq(qq, qql, q, ql) || - !mpx_ueq(a, al, r, rl)) { - fprintf(stderr, "\n*** vdiv failed\n"); - dumpmp(" divisor", b, bl); - dumpmp("expect r", r, rl); - dumpmp("result r", a, al); - dumpmp("expect q", q, ql); - dumpmp("result q", qq, qql); - ok = 0; - } - - xfree(a); xfree(b); xfree(r); xfree(q); xfree(qq); - return (ok); -} - -static test_chunk defs[] = { - { "add", vadd, { &type_hex, &type_hex, &type_hex, 0 } }, - { "mul", vmul, { &type_hex, &type_hex, &type_hex, 0 } }, - { "div", vdiv, { &type_hex, &type_hex, &type_hex, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, defs, SRCDIR"/tests/gfx"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gfx.h b/gfx.h deleted file mode 100644 index 91ea226..0000000 --- a/gfx.h +++ /dev/null @@ -1,175 +0,0 @@ -/* -*-c-*- - * - * $Id: gfx.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Low-level arithmetic on binary polynomials - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GFX_H -#define CATACOMB_GFX_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MPX_H -# include "mpx.h" -#endif - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @gfx_add@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = first addend vector base and limit - * @const mpw *bv, *bvl@ = second addend vector base and limit - * - * Returns: --- - * - * Use: Adds two %$\gf{2}$% polynomials. This is the same as - * subtraction. - */ - -extern void gfx_add(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, - const mpw */*bv*/, const mpw */*bvl*/); - -/* --- @gfx_acc@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = addend vector base and limit - * - * Returns: --- - * - * Use: Adds the addend into the destination. This is considerably - * faster than the three-address add call. - */ - -extern void gfx_acc(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/); - -/* --- @gfx_accshift@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = addend vector base and limit - * @size_t n@ = number of bits to shift - * - * Returns: --- - * - * Use: Shifts the argument left by %$n$% places and adds it to the - * destination. This is a primitive used by multiplication and - * division. - */ - -extern void gfx_accshift(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, - size_t /*n*/); - -/* --- @gfx_mul@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = first argument vector base and limit - * @const mpw *bv, *bvl@ = second argument vector base and limit - * - * Returns: --- - * - * Use: Does multiplication of polynomials over %$\gf{2}$%. - */ - -extern void gfx_mul(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, - const mpw */*bv*/, const mpw */*bvl*/); - -/* --- @gfx_sqr@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = argument vector base and limit - * - * Returns: --- - * - * Use: Performs squaring of binary polynomials. - */ - -extern void gfx_sqr(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/); - -/* --- @gfx_div@ --- * - * - * Arguments: @mpw *qv, *qvl@ = quotient vector base and limit - * @mpw *rv, *rvl@ = dividend/remainder vector base and limit - * @const mpw *dv, *dvl@ = divisor vector base and limit - * - * Returns: --- - * - * Use: Performs division on polynomials over %$\gf{2}$%. - */ - -extern void gfx_div(mpw */*qv*/, mpw */*qvl*/, mpw */*rv*/, mpw */*rvl*/, - const mpw */*dv*/, const mpw */*dvl*/); - -/*----- Karatsuba multiplication algorithms -------------------------------*/ - -/* --- @GFK_THRESH@ --- * - * - * This is the limiting length for using Karatsuba algorithms. It's best to - * use the simpler classical multiplication method on numbers smaller than - * this. - */ - -#define GFK_THRESH 2 - -/* --- @gfx_kmul@ --- * - * - * Arguments: @mpw *dv, *dvl@ = pointer to destination buffer - * @const mpw *av, *avl@ = pointer to first argument - * @const mpw *bv, *bvl@ = pointer to second argument - * @mpw *sv, *svl@ = pointer to scratch workspace - * - * Returns: --- - * - * Use: Multiplies two binary polynomials using Karatsuba's - * algorithm. This is rather faster than traditional long - * multiplication (e.g., @gfx_umul@) on polynomials with large - * degree, although more expensive on small ones. - * - * The destination must be twice as large as the larger - * argument. The scratch space must be twice as large as the - * larger argument. - */ - -extern void gfx_kmul(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, - const mpw */*bv*/, const mpw */*bvl*/, - mpw */*sv*/, mpw */*svl*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/ghash-def.h b/ghash-def.h deleted file mode 100644 index 6d20e5b..0000000 --- a/ghash-def.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -*-c-*- - * - * $Id: ghash-def.h,v 1.7 2004/04/08 01:36:15 mdw Exp $ - * - * Definitions for generic hash interface - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GHASH_DEF_H -#define CATACOMB_GHASH_DEF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#ifndef CATACOMB_ARENA_H -# include "arena.h" -#endif - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -#ifndef CATACOMB_PARANOIA_H -# include "paranoia.h" -#endif - -/*----- Generic hash function interface -----------------------------------*/ - -/* --- @GHASH_DEF@ --- * - * - * Arguments: @PRE, pre@ = prefixes for hash function - * - * Use: Defines the generic hash instance. - */ - -#define GHASH_DEF(PRE, pre) \ - \ -static const ghash_ops gops; \ - \ -typedef struct gctx { \ - ghash h; \ - pre##_ctx c; \ - octet buf[PRE##_HASHSZ]; \ -} gctx; \ - \ -static ghash *ghinit(void) \ -{ \ - gctx *g = S_CREATE(gctx); \ - g->h.ops = &gops; \ - pre##_init(&g->c); \ - return (&g->h); \ -} \ - \ -static void ghhash(ghash *h, const void *p, size_t sz) \ -{ \ - gctx *g = (gctx *)h; \ - pre##_hash(&g->c, p, sz); \ -} \ - \ -static octet *ghdone(ghash *h, void *buf) \ -{ \ - gctx *g = (gctx *)h; \ - if (!buf) \ - buf = g->buf; \ - pre##_done(&g->c, buf); \ - return (buf); \ -} \ - \ -static void ghdestroy(ghash *h) \ -{ \ - gctx *g = (gctx *)h; \ - BURN(*g); \ - S_DESTROY(g); \ -} \ - \ -static ghash *ghcopy(ghash *h) \ -{ \ - gctx *g = (gctx *)h; \ - gctx *gg = S_CREATE(gctx); \ - memcpy(gg, g, sizeof(gctx)); \ - return (&gg->h); \ -} \ - \ -static const ghash_ops gops = \ - { &pre, ghhash, ghdone, ghdestroy, ghcopy }; \ -const gchash pre = { #pre, PRE##_HASHSZ, ghinit, PRE##_BUFSZ }; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/ghash.h b/ghash.h deleted file mode 100644 index d20aff4..0000000 --- a/ghash.h +++ /dev/null @@ -1,156 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Generic hash function interface - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GHASH_H -#define CATACOMB_GHASH_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Generic hash function interface -----------------------------------*/ - -typedef struct ghash { - const struct ghash_ops *ops; /* Pointer to hash operations */ -} ghash; - -typedef struct ghash_ops { - const struct gchash *c; /* Pointer to hash class */ - void (*hash)(ghash */*h*/, const void */*p*/, size_t /*sz*/); /* Hash */ - octet *(*done)(ghash */*h*/, void */*buf*/); /* Write result */ - void (*destroy)(ghash */*h*/); /* Destroy hash block */ - ghash *(*copy)(ghash */*h*/); /* Make a copy of the hash context */ -} ghash_ops; - -#define GH_INIT(ch) (ch)->init() -#define GH_CLASS(h) (h)->ops->c -#define GH_HASH(h, p, sz) (h)->ops->hash((h), (p), (sz)) -#define GH_DONE(h, buf) (h)->ops->done((h), (buf)) -#define GH_DESTROY(h) (h)->ops->destroy((h)) -#define GH_COPY(h) (h)->ops->copy((h)) - -#define GH_HASHU_(h, n, W) do { \ - TY_U##W n_ = (n); octet b_[SZ_##W]; \ - STORE##W(b_, n_); GH_HASH((h), b_, SZ_##W); \ -} while (0) -#define GH_HASHU8(h, n) GH_HASHU_((h), (n), 8) -#define GH_HASHU16(h, n) GH_HASHU_((h), (n), 16) -#define GH_HASHU16_B(h, n) GH_HASHU_((h), (n), 16_B) -#define GH_HASHU16_L(h, n) GH_HASHU_((h), (n), 16_L) -#define GH_HASHU24(h, n) GH_HASHU_((h), (n), 24) -#define GH_HASHU24_B(h, n) GH_HASHU_((h), (n), 24_B) -#define GH_HASHU24_L(h, n) GH_HASHU_((h), (n), 24_L) -#define GH_HASHU32(h, n) GH_HASHU_((h), (n), 32) -#define GH_HASHU32_B(h, n) GH_HASHU_((h), (n), 32_B) -#define GH_HASHU32_L(h, n) GH_HASHU_((h), (n), 32_L) -#ifdef HAVE_UINT64 -# define GH_HASHU64(h, n) GH_HASHU_((h), (n), 64) -# define GH_HASHU64_B(h, n) GH_HASHU_((h), (n), 64_B) -# define GH_HASHU64_L(h, n) GH_HASHU_((h), (n), 64_L) -#endif - -#define GH_HASHBUF_(h, p, sz, W) do { \ - size_t sz_ = (sz); assert(sz_ <= MASK##W); \ - GH_HASHU_(h, sz_, W); GH_HASH(h, (p), sz_); \ -} while (0) -#define GH_HASHBUF8(h, p, sz) GH_HASHBUF_((h), (p), (sz), 8) -#define GH_HASHBUF16(h, p, sz) GH_HASHBUF_((h), (p), (sz), 16) -#define GH_HASHBUF16_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 16_L) -#define GH_HASHBUF16_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 16_B) -#define GH_HASHBUF24(h, p, sz) GH_HASHBUF_((h), (p), (sz), 24) -#define GH_HASHBUF24_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 24_L) -#define GH_HASHBUF24_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 24_B) -#define GH_HASHBUF32(h, p, sz) GH_HASHBUF_((h), (p), (sz), 32) -#define GH_HASHBUF32_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 32_L) -#define GH_HASHBUF32_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 32_B) -#ifdef HAVE_UINT64 -# define GH_HASHBUF64(h, p, sz) GH_HASHBUF_((h), (p), (sz), 64) -# define GH_HASHBUF64_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 64_L) -# define GH_HASHBUF64_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 64_B) -#endif - -#define GH_HASHSTR_(h, p, W) do { \ - const char *p_ = (p); GH_HASHBUF_((h), p_, strlen(p_), W); \ -} while (0) -#define GH_HASHSTR8(h, p) GH_HASHSTR_((h), (p), 8) -#define GH_HASHSTR16(h, p) GH_HASHSTR_((h), (p), 16) -#define GH_HASHSTR16_L(h, p) GH_HASHSTR_((h), (p), 16_L) -#define GH_HASHSTR16_B(h, p) GH_HASHSTR_((h), (p), 16_B) -#define GH_HASHSTR24(h, p) GH_HASHSTR_((h), (p), 24) -#define GH_HASHSTR24_L(h, p) GH_HASHSTR_((h), (p), 24_L) -#define GH_HASHSTR24_B(h, p) GH_HASHSTR_((h), (p), 24_B) -#define GH_HASHSTR32(h, p) GH_HASHSTR_((h), (p), 32) -#define GH_HASHSTR32_L(h, p) GH_HASHSTR_((h), (p), 32_L) -#define GH_HASHSTR32_B(h, p) GH_HASHSTR_((h), (p), 32_B) -#ifdef HAVE_UINT64 -# define GH_HASHSTR64(h, p) GH_HASHSTR_((h), (p), 64) -# define GH_HASHSTR64_L(h, p) GH_HASHSTR_((h), (p), 64_L) -# define GH_HASHSTR64_B(h, p) GH_HASHSTR_((h), (p), 64_B) -#endif - -#define GH_HASHSTRZ(h, p) do { \ - const char *p_ = (p); GH_HASH((h), p_, strlen(p_) + 1); \ -} while (0) -#define GH_HASHSTR(h, p) do { \ - const char *p_ = (p); GH_HASH((h), p_, strlen(p_)); \ -} while (0) - -typedef struct gchash { - const char *name; /* Name of the hash function */ - size_t hashsz; /* Size of output hash */ - ghash *(*init)(void); /* Create a new hash instance */ - size_t bufsz; /* Buffer size, or zero */ -} gchash; - -/*----- Tables ------------------------------------------------------------*/ - -extern const gchash *const ghashtab[]; - -/* --- @ghash_byname@ --- * - * - * Arguments: @const char *p@ = pointer to name string - * - * Returns: The named cipher class, or null. - */ - -extern const gchash *ghash_byname(const char */*p*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/gkcdsa.c b/gkcdsa.c deleted file mode 100644 index ed2b37d..0000000 --- a/gkcdsa.c +++ /dev/null @@ -1,311 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Generalized version of KCDSA - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "gkcdsa.h" -#include "group.h" -#include "ghash.h" -#include "mpbarrett.h" -#include "mprand.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @gkcdsa_beginhash@ --- * - * - * Arguments: @const gkcdsa *c@ = pointer to the context structure - * - * Returns: A hashing context for you to hash the message. - * - * Use: Initializes a hash function correctly for you to hash a - * message. Requires @h@, @g@ and @p@. - */ - -ghash *gkcdsa_beginhash(const gkcdsa *c) -{ - ghash *h = GH_INIT(c->h); - mp *v = G_TOINT(c->g, MP_NEW, c->p); - size_t sz = c->h->bufsz; - void *p = xmalloc(sz); - if (/*ouch*/ !v) memset(p, 0, sz); - else mp_storeb(v, p, sz); - GH_HASH(h, p, sz); - mp_drop(v); xfree(p); - return (h); -} - -/* --- @gkcdsa_endhash@ --- * - * - * Arguments: @const gkcdsa *c@ = pointer to the context structure - * @ghash *h@ = the hashing context - * - * Returns: --- - * - * Use: Does any final thing that KCDSA wants to do when hashing a - * message. (Actually, there's nothing.) The hashing context - * isn't finalized. - */ - -void gkcdsa_endhash(const gkcdsa *c, ghash *h) { ; } - -/* --- @hashge@ --- * - * - * Arguments: @group *g@ = abstract group - * @const gchash *hc@ = hash class - * @ge *w@ = a group element - * - * Returns: A hash context, with the hash of @w@ in it. - */ - -static ghash *hashge(group *g, const gchash *hc, ge *w) -{ - ghash *h; - size_t sz; - void *p; - buf b; - int rc; - - sz = hc->hashsz; - if (sz < g->noctets) - sz = g->noctets; - p = xmalloc(sz); - buf_init(&b, p, sz); - rc = G_TORAW(g, &b, w); - assert(rc == 0); - h = GH_INIT(hc); - GH_HASH(h, BBASE(&b), BLEN(&b)); - xfree(p); - return (h); -} - -/* --- @gkcdsa_sign@ --- * - * - * Arguments: @const gkcdsa *c@ = my context structure - * @gkcdsa_sig *s@ = where to put the signature (initialized) - * @const void *m@ = pointer to message hash - * @mp *k@ = random exponent for this message or null - * - * Returns: --- - * - * Use: Signs a message. Requires @g@, @u@, @h@, and @r@ if @k@ is - * null. This is a better idea than inventing @k@ yourself. - */ - -void gkcdsa_sign(const gkcdsa *c, gkcdsa_sig *s, const void *m, mp *k) -{ - group *g = c->g; - mp *x, *y; - ge *z = G_CREATE(g); - size_t hsz = c->h->hashsz; - ghash *h; - - if (k) { MP_COPY(k); goto have_k; } -new_k: - k = mprand_range(k, g->r, c->r, 0); -have_k: - if (MP_ZEROP(k)) goto new_k; - G_EXP(g, z, g->g, k); - if (!s->r) s->r = xmalloc(hsz); - h = hashge(g, c->h, z); GH_DONE(h, s->r); - - x = mp_loadb(s->s, m, hsz); - y = mp_loadb(MP_NEW, s->r, hsz); - x = mp_xor(x, x, y); - mp_div(0, &x, x, g->r); - x = mp_sub(x, g->r, x); - x = mp_add(x, x, k); - if (MP_CMP(x, >=, g->r)) x = mp_sub(x, x, g->r); - x = mp_mul(x, x, c->u); mp_div(0, &x, x, g->r); - s->s = x; - mp_drop(k); mp_drop(y); GH_DESTROY(h); G_DESTROY(g, z); -} - -/* --- @gkcdsa_verify@ --- * - * - * Arguments: @const gkcdsa *c@ = my context structure - * @const gkcdsa_sig *s@ = the signature to verify - * @const void *m@ = pointer to message hash - * - * Returns: Zero if OK, negative on failure. - * - * Use: Checks a signature on a message, Requires @g@, @p@, @h@. - */ - -int gkcdsa_verify(const gkcdsa *c, const gkcdsa_sig *s, const void *m) -{ - group *g = c->g; - size_t hsz = c->h->hashsz; - group_expfactor e[2]; - mp *x, *y; - ghash *h; - ge *z; - octet *p; - int rc = -1; - - if (MP_CMP(s->s, <, MP_ONE) || MP_CMP(s->s, >=, g->r)) - return (-1); - x = mp_loadb(MP_NEW, m, hsz); y = mp_loadb(MP_NEW, s->r, hsz); - x = mp_xor(x, x, y); mp_div(0, &x, x, g->r); - e[0].base = c->p; e[0].exp = s->s; - e[1].base = g->g; e[1].exp = x; - z = G_CREATE(g); G_MEXP(g, z, e, 2); - h = hashge(g, c->h, z); p = GH_DONE(h, 0); - if (memcmp(p, s->r, hsz) == 0) rc = 0; - mp_drop(x); mp_drop(y); G_DESTROY(g, z); GH_DESTROY(h); - return (rc); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static group *getgroup(const char *p) { - group *g; qd_parse qd; - qd.p = p; qd.e = 0; g = group_parse(&qd); - if (g && !qd_eofp(&qd)) { G_DESTROYGROUP(g); g = 0; qd.e = "junk at eof"; } - if (!g) { fprintf(stderr, "bad group string `%.*s|%s': %s\n", qd.p - p, - p, qd.p, qd.e); exit(1); } - return (g); -} - -static ge *getge(group *g, const char *p) { - ge *x = G_CREATE(g); - if (group_readstring(g, x, p, 0)) { - fprintf(stderr, "bad group element `%s'\n", p); - exit(1); - } - return (x); -} - -static void showge(group *g, const char *p, ge *x) { - fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr); - putc('\n', stderr); -} - -static void showmp(const char *p, mp *x, int r) { - fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r); - putc('\n', stderr); -} - -static int tsign(dstr *v) -{ - gdsa c; - gkcdsa_sig s, ss = GKCDSA_SIG_INIT; - ghash *h; - mp *k; - dstr d = DSTR_INIT; - mp *x; - int ok = 1; - - c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf); - c.u = *(mp **)v[2].buf; k = *(mp **)v[4].buf; - s.r = (octet *)v[5].buf; s.s = *(mp **)v[6].buf; - DENSURE(&d, c.h->hashsz); d.len = c.h->hashsz; memset(d.buf, 0, d.len); - ss.r = (octet *)d.buf; - - x = mp_modinv(MP_NEW, c.u, c.g->r); - c.p = G_CREATE(c.g); G_EXP(c.g, c.p, c.g->g, x); - h = gkcdsa_beginhash(&c); - GH_HASH(h, v[3].buf, v[3].len); - gkcdsa_endhash(&c, h); - gkcdsa_sign(&c, &ss, GH_DONE(h, 0), k); - if (memcmp(s.r, ss.r, c.h->hashsz) || !MP_EQ(s.s, ss.s)) { - ok = 0; - fprintf(stderr, "*** sign failed!\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - fprintf(stderr, "*** hash: %s\n", c.h->name); - showmp("private key", c.u, 16); - showge(c.g, "public key", c.p); - fprintf(stderr, "*** message: `%s'\n", v[3].buf); - fprintf(stderr, "*** computed r = "); - type_hex.dump(&d, stderr); putc('\n', stderr); - showmp("computed s", ss.s, 16); - fprintf(stderr, "*** computed r = "); - type_hex.dump(&v[5], stderr); putc('\n', stderr); - showmp("expected s", s.s, 16); - } - mp_drop(s.s); dstr_destroy(&d); mp_drop(ss.s); mp_drop(x); mp_drop(k); - mp_drop(c.u); G_DESTROY(c.g, c.p); G_DESTROYGROUP(c.g); GH_DESTROY(h); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tverify(dstr *v) -{ - gkcdsa c; - gkcdsa_sig s; - ghash *h; - int rc, erc; - int ok = 1; - - c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf); - c.p = getge(c.g, v[2].buf); - s.r = (octet *)v[4].buf; s.s = *(mp **)v[5].buf; - erc = *(int *)v[6].buf; - - h = gkcdsa_beginhash(&c); - GH_HASH(h, v[3].buf, v[3].len); - gkcdsa_endhash(&c, h); - rc = gkcdsa_verify(&c, &s, GH_DONE(h, 0)); - if (!rc != !erc) { - ok = 0; - fprintf(stderr, "*** verify failed!\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - fprintf(stderr, "*** hash: %s\n", c.h->name); - showge(c.g, "public key", c.p); - fprintf(stderr, "*** message: `%s'\n", v[3].buf); - fprintf(stderr, "*** sig r = "); - type_hex.dump(&v[4], stderr); putc('\n', stderr); - showmp("sig s", s.s, 16); - fprintf(stderr, "*** expected %s\n", !erc ? "pass" : "fail"); - } - mp_drop(s.s); G_DESTROY(c.g, c.p); G_DESTROYGROUP(c.g); - GH_DESTROY(h); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static const test_chunk tests[] = { - { "sign", tsign, { &type_string, &type_string, &type_mp, &type_string, - &type_mp, &type_hex, &type_mp } }, - { "verify", tverify, { &type_string, &type_string, &type_string, - &type_string, &type_hex, &type_mp, &type_int } }, - { 0 } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/gkcdsa"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/gkcdsa.h b/gkcdsa.h deleted file mode 100644 index 9dc893e..0000000 --- a/gkcdsa.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Generalized version of KCDSA - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GKCDSA_H -#define CATACOMB_GKCDSA_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GROUP_H -# include "group.h" -#endif - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -#ifndef CATACOMB_GDSA_H -# include "gdsa.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- Careful! --- * - * - * These structures are the same as for DSA. However, the private key @u@ is - * the %$\emph{inverse}$% of the exponent. Do this wrong and the maths will - * fail hopelessly. - */ - -typedef gdsa gkcdsa; - -typedef struct gkcdsa_sig { - octet *r; /* Null means @xmalloc@ me */ - mp *s; -} gkcdsa_sig; -#define GKCDSA_SIG_INIT { 0, 0 } - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @gkcdsa_beginhash@ --- * - * - * Arguments: @const gkcdsa *c@ = pointer to the context structure - * - * Returns: A hashing context for you to hash the message. - * - * Use: Initializes a hash function correctly for you to hash a - * message. Requires @h@, @g@ and @p@. - */ - -extern ghash *gkcdsa_beginhash(const gkcdsa */*c*/); - -/* --- @gkcdsa_endhash@ --- * - * - * Arguments: @const gkcdsa *c@ = pointer to the context structure - * @ghash *h@ = the hashing context - * - * Returns: --- - * - * Use: Does any final thing that KCDSA wants to do when hashing a - * message. (Actually, there's nothing.) The hashing context - * isn't finalized. - */ - -extern void gkcdsa_endhash(const gkcdsa */*c*/, ghash */*h*/); - -/* --- @gkcdsa_sign@ --- * - * - * Arguments: @const gkcdsa *c@ = my context structure - * @gkcdsa_sig *s@ = where to put the signature (initialized) - * @const void *m@ = pointer to message hash - * @mp *k@ = random exponent for this message or null - * - * Returns: --- - * - * Use: Signs a message. Requires @g@, @u@, @h@, and @r@ if @k@ is - * null. This is a better idea than inventing @k@ yourself. - */ - -extern void gkcdsa_sign(const gkcdsa */*c*/, gkcdsa_sig */*s*/, - const void */*m*/, mp */*k*/); - -/* --- @gkcdsa_verify@ --- * - * - * Arguments: @const gkcdsa *c@ = my context structure - * @const gkcdsa_sig *s@ = the signature to verify - * @const void *m@ = pointer to message hash - * - * Returns: Zero if OK, negative on failure. - * - * Use: Checks a signature on a message, Requires @g@, @p@, @h@. - */ - -extern int gkcdsa_verify(const gkcdsa */*c*/, const gkcdsa_sig */*s*/, - const void */*m*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/gmac.h b/gmac.h deleted file mode 100644 index 096c36d..0000000 --- a/gmac.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -*-c-*- - * - * $Id: gmac.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Generic MAC function interface - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GMAC_H -#define CATACOMB_GMAC_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Generic MAC function interface ------------------------------------*/ - -typedef struct gmac { - const struct gmac_ops *ops; /* Pointer to MAC operations */ -} gmac; - -typedef struct gmac_ops { - const struct gcmac *c; /* Pointer to MAC class */ - ghash *(*init)(gmac */*m*/); /* Create keyed hash instance */ - void (*destroy)(gmac */*m*/); /* Destroy MAC key block */ -} gmac_ops; - -typedef struct gcmac { - const char *name; /* Name of the MAC function */ - size_t hashsz; /* Size of output hash */ - const octet *keysz; /* Key size options */ - gmac *(*key)(const void */*k*/, size_t /*sz*/); /* Create key */ -} gcmac; - -#define GM_KEY(cm, k, ksz) (cm)->key((k), (ksz)) -#define GM_CLASS(km) (km)->ops->c -#define GM_INIT(km) (km)->ops->init((km)) -#define GM_DESTROY(km) (km)->ops->destroy((km)) - -/*----- Tables ------------------------------------------------------------*/ - -extern const gcmac *const gmactab[]; - -/* --- @gmac_byname@ --- * - * - * Arguments: @const char *p@ = pointer to name string - * - * Returns: The named cipher class, or null. - */ - -extern const gcmac *gmac_byname(const char */*p*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/grand.c b/grand.c deleted file mode 100644 index 0fa4e16..0000000 --- a/grand.c +++ /dev/null @@ -1,157 +0,0 @@ -/* -*-c-*- - * - * $Id: grand.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Generic interface to random number generators - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#include "grand.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @grand_byte@ --- * - * - * Arguments: @grand *r@ = pointet to generic generator - * - * Returns: A uniformly-distributed pseudorandom integer in the interval - * %$[0, 256)$%. - */ - -octet grand_byte(grand *r) -{ - if (r->ops->byte != grand_byte) - return (r->ops->byte(r)); - else if (r->ops->word != grand_word) - return (r->ops->word(r) & 0xff); - else if (r->ops->fill != grand_fill) { - octet o; - r->ops->fill(r, &o, 1); - return (o); - } else - return (grand_range(r, 256)); -} - -/* --- @grand_word@ --- * - * - * Arguments: @grand *r@ = pointet to generic generator - * - * Returns: A uniformly-distributed pseudorandom integer in the interval - * %$[0, 2^{32})$%. - */ - -uint32 grand_word(grand *r) -{ - if (r->ops->word != grand_word) - return (r->ops->word(r)); - else { - octet b[4]; - grand_fill(r, b, sizeof(b)); - return (LOAD32(b)); - } -} - -/* --- @grand_range@ --- * - * - * Arguments: @grand *r@ = pointet to generic generator - * @uint32 l@ = limit for acceptable results - * - * Returns: A uniformly-distributed pseudorandom integer in the interval - * %$[0, l)$%. - */ - -uint32 grand_range(grand *r, uint32 l) -{ - if (r->ops->range != grand_range) - return (r->ops->range(r, l)); - else { - uint32 m, z; - uint32 (*w)(grand */*r*/); - uint32 x; - - /* --- Decide where to get data from --- * - * - * The choice of %$2^{32} - 1$% as a limit when using @grand_word@ isn't - * wonderful, but working with %$2^{32}$% is awkward and the loss of a - * few return values isn't significant. The algorithm below still - * successfully returns uniformly distributed results. - */ - - if (r->ops->max) { - w = r->ops->raw; - m = r->ops->max; - } else { - w = grand_word; - m = 0xffffffff; - } - - /* --- Work out maximum acceptable return value --- * - * - * This will be the highest multiple of @l@ less than @m@. - */ - - z = m - (m % l); - - /* --- Generate numbers until something acceptable is found --- * - * - * This will require an expected number of attempts less than 2. - */ - - do x = w(r); while (x >= z); - return (x % l); - } -} - -/* --- @grand_fill@ --- * - * - * Arguments: @grand *r@ = pointet to generic generator - * @void *p@ = pointer to a buffer - * @size_t sz@ = size of the buffer - * - * Returns: --- - * - * Use: Fills a buffer with uniformly distributed pseudorandom bytes - * (see @grand_byte@). - */ - -void grand_fill(grand *r, void *p, size_t sz) -{ - if (r->ops->fill != grand_fill) - r->ops->fill(r, p, sz); - else { - octet *q = p; - while (sz) { - *q++ = r->ops->byte(r); - sz--; - } - } -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/grand.h b/grand.h deleted file mode 100644 index 49ac3b4..0000000 --- a/grand.h +++ /dev/null @@ -1,163 +0,0 @@ -/* -*-c-*- - * - * $Id: grand.h,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Generic interface to random number generators - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GRAND_H -#define CATACOMB_GRAND_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -/*----- Generic random number generator interface -------------------------*/ - -typedef struct grand { - const struct grand_ops *ops; -} grand; - -typedef struct grand_ops { - - /* --- Various important properties --- */ - - const char *name; /* Generator's name */ - unsigned f; /* Various flags */ - uint32 max; /* Maximum raw output */ - - /* --- Maintenance methods --- */ - - int (*misc)(grand */*r*/, unsigned /*op*/, ...); /* Miscellaneous ops */ - void (*destroy)(grand */*r*/); /* Destroy generator context */ - - /* --- Output methods --- * - * - * Only one of these operations need actually be implemented. All the - * other operations may be synthesized. Of course, performance is improved - * if more are provided. - */ - - uint32 (*raw)(grand */*r*/); /* Uniform over %$[0, max)$% */ - octet (*byte)(grand */*r*/); /* Uniform over %$[0, 256)$% */ - uint32 (*word)(grand */*r*/); /* Uniform over %$[0, 2^{32})$% */ - uint32 (*range)(grand */*r*/, uint32 /*l*/); /* Uniform over %$[0, l)$% */ - void (*fill)(grand */*r*/, void */*p*/, size_t /*sz*/); /* Fill buffer */ -} grand_ops; - -#define GR_DESTROY(r) (r)->ops->destroy((r)) -#define GR_RAW(r) (r)->ops->raw((r)) -#define GR_WORD(r) (r)->ops->word((r)) -#define GR_RANGE(r, l) (r)->ops->range((r), (l)) -#define GR_FILL(r, p, sz) (r)->ops->fill((r), (p), (sz)) - -/* --- Flag types --- */ - -#define GRAND_CRYPTO 1u /* Cryptographically strong */ - -/* --- Operation types --- */ - -enum { - - /* --- Required operations --- */ - - GRAND_CHECK, /* @unsigned op2@ */ - - /* --- Standard seeding operations --- */ - - GRAND_SEEDINT, /* @int i@ */ - GRAND_SEEDUINT32, /* @uint32 i@ */ - GRAND_SEEDBLOCK, /* @const void *p, size_t sz@ */ - GRAND_SEEDMP, /* @mp *m@ */ - GRAND_SEEDRAND /* @grand *g@ */ - - /* --- Generator-specific operations --- */ - -#define GRAND_SPECIFIC(ch) ((unsigned)(ch) << 8) -}; - -#define GRAND_BADOP assert(((void)"bad grand_misc op", 0)) - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @grand_byte@ --- * - * - * Arguments: @grand *r@ = pointet to generic generator - * - * Returns: A uniformly-distributed pseudorandom integer in the interval - * %$[0, 256)$%. - */ - -extern octet grand_byte(grand */*r*/); - -/* --- @grand_word@ --- * - * - * Arguments: @grand *r@ = pointet to generic generator - * - * Returns: A uniformly-distributed pseudorandom integer in the interval - * %$[0, 2^{32})$%. - */ - -extern uint32 grand_word(grand */*r*/); - -/* --- @grand_range@ --- * - * - * Arguments: @grand *r@ = pointet to generic generator - * @uint32 l@ = limit for acceptable results - * - * Returns: A uniformly-distributed pseudorandom integer in the interval - * %$[0, l)$%. - */ - -extern uint32 grand_range(grand */*r*/, uint32 /*l*/); - -/* --- @grand_fill@ --- * - * - * Arguments: @grand *r@ = pointet to generic generator - * @void *p@ = pointer to a buffer - * @size_t sz@ = size of the buffer - * - * Returns: --- - * - * Use: Fills a buffer with uniformly distributed pseudorandom bytes - * (see @grand_byte@). - */ - -extern void grand_fill(grand */*r*/, void */*p*/, size_t /*sz*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/group-dstr.c b/group-dstr.c deleted file mode 100644 index f41b978..0000000 --- a/group-dstr.c +++ /dev/null @@ -1,85 +0,0 @@ -/* -*-c-*- - * - * $Id: group-dstr.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Dynamic string I/O for group elements - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "group.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @group_readdstr@ --- * - * - * Arguments: @group *g@ = an abstract group - * @ge *d@ = destination group element - * @dstr *dd@ = string to read from - * @size_t *off@ = offset to start at (updated) - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Parses a group element from a dynamic string. - */ - -int group_readdstr(group *g, ge *d, dstr *dd, size_t *off) -{ - mptext_dstrctx md; - - md.d = dd; - md.i = off ? *off : 0; - if (G_READ(g, d, &mptext_dstrops, &md)) - return (-1); - if (off) *off = md.i; - return (0); -} - -/* --- @group_writedstr@ --- * - * - * Arguments: @group *g@ = an abstract group - * @ge *x@ = a group element - * @dstr *d@ = string to write to - * @size_t sz@ = how long the buffer is - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Writes a group element to a dstr buffer. - */ - -int group_writedstr(group *g, ge *x, dstr *d) -{ - mptext_dstrctx md; - - md.d = d; - if (G_WRITE(g, x, &mptext_dstrops, &md)) - return (-1); - DPUTZ(d); - return (0); -} - - - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/group-exp.c b/group-exp.c deleted file mode 100644 index a706125..0000000 --- a/group-exp.c +++ /dev/null @@ -1,109 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Exponentiation for abstract groups - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "group.h" -#include "group-exp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @group_stdexp@ --- * - * - * Arguments: @group *g@ = abstract group - * @ge *d@ = destination pointer - * @ge *x@ = base element - * @mp *n@ = exponent - * - * Returns: --- - * - * Use: Computes %$d = x^n$% efficiently. - */ - -void group_stdexp(group *gg, ge *d, ge *x, mp *n) -{ - ge *t = G_CREATE(gg); - - G_COPY(gg, t, x); - MP_SHRINK(n); - G_COPY(gg, d, gg->i); - if (n->f & MP_BURN) - G_BURN(gg, t); - if (MP_ZEROP(n)) - ; - else { - if (MP_NEGP(n)) - G_INV(gg, t, t); - if (MP_LEN(n) < EXP_THRESH) - EXP_SIMPLE(d, t, n); - else - EXP_WINDOW(d, t, n); - } - G_DESTROY(gg, t); -} - -/* --- @group_stdmexp@ --- * - * - * Arguments: @group *g@ = abstract group - * @ge *d@ = destination pointer - * @const group_expfactor *f@ = vector of factors - * @size_t n@ = number of factors - * - * Returns: --- - * - * Use: Computes %$d = g_0^{x_0} g_1^{x_1} \ldots$% efficiently. - */ - -#undef EXP_WINSZ -#define EXP_WINSZ 3 - -void group_stdmexp(group *gg, ge *d, const group_expfactor *f, size_t n) -{ - group_expfactor *ff = xmalloc(n * sizeof(group_expfactor)); - size_t i; - - for (i = 0; i < n; i++) { - ff[i].base = G_CREATE(gg); - MP_SHRINK(f[i].exp); - if (MP_NEGP(f[i].exp)) - G_INV(gg, ff[i].base, f[i].base); - else - G_COPY(gg, ff[i].base, f[i].base); - if (f[i].exp->f & MP_BURN) - G_BURN(gg, ff[i].base); - ff[i].exp = f[i].exp; - } - G_COPY(gg, d, gg->i); - EXP_SIMUL(d, ff, n); - for (i = 0; i < n; i++) - G_DESTROY(gg, ff[i].base); - xfree(ff); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/group-exp.h b/group-exp.h deleted file mode 100644 index 6f1c1c5..0000000 --- a/group-exp.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*-c-*- - * - * $Id: group-exp.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Exponentiation operations for abstract groups - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GROUP_EXP_H -#define CATACOMB_GROUP_EXP_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Exponentation definitions -----------------------------------------*/ - -#define EXP_TYPE ge * - -#define EXP_COPY(d, p) do { \ - (d) = G_CREATE(gg); \ - G_COPY(gg, (d), (p)); \ -} while (0) -#define EXP_DROP(x) G_DESTROY(gg, (x)) - -#define EXP_MUL(a, x) G_MUL(gg, (a), (a), (x)) -#define EXP_SQR(a) G_SQR(gg, (a), (a)); -#define EXP_FIX(x) - -#define EXP_SETMUL(d, x, y) do { \ - (d) = G_CREATE(gg); \ - G_MUL(gg, (d), (x), (y)); \ -} while (0) -#define EXP_SETSQR(d, x) do { \ - (d) = G_CREATE(gg); \ - G_SQR(gg, (d), (x)); \ -} while (0) - -#include "exp.h" - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/group-file.c b/group-file.c deleted file mode 100644 index 212e26e..0000000 --- a/group-file.c +++ /dev/null @@ -1,64 +0,0 @@ -/* -*-c-*- - * - * $Id: group-file.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * File I/O for group elements - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "group.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @group_readfile@ --- * - * - * Arguments: @group *g@ = an abstract group - * @ge *d@ = destination group element - * @FILE *fp@ = the file to read from - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Parses a group element from a file. - */ - -int group_readfile(group *g, ge *d, FILE *fp) - { return (G_READ(g, d, &mptext_fileops, fp)); } - -/* --- @group_writefile@ --- * - * - * Arguments: @group *g@ = an abstract group - * @ge *x@ = a group element - * @FILE *fp@ = the file to write on - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Writes a group element to a file. - */ - -int group_writefile(group *g, ge *x, FILE *fp) - { return (G_WRITE(g, x, &mptext_fileops, fp)); } - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/group-guts.h b/group-guts.h deleted file mode 100644 index 42ab20d..0000000 --- a/group-guts.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Internal structures for built-in groups - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GROUP_GUTS_H -#define CATACOMB_GROUP_GUTS_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_EC_H -# include "ec.h" -#endif - -#ifndef CATACOMB_MPMONT_H -# include "mpmont.h" -#endif - -#ifndef CATACOMB_GFREDUCE_H -# include "gfreduce.h" -#endif - -#ifndef CATACOMB_GROUP_H -# include "group.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct gctx_prime { - group g; - mp *gen; - mpmont mm; -} gctx_prime; - -typedef struct gctx_ec { - group g; - ec id, gen; - ec_info ei; -} gctx_ec; - -typedef struct gctx_bin { - group g; - mp *gen; - mp *one; - gfreduce r; -} gctx_bin; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/group-parse.c b/group-parse.c deleted file mode 100644 index 7711952..0000000 --- a/group-parse.c +++ /dev/null @@ -1,97 +0,0 @@ -/* -*-c-*- - * - * $Id: group-parse.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Parse group description strings - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Trivial IP Encryption (TrIPE). - * - * TrIPE 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 2 of the License, or - * (at your option) any later version. - * - * TrIPE 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 TrIPE; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "group.h" -#include "dh.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @group_parse@ --- * - * - * Arguments: @qd_parse *qd@ = quick-and-dirty parser - * - * Returns: Group pointer, or null for failure. - * - * Use: Parses a group description and returns the group. This has - * the form `TYPE { SPEC }' where TYPE is `prime' or `ec', and - * SPEC is the appropriate kind of group specification of the - * given type. - */ - -group *group_parse(qd_parse *qd) -{ - group *g = 0; - - switch (qd_enum(qd, "prime,ec")) { - case 0: { - dh_param dp; - qd_delim(qd, '{'); - if (dh_parse(qd, &dp)) goto ouch; - qd_delim(qd, '}'); - g = group_prime(&dp); - dh_paramfree(&dp); - } break; - case 1: { - ec_info ei; - qd_delim(qd, '{'); - if (ec_infoparse(qd, &ei)) goto ouch; - qd_delim(qd, '}'); - g = group_ec(&ei); - } break; - } - if (!g) qd->e = "bad group parameters"; -ouch: - return (g); -} - -/* --- @group_fromstring@ --- * - * - * Arguments: @const char *p@ = pointer to string to read - * @group **gg@ = where to put the group pointer - * - * Returns: Null if OK, or an error string. - * - * Use: Parses a group spec from a string, and returns the group. - */ - -const char *group_fromstring(const char *p, group **gg) -{ - group *g; - qd_parse qd; - - qd.p = p; - qd.e = 0; - if ((g = group_parse(&qd)) == 0) return (qd.e); - if (!qd_eofp(&qd)) { G_DESTROYGROUP(g); return ("junk at end of string"); } - *gg = g; - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/group-stdops.c b/group-stdops.c deleted file mode 100644 index 77f48f7..0000000 --- a/group-stdops.c +++ /dev/null @@ -1,168 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Standard group operations - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "group.h" -#include "pgen.h" - -/*----- Handy functions ---------------------------------------------------*/ - -/* --- @group_check@ --- * - * - * Arguments: @group *g@ = an abstract group - * @ge *x@ = a group element - * - * Returns: Zero on success, nonzero for failure. - * - * Use: Checks that @x@ is a valid group element. This may take a - * while, since it checks that %$x \ne 1$% and %$x^r = 1$%. - */ - -int group_check(group *g, ge *x) -{ - ge *d = G_CREATE(g); - int rc; - - G_EXP(g, d, x, g->r); - rc = (G_IDENTP(g, d) && !G_IDENTP(g, x)); - G_DESTROY(g, d); - if (!rc) return (-1); - return (0); -} - -/* --- @group_samep@ --- * - * - * Arguments: @group *g, *h@ = two abstract groups - * - * Returns: Nonzero if the groups are in fact identical (not just - * isomorphic). - * - * Use: Checks to see whether two groups are actually the same. This - * function does the full check: the group operatrion @samep@ - * just does the group-specific details. - */ - -int group_samep(group *g, group *h) -{ - return (g == h || (g->ops == h->ops && - MP_EQ(g->r, h->r) && MP_EQ(g->h, h->h) && - G_EQ(g, g->i, h->i) && G_EQ(g, g->g, h->g) && - G_SAMEP(g, h))); -} - -/*----- Standard implementations ------------------------------------------*/ - -/* --- @group_stdidentp@ --- * - * - * Arguments: @group *g@ = abstract group - * @ge *x@ = group element - * - * Returns: Nonzero if %$x$% is the group identity. - */ - -int group_stdidentp(group *g, ge *x) { return (G_EQ(g, x, g->i)); } - -/* --- @group_stdsqr@ --- * - * - * Arguments: @group *g@ = abstract group - * @ge *d@ = destination pointer - * @ge *x@ = group element - * - * Returns: --- - * - * Use: Computes %$d = x^2$% as %$d = x x$%. - */ - -void group_stdsqr(group *g, ge *d, ge *x) { G_MUL(g, d, x, x); } - -/* --- @group_stddiv@ --- * - * - * Arguments: @group *g@ = abstract group - * @ge *d@ = destination pointer - * @ge *x@ = dividend - * @ge *y@ = divisor - * - * Returns: --- - * - * Use: Computes %$d = x/y$% as %$d = x y^{-1}$%. - */ - -void group_stddiv(group *g, ge *d, ge *x, ge *y) - { G_INV(g, d, y); G_MUL(g, d, x, d); } - -/* --- @group_stdtoec@ --- * - * - * Arguments: @group *g@ = abstract group - * @ec *d@ = destination point - * @ge *x@ = group element - * - * Returns: @-1@, indicating failure. - * - * Use: Fails to convert a group element to an elliptic curve point. - */ - -int group_stdtoec(group *g, ec *d, ge *x) { return (-1); } - -/* --- @group_stdfromec@ --- * - * - * Arguments: @group *g@ = abstract group - * @ge *d@ = destination pointer - * @const ec *p@ = elliptic curve point - * - * Returns: Zero for success, @-1@ on failure. - * - * Use: Converts %$p$% to a group element by converting its %$x$%- - * coordinate. - */ - -int group_stdfromec(group *g, ge *d, const ec *p) - { if (EC_ATINF(p)) return (-1); return (G_FROMINT(g, d, p->x)); } - -/* --- @group_stdcheck@ --- * - * - * Arguments: @group *g@ = abstract group - * @grand *gr@ = random number source. - * - * Returns: Null on success, or a pointer to an error message. - */ - -const char *group_stdcheck(group *g, grand *gr) -{ - ge *t; - int rc; - - if (!pgen_primep(g->r, gr)) return ("group order not prime"); - t = G_CREATE(g); G_EXP(g, t, g->g, g->r); - rc = G_IDENTP(g, t); G_DESTROY(g, t); - if (!rc) return ("generator not in the group"); - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/group-string.c b/group-string.c deleted file mode 100644 index 7753d97..0000000 --- a/group-string.c +++ /dev/null @@ -1,84 +0,0 @@ -/* -*-c-*- - * - * $Id: group-string.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * String I/O for group elements - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "group.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @group_readstring@ --- * - * - * Arguments: @group *g@ = an abstract group - * @ge *d@ = destination group element - * @const char *p@ = where the string is - * @char **end@ = where to put the end pointer - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Parses a group element from a string. - */ - -int group_readstring(group *g, ge *d, const char *p, char **end) -{ - mptext_stringctx ms; - - ms.buf = (/*unconst*/ char *)p; - ms.lim = (/*unconst*/ char *)p + strlen(p); - if (G_READ(g, d, &mptext_stringops, &ms)) - return (-1); - if (end) *end = ms.buf; - return (0); -} - -/* --- @group_writestring@ --- * - * - * Arguments: @group *g@ = an abstract group - * @ge *x@ = a group element - * @char *p@ = where the string should go - * @size_t sz@ = how long the buffer is - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Writes a group element to a string buffer. - */ - -int group_writestring(group *g, ge *x, char *p, size_t sz) -{ - mptext_stringctx ms; - - ms.buf = p; - ms.lim = p + sz - 1; - if (G_WRITE(g, x, &mptext_stringops, &ms)) - return (-1); - *ms.buf = 0; - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/group-test.c b/group-test.c deleted file mode 100644 index 5608ec0..0000000 --- a/group-test.c +++ /dev/null @@ -1,563 +0,0 @@ -/* -*-c-*- - * - * $Id: group-test.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Testing group operations - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#include "group.h" -#include "fibrand.h" -#include "ec.h" -#include "ec-test.h" - -/*----- Main code ---------------------------------------------------------*/ - -static group *getgroup(const char *p) { - group *g; qd_parse qd; - qd.p = p; qd.e = 0; g = group_parse(&qd); - if (g && !qd_eofp(&qd)) { G_DESTROYGROUP(g); g = 0; qd.e = "junk at eof"; } - if (!g) { fprintf(stderr, "bad group string `%.*s|%s': %s\n", qd.p - p, - p, qd.p, qd.e); exit(1); } - return (g); -} - -static ge *getge(group *g, const char *p) { - ge *x = G_CREATE(g); - if (group_readstring(g, x, p, 0)) { - fprintf(stderr, "bad group element `%s'\n", p); - exit(1); - } - return (x); -} - -static void show(group *g, const char *p, ge *x) { - fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr); - putc('\n', stderr); -} - -static void showec(const char *p, ec *q) { - fprintf(stderr, "*** %s = ", p); - if (EC_ATINF(q)) fprintf(stderr, "inf\n"); - else { - mp_writefile(q->x, stderr, 16); fputs(", ", stderr); - mp_writefile(q->x, stderr, 16); putchar('\n'); - } -} - -static void showmp(const char *p, mp *x, int r) { - fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r); - putc('\n', stderr); -} - -static int check(const char *op, const char *gd, group *g, - ge *r, ge *c, ...) { - va_list ap; - - if (G_EQ(g, r, c)) return (1); - fprintf(stderr, "\n*** %s failed\n", op); - fprintf(stderr, "*** group: %s\n", gd); - va_start(ap, c); - for (;;) { - const char *p; ge *x; - p = va_arg(ap, const char *); if (!p) break; - x = va_arg(ap, ge *); show(g, p, x); - } - show(g, "expected", r); - show(g, "computed", c); - return (0); -} - -/*----- Actual tests ------------------------------------------------------*/ - -static int vcheck(dstr *v) -{ - group *g = getgroup(v[0].buf); - grand *gr = fibrand_create(0); - const char *e = G_CHECK(g, gr); - int ok = 1; - gr->ops->destroy(gr); - if (!e) e = "ok"; - G_DESTROYGROUP(g); - if (strcmp(e, v[1].buf)) { - ok = 0; - fprintf(stderr, "*** check failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - fprintf(stderr, "*** expected: %s\n", v[1].buf); - fprintf(stderr, "*** returned: %s\n", e); - } - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vcheckelt(dstr *v) -{ - group *g = getgroup(v[0].buf); - ge *x = getge(g, v[1].buf); - int ir = *(int *)v[2].buf; - int ic = group_check(g, x); - int ok = 1; - if (ir != ic) { - ok = 0; - fprintf(stderr, "*** check failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - show(g, "x", x); - fprintf(stderr, "*** expected %s\n", ir ? "failure" : "success"); - } - G_DESTROY(g, x); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vmul(dstr *v) -{ - group *g = getgroup(v[0].buf); - ge *x = getge(g, v[1].buf); - ge *y = getge(g, v[2].buf); - ge *r = getge(g, v[3].buf); - ge *c = G_CREATE(g); - int ok = 1; - G_MUL(g, c, x, y); - ok &= check("mul", v[0].buf, g, r, c, "x", x, "y", y, (char *)0); - G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vsqr(dstr *v) -{ - group *g = getgroup(v[0].buf); - ge *x = getge(g, v[1].buf); - ge *r = getge(g, v[2].buf); - ge *c = G_CREATE(g); - int ok = 1; - G_SQR(g, c, x); - ok &= check("sqr", v[0].buf, g, r, c, "x", x, (char *)0); - G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vinv(dstr *v) -{ - group *g = getgroup(v[0].buf); - ge *x = getge(g, v[1].buf); - ge *r = getge(g, v[2].buf); - ge *c = G_CREATE(g); - int ok = 1; - G_INV(g, c, x); - ok &= check("inv", v[0].buf, g, r, c, "x", x, (char *)0); - G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vdiv(dstr *v) -{ - group *g = getgroup(v[0].buf); - ge *x = getge(g, v[1].buf); - ge *y = getge(g, v[2].buf); - ge *r = getge(g, v[3].buf); - ge *c = G_CREATE(g); - int ok = 1; - G_DIV(g, c, x, y); - ok &= check("div", v[0].buf, g, r, c, "x", x, "y", y, (char *)0); - group_stddiv(g, c, x, y); - ok &= check("stddiv", v[0].buf, g, r, c, "x", x, "y", y, (char *)0); - G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vexp(dstr *v) -{ - group *g = getgroup(v[0].buf); - ge *x = getge(g, v[1].buf); - mp *n = *(mp **)v[2].buf; - ge *r = getge(g, v[3].buf); - ge *c = G_CREATE(g); - int ok = 1; - G_EXP(g, c, x, n); - if (!G_EQ(g, r, c)) { - ok = 0; - fprintf(stderr, "\n*** exp failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - show(g, "x", x); showmp("n", n, 10); - show(g, "expected", r); show(g, "computed", c); - } - group_stdexp(g, c, x, n); - if (!G_EQ(g, r, c)) { - ok = 0; - fprintf(stderr, "\n*** stdexp failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - show(g, "x", x); showmp("n", n, 10); - show(g, "expected", r); show(g, "computed", c); - } - G_DESTROY(g, x); MP_DROP(n); G_DESTROY(g, r); G_DESTROY(g, c); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vmexp(size_t n, dstr *v) -{ - group *g = getgroup(v[0].buf); - ge *c, *r; - group_expfactor *f = xmalloc(n * sizeof(group_expfactor)); - int ok = 1; - size_t i; - for (i = 0; i < n; i++) { - f[i].base = getge(g, v[1 + 2 * i].buf); - f[i].exp = *(mp **)v[2 + 2 * i].buf; - } - r = getge(g, v[1 + 2 * n].buf); - c = G_CREATE(g); - G_MEXP(g, c, f, n); - if (!G_EQ(g, r, c)) { - ok = 0; - fprintf(stderr, "\n*** mexp failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - for (i = 0; i < n; i++) { - show(g, "base", f[i].base); - showmp("exp", f[i].exp, 10); - } - show(g, "expected", r); show(g, "computed", c); - } - group_stdmexp(g, c, f, n); - if (!G_EQ(g, r, c)) { - ok = 0; - fprintf(stderr, "\n*** stdmexp failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - for (i = 0; i < n; i++) { - show(g, "base", f[i].base); - showmp("exp", f[i].exp, 10); - } - show(g, "expected", r); show(g, "computed", c); - } - for (i = 0; i < n; i++) { G_DESTROY(g, f[i].base); MP_DROP(f[i].exp); } - G_DESTROY(g, r); G_DESTROY(g, c); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vmexp1(dstr *v) { return vmexp(1, v); } -static int vmexp2(dstr *v) { return vmexp(2, v); } -static int vmexp3(dstr *v) { return vmexp(3, v); } -static int vmexp4(dstr *v) { return vmexp(4, v); } - -static int vtoint(dstr *v) -{ - group *g = getgroup(v[0].buf); - ge *x = getge(g, v[1].buf); - int ir = *(int *)v[2].buf; - mp *r = *(mp **)v[3].buf; - mp *c; - int ic; - int ok = 1; - c = G_TOINT(g, MP_NEW, x); - ic = c ? 0 : -1; - if (ir != ic || (!ic && !MP_EQ(r, c))) { - ok = 0; - fprintf(stderr, "\n*** toint failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - if (ir) fprintf(stderr, "*** expected failure\n"); - else { show(g, "x", x); showmp("expected", r, 16); - showmp("computed", c, 16); } - } - G_DESTROY(g, x); mp_drop(r); mp_drop(c); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vfromint(dstr *v) -{ - group *g = getgroup(v[0].buf); - mp *x = *(mp **)v[1].buf; - int ir = *(int *)v[2].buf; - ge *r = getge(g, v[3].buf); - int ic; - ge *c = G_CREATE(g); - int ok = 1; - ic = G_FROMINT(g, c, x); - if (ir != ic || (!ic && !G_EQ(g, r, c))) { - ok = 0; - fprintf(stderr, "\n*** fromint failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - showmp("x", x, 16); if (ir) fprintf(stderr, "*** should have failed\n"); - else { show(g, "expected", r); show(g, "computed", c); } - } - MP_DROP(x); G_DESTROY(g, r); G_DESTROY(g, c); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vtoec(dstr *v) -{ - group *g = getgroup(v[0].buf); - ge *x = getge(g, v[1].buf); - int ir = *(int *)v[2].buf; - ec *r = (ec *)v[3].buf; - int ic; - ec c = EC_INIT; - int ok = 1; - ic = G_TOEC(g, &c, x); - if (ir != ic || (!ic && !EC_EQ(r, &c))) { - ok = 0; - fprintf(stderr, "\n*** toec failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - show(g, "x", x); - if (ir) fprintf(stderr, "*** should have failed\n"); - else { showec("expected", r); showec("computed", &c); } - } - G_DESTROY(g, x); EC_DESTROY(&c); EC_DESTROY(r); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vfromec(dstr *v) -{ - group *g = getgroup(v[0].buf); - ec *p = (ec *)v[1].buf; - int ir = *(int *)v[2].buf; - ge *r = getge(g, v[3].buf); - int ic; - ge *c = G_CREATE(g); - int ok = 1; - ic = G_FROMEC(g, c, p); - if (ir != ic || (!ic && !G_EQ(g, r, c))) { - ok = 0; - fprintf(stderr, "\n*** fromec failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - showec("p", p); if (ir) fprintf(stderr, "*** should have failed\n"); - else { show(g, "expected", r); show(g, "computed", c); } - } - EC_DESTROY(p); G_DESTROY(g, r); G_DESTROY(g, c); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vtobuf(dstr *v) -{ - group *g = getgroup(v[0].buf); - ge *x = getge(g, v[1].buf); - int ir = *(int *)v[2].buf; - dstr c = DSTR_INIT; - int ic; - buf b; - int ok = 1; - - dstr_ensure(&c, v[3].len); - buf_init(&b, c.buf, v[3].len); - ic = G_TOBUF(g, &b, x); - c.len = BLEN(&b); - if (ic != ir || (!ic && (c.len != v[3].len || - memcmp(c.buf, v[3].buf, c.len)))) { - ok = 0; - fprintf(stderr, "*** tobuf failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - show(g, "x", x); - if (ir) fprintf(stderr, "*** expected failure\n"); - else { - fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr); - fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr); - fputc('\n', stderr); - } - } - G_DESTROY(g, x); dstr_destroy(&c); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vfrombuf(dstr *v) -{ - group *g = getgroup(v[0].buf); - int ir = *(int *)v[2].buf; - ge *r = getge(g, v[3].buf); - int ic; - ge *c = G_CREATE(g); - buf b; - int ok = 1; - - buf_init(&b, v[1].buf, v[1].len); - ic = G_FROMBUF(g, &b, c); - if ((ic < 0) != (ir < 0) || (ir >= 0 && - (ir != BLEN(&b) || !G_EQ(g, r, c)))) { - ok = 0; - fprintf(stderr, "*** frombuf failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr); - fputc('\n', stderr); - if (ir < 0) fprintf(stderr, "*** expected failure\n"); - else { - show(g, "expected", r); show(g, "computed", c); - fprintf(stderr, "*** expected used = %d\n", ir); - fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b)); - } - } - G_DESTROY(g, r); G_DESTROY(g, c); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vtoraw(dstr *v) -{ - group *g = getgroup(v[0].buf); - ge *x = getge(g, v[1].buf); - int ir = *(int *)v[2].buf; - dstr c = DSTR_INIT; - int ic; - buf b; - int ok = 1; - - dstr_ensure(&c, v[3].len); - buf_init(&b, c.buf, v[3].len); - ic = G_TORAW(g, &b, x); - c.len = BLEN(&b); - if (ic != ir || (!ic && (c.len != v[3].len || - memcmp(c.buf, v[3].buf, c.len)))) { - ok = 0; - fprintf(stderr, "*** toraw failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - show(g, "x", x); - if (ir) fprintf(stderr, "*** expected failure\n"); - else { - fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr); - fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr); - fputc('\n', stderr); - } - } - G_DESTROY(g, x); dstr_destroy(&c); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vfromraw(dstr *v) -{ - group *g = getgroup(v[0].buf); - int ir = *(int *)v[2].buf; - ge *r = getge(g, v[3].buf); - int ic; - ge *c = G_CREATE(g); - buf b; - int ok = 1; - - buf_init(&b, v[1].buf, v[1].len); - ic = G_FROMRAW(g, &b, c); - if ((ic < 0) != (ir < 0) || (ir >= 0 && - (ir != BLEN(&b) || !G_EQ(g, r, c)))) { - ok = 0; - fprintf(stderr, "*** fromraw failed\n"); - fprintf(stderr, "*** group: %s\n", v[0].buf); - fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr); - fputc('\n', stderr); - if (ir < 0) fprintf(stderr, "*** expected failure\n"); - else { - show(g, "expected", r); show(g, "computed", c); - fprintf(stderr, "*** expected used = %d\n", ir); - fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b)); - } - } - G_DESTROY(g, r); G_DESTROY(g, c); - G_DESTROYGROUP(g); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static const test_chunk tests[] = { - { "check", vcheck, { &type_string, &type_string } }, - { "checkelt", vcheckelt, { &type_string, &type_string, &type_int } }, - { "mul", vmul, { &type_string, &type_string, - &type_string, &type_string } }, - { "sqr", vsqr, { &type_string, &type_string, - &type_string } }, - { "inv", vinv, { &type_string, &type_string, - &type_string } }, - { "div", vdiv, { &type_string, &type_string, - &type_string, &type_string } }, - { "exp", vexp, { &type_string, &type_string, - &type_mp, &type_string } }, - { "mexp-1", vmexp1, { &type_string, - &type_string, &type_mp, - &type_string } }, - { "mexp-2", vmexp2, { &type_string, - &type_string, &type_mp, - &type_string, &type_mp, - &type_string } }, - { "mexp-3", vmexp3, { &type_string, - &type_string, &type_mp, - &type_string, &type_mp, - &type_string, &type_mp, - &type_string } }, - { "mexp-4", vmexp4, { &type_string, - &type_string, &type_mp, - &type_string, &type_mp, - &type_string, &type_mp, - &type_string, &type_mp, - &type_string } }, - { "toint", vtoint, { &type_string, &type_string, - &type_int, &type_mp } }, - { "fromint", vfromint, { &type_string, &type_mp, - &type_int, &type_string } }, - { "toec", vtoec, { &type_string, &type_string, - &type_int, &type_ec } }, - { "fromec", vfromec, { &type_string, &type_ec, - &type_int, &type_string } }, - { "tobuf", vtobuf, { &type_string, &type_string, - &type_int, &type_hex } }, - { "frombuf", vfrombuf, { &type_string, &type_hex, - &type_int, &type_string } }, - { "toraw", vtoraw, { &type_string, &type_string, - &type_int, &type_hex } }, - { "fromraw", vfromraw, { &type_string, &type_hex, - &type_int, &type_string } }, - { 0 } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/group"); - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/group.h b/group.h deleted file mode 100644 index a144706..0000000 --- a/group.h +++ /dev/null @@ -1,411 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * General cyclic group abstraction - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_GROUP_H -#define CATACOMB_GROUP_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_BUF_H -# include "buf.h" -#endif - -#ifndef CATACOMB_DH_H -# include "ec.h" -#endif - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_QDPARSE_H -# include "qdparse.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -#ifndef ge - typedef struct ge ge; /* Group element (abstract type) */ -#endif - -typedef struct group_ { - const struct group_ops *ops; /* Operations table */ - size_t nbits; /* Size of an element in bits */ - size_t noctets; /* Size of raw element in octets */ - ge *i; /* Identity element */ - ge *g; /* Generator element */ - mp *r; /* Order of the generator */ - mp *h; /* Cofactor */ -} group; - -typedef struct group_expfactor { - ge *base; /* The base */ - mp *exp; /* The exponent */ -} group_expfactor; - -typedef struct group_ops { - - /* --- General information --- */ - - unsigned ty; /* Type of this group */ - const char *name; /* Textual name string */ - - /* --- Memory management --- */ - - void (*destroygroup)(group */*g*/); - ge *(*create)(group */*g*/); - void (*copy)(group */*g*/, ge */*d*/, ge */*x*/); - void (*burn)(group */*g*/, ge */*x*/); - void (*destroy)(group */*g*/, ge */*e*/); - - /* --- Comparisons --- */ - - int (*samep)(group */*g*/, group */*h*/); - int (*eq)(group */*g*/, ge */*x*/, ge */*y*/); - int (*identp)(group */*g*/, ge */*x*/); - - /* --- Other stuff --- */ - - const char *(*check)(group */*g*/, grand */*gr*/); - - /* --- Arithmetic --- */ - - void (*mul)(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/); - void (*sqr)(group */*g*/, ge */*d*/, ge */*x*/); - void (*inv)(group */*g*/, ge */*d*/, ge */*x*/); - void (*div)(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/); - void (*exp)(group */*g*/, ge */*d*/, ge */*x*/, mp */*n*/); - void (*mexp)(group */*g*/, ge */*d*/, - const group_expfactor */*f*/, size_t /*n*/); - - /* --- Debugging --- */ - - int (*read)(group */*g*/, ge */*d*/, - const mptext_ops */*ops*/, void */*p*/); - int (*write)(group */*g*/, ge */*x*/, - const mptext_ops */*ops*/, void */*p*/); - - /* --- Conversions --- */ - - mp *(*toint)(group */*g*/, mp */*d*/, ge */*x*/); - int (*fromint)(group */*g*/, ge */*d*/, mp */*x*/); - int (*toec)(group */*g*/, ec */*d*/, ge */*x*/); - int (*fromec)(group */*g*/, ge */*d*/, const ec */*p*/); - int (*tobuf)(group */*h*/, buf */*b*/, ge */*x*/); - int (*frombuf)(group */*h*/, buf */*b*/, ge */*d*/); - int (*toraw)(group */*h*/, buf */*b*/, ge */*x*/); - int (*fromraw)(group */*h*/, buf */*b*/, ge */*d*/); - -} group_ops; - -enum { - GTY_PRIME, /* Prime field subgroup */ - GTY_BINARY, /* Binary feld subgroup */ - GTY_EC /* Elliptic curve group */ -}; - -#define G_NAME(g) (g)->ops->name -#define G_TYPE(g) (g)->ops->ty - -#define G_DESTROYGROUP(g) (g)->ops->destroygroup((g)) -#define G_CREATE(g) (g)->ops->create((g)) -#define G_COPY(g, d, x) (g)->ops->copy((g), (d), (x)) -#define G_BURN(g, x) (g)->ops->burn((g), (x)) -#define G_DESTROY(g, x) (g)->ops->destroy((g), (x)) - -#define G_SAMEP(g, h) (g)->ops->samep((g), (h)) -#define G_EQ(g, x, y) (g)->ops->eq((g), (x), (y)) -#define G_IDENTP(g, x) (g)->ops->identp((g), (x)) - -#define G_CHECK(g, gr) (g)->ops->check((g), (gr)) - -#define G_MUL(g, d, x, y) (g)->ops->mul((g), (d), (x), (y)) -#define G_SQR(g, d, x) (g)->ops->sqr((g), (d), (x)) -#define G_INV(g, d, x) (g)->ops->inv((g), (d), (x)) -#define G_DIV(g, d, x, y) (g)->ops->div((g), (d), (x), (y)) -#define G_EXP(g, d, x, n) (g)->ops->exp((g), (d), (x), (n)) -#define G_MEXP(g, d, f, n) (g)->ops->mexp((g), (d), (f), (n)) - -#define G_READ(g, d, o, p) (g)->ops->read((g), (d), (o), (p)) -#define G_WRITE(g, x, o, p) (g)->ops->write((g), (x), (o), (p)) - -#define G_TOINT(g, d, x) (g)->ops->toint((g), (d), (x)) -#define G_FROMINT(g, d, x) (g)->ops->fromint((g), (d), (x)) -#define G_TOEC(g, d, x) (g)->ops->toec((g), (d), (x)) -#define G_FROMEC(g, d, p) (g)->ops->fromec((g), (d), (p)) -#define G_TOBUF(g, b, x) (g)->ops->tobuf((g), (b), (x)) -#define G_FROMBUF(g, b, d) (g)->ops->frombuf((g), (b), (d)) -#define G_TORAW(g, b, x) (g)->ops->toraw((g), (b), (x)) -#define G_FROMRAW(g, b, d) (g)->ops->fromraw((g), (b), (d)) - -/*----- Handy functions ---------------------------------------------------*/ - -/* --- @group_check@ --- * - * - * Arguments: @group *g@ = an abstract group - * @ge *x@ = a group element - * - * Returns: Zero on success, nonzero for failure. - * - * Use: Checks that @x@ is a valid group element. This may take a - * while, since it checks that %$x^h \ne 1$%. - */ - -extern int group_check(group */*g*/, ge */*x*/); - -/* --- @group_samep@ --- * - * - * Arguments: @group *g, *h@ = two abstract groups - * - * Returns: Nonzero if the groups are in fact identical (not just - * isomorphic). - * - * Use: Checks to see whether two groups are actually the same. This - * function does the full check: the group operatrion @samep@ - * just does the group-specific details. - */ - -extern int group_samep(group */*g*/, group */*h*/); - -/*----- Textual I/O on group elements -------------------------------------*/ - -extern int group_readstring(group */*g*/, ge */*d*/, - const char */*p*/, char **/*end*/); -extern int group_writestring(group */*g*/, ge */*d*/, - char */*p*/, size_t /*sz*/); - -extern int group_readfile(group */*g*/, ge */*d*/, FILE */*fp*/); -extern int group_writefile(group */*g*/, ge */*x*/, FILE */*fp*/); - -extern int group_readdstr(group */*g*/, ge */*d*/, - dstr */*dd*/, size_t */*off*/); -extern int group_writedstr(group */*g*/, ge */*x*/, dstr */*d*/); - -/*----- Standard implementations ------------------------------------------*/ - -/* --- @group_stdidentp@ --- * - * - * Arguments: @group *g@ = abstract group - * @ge *x@ = group element - * - * Returns: Nonzero if %$x$% is the group identity. - */ - -extern int group_stdidentp(group */*g*/, ge */*x*/); - -/* --- @group_stdcheck@ --- * - * - * Arguments: @group *g@ = abstract group - * @grand *gr@ = random number source. - * - * Returns: Null on success, or a pointer to an error message. - */ - -extern const char *group_stdcheck(group */*g*/, grand */*gr*/); - -/* --- @group_stdsqr@ --- * - * - * Arguments: @group *g@ = abstract group - * @ge *d@ = destination pointer - * @ge *x@ = group element - * - * Returns: --- - * - * Use: Computes %$d = x^2$% as %$d = x x$%. - */ - -extern void group_stdsqr(group */*g*/, ge */*d*/, ge */*x*/); - -/* --- @group_stddiv@ --- * - * - * Arguments: @group *g@ = abstract group - * @ge *d@ = destination pointer - * @ge *x@ = dividend - * @ge *y@ = divisor - * - * Returns: --- - * - * Use: Computes %$d = x/y$% as %$d = x y^{-1}$%. - */ - -extern void group_stddiv(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/); - -/* --- @group_stdexp@ --- * - * - * Arguments: @group *g@ = abstract group - * @ge *d@ = destination pointer - * @ge *x@ = base element - * @mp *n@ = exponent - * - * Returns: --- - * - * Use: Computes %$d = x^n$% efficiently. - */ - -extern void group_stdexp(group */*g*/, ge */*d*/, ge */*x*/, mp */*n*/); - -/* --- @group_stdmexp@ --- * - * - * Arguments: @group *g@ = abstract group - * @ge *d@ = destination pointer - * @const group_expfactor *f@ = vector of factors - * @size_t n@ = number of factors - * - * Returns: --- - * - * Use: Computes %$d = g_0^{x_0} g_1^{x_1} \ldots$% efficiently. - */ - -extern void group_stdmexp(group */*g*/, ge */*d*/, - const group_expfactor */*f*/, size_t /*n*/); - -/* --- @group_stdtoec@ --- * - * - * Arguments: @group *g@ = abstract group - * @ec *d@ = destination point - * @ge *x@ = group element - * - * Returns: @-1@, indicating failure. - * - * Use: Fails to convert a group element to an elliptic curve point. - */ - -extern int group_stdtoec(group */*g*/, ec */*d*/, ge */*x*/); - -/* --- @group_stdfromec@ --- * - * - * Arguments: @group *g@ = abstract group - * @ge *d@ = destination pointer - * @const ec *p@ = elliptic curve point - * - * Returns: Zero for success, @-1@ on failure. - * - * Use: Converts %$p$% to a group element by converting its %$x$%- - * coordinate. - */ - -extern int group_stdfromec(group */*g*/, ge */*d*/, const ec */*p*/); - -/*----- Prime field subgroups ---------------------------------------------*/ - -typedef struct gprime_param { - mp *p, *q; /* Prime numbers %$p$% and %$q$% */ - mp *g; /* Generates order-%$q$% subgroup */ -} gprime_param; - -/* --- @group_prime@ --- * - * - * Arguments: @const gprime_param *gp@ = group parameters - * - * Returns: A pointer to the group, or null. - * - * Use: Constructs an abstract group interface for a subgroup of a - * prime field. Group elements are @mp *@ pointers. - */ - -group *group_prime(const gprime_param */*gp*/); - -/*----- Binary field subgroups --------------------------------------------*/ - -typedef gprime_param gbin_param; - -/* --- @group_binary@ --- * - * - * Arguments: @const gbin_param *gb@ = group parameters - * - * Returns: A pointer to the group, or null. - * - * Use: Constructs an abstract group interface for a subgroup of a - * prime field. Group elements are @mp *@ pointers. - */ - -group *group_binary(const gbin_param */*gp*/); - -/*----- Elliptic curve groups ---------------------------------------------*/ - -/* --- @group_ec@ --- * - * - * Arguments: @const ec_info *ei@ = elliptic curve parameters - * - * Returns: A pointer to the group, or null. - * - * Use: Constructs an abstract group interface for an elliptic curve - * group. Group elements are @ec@ structures. The contents of - * the @ec_info@ structure becomes the property of the @group@ - * object; you can (and should) free the structure itself, but - * calling @ec_freeinfo@ on it is not allowed. - */ - -group *group_ec(const ec_info */*ei*/); - -/*----- General group initialization --------------------------------------*/ - -/* --- @group_parse@ --- * - * - * Arguments: @qd_parse *qd@ = quick-and-dirty parser - * - * Returns: Group pointer, or null for failure. - * - * Use: Parses a group description and returns the group. This has - * the form `TYPE { SPEC }' where TYPE is `prime' or `ec', and - * SPEC is the appropriate kind of group specification of the - * given type. - */ - -extern group *group_parse(qd_parse */*qd*/); - -/* --- @group_fromstring@ --- * - * - * Arguments: @const char *p@ = pointer to string to read - * @group **gg@ = where to put the group pointer - * - * Returns: Null if OK, or an error string. - * - * Use: Parses a group spec from a string, and returns the group. - */ - -extern const char *group_fromstring(const char */*p*/, group **/*gg*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/has160.c b/has160.c deleted file mode 100644 index 76c63aa..0000000 --- a/has160.c +++ /dev/null @@ -1,248 +0,0 @@ -/* -*-c-*- - * - * $Id: has160.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The HAS160 message digest function - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "has160.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @has160_compress@ --- * - * - * Arguments: @has160_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: HAS160 compression function. - */ - -void has160_compress(has160_ctx *ctx, const void *sbuf) -{ - uint32 a, b, c, d, e; - uint32 buf[16]; - - /* --- Fetch the chaining variables --- */ - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - e = ctx->e; - - /* --- Fetch the buffer contents --- */ - - { - int i; - const octet *p; - - for (i = 0, p = sbuf; i < 16; i++, p += 4) - buf[i] = LOAD32_L(p); - } - - /* --- Definitions for round functions --- */ - -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define G(x, y, z) ((x) ^ (y) ^ (z)) -#define H(x, y, z) ((y) ^ ((x) | ~(z))) - -#define FF(f, a, b, c, d, e, x, s, ss, k) do { \ - e += ROL32(a, s) + f(b, c, d) + (x) + k; \ - b = ROL32(b, ss); \ -} while (0) - - /* --- The actual hashing --- * - * - * Hmm, this is more regular than most. The macros are quite grim, - * though. - */ - -#define ROUND(f, ss, k, \ - i0, i1, i2, i3, i4, i5, i6, i7, \ - i8, i9, i10, i11, i12, i13, i14, i15) do { \ - FF(f, a, b, c, d, e, buf[ i8]^buf[ i9]^buf[i10]^buf[i11], 5, ss, k); \ - FF(f, e, a, b, c, d, buf[ i0], 11, ss, k); \ - FF(f, d, e, a, b, c, buf[ i1], 7, ss, k); \ - FF(f, c, d, e, a, b, buf[ i2], 15, ss, k); \ - FF(f, b, c, d, e, a, buf[ i3], 6, ss, k); \ - FF(f, a, b, c, d, e, buf[i12]^buf[i13]^buf[i14]^buf[i15], 13, ss, k); \ - FF(f, e, a, b, c, d, buf[ i4], 8, ss, k); \ - FF(f, d, e, a, b, c, buf[ i5], 14, ss, k); \ - FF(f, c, d, e, a, b, buf[ i6], 7, ss, k); \ - FF(f, b, c, d, e, a, buf[ i7], 12, ss, k); \ - FF(f, a, b, c, d, e, buf[ i0]^buf[ i1]^buf[ i2]^buf[ i3], 9, ss, k); \ - FF(f, e, a, b, c, d, buf[ i8], 11, ss, k); \ - FF(f, d, e, a, b, c, buf[ i9], 8, ss, k); \ - FF(f, c, d, e, a, b, buf[i10], 15, ss, k); \ - FF(f, b, c, d, e, a, buf[i11], 6, ss, k); \ - FF(f, a, b, c, d, e, buf[ i4]^buf[ i5]^buf[ i6]^buf[ i7], 12, ss, k); \ - FF(f, e, a, b, c, d, buf[i12], 9, ss, k); \ - FF(f, d, e, a, b, c, buf[i13], 14, ss, k); \ - FF(f, c, d, e, a, b, buf[i14], 5, ss, k); \ - FF(f, b, c, d, e, a, buf[i15], 13, ss, k); \ -} while (0) - - ROUND(F, 10, 0x00000000, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - ROUND(G, 17, 0x5a827999, - 3, 6, 9, 12, 15, 2, 5, 8, 11, 14, 1, 4, 7, 10, 13, 0); - ROUND(H, 25, 0x6ed9eba1, - 12, 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3); - ROUND(G, 30, 0x8f1bbcdc, - 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5, 0, 11, 6, 1, 12); - - /* --- Update the chaining variables --- */ - - ctx->a += a; - ctx->b += b; - ctx->c += c; - ctx->d += d; - ctx->e += e; -} - -/* --- @has160_init@ --- * - * - * Arguments: @has160_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void has160_init(has160_ctx *ctx) -{ - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; - ctx->e = 0xc3d2e1f0; - ctx->off = 0; - ctx->nl = ctx->nh = 0; -} - -/* --- @has160_set@ --- * - * - * Arguments: @has160_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -void has160_set(has160_ctx *ctx, const void *buf, unsigned long count) -{ - const octet *p = buf; - ctx->a = LOAD32_L(p + 0); - ctx->b = LOAD32_L(p + 4); - ctx->c = LOAD32_L(p + 8); - ctx->d = LOAD32_L(p + 12); - ctx->e = LOAD32_L(p + 16); - ctx->off = 0; - ctx->nl = U32(count); - ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); -} - -/* --- @has160_hash@ --- * - * - * Arguments: @has160_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void has160_hash(has160_ctx *ctx, const void *buf, size_t sz) -{ - HASH_BUFFER(HAS160, has160, ctx, buf, sz); -} - -/* --- @has160_done@ --- * - * - * Arguments: @has160_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -void has160_done(has160_ctx *ctx, void *hash) -{ - octet *p = hash; - HASH_MD5STRENGTH(HAS160, has160, ctx); - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); - STORE32_L(p + 16, ctx->e); -} - -/* --- @has160_state@ --- * - * - * Arguments: @has160_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @has160_set@. - */ - -unsigned long has160_state(has160_ctx *ctx, void *state) -{ - octet *p = state; - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); - STORE32_L(p + 16, ctx->e); - return (ctx->nl | ((ctx->nh << 16) << 16)); -} - -/* --- Generic interface --- */ - -GHASH_DEF(HAS160, has160) - -/* --- Test code --- */ - -HASH_TEST(HAS160, has160) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/has160.h b/has160.h deleted file mode 100644 index 699260a..0000000 --- a/has160.h +++ /dev/null @@ -1,159 +0,0 @@ -/* -*-c-*- - * - * $Id: has160.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The HAS160 message digest function - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the HAS160 hash function ---------------------------------* - * - * HAS160 was designed by Chae Hoon Lim and the Korean Information Security - * Agency (KISA). It's recommended for use with KCDSA (though I think I'm - * happer with RIPEMD-160 or SHA1). It's here so I can check KCDSA test - * vectors. - */ - -#ifndef CATACOMB_HAS160_H -#define CATACOMB_HAS160_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define HAS160_BUFSZ 64 -#define HAS160_HASHSZ 20 -#define HAS160_STATESZ 20 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct has160_ctx { - uint32 a, b, c, d, e; /* Chaining variables */ - uint32 nl, nh; /* Byte count so far */ - unsigned off; /* Offset into buffer */ - octet buf[HAS160_BUFSZ]; /* Accumulation buffer */ -} has160_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @has160_compress@ --- * - * - * Arguments: @has160_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: HAS160 compression function. - */ - -extern void has160_compress(has160_ctx */*ctx*/, const void */*sbuf*/); - -/* --- @has160_init@ --- * - * - * Arguments: @has160_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -extern void has160_init(has160_ctx */*ctx*/); - -/* --- @has160_set@ --- * - * - * Arguments: @has160_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -extern void has160_set(has160_ctx */*ctx*/, const void */*buf*/, - unsigned long /*count*/); - -/* --- @has160_hash@ --- * - * - * Arguments: @has160_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -extern void has160_hash(has160_ctx */*ctx*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @has160_done@ --- * - * - * Arguments: @has160_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -extern void has160_done(has160_ctx */*ctx*/, void */*hash*/); - -/* --- @has160_state@ --- * - * - * Arguments: @has160_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @has160_set@. - */ - -extern unsigned long has160_state(has160_ctx */*ctx*/, void */*state*/); - -/*----- Generic hash interface --------------------------------------------*/ - -extern const gchash has160; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/hash.h b/hash.h deleted file mode 100644 index c2c10d0..0000000 --- a/hash.h +++ /dev/null @@ -1,279 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Generic handling for message digest functions - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_HASH_H -#define CATACOMB_HASH_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @HASH_BUFFER@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for hash-specific definitions - * @ictx@ = pointer to context block for the hash - * @ibuf@ = pointer to input data to hash - * @isz@ = size of buffer - * - * Use: Handles buffering of input data to a hash function. The - * hash's compression function is called when the buffer is - * full. Note that the compression function can be called on - * data which is at odd alignments; it is expected to cope - * gracefully with this (possibly by copying the data into its - * internal buffer before starting). - */ - -#define HASH_BUFFER(PRE, pre, ictx, ibuf, isz) do { \ - pre##_ctx *_bctx = (ictx); \ - size_t _bsz = (isz); \ - const octet *_bbuf = (octet *)(ibuf); \ - \ - /* --- Add on the size done so far --- * \ - * \ - * Messy, because trapping overflow is difficult when you don't know \ - * how many bits you've actually got. \ - */ \ - \ - { \ - uint32 _l = U32(_bsz); \ - uint32 _h = ((_bsz & ~MASK32) >> 16) >> 16; \ - _bctx->nh += _h; \ - _bctx->nl += _l; \ - if (_bctx->nl < _l || _bctx->nl & ~MASK32) \ - _bctx->nh++; \ - } \ - \ - /* --- Handle very small contributions --- */ \ - \ - if (_bctx->off + _bsz < PRE##_BUFSZ) { \ - memcpy(_bctx->buf + _bctx->off, _bbuf, _bsz); \ - _bctx->off += _bsz; \ - } else { \ - \ - /* --- Handle an initial partial buffer --- */ \ - \ - if (_bctx->off) { \ - size_t s = PRE##_BUFSZ - _bctx->off; \ - memcpy(_bctx->buf + _bctx->off, _bbuf, s); \ - pre##_compress(_bctx, _bctx->buf); \ - _bsz -= s; _bbuf += s; \ - } \ - \ - /* --- Do whole buffers while we can --- */ \ - \ - while (_bsz >= PRE##_BUFSZ) { \ - pre##_compress(_bctx, _bbuf); \ - _bsz -= PRE##_BUFSZ; _bbuf += PRE##_BUFSZ; \ - } \ - \ - /* --- And wrap up at the end --- */ \ - \ - if (_bsz) \ - memcpy(_bctx->buf, _bbuf, _bsz); \ - _bctx->off = _bsz; \ - } \ -} while (0) - -/* --- @HASH_PAD@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for hash-specific definitions - * @ictx@ = pointer to context block for the hash - * @term@ = terminator character to write following the data - * @pad@ = pad character to fill with - * @diff@ = size of space to leave at the end of the last block - * - * Use: Does padding for message digest functions. - */ - -#define HASH_PAD(PRE, pre, ictx, term, pad, diff) do { \ - pre##_ctx *_pctx = (ictx); \ - \ - _pctx->buf[_pctx->off] = term; \ - _pctx->off++; \ - if (_pctx->off > PRE##_BUFSZ - diff) { \ - if (_pctx->off < PRE##_BUFSZ) \ - memset(_pctx->buf + _pctx->off, pad, PRE##_BUFSZ - _pctx->off); \ - pre##_compress(_pctx, _pctx->buf); \ - memset(_pctx->buf, pad, PRE##_BUFSZ - diff); \ - } else \ - memset(_pctx->buf + _pctx->off, pad, \ - PRE##_BUFSZ - _pctx->off - diff); \ -} while (0) - -/* --- @HASH_MD5STRENGTH@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for hash-specific definitions - * @ictx@ = pointer to context block for the hash - * - * Use: Does MD5-style MD strengthening. The data is terminated - * by a single set bit, padded with zero bits, and then a 64- - * bit length is written, little-end first. - */ - -#define HASH_MD5STRENGTH(PRE, pre, ictx) do { \ - pre##_ctx *_mctx = (ictx); \ - HASH_PAD(PRE, pre, _mctx, 0x80u, 0, 8); \ - STORE32_L(_mctx->buf + PRE##_BUFSZ - 8, _mctx->nl << 3); \ - STORE32_L(_mctx->buf + PRE##_BUFSZ - 4, \ - (_mctx->nl >> 29) | (_mctx->nh << 3)); \ - pre##_compress(_mctx, _mctx->buf); \ -} while (0) - -/* --- @HASH_TEST@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for hash-specfic definitions - * - * Use: Standard test rig for hash functions. - */ - -#ifdef TEST_RIG - -#include -#include - -#define HASH_BUFLEN 100000 - -#define HASH_TEST(PRE, pre) \ - \ -static int verify(dstr *v) \ -{ \ - pre##_ctx ctx; \ - int ok = 1; \ - int i; \ - octet *p; \ - int szs[] = { 1, 7, 192, -1, 0 }, *ip; \ - size_t sz; \ - dstr d; \ - \ - dstr_create(&d); \ - dstr_ensure(&d, PRE##_HASHSZ); \ - d.len = PRE##_HASHSZ; \ - \ - for (ip = szs; *ip; ip++) { \ - i = *ip; \ - sz = v[0].len; \ - if (i == -1) \ - i = sz; \ - if (i > sz) \ - continue; \ - p = (octet *)v[0].buf; \ - pre##_init(&ctx); \ - while (sz) { \ - if (i > sz) \ - i = sz; \ - pre##_hash(&ctx, p, i); \ - p += i; \ - sz -= i; \ - } \ - pre##_done(&ctx, d.buf); \ - if (memcmp(d.buf, v[1].buf, PRE##_HASHSZ) != 0) { \ - printf("\nfail:\n\tstep = %i\n\tinput = `%s'\n\texpected = ", \ - *ip, v[0].buf); \ - type_hex.dump(&v[1], stdout); \ - fputs("\n\tcomputed = ", stdout); \ - type_hex.dump(&d, stdout); \ - putchar('\n'); \ - ok = 0; \ - } \ - } \ - \ - dstr_destroy(&d); \ - return (ok); \ -} \ - \ -static int verifyrep(dstr *v) \ -{ \ - pre##_ctx ctx; \ - size_t len = v[0].len; \ - int n = *(int *)v[1].buf; \ - int nd = 0; \ - int nn = len; \ - int ok = 1; \ - octet *p, *q; \ - dstr d = DSTR_INIT; \ - \ - while (nn < HASH_BUFLEN && (n & 1) == 0) { nd++; nn <<= 1; n >>= 1; } \ - p = xmalloc(nn); \ - memcpy(p, v[0].buf, len); \ - q = p + len; \ - while (nd--) { memcpy(q, p, len); q += len; len <<= 1; } \ - \ - dstr_ensure(&d, PRE##_HASHSZ); \ - d.len = PRE##_HASHSZ; \ - pre##_init(&ctx); \ - while (n--) pre##_hash(&ctx, p, len); \ - pre##_done(&ctx, d.buf); \ - \ - if (memcmp(d.buf, v[2].buf, PRE##_HASHSZ) != 0) { \ - printf("\nfail:\n\tinput = `%s'\n\treps = `%i'\n\texpected = ", \ - v[0].buf, *(int *)v[1].buf); \ - type_hex.dump(&v[2], stdout); \ - fputs("\n\tcomputed = ", stdout); \ - type_hex.dump(&d, stdout); \ - putchar('\n'); \ - ok = 0; \ - } \ - xfree(p); \ - dstr_destroy(&d); \ - return (ok); \ -} \ - \ -static test_chunk defs[] = { \ - { #pre, verify, { &type_string, &type_hex, 0 } }, \ - { #pre "-rep", verifyrep, \ - { &type_string, &type_int, &type_hex, 0 } }, \ - { 0, 0, { 0 } } \ -}; \ - \ -int main(int argc, char *argv[]) \ -{ \ - ego(argv[0]); \ - test_run(argc, argv, defs, SRCDIR"/tests/" #pre); \ - return (0); \ -} - -#else -# define HASH_TEST(PRE, pre) -#endif - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/hashsum.c b/hashsum.c deleted file mode 100644 index 290641b..0000000 --- a/hashsum.c +++ /dev/null @@ -1,412 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Hash files using some secure hash function - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _FILE_OFFSET_BITS 64 - -#include "config.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "ghash.h" -#include "cc.h" - -/*----- Static variables --------------------------------------------------*/ - -#define f_bogus 1u -#define f_verbose 2u -#define f_check 4u -#define f_files 8u -#define f_oddhash 16u -#define f_escape 32u -#define f_oddenc 64u - -/*----- Guts --------------------------------------------------------------*/ - -static int checkjunk(const char *path, const struct stat *st, void *p) -{ - const char *what; - fhashstate *fh = p; - - if (!st) { - if (fh->f & f_verbose) - fprintf(stderr, "JUNK (error %s) %s\n", strerror(errno), path); - else - moan("couldn't stat junk file `%s': %s", path, strerror(errno)); - } else { - what = describefile(st); - if (fh->f & f_verbose) - fprintf(stderr, "JUNK %s %s\n", what, path); - else - moan("found junk %s `%s'", what, path); - } - return (0); -} - -static int warnjunk(const char *path, const struct stat *st, void *p) -{ - if (st) - moan("unexpected %s `%s'", describefile(st), path); - else - moan("couldn't stat unexpected file `%s': %s", path, strerror(errno)); - return (0); -} - -static int checkhash(fhashstate *fh, const char *file, const encodeops *e) -{ - int rc; - hfpctx hfp; - dstr dl = DSTR_INIT; - dstr df = DSTR_INIT; - unsigned long n = 0, nfail = 0; - int hf; - - if (!file || strcmp(file, "-") == 0) - hfp.fp = stdin; - else if ((hfp.fp = fopen(file, fh->f & GSF_RAW ? "r" : "rb")) == 0) { - moan("couldn't open `%s': %s", file, strerror(errno)); - return (EXIT_FAILURE); - } - - hfp.dline = &dl; - hfp.dfile = &df; - hfp.hbuf = xmalloc(2 * fh->gch->hashsz); - hfp.gch = fh->gch; - hfp.ee = e; - hfp.f = fh->f; - - while ((hf = hfparse(&hfp)) != HF_EOF) { - switch (hf) { - case HF_HASH: - xfree(hfp.hbuf); - hfp.hbuf = xmalloc(2 * hfp.gch->hashsz); - break; - case HF_FILE: - if (fhash(fh, df.buf, hfp.hbuf + hfp.gch->hashsz)) { - moan("couldn't read `%s': %s", df.buf, strerror(errno)); - rc = EXIT_FAILURE; - continue; - } - if (memcmp(hfp.hbuf, hfp.hbuf + hfp.gch->hashsz, - hfp.gch->hashsz) != 0) { - if (hfp.f & f_verbose) - fprintf(stderr, "FAIL %s\n", df.buf); - else - moan("%s check failed for `%s'", hfp.gch->name, df.buf); - nfail++; - rc = EXIT_FAILURE; - } else { - if (hfp.f & f_verbose) - fprintf(stderr, "OK %s\n", df.buf); - } - n++; - } - } - - if (ferror(hfp.fp)) { - moan("error reading input `%s': %s", - file ? file : "", strerror(errno)); - rc = EXIT_FAILURE; - } - dstr_destroy(&dl); - dstr_destroy(&df); - xfree(hfp.hbuf); - if ((fh->f & f_verbose) && nfail) - moan("%lu of %lu file(s) failed %s check", nfail, n, hfp.gch->name); - else if (!n) - moan("no files checked"); - return (rc); -} - -static int dohash(fhashstate *fh, const char *file, const encodeops *e) -{ - int rc = 0; - octet *p = xmalloc(fh->gch->hashsz); - - if (fhash(fh, file, p)) { - moan("couldn't read `%s': %s", file ? file : "", strerror(errno)); - rc = EXIT_FAILURE; - } else { - e->put(p, fh->gch->hashsz, stdout); - if (file) { - fputc(' ', stdout); - fputc(fh->f & FHF_BINARY ? '*' : ' ', stdout); - if (fh->f & f_escape) - putstring(stdout, file, 0); - else - fputs(file, stdout); - } - fputc('\n', stdout); - } - - xfree(p); - return (rc); -} - -static int dofile(fhashstate *fh, const char *file, const encodeops *e) - { return (fh->f & f_check ? checkhash : dohash)(fh, file, e); } - -static int hashfiles(fhashstate *fh, const char *file, const encodeops *e) -{ - FILE *fp; - dstr d = DSTR_INIT; - int rc = 0; - int rrc; - - if (!file || strcmp(file, "-") == 0) - fp = stdin; - else if ((fp = fopen(file, fh->f & GSF_RAW ? "r" : "rb")) == 0) { - moan("couldn't open `%s': %s", file, strerror(errno)); - return (EXIT_FAILURE); - } - - for (;;) { - DRESET(&d); - if (getstring(fp, &d, GSF_FILE | fh->f)) - break; - if ((rrc = dofile(fh, d.buf, e)) != 0) - rc = rrc; - } - - return (rc); -} - -static int hashsum(fhashstate *fh, const char *file, const encodeops *e) - { return (fh->f & f_files ? hashfiles : dofile)(fh, file, e); } - -/*----- Main driver -------------------------------------------------------*/ - -void version(FILE *fp) -{ - pquis(fp, "$, Catacomb version " VERSION "\n"); -} - -static void usage(FILE *fp) -{ - pquis(fp, "Usage: $ [-f0ebcv] [-a ALGORITHM] [-E ENC] [FILES...]\n"); -} - -static void help(FILE *fp, const gchash *gch) -{ - version(fp); - fputc('\n', fp); - usage(fp); - pquis(fp, "\n\ -Generates or checks message digests on files. Options available:\n\ -\n\ --h, --help Display this help message.\n\ --V, --version Display program's version number.\n\ --u, --usage Display a terse usage message.\n\ --l, --list [ITEM...] Show known hash functions and/or encodings.\n\ -\n\ --a, --algorithm=ALG Use the message digest algorithm ALG.\n\ --E, --encoding=ENC Represent hashes using encoding ENC.\n\ -\n\ --f, --files Read a list of file names from standard input.\n\ --0, --null File names are null terminated, not plain text.\n\ -\n\ --e, --escape Escape funny characters in filenames.\n\ --c, --check Check message digests rather than emitting them.\n\ --b, --binary When reading files, treat them as binary.\n\ --p, --progress Show a progress indicator for large files.\n\ --v, --verbose Be verbose when checking digests.\n\ -\n\ -For a list of hashing algorithms and encodings, type `$ --list'.\n\ -"); - if (gch) - fprintf(fp, "The default message digest algorithm is %s.\n", gch->name); -} - -#define LISTS(LI) \ - LI("Lists", list, listtab[i].name, listtab[i].name) \ - LI("Hash functions", hash, ghashtab[i], ghashtab[i]->name) \ - LI("Encodings", enc, encodingtab[i].name, encodingtab[i].name) - -MAKELISTTAB(listtab, LISTS) - -int main(int argc, char *argv[]) -{ - fhashstate fh; - const encodeops *e = &encodingtab[ENC_HEX]; - int rc; - - /* --- Initialization --- */ - - ego(argv[0]); - sub_init(); - fhash_init(&fh, 0, 0); - - /* --- Choose a hash function from the name --- */ - - { - char *q = xstrdup(QUIS); - size_t len = strlen(q); - if (len > 3 && strcmp(q + len - 3, "sum") == 0) { - q[len - 3] = 0; - fh.gch = gethash(q); - } - if (!fh.gch) - fh.gch = gethash("md5"); - xfree(q); - } - - /* --- Read options --- */ - - for (;;) { - static struct option opts[] = { - { "help", 0, 0, 'h' }, - { "verbose", 0, 0, 'V' }, - { "usage", 0, 0, 'u' }, - - { "algorithm", OPTF_ARGREQ, 0, 'a' }, - { "hash", OPTF_ARGREQ, 0, 'a' }, - { "encoding", OPTF_ARGREQ, 0, 'E' }, - { "list", 0, 0, 'l' }, - - { "files", 0, 0, 'f' }, - { "find", 0, 0, 'f' }, - { "null", 0, 0, '0' }, - - { "escape", 0, 0, 'e' }, - { "check", 0, 0, 'c' }, - { "junk", 0, 0, 'j' }, - { "binary", 0, 0, 'b' }, - { "verbose", 0, 0, 'v' }, - { "progress", 0, 0, 'p' }, - - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "hVu a:E:l f0 ecjbvp", opts, 0, 0, 0); - if (i < 0) - break; - - switch (i) { - case 'h': - help(stdout, fh.gch); - exit(0); - case 'V': - version(stdout); - exit(0); - case 'u': - usage(stdout); - exit(0); - case 'l': - exit(displaylists(listtab, argv + optind)); - case 'a': - if ((fh.gch = gethash(optarg)) == 0) - die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg); - fh.f |= f_oddhash; - break; - case 'E': - if ((e = getencoding(optarg)) == 0) - die(EXIT_FAILURE, "unknown encoding `%s'", optarg); - fh.f |= f_oddenc; - break; - case 'f': - fh.f |= f_files; - break; - case '0': - fh.f |= GSF_RAW; - break; - case 'e': - fh.f |= f_escape; - break; - case 'c': - fh.f |= f_check; - break; - case 'j': - fh.f |= FHF_JUNK; - break; - case 'b': - fh.f |= FHF_BINARY; - break; - case 'v': - fh.f |= f_verbose; - break; - case 'p': - fh.f |= FHF_PROGRESS; - break; - default: - fh.f |= f_bogus; - break; - } - } - - if (fh.f & f_bogus) { - usage(stderr); - exit(EXIT_FAILURE); - } - argv += optind; - argc -= optind; - - /* --- Generate output --- */ - - if (!(fh.f & f_check) && (argc || (fh.f & f_files))) { - if (fh.f & f_oddhash) printf("#hash %s\n", fh.gch->name); - if (fh.f & f_oddenc) printf("#encoding %s\n", e->name); - if (fh.f & f_escape) fputs("#escape\n", stdout); - } - if (!argc) - rc = hashsum(&fh, 0, e); - else { - int i; - int rrc; - - rc = 0; - for (i = 0; i < argc; i++) { - if ((rrc = hashsum(&fh, argv[i], e)) != 0) - rc = rrc; - } - } - - if (fh.f & FHF_JUNK) { - if (fh.f & f_check) { - if (fhash_junk(&fh, checkjunk, &fh)) rc = EXIT_FAILURE; - } else { - if (fhash_junk(&fh, warnjunk, 0) < 0) rc = EXIT_FAILURE; - } - } - fhash_free(&fh); - - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/hmac-def.h b/hmac-def.h deleted file mode 100644 index 8b6b4f5..0000000 --- a/hmac-def.h +++ /dev/null @@ -1,444 +0,0 @@ -/* -*-c-*- - * - * $Id: hmac-def.h,v 1.8 2004/04/08 01:36:15 mdw Exp $ - * - * Definitions for HMAC and NMAC - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_HMAC_DEF_H -#define CATACOMB_HMAC_DEF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include -#include - -#ifndef CATACOMB_ARENA_H -# include "arena.h" -#endif - -#ifndef CATACOMB_GMAC_H -# include "gmac.h" -#endif - -#ifndef CATACOMB_PARANOIA_H -# include "paranoia.h" -#endif - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @HMAC_DEF@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for the underlying hash function - * - * Use: Creates implementations for the HMAC and NMAC functions. - */ - -#define HMAC_DEF(PRE, pre) \ - \ -/* --- Useful constants --- */ \ - \ -const octet pre##_hmackeysz[] = { KSZ_ANY, PRE##_STATESZ }; \ -const octet pre##_sslmackeysz[] = { KSZ_ANY, PRE##_STATESZ }; \ -const octet pre##_nmackeysz[] = { KSZ_SET, 2 * PRE##_STATESZ, 0 }; \ - \ -/* --- @pre_nmacinit@ --- * \ - * \ - * Arguments: @pre_macctx *key@ = pointer to a MAC key object \ - * @const void *ok@ = pointer to outer hash init vector \ - * @const void *ik@ = pointer to inner hash init vector \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a MAC key for doing NMAC hashing. \ - */ \ - \ -void pre##_nmacinit(pre##_mackey *key, const void *ok, const void *ik) \ -{ \ - memcpy(key->ochain, ok, PRE##_STATESZ); \ - memcpy(key->ichain, ik, PRE##_STATESZ); \ - key->ocount = key->icount = 0; \ -} \ - \ -/* --- @pre_hmacinit@ --- * \ - * \ - * Arguments: @pre_mackey *key@ = pointer to MAC key object \ - * @const void *k@ = pointer to key to use \ - * @size_t sz@ = size of key data \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a MAC key for doing HMAC hashing. Keys \ - * longer than the hash function's output size aren't very \ - * useful, but are accepted. Keys longer than the hash's \ - * block size are also accepted; they are hashed before \ - * use, as specified in RFC2104. \ - */ \ - \ -void pre##_hmacinit(pre##_mackey *key, const void *k, size_t sz) \ -{ \ - int i; \ - const octet *kbuf = k; \ - pre##_ctx ctx; \ - octet buf[PRE##_HASHSZ]; \ - \ - if (sz > PRE##_BUFSZ) { \ - pre##_init(&ctx); \ - pre##_hash(&ctx, k, sz); \ - pre##_done(&ctx, buf); \ - kbuf = buf; \ - sz = PRE##_HASHSZ; \ - } \ - \ - pre##_init(&ctx); \ - memset(ctx.buf, 0x5c, PRE##_BUFSZ); \ - for (i = 0; i < sz; i++) \ - ctx.buf[i] ^= kbuf[i]; \ - pre##_compress(&ctx, ctx.buf); \ - pre##_state(&ctx, key->ochain); \ - \ - pre##_init(&ctx); \ - memset(ctx.buf, 0x36, PRE##_BUFSZ); \ - for (i = 0; i < sz; i++) \ - ctx.buf[i] ^= kbuf[i]; \ - pre##_compress(&ctx, ctx.buf); \ - pre##_state(&ctx, key->ichain); \ - \ - key->ocount = key->icount = PRE##_BUFSZ; \ - BURN(ctx); \ -} \ - \ -/* --- @pre_sslmacinit@ --- * \ - * \ - * Arguments: @pre_mackey *key@ = pointer to MAC key object \ - * @const void *k@ = pointer to key to use \ - * @size_t sz@ = size of key data \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a MAC key for doing hasing using the SSL3 \ - * variant of HMAC. \ - */ \ - \ -void pre##_sslmacinit(pre##_mackey *key, const void *k, size_t sz) \ -{ \ - const octet *kbuf = k; \ - pre##_ctx ctx; \ - octet buf[PRE##_HASHSZ]; \ - \ - if (sz > PRE##_BUFSZ) { \ - pre##_init(&ctx); \ - pre##_hash(&ctx, k, sz); \ - pre##_done(&ctx, buf); \ - kbuf = buf; \ - sz = PRE##_HASHSZ; \ - } \ - \ - pre##_init(&ctx); \ - memcpy(ctx.buf, kbuf, sz); \ - memset(ctx.buf + sz, 0x5c, PRE##_BUFSZ - sz); \ - pre##_compress(&ctx, ctx.buf); \ - pre##_state(&ctx, key->ochain); \ - \ - pre##_init(&ctx); \ - memcpy(ctx.buf, kbuf, sz); \ - memset(ctx.buf + sz, 0x36, PRE##_BUFSZ - sz); \ - pre##_compress(&ctx, ctx.buf); \ - pre##_state(&ctx, key->ichain); \ - \ - key->ocount = key->icount = PRE##_BUFSZ; \ - BURN(ctx); \ -} \ - \ -/* --- @pre_macinit@ --- * \ - * \ - * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \ - * @const pre_mackey *key@ = pointer to MAC key block \ - * \ - * Returns: --- \ - * \ - * Use: Instantiates a MAC context from a key block. \ - */ \ - \ -void pre##_macinit(pre##_macctx *ctx, const pre##_mackey *key) \ -{ \ - memcpy(ctx->chain, key->ochain, PRE##_STATESZ); \ - ctx->count = key->ocount; \ - pre##_set(&ctx->ctx, key->ichain, key->icount); \ -} \ - \ -/* --- @pre_machash@ --- * \ - * \ - * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \ - * @const void *buf@ = pointer to buffer \ - * @size_t sz@ = size of the buffer \ - * \ - * Returns: --- \ - * \ - * Use: Hashes a buffer. \ - */ \ - \ -void pre##_machash(pre##_macctx *ctx, const void *buf, size_t sz) \ -{ \ - pre##_hash(&ctx->ctx, buf, sz); \ -} \ - \ -/* --- @pre_macdone@ --- * \ - * \ - * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \ - * @void *mac@ = pointer to buffer to receive MAC \ - * \ - * Returns: --- \ - * \ - * Use: Returns the result of a MAC computation. \ - */ \ - \ -void pre##_macdone(pre##_macctx *ctx, void *mac) \ -{ \ - pre##_done(&ctx->ctx, mac); \ - pre##_set(&ctx->ctx, ctx->chain, ctx->count); \ - pre##_hash(&ctx->ctx, mac, PRE##_HASHSZ); \ - pre##_done(&ctx->ctx, mac); \ -} \ - \ -/* --- Generic MAC interface --- */ \ - \ -static const gmac_ops gkops; \ -static const ghash_ops gops, gnops, gsslops; \ - \ -typedef struct gkctx { \ - gmac m; \ - const ghash_ops *gops; \ - pre##_mackey k; \ -} gkctx; \ - \ -typedef struct gctx { \ - ghash h; \ - pre##_macctx c; \ - octet buf[PRE##_HASHSZ]; \ -} gctx; \ - \ -static ghash *gkinit(gmac *m) \ -{ \ - gkctx *gk = (gkctx *)m; \ - gctx *g = S_CREATE(gctx); \ - g->h.ops = gk->gops; \ - pre##_macinit(&g->c, &gk->k); \ - return (&g->h); \ -} \ - \ -static gmac *gkey(const void *k, size_t sz) \ -{ \ - gkctx *gk = S_CREATE(gkctx); \ - gk->m.ops = &gkops; \ - gk->gops = &gops; \ - pre##_hmacinit(&gk->k, k, sz); \ - return (&gk->m); \ -} \ - \ -static gmac *gnkey(const void *k, size_t sz) \ -{ \ - gkctx *gk = S_CREATE(gkctx); \ - const octet *kk = k; \ - assert(keysz(sz, pre##_nmackeysz) == sz); \ - gk->m.ops = &gkops; \ - gk->gops = &gnops; \ - pre##_nmacinit(&gk->k, kk, kk + PRE##_STATESZ); \ - return (&gk->m); \ -} \ - \ -static gmac *gsslkey(const void *k, size_t sz) \ -{ \ - gkctx *gk = S_CREATE(gkctx); \ - gk->m.ops = &gkops; \ - gk->gops = &gsslops; \ - pre##_sslmacinit(&gk->k, k, sz); \ - return (&gk->m); \ -} \ - \ -static void ghhash(ghash *h, const void *p, size_t sz) \ -{ \ - gctx *g = (gctx *)h; \ - pre##_machash(&g->c, p, sz); \ -} \ - \ -static octet *ghdone(ghash *h, void *buf) \ -{ \ - gctx *g = (gctx *)h; \ - if (!buf) \ - buf = g->buf; \ - pre##_macdone(&g->c, buf); \ - return (buf); \ -} \ - \ -static ghash *ghcopy(ghash *h) \ -{ \ - gctx *g = (gctx *)h; \ - gctx *gg = S_CREATE(gctx); \ - memcpy(gg, g, sizeof(gctx)); \ - return (&gg->h); \ -} \ - \ -static void ghdestroy(ghash *h) \ -{ \ - gctx *g = (gctx *)h; \ - BURN(*g); \ - S_DESTROY(g); \ -} \ - \ -static void gkdestroy(gmac *m) \ -{ \ - gkctx *gk = (gkctx *)m; \ - BURN(*gk); \ - S_DESTROY(gk); \ -} \ - \ -static ghash *ghinit(void) \ -{ \ - assert(((void)"Attempt to instantiate an unkeyed MAC", 0)); \ - return (0); \ -} \ - \ -const gcmac pre##_nmac = \ - { #pre "-nmac", PRE##_HASHSZ, pre##_nmackeysz, gnkey }; \ -const gcmac pre##_hmac = \ - { #pre "-hmac", PRE##_HASHSZ, pre##_hmackeysz, gkey }; \ -const gcmac pre##_sslmac = \ - { #pre "-sslmac", PRE##_HASHSZ, pre##_sslmackeysz, gsslkey }; \ -static const gmac_ops gkops = { &pre##_hmac, gkinit, gkdestroy }; \ -static const gmac_ops gnkops = { &pre##_nmac, gkinit, gkdestroy }; \ -static const gmac_ops gsslkops = { &pre##_sslmac, gkinit, gkdestroy }; \ -static const gchash gch = { #pre "-hmac", PRE##_HASHSZ, ghinit }; \ -static const ghash_ops gops = \ - { &gch, ghhash, ghdone, ghdestroy, ghcopy }; \ -static const gchash gnch = { #pre "-nmac", PRE##_HASHSZ, ghinit }; \ -static const ghash_ops gnops = \ - { &gch, ghhash, ghdone, ghdestroy, ghcopy }; \ -static const gchash gsslch = { #pre "-sslmac", PRE##_HASHSZ, ghinit }; \ -static const ghash_ops gsslops = \ - { &gch, ghhash, ghdone, ghdestroy, ghcopy }; \ - \ -HMAC_TEST(PRE, pre) - -/* --- @HMAC_TEST@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for hash-specfic definitions - * - * Use: Standard test rig for MAC functions. - */ - -#ifdef TEST_RIG - -#include - -#include -#include -#include - -#define HMAC_TEST(PRE, pre) \ - \ -static int macverify(dstr *v) \ -{ \ - pre##_macctx cctx; \ - pre##_mackey ckey; \ - int ok = 1; \ - int i; \ - octet *p; \ - int szs[] = { 1, 7, 192, -1, 0 }, *ip; \ - size_t csz; \ - dstr d; \ - \ - dstr_create(&d); \ - dstr_ensure(&d, PRE##_HASHSZ); \ - d.len = PRE##_HASHSZ; \ - \ - pre##_hmacinit(&ckey, v[1].buf, v[1].len); \ - \ - for (ip = szs; *ip; ip++) { \ - i = *ip; \ - csz = v[0].len; \ - if (i == -1) \ - i = csz; \ - if (i > csz) \ - continue; \ - p = (octet *)v[0].buf; \ - pre##_macinit(&cctx, &ckey); \ - while (csz) { \ - if (i > csz) \ - i = csz; \ - pre##_machash(&cctx, p, i); \ - p += i; \ - csz -= i; \ - } \ - pre##_macdone(&cctx, d.buf); \ - if (memcmp(d.buf, v[2].buf, PRE##_HASHSZ) != 0) { \ - printf("\nfail:\n\tstep = %i\n\tinput = `%s'\n\tkey = ", \ - *ip, v[0].buf); \ - type_hex.dump(&v[1], stdout); \ - fputs("\n\texpected = ", stdout); \ - type_hex.dump(&v[2], stdout); \ - fputs("\n\tcomputed = ", stdout); \ - type_hex.dump(&d, stdout); \ - putchar('\n'); \ - ok = 0; \ - } \ - } \ - \ - dstr_destroy(&d); \ - return (ok); \ -} \ - \ -static test_chunk macdefs[] = { \ - { #pre "-hmac", macverify, \ - { &type_string, &type_hex, &type_hex, 0 } }, \ - { 0, 0, { 0 } } \ -}; \ - \ -int main(int argc, char *argv[]) \ -{ \ - ego(argv[0]); \ - test_run(argc, argv, macdefs, SRCDIR"/tests/" #pre); \ - return (0); \ -} - -#else -# define HMAC_TEST(PRE, pre) -#endif - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/hmac.h b/hmac.h deleted file mode 100644 index fffb093..0000000 --- a/hmac.h +++ /dev/null @@ -1,191 +0,0 @@ -/* -*-c-*- - * - * $Id: hmac.h,v 1.7 2004/04/08 01:36:15 mdw Exp $ - * - * Generic code for HMAC and NMAC - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the HMAC and NMAC constructions --------------------------* - * - * Designed by Mihir Bellare, Ran Canetti and Hugo Krawczyk, NMAC is a method - * for constructing keyed message authentication algorithms from unkeyed hash - * functions. It has been proven to provide useful security given reasonable - * assumptions about the underlying hash function. HMAC is an alternative - * formulation which doesn't require low-level access to the hash function's - * implementation. NMAC was designed to allow MD5 has a suitable underlying - * hash function, even though doubts were already being raised about its - * collision resistance. - */ - -#ifndef CATACOMB_HMAC_H -#define CATACOMB_HMAC_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#ifndef CATACOMB_GMAC_H -# include "gmac.h" -#endif - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @HMAC_DECL@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for the underlying hash function - * - * Use: Creates declarations for the HMAC and NMAC functions. - */ - -#define HMAC_DECL(PRE, pre) \ - \ -/* --- An HMAC or NMAC key --- */ \ - \ -typedef struct pre##_mackey { \ - octet ochain[PRE##_STATESZ]; /* Chaining for outer hash */ \ - unsigned ocount; /* Byte count for outer hash */ \ - octet ichain[PRE##_STATESZ]; /* Chaining for inner hash */ \ - unsigned icount; /* Byte count for inner hash */ \ -} pre##_mackey; \ - \ -/* --- An HMAC or NMAC hashing context --- */ \ - \ -typedef struct pre##_macctx { \ - pre##_ctx ctx; /* Context for main hashing */ \ - octet chain[PRE##_STATESZ]; /* Chaining for outer hash */ \ - unsigned count; /* Byte count for outer hash */ \ -} pre##_macctx; \ - \ -/* --- Other useful constants --- */ \ - \ -extern const octet pre##_hmackeysz[]; \ -extern const octet pre##_nmackeysz[]; \ -extern const octet pre##_sslmackeysz[]; \ - \ -/* --- @pre_nmacinit@ --- * \ - * \ - * Arguments: @pre_macctx *key@ = pointer to a MAC key object \ - * @const void *ok@ = pointer to outer hash init vector \ - * @const void *ik@ = pointer to inner hash init vector \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a MAC key for doing NMAC hashing. \ - */ \ - \ -extern void pre##_nmacinit(pre##_mackey */*key*/, \ - const void */*ok*/, const void */*ik*/); \ - \ -/* --- @pre_hmacinit@ --- * \ - * \ - * Arguments: @pre_mackey *key@ = pointer to MAC key object \ - * @const void *k@ = pointer to key to use \ - * @size_t sz@ = size of key data \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a MAC key for doing HMAC hashing. Keys \ - * longer than the hash function's output size aren't very \ - * useful, but are accepted. Keys longer than the hash's \ - * block size are also accepted; they are hashed before \ - * use, as specified in RFC2104. \ - */ \ - \ -extern void pre##_hmacinit(pre##_mackey */*key*/, \ - const void */*k*/, size_t /*sz*/); \ - \ -/* --- @pre_sslmacinit@ --- * \ - * \ - * Arguments: @pre_mackey *key@ = pointer to MAC key object \ - * @const void *k@ = pointer to key to use \ - * @size_t sz@ = size of key data \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a MAC key for doing hasing using the SSL3 \ - * variant of HMAC. \ - */ \ - \ -extern void pre##_sslmacinit(pre##_mackey */*key*/, \ - const void */*k*/, size_t /*sz*/); \ - \ -/* --- @pre_macinit@ --- * \ - * \ - * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \ - * @const pre_mackey *key@ = pointer to MAC key block \ - * \ - * Returns: --- \ - * \ - * Use: Instantiates a MAC context from a key block. \ - */ \ - \ -extern void pre##_macinit(pre##_macctx */*ctx*/, \ - const pre##_mackey */*key*/); \ - \ -/* --- @pre_machash@ --- * \ - * \ - * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \ - * @const void *buf@ = pointer to buffer \ - * @size_t sz@ = size of the buffer \ - * \ - * Returns: --- \ - * \ - * Use: Hashes a buffer. \ - */ \ - \ -extern void pre##_machash(pre##_macctx */*ctx*/, \ - const void */*buf*/, size_t /*sz*/); \ - \ -/* --- @pre_macdone@ --- * \ - * \ - * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \ - * @void *mac@ = pointer to buffer to receive MAC \ - * \ - * Returns: --- \ - * \ - * Use: Returns the result of a MAC computation. \ - */ \ - \ -extern void pre##_macdone(pre##_macctx */*ctx*/, void */*mac*/); \ - \ -/* --- Generic MAC interface --- */ \ - \ -extern const gcmac pre##_hmac; \ -extern const gcmac pre##_nmac; \ -extern const gcmac pre##_sslmac; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/idea.c b/idea.c deleted file mode 100644 index c0f7fe7..0000000 --- a/idea.c +++ /dev/null @@ -1,275 +0,0 @@ -/* -*-c-*- - * - * $Id: idea.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Implementation of the IDEA cipher - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "idea.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet idea_keysz[] = { KSZ_SET, IDEA_KEYSZ }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @inv@ --- * - * - * Arguments: @uint16 n@ = number to invert - * - * Returns: Multiplicative inverse of @n@ %$\pmod{2^{16} + 1}$%. - * - * Use: Computes multiplicative inverses. This is handy for the - * decryption key scheduling. - */ - -static uint16 inv(uint16 n) -{ - uint32 m = 0x10001; - uint32 a = 1, b = 0; - uint32 nn = n; - - if (!nn) - nn = 0x10000; - for (;;) { - uint32 q, r, t; - if (!(r = m % nn)) - break; - q = m / nn; - m = nn; nn = r; - t = a; a = b - q * a; b = t; - } - if (a > MASK16) - a += 1; - return (U16(a)); -} - -/* --- @MUL@ --- * - * - * Arguments @x@ and @y@ are two 32-bit values to multiply. On exit, @x@ is - * the product of the two arguments. The result is not normalized back to 16 - * bits; the arguments are not expected to be normalized. - * - * This code is from `Side Channel Attack Hardening of the IDEA Cipher', - * published by Ascom Tech. - */ - -#define MUL(x, y) do { \ - unsigned _t; \ - uint32 _tt; \ - \ - x = U16(x - 1); \ - _t = U16(y - 1); \ - _tt = (uint32)x * (uint32)_t + (uint32)x + (uint32)_t + 1; \ - x = U16(_tt); \ - _t = U16(_tt >> 16); \ - x = x - _t + (x <= _t); \ -} while (0) - -/* --- @idea_init@ --- * - * - * Arguments: @idea_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes an IDEA key buffer. The buffer must be exactly - * 16 bytes in size, because IDEA is only defined with a key - * size of 128 bits. - */ - -void idea_init(idea_ctx *k, const void *buf, size_t sz) -{ - KSZ_ASSERT(idea, sz); - - /* --- Unpack the encryption key --- */ - - { - const octet *p = buf; - uint16 *q = k->e; - uint32 a = LOAD32(p + 0); - uint32 b = LOAD32(p + 4); - uint32 c = LOAD32(p + 8); - uint32 d = LOAD32(p + 12); - int i; - - /* --- Main unpacking loop --- */ - - for (i = 0; i < 6; i++) { - - /* --- Spit out the next 8 subkeys --- */ - - q[0] = U16(a >> 16); - q[1] = U16(a >> 0); - q[2] = U16(b >> 16); - q[3] = U16(b >> 0); - q[4] = U16(c >> 16); - q[5] = U16(c >> 0); - q[6] = U16(d >> 16); - q[7] = U16(d >> 0); - q += 8; - - /* --- Rotate and permute the subkeys --- */ - - { - uint32 t = a; - a = U32((a << 25) | (b >> 7)); - b = U32((b << 25) | (c >> 7)); - c = U32((c << 25) | (d >> 7)); - d = U32((d << 25) | (t >> 7)); - } - } - - /* --- Write out the tail-enders --- */ - - q[0] = U16(a >> 16); - q[1] = U16(a >> 0); - q[2] = U16(b >> 16); - q[3] = U16(b >> 0); - } - - /* --- Convert this into the decryption key --- */ - - { - uint16 *p = k->e + 52; - uint16 *q = k->d; - int i; - - /* --- Translate the main round keys --- */ - - for (i = 0; i < 8; i++) { - p -= 6; - q[4] = p[0]; - q[5] = p[1]; - q[0] = inv(p[2]); - q[3] = inv(p[5]); - if (i) { - q[1] = 0x10000 - p[4]; - q[2] = 0x10000 - p[3]; - } else { - q[1] = 0x10000 - p[3]; - q[2] = 0x10000 - p[4]; - } - q += 6; - } - - /* --- Translate the tail-enders --- */ - - p -= 4; - q[0] = inv(p[0]); - q[1] = 0x10000 - p[1]; - q[2] = 0x10000 - p[2]; - q[3] = inv(p[3]); - } -} - -/* --- @ROUND@ --- */ - -#define MIX(k, a, b, c, d) do { \ - MUL(a, k[0]); \ - b += k[1]; \ - c += k[2]; \ - MUL(d, k[3]); \ -} while (0) - -#define MA(k, a, b, c, d) do { \ - unsigned _u = a ^ c; \ - unsigned _v = b ^ d; \ - MUL(_u, k[4]); \ - _v += _u; \ - MUL(_v, k[5]); \ - _u += _v; \ - a ^= _v; \ - b ^= _u; \ - c ^= _v; \ - d ^= _u; \ -} while (0); - -#define ROUND(k, a, b, c, d) do { \ - MIX(k, a, b, c, d); \ - MA(k, a, b, c, d); \ - (k) += 6; \ -} while (0) - -/* --- Encryption --- */ - -#define EBLK(k, a, b, c, d) do { \ - unsigned _a = U16(a >> 16); \ - unsigned _b = U16(a >> 0); \ - unsigned _c = U16(b >> 16); \ - unsigned _d = U16(b >> 0); \ - const uint16 *_k = (k); \ - \ - ROUND(_k, _a, _b, _c, _d); \ - ROUND(_k, _a, _c, _b, _d); \ - ROUND(_k, _a, _b, _c, _d); \ - ROUND(_k, _a, _c, _b, _d); \ - ROUND(_k, _a, _b, _c, _d); \ - ROUND(_k, _a, _c, _b, _d); \ - ROUND(_k, _a, _b, _c, _d); \ - ROUND(_k, _a, _c, _b, _d); \ - MIX (_k, _a, _c, _b, _d); \ - c = ((uint32)U16(_a) << 16) | (uint32)U16(_c); \ - d = ((uint32)U16(_b) << 16) | (uint32)U16(_d); \ -} while (0) - -#define DBLK(k, a, b) EBLK((k), (a), (b)) - -/* --- @idea_eblk@, @idea_dblk@ --- * - * - * Arguments: @const idea_ctx *k@ = pointer to a key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -void idea_eblk(const idea_ctx *k, const uint32 *s, uint32 *d) -{ - EBLK(k->e, s[0], s[1], d[0], d[1]); -} - -void idea_dblk(const idea_ctx *k, const uint32 *s, uint32 *d) -{ - EBLK(k->d, s[0], s[1], d[0], d[1]); -} - -BLKC_TEST(IDEA, idea) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/idea.h b/idea.h deleted file mode 100644 index b049d74..0000000 --- a/idea.h +++ /dev/null @@ -1,113 +0,0 @@ -/* -*-c-*- - * - * $Id: idea.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Implementation of the IDEA cipher - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the IDEA block cipher ------------------------------------* - * - * IDEA was invented by James Massey and Xuejia Lai. The fundamental idea - * underlying the cipher is combining incompatible group operations. The - * algorithm's main claim to fame is that it is the symmetric cipher in PGP - * version 2. - * - * The IDEA algorithm is allegedly patented by Ascom Tech A.G., even in the - * UK and Europe. Ascom are willing to grant licences for use in software - * which forbids commercial use, but this is not compatible with Free - * Software Foundation ideology. The author recommends against the use of - * the IDEA cipher entirely. Blowfish is conceptually simpler, appears more - * concervative, offers a larger keyspace, runs faster, and is in the public - * domain. - */ - -#ifndef CATACOMB_IDEA_H -#define CATACOMB_IDEA_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magical numbers ---------------------------------------------------*/ - -#define IDEA_BLKSZ 8 -#define IDEA_KEYSZ 16 -#define IDEA_CLASS (N, B, 64) - -extern const octet idea_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct idea_ctx { - uint16 e[52]; - uint16 d[52]; -} idea_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @idea_init@ --- * - * - * Arguments: @idea_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes an IDEA key buffer. The buffer must be exactly - * 16 bytes in size, because IDEA is only defined with a key - * size of 128 bits. - */ - -extern void idea_init(idea_ctx */*k*/, const void */*buf*/, size_t /*sz*/); - -/* --- @idea_eblk@, @idea_dblk@ --- * - * - * Arguments: @const idea_ctx *k@ = pointer to a key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void idea_eblk(const idea_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); -extern void idea_dblk(const idea_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/karatsuba.h b/karatsuba.h deleted file mode 100644 index d0b81fc..0000000 --- a/karatsuba.h +++ /dev/null @@ -1,144 +0,0 @@ -/* -*-c-*- - * - * $Id: karatsuba.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Macros for Karatsuba functions - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_KARATSUBA_H -#define CATACOMB_KARATSUBA_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MPW_H -# include "mpw.h" -#endif - -/*----- Normal arithmetic macros ------------------------------------------*/ - -#define UADD(dv, av, avl) do { \ - mpw *_dv = (dv); \ - const mpw *_av = (av), *_avl = (avl); \ - mpw _c = 0; \ - \ - while (_av < _avl) { \ - mpw _a, _b; \ - mpd _x; \ - _a = *_av++; \ - _b = *_dv; \ - _x = (mpd)_a + (mpd)_b + _c; \ - *_dv++ = MPW(_x); \ - _c = _x >> MPW_BITS; \ - } \ - while (_c) { \ - mpd _x = (mpd)*_dv + (mpd)_c; \ - *_dv++ = MPW(_x); \ - _c = _x >> MPW_BITS; \ - } \ -} while (0) - -#define UADD2(dv, dvl, av, avl, bv, bvl) do { \ - mpw *_dv = (dv), *_dvl = (dvl); \ - const mpw *_av = (av), *_avl = (avl); \ - const mpw *_bv = (bv), *_bvl = (bvl); \ - mpw _c = 0; \ - \ - while (_av < _avl || _bv < _bvl) { \ - mpw _a, _b; \ - mpd _x; \ - _a = (_av < _avl) ? *_av++ : 0; \ - _b = (_bv < _bvl) ? *_bv++ : 0; \ - _x = (mpd)_a + (mpd)_b + _c; \ - *_dv++ = MPW(_x); \ - _c = _x >> MPW_BITS; \ - } \ - *_dv++ = _c; \ - while (_dv < _dvl) \ - *_dv++ = 0; \ -} while (0) - -#define USUB(dv, av, avl) do { \ - mpw *_dv = (dv); \ - const mpw *_av = (av), *_avl = (avl); \ - mpw _c = 0; \ - \ - while (_av < _avl) { \ - mpw _a, _b; \ - mpd _x; \ - _a = *_av++; \ - _b = *_dv; \ - _x = (mpd)_b - (mpd)_a - _c; \ - *_dv++ = MPW(_x); \ - if (_x >> MPW_BITS) \ - _c = 1; \ - else \ - _c = 0; \ - } \ - while (_c) { \ - mpd _x = (mpd)*_dv - (mpd)_c; \ - *_dv++ = MPW(_x); \ - if (_x >> MPW_BITS) \ - _c = 1; \ - else \ - _c = 0; \ - } \ -} while (0) - -/*----- Binary polynomial arithmetic macros -------------------------------*/ - -#define UXOR(dv, av, avl) do { \ - mpw *_dv = (dv); \ - const mpw *_av = (av), *_avl = (avl); \ - \ - while (_av < _avl) \ - *_dv++ ^= *_av++; \ -} while (0) - -#define UXOR2(dv, dvl, av, avl, bv, bvl) do { \ - mpw *_dv = (dv), *_dvl = (dvl); \ - const mpw *_av = (av), *_avl = (avl); \ - const mpw *_bv = (bv), *_bvl = (bvl); \ - \ - while (_av < _avl || _bv < _bvl) { \ - mpw _a, _b; \ - _a = (_av < _avl) ? *_av++ : 0; \ - _b = (_bv < _bvl) ? *_bv++ : 0; \ - *_dv++ = _a ^ _b; \ - } \ - while (_dv < _dvl) \ - *_dv++ = 0; \ -} while (0) - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/key-attr.c b/key-attr.c deleted file mode 100644 index b6a3616..0000000 --- a/key-attr.c +++ /dev/null @@ -1,308 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Key attribute manipulation - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include -#include - -#include -#include - -#include "key.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @key_chkident@ --- * - * - * Arguments: @const char *p@ = pointer to a type string - * - * Returns: Zero if OK, -1 on error. - * - * Use: Checks whether an identification component string is OK. - */ - -int key_chkident(const char *p) -{ - if (!p || !*p || strlen(p) > 255) - return (-1); - while (*p) { - if (*p == ':' || *p == '.' || isspace((unsigned char)*p)) - return (-1); - p++; - } - return (0); -} - -/* --- @key_chkcomment@ --- * - * - * Arguments: @const char *p@ = pointer to a comment string - * - * Returns: Zero if OK, -1 on error. - * - * Use: Checks whether a comment string is OK. - */ - -int key_chkcomment(const char *p) -{ - if (!p) - return (0); - if (!*p) - return (-1); - while (*p) { - if (*p == '\n') - return (-1); - p++; - } - return (0); -} - -/* --- @key_mkattriter@ --- * - * - * Arguments: @key_attriter *i@ = pointer to attribute iterator - * @key *k@ = pointer to key - * - * Returns: --- - * - * Use: Initializes an attribute iterator. The attributes are - * returned by @key_nextattr@. - */ - -void key_mkattriter(key_attriter *i, key *k) -{ - sym_mkiter(&i->i, &k->a); -} - -/* --- @key_nextattr@ --- * - * - * Arguments: @key_attriter *i@ = pointer to attribute iterator - * @const char **n, **v@ = pointers to name and value - * - * Returns: Zero if no attribute available, or nonzero if returned OK. - * - * Use: Returns the next attribute. - */ - -int key_nextattr(key_attriter *i, const char **n, const char **v) -{ - key_attr *a = sym_next(&i->i); - if (!a) - return (0); - if (n) *n = SYM_NAME(a); - if (v) *v = a->p; - return (1); -} - -/* --- @key_getattr@ --- * - * - * Arguments: @key_file *f@ = pointer to file - * @key *k@ = pointer to key - * @const char *n@ = pointer to attribute name - * - * Returns: Pointer to attribute value, or null if not found. - * - * Use: Returns the value of a key attribute. - */ - -const char *key_getattr(key_file *f, key *k, const char *n) -{ - key_attr *a; - if ((a = sym_find(&k->a, n, -1, 0, 0)) == 0) - return (0); - return (a->p); -} - -/* --- @key_putattr@ --- * - * - * Arguments: @key_file *f@ = pointer to file - * @key *k@ = pointer to key - * @const char *n@ = pointer to attribute name - * @const char *v@ = pointer to attribute value or null - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Inserts an attribute on a key. If an attribute with the same - * name already exists, it is deleted. Setting a null value - * removes the attribute. - */ - -int key_putattr(key_file *f, key *k, const char *n, const char *v) -{ - key_attr *a; - unsigned found; - - if (!(f->f & KF_WRITE)) - return (KERR_READONLY); - if (strlen(n) > 255) - return (KERR_BADATTR); - - if (v) { - a = sym_find(&k->a, n, -1, sizeof(*a), &found); - if (found) - xfree(a->p); - a->p = xstrdup(v); - } else if ((a = sym_find(&k->a, n, -1, 0, 0)) != 0) { - xfree(a->p); - sym_remove(&k->a, a); - } - - f->f |= KF_MODIFIED; - return (0); -} - -/* --- @key_setkeydata@ --- * - * - * Arguments: @key_file *kf@ = pointer to key file - * @key *k@ = pointer to key - * @key_data *kd@ = new key data - * - * Returns: Zero on success, or a @KERR_@ error code on failure. - * - * Use: Sets the key data for a key. - */ - -int key_setkeydata(key_file *kf, key *k, key_data *kd) -{ - if (!(kf->f & KF_WRITE)) - return (KERR_READONLY); - key_incref(kd); - key_drop(k->k); - k->k = kd; - kf->f |= KF_MODIFIED; - return (0); -} - -/* --- @key_setcomment@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * @key *k@ = pointer to key block - * @const char *c@ = pointer to comment to set, or zero - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Replaces the key's current comment with a new one. - */ - -int key_setcomment(key_file *f, key *k, const char *c) -{ - if (!(f->f & KF_WRITE)) - return (KERR_READONLY); - if (key_chkcomment(c)) - return (KERR_BADCOMMENT); - if (k->c) - xfree(k->c); - if (c) - k->c = xstrdup(c); - else - k->c = 0; - f->f |= KF_MODIFIED; - return (0); -} - -/* --- @key_settag@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * @key *k@ = pointer to key block - * @const char *tag@ = pointer to comment to set, or zero - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Replaces the key's current tag with a new one. - */ - -int key_settag(key_file *f, key *k, const char *tag) -{ - key_ref *kr; - unsigned found; - - if (!(f->f & KF_WRITE)) - return (KERR_READONLY); - - /* --- Make sure the tag is OK --- */ - - if (tag && key_chkident(tag)) - return (KERR_BADTAG); - - /* --- See if the new tag is the same as the old one --- */ - - if ((!tag && !k->tag) || - (tag && k->tag && strcmp(tag, k->tag) == 0)) - return (0); - - /* --- Allocate an entry for the new tag --- */ - - if (tag) { - kr = sym_find(&f->bytag, tag, -1, sizeof(*kr), &found); - if (found && !KEY_EXPIRED(time(0), kr->k->del)) - return (KERR_DUPTAG); - kr->k = k; - } - - /* --- Remove any existing tag --- */ - - if (k->tag) { - kr = sym_find(&f->bytag, k->tag, -1, 0, 0); - assert(((void)"No bytag link", kr)); - sym_remove(&f->bytag, kr); - xfree(k->tag); - } - - /* --- Done --- */ - - f->f |= KF_MODIFIED; - if (tag) - k->tag = xstrdup(tag); - else - k->tag = 0; - return (0); -} - -/* --- @key_fulltag@ --- * - * - * Arguments: @key *k@ = pointer to key - * @dstr *d@ = pointer to destination string - * - * Returns: --- - * - * Use: Emits the key's full tag, which has the form - * `ID:TYPE[:TAG]'. This is used in the textual file format, - * and to identify passphrases for locked keys. - */ - -void key_fulltag(key *k, dstr *d) -{ - dstr_putf(d, "%08lx:%s", (unsigned long)k->id, k->type); - if (k->tag) - dstr_putf(d, ":%s", k->tag); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/key-binary.c b/key-binary.c deleted file mode 100644 index c1ef53b..0000000 --- a/key-binary.c +++ /dev/null @@ -1,316 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Key binary encoding - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include -#include -#include -#include - -#include "key-data.h" -#include "mp.h" -#include "mptext.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @key_decode@ --- * - * - * Arguments: @const void *p@ = pointer to buffer to read - * @size_t sz@ = size of the buffer - * - * Returns: The newly-read key data, or null if it failed. - * - * Use: Decodes a binary representation of a key. - */ - -key_data *key_decode(const void *p, size_t sz) -{ - const octet *q = p; - size_t psz; - key_data *kd; - unsigned e; - - /* --- Parse the header information --- * - * - * Make sure the size matches external reality. Security holes have been - * known to creep in without this sort of check. (No, this isn't an after- - * the-fact patch-up.) - */ - - e = LOAD16(q); - psz = LOAD16(q + 2); - if (psz + 4 > sz) - return (0); - - /* --- Now decide what to do --- */ - - switch (e & KF_ENCMASK) { - - /* --- Plain binary data --- */ - - case KENC_BINARY: - case KENC_ENCRYPT: - kd = key_newbinary(e, q + 4, psz); - break; - - /* --- Multiprecision integer data --- */ - - case KENC_MP: - kd = key_newmp(e, mp_loadb(e & KF_BURN ? MP_NEWSEC : MP_NEW, - q + 4, psz)); - break; - - /* --- String data --- */ - - case KENC_STRING: - kd = key_newraw(e); - kd->u.p = xmalloc(sz + 1); - memcpy(kd->u.p, q + 4, sz); - kd->u.p[sz] = 0; - break; - - /* --- Elliptic curve point data --- */ - - case KENC_EC: { - size_t xsz, ysz; - kd = key_newraw(e); - EC_CREATE(&kd->u.e); - if (!sz) break; - if (sz < 2) return (0); - xsz = LOAD16(q + 4); - if (sz < xsz + 4) return (0); - ysz = LOAD16(q + 6 + xsz); - if (sz < xsz + ysz + 4) return (0); - kd->u.e.x = mp_loadb(MP_NEW, q + 6, xsz); - kd->u.e.y = mp_loadb(MP_NEW, q + 8 + xsz, ysz); - } break; - - /* --- Structured key data --- */ - - case KENC_STRUCT: { - dstr d = DSTR_INIT; - key_data *nkd; - - if ((e & ~KF_ENCMASK) || (psz & 3)) - return (0); - q += 4; - kd = key_newstruct(); - - while (psz) { - - /* --- Read the tag string --- */ - - DRESET(&d); - sz = LOAD8(q); - if (sz >= psz) - goto fail; - DPUTM(&d, q + 1, sz); - DPUTZ(&d); - sz = (sz + 4) & ~3; - q += sz; psz -= sz; - - /* --- Read the encoding and size --- */ - - sz = (LOAD16(q + 2) + 7) & ~3; - if (sz > psz) - goto fail; - - /* --- Create a table node and fill it in --- */ - - if ((nkd = key_decode(q, sz)) == 0) - goto fail; - key_structsteal(kd, d.buf, nkd); - psz -= sz; - q += sz; - } - dstr_destroy(&d); - break; - - /* --- Tidy up after a failure --- */ - - fail: - dstr_destroy(&d); - key_drop(kd); - return (0); - } break; - - /* --- Everything else --- */ - - default: - return (0); - } - - /* --- OK, that was good --- */ - - kd->e = e; - return (kd); -} - -/* --- @key_encode@ --- * - * - * Arguments: @key_data *k@ = pointer to key data block - * @dstr *d@ = pointer to destination string - * @const key_filter *kf@ = pointer to key selection block - * - * Returns: Nonzero if an item was actually written. - * - * Use: Encodes a key block as binary data. - */ - -static int ksbyname(const void *a, const void *b) { - key_struct *const *x = a, *const *y = b; - return (strcmp(SYM_NAME(*x), SYM_NAME(*y))); -} - -int key_encode(key_data *k, dstr *d, const key_filter *kf) -{ - int rc = 0; - if (!KEY_MATCH(k, kf)) - return (0); - switch (k->e & KF_ENCMASK) { - case KENC_BINARY: - case KENC_ENCRYPT: { - char *p; - - DENSURE(d, (k->u.k.sz + 7) & ~3); - p = d->buf + d->len; - STORE16(p, k->e); - STORE16(p + 2, k->u.k.sz); - d->len += 4; - DPUTM(d, k->u.k.k, k->u.k.sz); - rc = 1; - } break; - - case KENC_MP: { - char *p; - size_t sz = mp_octets(k->u.m); - - DENSURE(d, (sz + 7) & ~3); - p = d->buf + d->len; - STORE16(p, k->e); - STORE16(p + 2, sz); - mp_storeb(k->u.m, p + 4, sz); - d->len += sz + 4; - rc = 1; - } break; - - case KENC_STRING: { - char *p; - size_t sz = strlen(k->u.p); - - DENSURE(d, (sz + 7) & ~3); - p = d->buf + d->len; - STORE16(p, k->e); - STORE16(p + 2, sz); - memcpy(p + 4, k->u.p, sz); - d->len += sz + 4; - rc = 1; - } break; - - case KENC_EC: { - char *p; - size_t xsz = 0, ysz = 0; - size_t sz; - - if (EC_ATINF(&k->u.e)) - sz = 0; - else { - xsz = mp_octets(k->u.e.x); - ysz = mp_octets(k->u.e.y); - sz = xsz + ysz + 4; - } - DENSURE(d, (sz + 7) & ~3); - p = d->buf + d->len; - STORE16(p, k->e); - STORE16(p + 2, sz); - if (!EC_ATINF(&k->u.e)) { - STORE16(p + 4, xsz); - mp_storeb(k->u.e.x, p + 6, xsz); - STORE16(p + 6 + xsz, ysz); - mp_storeb(k->u.e.y, p + 8 + xsz, ysz); - } - d->len += sz + 4; - rc = 1; - } break; - - case KENC_STRUCT: { - size_t n; - char *p; - key_struct *ks, **ksv; - size_t nks, j; - sym_iter i; - - n = d->len; - DENSURE(d, 4); - p = d->buf + n; - STORE16(p, k->e & KF_ENCMASK); - d->len += 4; - - for (nks = 0, sym_mkiter(&i, &k->u.s); - (ks = sym_next(&i)) != 0; - nks++); - if (nks) { - ksv = xmalloc(nks * sizeof(*ksv)); - for (j = 0, sym_mkiter(&i, &k->u.s); (ks = sym_next(&i)) != 0; j++) - ksv[j] = ks; - qsort(ksv, nks, sizeof(*ksv), ksbyname); - for (j = 0; j < nks; j++) { - size_t o = d->len; - ks = ksv[j]; - DENSURE(d, 1); - *(octet *)(d->buf + d->len++) = strlen(SYM_NAME(ks)); - DPUTS(d, SYM_NAME(ks)); - while (d->len & 3) - DPUTC(d, 0); - if (key_encode(ks->k, d, kf)) - rc = 1; - else - d->len = o; - } - xfree(ksv); - } - if (!rc) - d->len = n; - else { - p = d->buf + n + 2; - n = d->len - n - 4; - STORE16(p, n); - } - } break; - } - while (d->len & 3) - DPUTC(d, 0); - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/key-data.c b/key-data.c deleted file mode 100644 index 69795fe..0000000 --- a/key-data.c +++ /dev/null @@ -1,469 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Encoding and decoding of key data - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "key-data.h" -#include "mp.h" -#include "mptext.h" - -/*----- Reference counting stuff ------------------------------------------*/ - -/* --- @key_incref@ --- * - * - * Arguments: @key_data *k@ = pointer to key data - * - * Returns: --- - * - * Use: Increments the refcount on a key data block. - */ - -void key_incref(key_data *k) { KEY_INCREF(k); } - -/* --- @key_destroy@ --- * - * - * Arguments: @key_data *k@ = pointer to key data to destroy - * - * Returns: --- - * - * Use: Destroys a block of key data, regardless of reference count. - * Don't use this unless you know what you're doing. - */ - -void key_destroy(key_data *k) -{ - switch (k->e & KF_ENCMASK) { - case KENC_BINARY: - case KENC_ENCRYPT: - if (k->u.k.k) { - if (k->e & KF_BURN) - memset(k->u.k.k, 0, k->u.k.sz); - sub_free(k->u.k.k, k->u.k.sz); - } - break; - case KENC_MP: - mp_drop(k->u.m); - break; - case KENC_STRING: - xfree(k->u.p); - break; - case KENC_EC: - EC_DESTROY(&k->u.e); - break; - case KENC_STRUCT: { - key_data *kd; - key_subkeyiter i; - - for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, 0, &kd); ) - KEY_DROP(kd); - sym_destroy(&k->u.s); - } break; - default: - abort(); - } - DESTROY(k); -} - -/* --- @key_drop@ --- * - * - * Arguments: @key_data *k@ = pointer to key data to destroy - * - * Returns: --- - * - * Use: Drops a reference to key data, destroying it if necessary. - */ - -void key_drop(key_data *k) { KEY_DROP(k); } - -/* --- @key_split@ --- * - * - * Arguments: @key_data **kk@ = address of pointer to key data block - * - * Returns: --- - * - * Use: Replaces @*kk@ with a pointer to the same key data, but with - * just one reference. - */ - -void key_split(key_data **kk) -{ - key_data *k = *kk; - - if (k->ref == 1) - return; - switch (k->e & KF_ENCMASK) { - case KENC_BINARY: - *kk = key_newbinary(k->e, k->u.k.k, k->u.k.sz); - break; - case KENC_ENCRYPT: - *kk = key_newencrypted(k->e, k->u.k.k, k->u.k.sz); - break; - case KENC_MP: - *kk = key_newmp(k->e, k->u.m); - break; - case KENC_STRING: - *kk = key_newstring(k->e, k->u.p); - break; - case KENC_EC: - *kk = key_newec(k->e, &k->u.e); - break; - case KENC_STRUCT: { - key_subkeyiter i; - const char *tag; - key_data *kd; - - *kk = key_newstruct(); - for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) - key_structset(*kk, tag, kd); - } break; - default: - abort(); - } -} - -/*----- Setting new values ------------------------------------------------*/ - -/* --- @key_newraw@ --- * - * - * Arguments: @unsigned e@ = encoding type to set - * - * Returns: New key block, not filled in. - */ - -key_data *key_newraw(unsigned e) -{ - key_data *k = CREATE(key_data); - k->e = e; - k->ref = 1; - return (k); -} - -/* --- @key_newbinary@ --- * - * - * Arguments: @unsigned e@ = other encoding flags - * @const void *p@ = pointer to key data - * @size_t sz@ = size of the key data - * - * Returns: New key data object. - */ - -key_data *key_newbinary(unsigned e, const void *p, size_t sz) -{ - key_data *k = key_newraw(KENC_BINARY | e); - k->u.k.k = sub_alloc(sz); - memcpy(k->u.k.k, p, sz); - k->u.k.sz = sz; - return (k); -} - -/* --- @key_newencrypted@ --- * - * - * Arguments: @unsigned e@ = other encoding flags - * @const void *p@ = pointer to key data - * @size_t sz@ = size of the key data - * - * Returns: New key data object. - */ - -key_data *key_newencrypted(unsigned e, const void *p, size_t sz) -{ - key_data *k = key_newraw(KENC_ENCRYPT | e); - k->u.k.k = sub_alloc(sz); - memcpy(k->u.k.k, p, sz); - k->u.k.sz = sz; - return (k); -} - -/* --- @key_newmp@ --- * - * - * Arguments: @unsigned e@ = other encoding flags - * @mp *m@ = pointer to the value to set - * - * Returns: New key data object. - */ - -key_data *key_newmp(unsigned e, mp *m) -{ - key_data *k = key_newraw(KENC_MP | e); - k->u.m = MP_COPY(m); - return (k); -} - -/* --- @key_newstring@ --- * - * - * Arguments: @unsigned e@ = other encoding flags - * @const char *p@ = pointer to the value to set - * - * Returns: New key data object. - */ - -key_data *key_newstring(unsigned e, const char *p) -{ - key_data *k = key_newraw(KENC_STRING | e); - k->u.p = xstrdup(p); - return (k); -} - -/* --- @key_newec@ --- * - * - * Arguments: @unsigned e@ = other encoding flags - * @const ec *pt@ = pointer to the value to set - * - * Returns: New key data object. - */ - -key_data *key_newec(unsigned e, const ec *pt) -{ - key_data *k = key_newraw(KENC_EC | e); - EC_CREATE(&k->u.e); - EC_COPY(&k->u.e, pt); - return (k); -} - -/* --- @key_newstruct@ --- * - * - * Arguments: --- - * - * Returns: New key data object. - */ - -key_data *key_newstruct(void) -{ - key_data *k = key_newraw(KENC_STRUCT); - sym_create(&k->u.s); - return (k); -} - -/* --- @key_structfind@ --- * - * - * Arguments: @key_data *k@ = pointer to key data block - * @const char *tag@ = pointer to tag string - * - * Returns: Pointer to key data block, or null. - * - * Use: Looks up the tag in a structured key. - */ - -key_data *key_structfind(key_data *k, const char *tag) -{ - key_struct *ks; - assert(((void)"Key is not structured", - (k->e & KF_ENCMASK) == KENC_STRUCT)); - ks = sym_find(&k->u.s, tag, -1, 0, 0); - if (!ks) - return (0); - return (ks->k); -} - -/* --- @key_mksubkeyiter@ --- * - * - * Arguments: @key_subkeyiter *i@ = pointer to iterator block - * @key_data *k@ = pointer to key data block - * - * Returns: --- - * - * Use: Initializes a subkey iterator. - */ - -void key_mksubkeyiter(key_subkeyiter *i, key_data *k) -{ - assert(((void)"Key is not structured", - (k->e & KF_ENCMASK) == KENC_STRUCT)); - sym_mkiter(&i->i, &k->u.s); -} - -/* --- @key_nextsubkey@ --- * - * - * Arguments: @key_structiter *i@ = pointer to iterator block - * @const char **tag@ = where to put the tag pointer, or null - * @key_data **kd@ = where to put the key data pointer, or null - * - * Returns: Nonzero if there was another item, zero if we hit the - * end-stop. - * - * Use: Collects the next subkey of a structured key. - */ - -int key_nextsubkey(key_subkeyiter *i, const char **tag, key_data **kd) -{ - key_struct *ks; - - if ((ks = sym_next(&i->i)) == 0) - return (0); - if (tag) *tag = SYM_NAME(ks); - if (kd) *kd = ks->k; - return (1); -} - -/* --- @key_structset@, @key_structsteal@ --- * - * - * Arguments: @key_data *k@ = pointer to key data block - * @const char *tag@ = pointer to tag string - * @key_data *kd@ = new key data to store - * - * Returns: --- - * - * Use: Creates a new subkey. Stealing doesn't affect @kd@'s - * refcount. If @kd@ is null, the subkey is deleted. - */ - -static void structset(key_data *k, int stealp, - const char *tag, key_data *kd) -{ - key_struct *ks; - unsigned f; - - assert(((void)"Key is not structured", k->e == KENC_STRUCT)); - assert(((void)"Key has multiple references", k->ref == 1)); - if (!kd) { - ks = sym_find(&k->u.s, tag, -1, 0, 0); - if (ks) sym_remove(&k->u.s, ks); - } else { - ks = sym_find(&k->u.s, tag, -1, sizeof(*ks), &f); - if (f) - key_drop(ks->k); - if (!stealp) KEY_INCREF(kd); - ks->k = kd; - } -} - -void key_structset(key_data *k, const char *tag, key_data *kd) - { structset(k, 0, tag, kd); } -void key_structsteal(key_data *k, const char *tag, key_data *kd) - { structset(k, 1, tag, kd); } - -/*----- Miscellaneous operations ------------------------------------------*/ - -/* --- @key_do@ --- * - * - * Arguments: @key_data *k@ = pointer to key data block - * @const key_filter *kf@ = pointer to filter block - * @dstr *d@ = pointer to base string - * @int (*func)(key_data *kd, dstr *d, void *p@ = function - * @void *p@ = argument to function - * - * Returns: Nonzero return code from function, or zero. - * - * Use: Runs a function over all the leaves of a key. - */ - -int key_do(key_data *k, const key_filter *kf, dstr *d, - int (*func)(key_data */*kd*/, dstr */*d*/, void */*p*/), - void *p) -{ - if (!KEY_MATCH(k, kf)) - return (0); - if ((k->e & KF_ENCMASK) != KENC_STRUCT) - return (func(k, d, p)); - else { - key_subkeyiter i; - const char *tag; - size_t n = 0; - int rc; - - if (d) - n = d->len; - for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) { - if (d) { - d->len = n; - dstr_putf(d, ".%s", tag); - } - if ((rc = key_do(k, kf, d, func, p)) != 0) - return (rc); - } - return (0); - } -} - -/* --- @key_copydata@ --- * - * - * Arguments: @key_data *k@ = key data to copy - * @const key_filter *kf@ = pointer to filter block - * - * Returns: Pointer to a copy of the data, or null if the root subkey - * didn't match the filter. - * - * Use: Copies a chunk of key data. Subkeys, whether they're - * structured or leaves, which don't match the filter aren't - * copied. The copy may or may not have structure in common - * with the original. - */ - -static int structmatchp(key_data *k, const key_filter *kf) -{ - key_subkeyiter i; - - if (!KEY_MATCH(k, kf)) return (0); - else if ((k->e & KF_ENCMASK) == KENC_STRUCT) return (1); - else { - for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, 0, &k); ) - if (!structmatchp(k, kf)) return (0); - return (1); - } -} - -key_data *key_copydata(key_data *k, const key_filter *kf) -{ - key_subkeyiter i; - const char *tag; - key_data *kd, *kkd; - - /* --- Trivial cases --- */ - - if (!KEY_MATCH(k, kf)) - return (0); - else if (structmatchp(k, kf)) { - key_incref(k); - return (k); - } - - /* --- Copy a structured key recursively --- */ - - kkd = key_newstruct(); - for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) { - if ((kd = key_copydata(kd, kf)) != 0) - key_structsteal(kkd, tag, kd); - } - - /* --- Done --- */ - - return (kkd); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/key-data.h b/key-data.h deleted file mode 100644 index d6a5636..0000000 --- a/key-data.h +++ /dev/null @@ -1,594 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Manipulating key data - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_KEY_DATA_H -#define CATACOMB_KEY_DATA_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include -#include -#include - -#ifndef CATACOMB_KEY_ERROR_H -# include "key-error.h" -#endif - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_EC_H -# include "ec.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- Key binary data --- */ - -typedef struct key_bin { - octet *k; /* Pointer to key data */ - size_t sz; /* Size of the key data (in bytes) */ -} key_bin; - -/* --- Key data structure --- */ - -typedef struct key_data { - unsigned e; /* Encoding type for key data */ - unsigned ref; /* Reference counter */ - union { - key_bin k; /* Binary key data */ - mp *m; /* Multiprecision integer */ - sym_table s; /* Structured key data */ - char *p; /* String pointer */ - ec e; /* Elliptic curve point */ - } u; -} key_data; - -typedef struct key_struct { - sym_base _b; - key_data *k; -} key_struct; - -typedef struct key_subkeyiter { sym_iter i; } key_subkeyiter; - -/* --- Packing and unpacking --- */ - -typedef struct key_packdef { - unsigned e; /* Key data encoding type */ - void *p; /* Pointer to the destination */ - key_data *kd; /* Key data block */ -} key_packdef; - -typedef struct key_packstruct { - char *name; /* Pointer to name string */ - key_packdef kp; /* Packing structure */ -} key_packstruct; - -/* --- Key binary encoding --- * - * - * The binary encoding consists of a header containing a 16-bit encoding type - * and a 16-bit length, followed immediately by the key data, followed by - * between zero and three zero bytes to make the total length a multiple of - * four. The format of the following data depends on the encoding type: - * - * @KENC_BINARY@ Binary data. - * - * @KENC_MP@ Octet array interpreted in big-endian byte order. - * - * @KENC_STRUCT@ An array of pairs, each containing a string (8-bit - * length followed by data and zero-padding to 4-byte - * boundary) and key binary encodings. - * - * @KENC_ENCRYPT@ Binary data, format - */ - -/* --- Key encoding methods and other flags--- */ - -enum { - - /* --- Bottom two bits are the encoding type --- */ - - KF_ENCMASK = 0x83, /* Encoding mask */ - KENC_BINARY = 0x00, /* Plain binary key (@k@) */ - KENC_MP = 0x01, /* Multiprecision integer (@i@) */ - KENC_STRUCT = 0x02, /* Structured key data (@s@) */ - KENC_ENCRYPT = 0x03, /* Encrypted key type (@k@) */ - KENC_STRING = 0x80, /* ASCII string (@p@) */ - KENC_EC = 0x81, /* Elliptic curve point (@e@) */ - - /* --- Key category bits --- */ - - KF_CATMASK = 0x0c, /* Category mask */ - KCAT_SYMM = 0x00, /* Symmetric encryption key */ - KCAT_PRIV = 0x04, /* Private (asymmetric) key */ - KCAT_PUB = 0x08, /* Public (asymmetric) key */ - KCAT_SHARE = 0x0c, /* Shared (asymmetric) key */ - KF_NONSECRET = 0x08, /* Bit flag for non-secret keys */ - - /* --- Other flags --- */ - - KF_BURN = 0x10, /* Burn key after use */ - KF_OPT = 0x20, /* Optional key (for @key_unpack@) */ - - /* --- Tag end --- */ - - KENC_MAX /* Dummy limit constant */ -}; - -/* --- Key locking return codes --- */ - -#define KL_OK 0 /* All good */ -#define KL_IOERR -1 /* I/O problem (e.g., getting pp) */ -#define KL_KEYERR -2 /* Wrong key supplied */ -#define KL_DATAERR -3 /* Data format error */ - -/* --- Key flag filtering --- */ - -typedef struct key_filter { - unsigned f; - unsigned m; -} key_filter; - -/* --- Matching aginst key selection --- */ - -#define KEY_MATCH(kd, kf) \ - (!(kf) || \ - ((kd)->e & KF_ENCMASK) == KENC_STRUCT || \ - ((kd)->e & (kf)->m) == (kf)->f) - -/*----- Key flags and filtering -------------------------------------------*/ - -/* --- @key_readflags@ --- * - * - * Arguments: @const char *p@ = pointer to string to read - * @char **pp@ = where to store the end pointer - * @unsigned *ff@ = where to store the flags - * @unsigned *mm@ = where to store the mask - * - * Returns: Zero if all went well, nonzero if there was an error. - * - * Use: Reads a flag string. - */ - -extern int key_readflags(const char */*p*/, char **/*pp*/, - unsigned */*ff*/, unsigned */*mm*/); - -/* --- @key_writeflags@ --- * - * - * Arguments: @unsigned f@ = flags to write - * @dstr *d@ = pointer to destination string - * - * Returns: --- - * - * Use: Emits a flags word as a string representation. - */ - -extern void key_writeflags(unsigned /*f*/, dstr */*d*/); - -/* --- @key_match@ --- * - * - * Arguments: @key_data *k@ = pointer to key data block - * @const key_filter *kf@ = pointer to filter block - * - * Returns: Nonzero if the key matches the filter. - * - * Use: Checks whether a key matches a filter. - */ - -extern int key_match(key_data */*k*/, const key_filter */*kf*/); - -/*----- Setting new key data ----------------------------------------------*/ - -/* --- @key_newraw@ --- * - * - * Arguments: @unsigned e@ = encoding type to set - * - * Returns: New key block, not filled in. - */ - -extern key_data *key_newraw(unsigned /*e*/); - -/* --- @key_newbinary@ --- * - * - * Arguments: @unsigned e@ = other encoding flags - * @const void *p@ = pointer to key data - * @size_t sz@ = size of the key data - * - * Returns: New key data object. - */ - -extern key_data *key_newbinary(unsigned /*e*/, - const void */*p*/, size_t /*sz*/); - -/* --- @key_newencrypted@ --- * - * - * Arguments: @unsigned e@ = other encoding flags - * @const void *p@ = pointer to key data - * @size_t sz@ = size of the key data - * - * Returns: New key data object. - */ - -extern key_data *key_newencrypted(unsigned /*e*/, - const void */*p*/, size_t /*sz*/); - -/* --- @key_newmp@ --- * - * - * Arguments: @unsigned e@ = other encoding flags - * @mp *m@ = pointer to the value to set - * - * Returns: New key data object. - */ - -extern key_data *key_newmp(unsigned /*e*/, mp */*m*/); - -/* --- @key_newstring@ --- * - * - * Arguments: @unsigned e@ = other encoding flags - * @const char *p@ = pointer to the value to set - * - * Returns: New key data object. - */ - -extern key_data *key_newstring(unsigned /*e*/, const char */*p*/); - -/* --- @key_newec@ --- * - * - * Arguments: @unsigned e@ = other encoding flags - * @const ec *pt@ = pointer to the value to set - * - * Returns: New key data object. - */ - -extern key_data *key_newec(unsigned /*e*/, const ec */*pt*/); - -/* --- @key_newstruct@ --- * - * - * Arguments: --- - * - * Returns: New key data object. - */ - -extern key_data *key_newstruct(void); - -/* --- @key_structfind@ --- * - * - * Arguments: @key_data *k@ = pointer to key data block - * @const char *tag@ = pointer to tag string - * - * Returns: Pointer to key data block, or null. - * - * Use: Looks up the tag in a structured key. - */ - -extern key_data *key_structfind(key_data */*k*/, const char */*tag*/); - -/* --- @key_mksubkeyiter@ --- * - * - * Arguments: @key_subkeyiter *i@ = pointer to iterator block - * @key_data *k@ = pointer to key data block - * - * Returns: --- - * - * Use: Initializes a subkey iterator. - */ - -extern void key_mksubkeyiter(key_subkeyiter */*i*/, key_data */*k*/); - -/* --- @key_nextsubkey@ --- * - * - * Arguments: @key_structiter *i@ = pointer to iterator block - * @const char **tag@ = where to put the tag pointer, or null - * @key_data **kd@ = where to put the key data pointer, or null - * - * Returns: Nonzero if there was another item, zero if we hit the - * end-stop. - * - * Use: Collects the next subkey of a structured key. - */ - -extern int key_nextsubkey(key_subkeyiter */*i*/, - const char **/*tag*/, key_data **/*kd*/); - -/* --- @key_structset@, @key_structsteal@ --- * - * - * Arguments: @key_data *k@ = pointer to key data block - * @const char *tag@ = pointer to tag string - * @key_data *kd@ = new key data to store - * - * Returns: --- - * - * Use: Creates a new subkey. Stealing doesn't affect @kd@'s - * refcount. If @kd@ is null, the subkey is deleted. - */ - -extern void key_structset(key_data */*k*/, - const char */*tag*/, key_data */*kd*/); -extern void key_structsteal(key_data */*k*/, - const char */*tag*/, key_data */*kd*/); - -/* --- @key_split@ --- * - * - * Arguments: @key_data **kk@ = address of pointer to key data block - * - * Returns: --- - * - * Use: Replaces @*kk@ with a pointer to the same key data, but with - * just one reference. - */ - -extern void key_split(key_data **/*kk*/); - -/*----- Miscellaneous operations ------------------------------------------*/ - -/* --- @key_incref@ --- * - * - * Arguments: @key_data *k@ = pointer to key data - * - * Returns: --- - * - * Use: Increments the refcount on a key data block. - */ - -#define KEY_INCREF(k) ((k)->ref++) -extern void key_incref(key_data */*k*/); - -/* --- @key_destroy@ --- * - * - * Arguments: @key_data *k@ = pointer to key data to destroy - * - * Returns: --- - * - * Use: Destroys a block of key data, regardless of reference count. - * Don't use this unless you know what you're doing. - */ - -extern void key_destroy(key_data */*k*/); - -/* --- @key_drop@ --- * - * - * Arguments: @key_data *k@ = pointer to key data to destroy - * - * Returns: --- - * - * Use: Drops a reference to key data, destroying it if necessary. - */ - -#define KEY_DROP(k) do { \ - key_data *_k = k; \ - _k->ref--; \ - if (_k->ref == 0) \ - key_destroy(_k); \ -} while (0) - -extern void key_drop(key_data */*k*/); - -/* --- @key_do@ --- * - * - * Arguments: @key_data *k@ = pointer to key data block - * @const key_filter *kf@ = pointer to filter block - * @dstr *d@ = pointer to base string - * @int (*func)(key_data *kd, dstr *d, void *p@ = function - * @void *p@ = argument to function - * - * Returns: Nonzero return code from function, or zero. - * - * Use: Runs a function over all the leaves of a key. - */ - -extern int key_do(key_data */*k*/, const key_filter */*kf*/, dstr */*d*/, - int (*/*func*/)(key_data */*kd*/, - dstr */*d*/, void */*p*/), - void */*p*/); - -/* --- @key_copydata@ --- * - * - * Arguments: @key_data *k@ = key data to copy - * @const key_filter *kf@ = pointer to filter block - * - * Returns: Pointer to a copy of the data, or null if the root subkey - * didn't match the filter. - * - * Use: Copies a chunk of key data. Subkeys, whether they're - * structured or leaves, which don't match the filter aren't - * copied. The copy may or may not have structure in common - * with the original. - */ - -extern key_data *key_copydata(key_data */*k*/, const key_filter */*kf*/); - -/*----- Textual encoding --------------------------------------------------*/ - -/* --- @key_read@ --- * - * - * Arguments: @const char *p@ = pointer to textual key representation - * @char **pp@ = where to store the end pointer - * - * Returns: The newly-read key data, or null if it failed. - * - * Use: Parses a textual key description. - */ - -extern key_data *key_read(const char */*p*/, char **/*pp*/); - -/* --- @key_write@ --- * - * - * Arguments: @key_data *k@ = pointer to key data - * @dstr *d@ = destination string to write on - * @const key_filter *kf@ = pointer to key selection block - * - * Returns: Nonzero if any items were actually written. - * - * Use: Writes a key in a textual encoding. - */ - -extern int key_write(key_data */*k*/, dstr */*d*/, const key_filter */*kf*/); - -/*----- Key binary encoding -----------------------------------------------*/ - -/* --- @key_decode@ --- * - * - * Arguments: @const void *p@ = pointer to buffer to read - * @size_t sz@ = size of the buffer - * - * Returns: The newly-read key data, or null if it failed. - * - * Use: Decodes a binary representation of a key. - */ - -extern key_data *key_decode(const void */*p*/, size_t /*sz*/); - -/* --- @key_encode@ --- * - * - * Arguments: @key_data *k@ = pointer to key data block - * @dstr *d@ = pointer to destination string - * @const key_filter *kf@ = pointer to key selection block - * - * Returns: Nonzero if any items were actually written. - * - * Use: Encodes a key block as binary data. - */ - -extern int key_encode(key_data */*k*/, dstr */*d*/, - const key_filter */*kf*/); - -/*----- Packing and unpacking keys ----------------------------------------*/ - -/* --- @key_pack@ --- * - * - * Arguments: @key_packdef *kp@ = pointer to packing structure - * @key_data **kd@ = where to put the key data pointer - * @dstr *d@ = pointer to tag string for the key data - * - * Returns: Error code, or zero. - * - * Use: Packs a key from a data structure. - */ - -extern int key_pack(key_packdef */*kp*/, key_data **/*kd*/, dstr */*d*/); - -/* --- @key_unpack@ --- * - * - * Arguments: @key_packdef *kp@ = pointer to packing structure - * @key_data *kd@ = pointer to source key data - * @dstr *d@ = pointer to tag string for the key data - * - * Returns: Error code, or zero. - * - * Use: Unpacks a key into an appropriate data structure. - */ - -extern int key_unpack(key_packdef */*kp*/, key_data */*kd*/, dstr */*d*/); - -/* --- @key_unpackdone@ --- * - * - * Arguments: @key_packdef *kp@ = pointer to packing definition - * - * Returns: --- - * - * Use: Frees the key components contained within a packing - * definition, created during key unpacking. - */ - -extern void key_unpackdone(key_packdef */*kp*/); - -/*----- Key encryption ----------------------------------------------------*/ - -/* --- @key_lock@ --- * - * - * Arguments: @key_data **kt@ = where to store the destination pointer - * @key_data *k@ = source key data block or null to use @*kt@ - * @const void *e@ = secret to encrypt key with - * @size_t esz@ = size of the secret - * - * Returns: --- - * - * Use: Encrypts a key data block using a secret. - */ - -extern void key_lock(key_data **/*kt*/, key_data */*k*/, - const void */*e*/, size_t /*esz*/); - -/* --- @key_unlock@ --- * - * - * Arguments: @key_data **kt@ = where to store the destination pointer - * @key_data *k@ = source key data block or null to use @*kt@ - * @const void *e@ = secret to decrypt the block with - * @size_t esz@ = size of the secret - * - * Returns: Zero for success, or a @KERR_@ error code. - * - * Use: Unlocks a key using a secret. - */ - -extern int key_unlock(key_data **/*kt*/, key_data */*k*/, - const void */*e*/, size_t /*esz*/); - -/* --- @key_plock@ --- * - * - * Arguments: @key_data **kt@ = where to store the destination pointer - * @key_data *k@ = source key data block or null to use @*kt@ - * @const char *tag@ = tag to use for passphrase - * - * Returns: Zero if successful, a @KERR@ error code on failure. - * - * Use: Locks a key by encrypting it with a passphrase. - */ - -extern int key_plock(key_data **/*kt*/, key_data */*k*/, - const char */*tag*/); - -/* --- @key_punlock@ --- * - * - * Arguments: @key_data **kt@ = where to store the destination pointer - * @key_data *k@ = source key data block or null to use @*kt@ - * @const char *tag@ = tag to use for passphrase - * - * Returns: Zero if successful, a @KERR@ error code on failure. - * - * Use: Unlocks a passphrase-locked key. - */ - -extern int key_punlock(key_data **/*kt*/, key_data */*k*/, - const char */*tag*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/key-error.c b/key-error.c deleted file mode 100644 index cd7d386..0000000 --- a/key-error.c +++ /dev/null @@ -1,62 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Translating key error codes into strings - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include "key-error.h" - -/*----- Error reporting ---------------------------------------------------*/ - -/* --- @key_strerror@ --- * - * - * Arguments: @int err@ = error code from @key_new@ - * - * Returns: Pointer to error string. - * - * Use: Translates a @KERR@ error code into a human-readable - * string. - */ - -const char *key_strerror(int err) -{ - static const char *const tab[] = { -#define ENTRY(tag, num, str) str, - KEY_ERRORS(ENTRY) -#undef ENTRY - "Unknown error code" - }; - - unsigned e = -err; - if (e >= N(tab)) - e = N(tab) - 1; - return (tab[e]); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/key-error.h b/key-error.h deleted file mode 100644 index 2029a2b..0000000 --- a/key-error.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Key management error codes - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_KEY_ERROR_H -#define CATACOMB_KEY_ERROR_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Error codes -------------------------------------------------------*/ - -#define KEY_ERRORS(_) \ - _(OK, 0, "No error") \ - _(BADTAG, -1, "Bad tag string") \ - _(BADTYPE, -2, "Bad type string") \ - _(BADCOMMENT, -3, "Bad comment string") \ - _(DUPID, -4, "Key id already exists") \ - _(DUPTAG, -5, "Key tag already exists") \ - _(READONLY, -6, "Key file is read-only") \ - _(WILLEXPIRE, -7, "Key will eventually expire") \ - _(EXPIRED, -8, "Key has expired") \ - _(BADFLAGS, -9, "Bad key flags string") \ - _(BADPASS, -10, "Failed to unlock key") \ - _(WRONGTYPE, -11, "Unexpected key encoding type") \ - _(NOTFOUND, -12, "Key not found") \ - _(BADATTR, -13, "Bad attribute name") \ - _(MALFORMED, -14, "Malformed key data") \ - _(IO, -15, "I/O error") \ - -enum { -#define ENTRY(tag, num, str) KERR_##tag = num, - KEY_ERRORS(ENTRY) -#undef ENTRY - KERR__dummy -}; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @key_strerror@ --- * - * - * Arguments: @int err@ = error code from @key_new@ - * - * Returns: Pointer to error string. - * - * Use: Translates a @KERR@ error code into a human-readable string. - */ - -extern const char *key_strerror(int /*err*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/key-fetch.c b/key-fetch.c deleted file mode 100644 index 08a800b..0000000 --- a/key-fetch.c +++ /dev/null @@ -1,208 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Higher-level key unpacking - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "key.h" -#include "key-data.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @key_fetchinit@ --- * - * - * Arguments: @const key_fetchdef *kf@ = pointer to base definition - * @key_packstruct *kps@ = pointer to destination packing def - * @void *p@ = pointer to destination block - * - * Returns: Pointer to packing definition. - * - * Use: Initializes a packing definition (@key_packdef@ structure). - * If @kps@ is null on entry, an appropriately sized block is - * allocated automatically. Otherwise it must be large enough. - */ - -static size_t kfcount(const key_fetchdef *kf) -{ - size_t n = 1; - while (kf->name) { - n++; - if (kf->kf) - n += kfcount(kf->kf); - kf++; - } - return (n); -} - -key_packdef *key_fetchinit(const key_fetchdef *kf, - key_packstruct *kp, void *p) -{ - size_t n = 1 + kfcount(kf); - key_packdef *kpd; - key_packstruct *kps; - char *cp = p; - - /* --- If @kps@ is null, count the entries and allocate --- */ - - if (kp) - kp->name = 0; - else { - kp = xmalloc(n * sizeof(*kp)); - kp->name = (char *)kp; - } - - /* --- Fill in the top part --- */ - - kp->kp.e = KENC_STRUCT; - kp->kp.p = &kp[1]; - kp->kp.kd = 0; - kpd = &kp->kp; - - /* --- Initialize for the main loop --- */ - - kps = kp + n; - n = 0; - kp++; - - /* --- Iterate over the entries in the table --- * - * - * The end of the target block is used as a stack to record where - * substructure is meant to occur. The integer @n@ is the depth of the - * stack; @kps@ is a full descending stack pointer. The @kp.p@ member of a - * stack element points back to an entry with substructure, the @kp.p@ - * member of which refers to the @kf@ table for the substructure. - * - * This should all be about as clear as mud. - */ - - for (;;) { - - /* --- Blat out a level's worth --- */ - - while (kf->name) { - kp->name = kf->name; - kp->kp.e = kf->e; - kp->kp.kd = 0; - if ((kf->e & KF_ENCMASK) != KENC_STRUCT) - kp->kp.p = cp + kf->off; - else { - (--kps)->kp.p = kp; - kp->kp.p = (void *)kf->kf; - n++; - } - kf++; - kp++; - } - (kp++)->name = 0; - if (!n) - break; - - /* --- Pop an entry from the stack --- */ - - { - key_packstruct *kkp = (kps++)->kp.p; - kf = kkp->kp.p; - kkp->kp.p = kp; - n--; - } - } - - /* --- We're done --- */ - - return (kpd); -} - -/* --- @key_fetch@ --- * - * - * Arguments: @key_packdef *kp@ = pointer to packing structure - * @key *k@ = key file containing desired key - * - * Returns: Error code, or zero. - * - * Use: Fetches an unpacked key from a packed one. - */ - -int key_fetch(key_packdef *kp, key *k) -{ - dstr d = DSTR_INIT; - int e; - - key_fulltag(k, &d); - e = key_unpack(kp, k->k, &d); - dstr_destroy(&d); - return (e); -} - -/* --- @key_fetchbyname@ --- * - * - * Arguments: @key_packdef *kp@ = pointer to packing structure - * @key_file *kf@ = key file containing desired key - * @const char *tag@ = user's tag describing the key - * - * Returns: Error code, or zero. - * - * Use: Fetches a named key from a key file and unpacks it - * conveniently. - */ - -int key_fetchbyname(key_packdef *kp, key_file *kf, const char *tag) -{ - dstr d = DSTR_INIT; - key_data **kd; - int e; - - if (key_qtag(kf, tag, &d, 0, &kd)) - e = KERR_NOTFOUND; - else - e = key_unpack(kp, *kd, &d); - dstr_destroy(&d); - return (e); -} - -/* --- @key_fetchdone@ --- * - * - * Arguments: @key_packdef *kp@ = pointer to packing structure - * - * Returns: --- - * - * Use: Frees a packing structure. If the structure was allocated by - * @key_fetchinit@ then it is freed. - */ - -void key_fetchdone(key_packdef *kp) -{ - key_packstruct *kps = - (key_packstruct *)(((char *)kp) - offsetof(key_packstruct, kp)); - key_unpackdone(kp); - if (kps->name) - xfree(kps); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/key-file.c b/key-file.c deleted file mode 100644 index 3245b93..0000000 --- a/key-file.c +++ /dev/null @@ -1,338 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * System-dependent key filing operations - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "key.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @fdcopy@ --- * - * - * Arguments: @int source@ = source file descriptor - * @int dest@ = destination file descriptor - * - * Returns: Zero if OK, nonzero otherwise. - * - * Use: Copies data from one file descriptor to another. - */ - -static int fdcopy(int source, int dest) -{ - char buf[4096]; - char *p; - - if (lseek(source, 0, SEEK_SET) < 0|| - lseek(dest, 0, SEEK_SET) < 0 || - ftruncate(dest, 0) < 0) - return (-1); - for (;;) { - int n = read(source, buf, sizeof(buf)); - if (n < 0) - return (-1); - else if (n == 0) - break; - p = buf; - while (n) { - int nn = write(dest, p, n); - if (nn < 0) - return (-1); - p += nn; - n -= nn; - } - } - return (0); -} - -/* --- @key_save@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * - * Returns: A @KWRITE_@ code indicating how well it worked. - * - * Use: Writes a key file's data back to the actual file. This code - * is extremely careful about error handling. It should usually - * be able to back out somewhere sensible, but it can tell when - * it's got itself into a real pickle and starts leaving well - * alone. - * - * Callers, please make sure that you ring alarm bells when this - * function returns @KWRITE_BROKEN@. - */ - -int key_save(key_file *f) -{ - dstr n_older = DSTR_INIT, n_old = DSTR_INIT, n_new = DSTR_INIT; - int rc = KWRITE_FAIL; - - if (!(f->f & KF_MODIFIED)) - return (KWRITE_OK); - if (!f->fp) - return (KWRITE_FAIL); - - /* --- Write a new key file out --- * - * - * Check for an error after each key line. This ought to be enough. - * Checking after each individual byte write and @fprintf@ isn't much fun. - */ - - dstr_putf(&n_new, "%s.new", f->name); - - { - key *k; - key_iter i; - FILE *fp; - - if ((fp = fopen(n_new.buf, "w")) == 0) - goto fail_open; - - for (key_mkiter(&i, f); (k = key_next(&i)) != 0; ) { - if (key_extract(f, k, fp, 0)) { - fclose(fp); - goto fail_write; - } - } - - if (fclose(fp)) - goto fail_write; - } - - /* --- Set up the other filenames --- */ - - dstr_putf(&n_older, "%s.older", f->name); - dstr_putf(&n_old, "%s.old", f->name); - - /* --- Move the current backup on one --- * - * - * If the `older' file exists, then we're in need of attention. - */ - - { - struct stat st; - if (stat(n_older.buf, &st) == 0 || errno != ENOENT) { - errno = EEXIST; - rc = KWRITE_BROKEN; - goto fail_shift; - } - if (rename(n_old.buf, n_older.buf) && errno != ENOENT) - goto fail_shift; - } - - /* --- Copy the current file to the backup --- */ - - { - int fd; - if ((fd = open(n_old.buf, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0) - goto fail_backup; - if (fdcopy(fileno(f->fp), fd)) { - close(fd); - goto fail_backup; - } - if (close(fd)) - goto fail_backup; - } - - /* --- Copy the newly created file to the current one --- * - * - * This is the dangerous bit. - */ - - { - int fd; - if ((fd = open(n_new.buf, O_RDONLY)) < 0) - goto fail_update; - if (fdcopy(fd, fileno(f->fp))) { - close(fd); - goto fail_update; - } - close(fd); - if (fsync(fileno(f->fp))) - goto fail_update; - } - - /* --- Clean up --- * - * - * Remove the `new' file and the `older' backup. Then we're done. - */ - - unlink(n_new.buf); - unlink(n_older.buf); - dstr_destroy(&n_new); - dstr_destroy(&n_old); - dstr_destroy(&n_older); - return (KWRITE_OK); - - /* --- Failure while writing the new key file --- * - * - * I need to copy the backup back. If that fails then I'm really stuffed. - * If not, then I might as well try to get the backups sorted back out - * again. - */ - -fail_update: - { - int fd; - int e = errno; - - if ((fd = open(n_old.buf, O_RDONLY)) < 0) - rc = KWRITE_BROKEN; - else if (fdcopy(fd, fileno(f->fp))) { - close(fd); - rc = KWRITE_BROKEN; - } else { - close(fd); - if (fsync(fileno(f->fp))) - rc = KWRITE_BROKEN; - } - - errno = e; - if (rc == KWRITE_BROKEN) - goto fail_shift; - } - /* Now drop through */ - - /* --- Failure while writing the new backup --- * - * - * The new backup isn't any use. Try to recover the old one. - */ - -fail_backup: - { - int e = errno; - unlink(n_old.buf); - if (rename(n_older.buf, n_old.buf) && errno != ENOENT) - rc = KWRITE_BROKEN; - errno = e; - } - /* Now drop through */ - - /* --- Failure while demoting the current backup --- * - * - * Leave the completed output file there for the operator in case he wants - * to clean up. - */ - -fail_shift: - dstr_destroy(&n_new); - dstr_destroy(&n_old); - dstr_destroy(&n_older); - return (rc); - - /* --- Failure during write of new data --- * - * - * Clean up the new file and return. These errors can never cause - * breakage. - */ - -fail_write: - unlink(n_new.buf); -fail_open: - dstr_destroy(&n_new); - return (rc); -} - -/* --- @key_lockfile@ --- * - * - * Arguments: @key_file *f@ = pointer to file structure to initialize - * @const char *file@ = pointer to the file name - * @unsigned how@ = opening options (@KOPEN_*@). - * - * Returns: Zero if it worked, nonzero otherwise. - * - * Use: Opens a keyfile and stores the information needed for - * continued access in the structure. - * - * If the file is opened with @KOPEN_WRITE@, it's created if - * necessary with read and write permissions for owner only, and - * locked for update while it's open. - * - * This is a system-dependent routine, and only really intended - * for the private use of @key_open@. - */ - -int key_lockfile(key_file *f, const char *file, unsigned how) -{ - int of, lf; - const char *ff; - int fd; - - /* --- Handle the magic no-file option --- */ - - if (how & KOPEN_NOFILE) { - f->fp = 0; - return (0); - } - - /* --- Lots of things depend on whether we're writing --- */ - - switch (how & KOPEN_MASK) { - case KOPEN_READ: - of = O_RDONLY; - lf = LOCK_NONEXCL; - ff = "r"; - break; - case KOPEN_WRITE: - of = O_RDWR | O_CREAT; - lf = LOCK_EXCL; - ff = "r+"; - break; - default: - errno = EINVAL; - return (-1); - } - - /* --- Open and lock the file --- */ - - if ((fd = open(file, of, 0600)) < 0) - return (-1); - if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0 || - lock_file(fd, lf) < 0 || - (f->fp = fdopen(fd, ff)) == 0) { - close(fd); - return (-1); - } - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/key-flags.c b/key-flags.c deleted file mode 100644 index a547898..0000000 --- a/key-flags.c +++ /dev/null @@ -1,204 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Reading and writing key flag strings - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include -#include - -#include "key-data.h" - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct key_flags { - unsigned f; - unsigned m; -} key_flags; - -/*----- Flags table -------------------------------------------------------*/ - -typedef struct flagent { - const char *name; - unsigned f; - unsigned m; -} flagent; - -static const flagent flagtab[] = { - - /* --- Encoding types --- */ - - { "binary", KENC_BINARY, KF_ENCMASK }, - { "integer", KENC_MP, KF_ENCMASK }, - { "struct", KENC_STRUCT, KF_ENCMASK }, - { "encrypt", KENC_ENCRYPT, KF_ENCMASK }, - { "string", KENC_STRING, KF_ENCMASK }, - { "ec", KENC_EC, KF_ENCMASK }, - - /* --- Classes of keys --- */ - - { "shared", KCAT_SHARE, KF_CATMASK }, - { "public", KCAT_PUB, KF_CATMASK }, - { "private", KCAT_PRIV, KF_CATMASK }, - { "symmetric", KCAT_SYMM, KF_CATMASK }, - { "secret", 0, KF_NONSECRET }, - { "-secret", KF_NONSECRET, KF_NONSECRET }, - - /* --- Other flags --- */ - - { "burn", KF_BURN, KF_BURN }, - { "-burn", 0, KF_BURN }, - - /* --- End marker --- */ - - { 0, 0, 0 } -}; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @key_readflags@ --- * - * - * Arguments: @const char *p@ = pointer to string to read - * @char **pp@ = where to store the end pointer - * @unsigned *ff@ = where to store the flags - * @unsigned *mm@ = where to store the mask - * - * Returns: Zero if all went well, nonzero if there was an error. - * - * Use: Reads a flag string. - */ - -int key_readflags(const char *p, char **pp, unsigned *ff, unsigned *mm) -{ - unsigned f = 0, m = 0; - - for (;;) { - size_t sz = strcspn(p, ",:"); - const flagent *e, *ee = 0; - - /* --- Look up the string in the flags table --- */ - - if (sz == 4 && strncmp(p, "none", 4) == 0) - goto next; - for (e = flagtab; e->name; e++) { - if (strncmp(e->name, p, sz) == 0) { - if (e->name[sz] == 0) { - ee = e; - break; - } else if (ee) - return (KERR_BADFLAGS); - else - ee = e; - } - } - if (!ee) - return (KERR_BADFLAGS); - - /* --- Adjust the flag words --- * - * - * Ensure that the flags set are disjoint. - */ - - if (m & ee->m) - return (KERR_BADFLAGS); - m |= ee->m; - f |= ee->f; - next: - p += sz; - if (*p == 0 || *p == ':') - break; - p++; - } - - /* --- Report the results --- */ - - if (ff) *ff = f; - if (mm) *mm = m; - if (pp) *pp = (char *)p; - return (0); -} - -/* --- @key_writeflags@ --- * - * - * Arguments: @unsigned f@ = flags to write - * @dstr *d@ = pointer to destination string - * - * Returns: --- - * - * Use: Emits a flags word as a string representation. - */ - -void key_writeflags(unsigned f, dstr *d) -{ - int del = 0; - const flagent *e; - unsigned m = 0; - - for (e = flagtab; e->name; e++) { - if (m & e->m || e->name[0] == '-' || (f & e->m) != e->f) - continue; - if (del) - DPUTC(d, ','); - DPUTS(d, e->name); - m |= e->m; - del = 1; - } -} - -/* --- @key_match@ --- * - * - * Arguments: @key_data *k@ = pointer to key data block - * @const key_filter *kf@ = pointer to filter block - * - * Returns: Nonzero if the key matches the filter. - * - * Use: Checks whether a key matches a filter. - */ - -int key_match(key_data *k, const key_filter *kf) -{ - key_subkeyiter i; - const char *tag; - key_data *kd; - - if (!kf) - return (1); - if ((k->e & KF_ENCMASK) != KENC_STRUCT) - return ((k->e & kf->m) == kf->f); - - for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) { - if (key_match(kd, kf)) - return (1); - } - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/key-io.c b/key-io.c deleted file mode 100644 index 5c70909..0000000 --- a/key-io.c +++ /dev/null @@ -1,571 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Adding new keys to a key file - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "key.h" - -/*----- Tweakable macros --------------------------------------------------*/ - -#define KEY_INITSZ 16 - -/*----- Low-level functions -----------------------------------------------*/ - -/* --- @insert@ --- * - * - * Arguments: @key_file *f@ = pointer to file structure - * @key *k@ = pointer to key block to insert - * - * Returns: Error code (one of the @KERR@ code). - * - * Use: Links a new key block into the complicated data structure - * which is a keyring file. - */ - -static int insert(key_file *f, key *k) -{ - key_ref *kr = 0; - unsigned found; - - /* --- Sanity preservatives --- */ - - if (key_chkident(k->type)) - return (KERR_BADTYPE); - else if (k->tag && key_chkident(k->tag)) - return (KERR_BADTAG); - - /* --- Insert into the tag table --- */ - - if (k->tag) { - kr = sym_find(&f->bytag, k->tag, -1, sizeof(*kr), &found); - if (found) - return (KERR_DUPTAG); - kr->k = k; - } - - /* --- Insert into the id table --- */ - - { - hash_base **bin, *b; - - bin = HASH_BIN(&f->byid, k->id); - for (b = *bin; b; b = b->next) { - if (b->hash == k->id) { - if (kr) - sym_remove(&f->bytag, kr); - return (KERR_DUPID); - } - } - - k->_b.next = *bin; - *bin = &k->_b; - k->_b.hash = k->id; - } - - /* --- Extend the table --- */ - - if (f->idload > 0) - f->idload--; - else if (hash_extend(&f->byid)) - f->idload = SYM_LIMIT(f->byid.mask / 2); - - /* --- Insert into the type table --- */ - - kr = sym_find(&f->bytype, k->type, -1, sizeof(*kr), &found); - if (!found) { - kr->k = k; - k->next = 0; - } else { - key **p = &kr->k; - if (k->exp != KEXP_FOREVER) { - while (*p && (*p)->exp != KEXP_EXPIRE && (*p)->exp > k->exp) - p = &(*p)->next; - } - k->next = *p; - *p = k; - } - - return (KERR_OK); -} - -/*----- Reading and writing keys ------------------------------------------*/ - -/* --- @exptime@ --- * - * - * Arguments: @const char *p@ = pointer to string - * - * Returns: Time value. - * - * Use: Translates an expiry or deletion time. - */ - -time_t exptime(const char *p) -{ - size_t sz = strlen(p); - if (strncmp(p, "expired", sz) == 0) - return (KEXP_EXPIRE); - else if (strncmp(p, "forever", sz) == 0) - return (KEXP_FOREVER); - else - return (atol(p)); -} - -/* --- @key_merge@ --- * - * - * Arguments: @key_file *f@ = pointer to file structure - * @const char *file@ = name of file (for error messages) - * @FILE *fp@ = file handle to read from - * @key_reporter *rep@ = error reporting function - * @void *arg@ = argument for function - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Reads keys from a file, and inserts them into the file. - */ - -int key_merge(key_file *f, const char *file, FILE *fp, - key_reporter *rep, void *arg) -{ - int line = 0; - dstr l = DSTR_INIT; - dstr n = DSTR_INIT, v = DSTR_INIT; - - if (!(f->f & KF_WRITE)) - return (KERR_READONLY); - - for (; dstr_putline(&l, fp) != EOF; DRESET(&l)) { - char *vf[6]; - char *p = l.buf; - key *k; - - /* --- Skip blank lines and comments --- * - * - * Quite what they're doing in what ought to be an automatically- - * maintained file I don't know. - */ - - line++; - while (isspace((unsigned char)*p)) - p++; - if (!*p || *p == '#') - continue; - - /* --- Break the line into fields --- * - * - * There are currently six fields of interest: - * - * * The key's identification (id, tag and type). - * * The actual key data itself. - * * The key expiry time. - * * The key deletion time. - * * The attributes field. - * * Any further comments. - * - * All but the last field can contain no spaces. - */ - - { - int n = str_split(p, vf, 5, &vf[5]); - if (n < 4) { - if (rep) - rep(file, line, "too few fields", arg); - goto skip_0; - } - } - - /* --- Allocate a new key block --- */ - - k = CREATE(key); - - /* --- Extract the key data into the block --- */ - - if ((k->k = key_read(vf[1], 0)) == 0) { - if (rep) - rep(file, line, "bad key data", arg); - goto skip_1; - } - - /* --- Decode the identification field --- * - * - * For compatibility, derive a keyid from the key data. This can only be - * done if the key encoding is binary (and presumably old-encoding binary - * at that). - */ - - { - char *q = strchr(vf[0], ':'); - char *qq; - - if (!q) { - if (k->k->e != KENC_BINARY) { - if (rep) - rep(file, line, "new-style key encoding but no keyid", arg); - goto skip_2; - } - k->id = crc32(0, k->k->u.k.k, k->k->u.k.sz); - k->type = xstrdup(vf[0]); - k->tag = 0; - } else { - *q++ = 0; - k->id = strtoul(p, 0, 16); - if ((qq = strchr(q, ':')) == 0 || !qq[1]) { - if (qq) - *qq = 0; - k->tag = 0; - } else { - *qq++ = 0; - k->tag = xstrdup(qq); - } - k->type = xstrdup(q); - } - } - - /* --- Get a key block for the new key --- */ - - k->exp = exptime(vf[2]); - k->del = exptime(vf[3]); - - /* --- Insert the key block into the table --- */ - - { - int err; - - again: - if ((err = insert(f, k)) < 0) { - if (err == KERR_DUPTAG) { - if (rep) - rep(file, line, "duplicate key tag stripped", arg); - xfree(k->tag); - k->tag = 0; - goto again; - } - if (rep) - rep(file, line, key_strerror(err), arg); - goto skip_3; - } - } - - /* --- Parse up the attributes, if specified --- */ - - sym_create(&k->a); - if (vf[4] && strcmp(vf[4], "-") != 0) { - url_dctx uc; - for (url_initdec(&uc, vf[4]); url_dec(&uc, &n, &v); ) { - key_putattr(f, k, n.buf, v.buf); - DRESET(&n); DRESET(&v); - } - } - - /* --- Insert the comment --- */ - - if (vf[5]) - k->c = xstrdup(vf[5]); - else - k->c = 0; - continue; - - /* --- Tidy up after something going wrong --- */ - - skip_3: - if (k->tag) - xfree(k->tag); - xfree(k->type); - skip_2: - key_drop(k->k); - skip_1: - DESTROY(k); - skip_0:; - } - - /* --- Extensive tidying up now required --- */ - - dstr_destroy(&l); - dstr_destroy(&n); - dstr_destroy(&v); - f->f |= KF_MODIFIED; - return (0); -} - -/* --- @key_extract@ --- * - * - * Arguments: @key_file *f@ = pointer to file structure - * @key *k@ = key to extract - * @FILE *fp@ = file to write on - * @const key_filter *kf@ = pointer to key selection block - * - * Returns: Zero if OK, EOF on error. - * - * Use: Extracts a key to an ouptut file. - */ - -int key_extract(key_file *f, key *k, FILE *fp, const key_filter *kf) -{ - dstr d = DSTR_INIT; - time_t t = time(0); - - /* --- Skip the key if it's deleted or unselected--- */ - - if (KEY_EXPIRED(t, k->del) || !key_match(k->k, kf)) - return (0); - - /* --- Encode the key and write the easy stuff --- */ - - key_fulltag(k, &d); - DPUTC(&d, ' '); - key_write(k->k, &d, kf); - DPUTC(&d, ' '); - dstr_write(&d, fp); - DRESET(&d); - - /* --- Write out the expiry and deletion times --- */ - - if (KEY_EXPIRED(t, k->exp)) - fputs("expired ", fp); - else if (k->exp == KEXP_FOREVER) - fputs("forever ", fp); - else - fprintf(fp, "%li ", (long)k->exp); - - if (k->del == KEXP_FOREVER) - fputs("forever ", fp); - else - fprintf(fp, "%li ", (long)k->del); - - /* --- Output the attributes --- */ - - { - int none = 1; - sym_iter i; - key_attr *a; - url_ectx uc; - - url_initenc(&uc); - for (sym_mkiter(&i, &k->a); (a = sym_next(&i)) != 0; ) { - none = 0; - url_enc(&uc, &d, SYM_NAME(a), a->p); - } - if (none) - DPUTS(&d, "-"); - DWRITE(&d, fp); - } - - dstr_destroy(&d); - if (k->c) { - putc(' ', fp); - fputs(k->c, fp); - } - putc('\n', fp); - return (ferror(fp) ? EOF : 0); -} - -/*----- Opening and closing files -----------------------------------------*/ - -/* --- @key_open@ --- * - * - * Arguments: @key_file *f@ = pointer to file structure to initialize - * @const char *file@ = pointer to the file name - * @unsigned how@ = opening options (@KOPEN_*@). - * @key_reporter *rep@ = error reporting function - * @void *arg@ = argument for function - * - * Returns: Zero if it worked, nonzero otherwise. - * - * Use: Opens a key file, reads its contents, and stores them in a - * structure. The file is locked appropriately until closed - * using @key_close@. On an error, everything is cleared away - * tidily. If the file is opened with @KOPEN_WRITE@, it's - * created if necessary, with read and write permissions for its - * owner only. - */ - -int key_open(key_file *f, const char *file, unsigned how, - key_reporter *rep, void *arg) -{ - if (key_lockfile(f, file, how)) { - rep(file, 0, strerror(errno), arg); - return (-1); - } - f->f = 0; - f->name = xstrdup(file); - - hash_create(&f->byid, KEY_INITSZ); - f->idload = SYM_LIMIT(KEY_INITSZ); - sym_create(&f->bytype); - sym_create(&f->bytag); - f->f |= KF_WRITE; - if (f->fp) - key_merge(f, file, f->fp, rep, arg); - f->f &= ~KF_MODIFIED; - - if ((how & KOPEN_MASK) == KOPEN_READ) { - f->f &= ~KF_WRITE; - fclose(f->fp); - f->fp = 0; - } - - return (0); -} - -/* --- @key_discard@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * - * Returns: --- - * - * Use: Frees all the key data, without writing changes. - */ - -void key_discard(key_file *f) -{ - hash_base *b; - hash_iter i; - - /* --- Free all the individual keys --- */ - - for (hash_mkiter(&i, &f->byid); (b = hash_next(&i)) != 0; ) { - sym_iter j; - key_attr *a; - key *k = (key *)b; - - if (k->k) key_drop(k->k); - xfree(k->type); - xfree(k->tag); - if (k->c) - xfree(k->c); - for (sym_mkiter(&j, &k->a); (a = sym_next(&j)) != 0; ) - xfree(a->p); - sym_destroy(&k->a); - DESTROY(k); - } - hash_destroy(&f->byid); - sym_destroy(&f->bytype); - sym_destroy(&f->bytag); - - if (f->fp) - fclose(f->fp); - xfree(f->name); -} - -/* --- @key_close@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * - * Returns: A @KWRITE_@ code indicating how it went. - * - * Use: Frees all the key data, writes any changes. Make sure that - * all hell breaks loose if this returns @KWRITE_BROKEN@. - */ - -int key_close(key_file *f) -{ - int e; - - if (f->fp && (e = key_save(f)) != KWRITE_OK) - return (e); - key_discard(f); - return (KWRITE_OK); -} - -/* --- @key_new@ --- - * - * Arguments: @key_file *f@ = pointer to key file - * @uint32 id@ = keyid to set - * @const char *type@ = the type of this key - * @time_t exp@ = when the key expires - * @key *kk@ = where to put the key pointer - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Attaches a new key to a key file. You must have a writable - * key file for this to work. - * - * The type is a key type string. This interface doesn't care - * about how type strings are formatted: it just treats them as - * opaque gobs of text. Clients are advised to choose some - * standard for representing key types, though. - * - * The expiry time should either be a time in the future, or the - * magic value @KEXP_FOREVER@ which means `never expire this - * key'. Be careful with `forever' keys. If I were you, I'd - * use a more sophisticated key management system than this for - * them. - */ - -int key_new(key_file *f, uint32 id, const char *type, time_t exp, key **kk) -{ - key *k = 0; - time_t t = time(0); - int e = KERR_OK; - - /* --- Make sure the file is writable --- */ - - if (!(f->f & KF_WRITE)) - e = KERR_READONLY; - else if (KEY_EXPIRED(t, exp)) - e = KERR_EXPIRED; - else if (key_chkident(type)) - e = KERR_BADTYPE; - else { - k = CREATE(key); - k->id = id; - k->tag = 0; - k->exp = k->del = exp; - k->c = 0; - k->type = (char *)type; /* temporarily */ - sym_create(&k->a); - if ((e = insert(f, k)) != 0) - DESTROY(k); - else { - k->k = key_newstring(KCAT_SHARE, ""); - k->type = xstrdup(type); - *kk = k; - f->f |= KF_MODIFIED; - } - } - - return (e); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/key-misc.c b/key-misc.c deleted file mode 100644 index 5ff7078..0000000 --- a/key-misc.c +++ /dev/null @@ -1,407 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Simple key management - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "key.h" - -/*----- Useful macros -----------------------------------------------------*/ - -#define KEY_WRITE(f) do { \ - if (!(f)->f & KF_WRITE) \ - return (KERR_READONLY); \ - } while (0) - -#define KEY_MODIFY(f) do { (f)->f |= KF_MODIFIED; } while (0) - -#define KEY_LOAD(n) ((n) * 2) - -/*----- Iteration and iterators -------------------------------------------*/ - -/* --- @key_mkiter@ --- * - * - * Arguments: @key_iter *i@ = pointer to iterator object - * @key_file *f@ = pointer to file structure - * - * Returns: --- - * - * Use: Initializes a key iterator. The keys are returned by - * @key_next@. - */ - -void key_mkiter(key_iter *i, key_file *f) -{ - HASH_MKITER(&i->i, &f->byid); - i->t = time(0); -} - -/* --- @key_next@ --- * - * - * Arguments: @key_iter *i@ = pointer to iterator object - * - * Returns: Pointer to next key, or null. - * - * Use: Returns the next key in some arbitrary sequence. - */ - -key *key_next(key_iter *i) -{ - hash_base *b; - key *k; - do { - HASH_NEXT(&i->i, b); - k = (key *)b; - } while (k && KEY_EXPIRED(i->t, k->exp) && KEY_EXPIRED(i->t, k->del)); - return (k); -} - -/*----- Lookup ------------------------------------------------------------*/ - -/* --- @key_bytype@ --- * - * - * Arguments: @key_file *f@ = key file we want a key from - * @const char *type@ = type string for desired key - * - * Returns: Pointer to the best key to use, or null. - * - * Use: Looks up a key by its type. Returns the key with the latest - * expiry time. This function will not return an expired key. - */ - -key *key_bytype(key_file *f, const char *type) -{ - time_t now = time(0); - key *k; - key_ref *kr; - - if ((kr = sym_find(&f->bytype, type, -1, 0, 0)) == 0) - return (0); - for (k = kr->k; k && KEY_EXPIRED(now, k->exp); k = k->next) - ; - return (k); -} - -/* --- @key_byid@ --- * - * - * Arguments: @key_file *f@ = key file to find a key from - * @uint32 id@ = id to look for - * - * Returns: Key with matching id. - * - * Use: Returns a key given its id. This function will return an - * expired key, but not a deleted one. - */ - -key *key_byid(key_file *f, uint32 id) -{ - time_t t = time(0); - hash_base **bin, *b; - - bin = HASH_BIN(&f->byid, id); - for (b = *bin; b; b = b->next) { - if (b->hash == id) { - key *k = (key *)b; - if (KEY_EXPIRED(t, k->exp) && KEY_EXPIRED(t, k->del)) - return (0); - return (k); - } - } - return (0); -} - -/* --- @key_bytag@ --- * - * - * Arguments: @key_file *f@ = key file to find a key from - * @const char *tag@ = pointer to tag string - * - * Returns: Key with matching id or tag. - * - * Use: Returns a key given its tag or id. This function will return - * an expired key, but not a deleted one. - */ - -key *key_bytag(key_file *f, const char *tag) -{ - time_t t = time(0); - char *p; - uint32 id; - key_ref *kr = sym_find(&f->bytag, tag, -1, 0, 0); - - if (kr && !(KEY_EXPIRED(t, kr->k->exp) && KEY_EXPIRED(t, kr->k->del))) - return (kr->k); - id = strtoul(tag, &p, 16); - if (!*p) - return (key_byid(f, id)); - return (key_bytype(f, tag)); -} - -/* --- @key_qtag@ --- * - * - * Arguments: @key_file *f@ = key file to find a key from - * @const char *tag@ = pointer to tag string - * @dstr *d@ = pointer to string for full tag name - * @key **k@ = where to store the key pointer - * @key_data ***kd@ = where to store the key data pointer - * - * Returns: Zero if OK, nonzero if it failed. - * - * Use: Performs a full lookup on a qualified tag name. The tag is - * qualified by the names of subkeys, separated by dots. Hence, - * a qualified tag is ID|TAG[.TAG...]. The various result - * pointers can be null to indicate that the result isn't - * interesting. - */ - -int key_qtag(key_file *f, const char *tag, dstr *d, key **k, key_data ***kd) -{ - dstr dd = DSTR_INIT; - const char *q; - key *kk; - key_data **kkd; - - /* --- Find the end of the base tag --- */ - - if ((q = strchr(tag, '.')) == 0) - DPUTS(&dd, tag); - else { - DPUTM(&dd, tag, q - tag); - DPUTZ(&dd); - q++; - } - - /* --- Look up the key tag --- */ - - if ((kk = key_bytag(f, dd.buf)) == 0) { - dstr_destroy(&dd); - return (-1); - } - - /* --- Set the various initial bits of result up --- */ - - if (d) - key_fulltag(kk, d); - if (k) - *k = kk; - kkd = &kk->k; - - /* --- Now dig through the rest of the tag --- */ - - if (q) { - while (*q) { - key_struct *ks; - - /* --- Stick on the next bit of the fullqtag --- */ - - DRESET(&dd); - while (*q && *q != '.') { - DPUTC(&dd, *q); - q++; - } - DPUTZ(&dd); - if (d) { - DPUTC(d, '.'); - DPUTD(d, &dd); - } - - /* --- Look up the subkey --- */ - - if ((*kkd)->e != KENC_STRUCT) { - kkd = 0; - break; - } - if ((ks = sym_find(&(*kkd)->u.s, dd.buf, -1, 0, 0)) == 0) { - kkd = 0; - break; - } - kkd = &ks->k; - } - } - - /* --- Return the results --- */ - - dstr_destroy(&dd); - if (!kkd) - return (-1); - if (kd) - *kd = kkd; - return (0); -} - -/*----- Miscellaneous functions -------------------------------------------*/ - -/* --- @key_delete@ --- * - * - * Arguments: @key_file *f@ = pointer to file block - * @key *k@ = key to delete - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Removes the given key from the list. The key file must be - * writable. (Due to the horridness of the data structures, - * deleted keys aren't actually removed, just marked so that - * they can't be looked up or iterated over. One upshot of - * this is that they don't get written back to the file when - * it's closed.) - */ - -int key_delete(key_file *f, key *k) -{ - KEY_WRITE(f); - k->exp = KEXP_EXPIRE; - k->del = KEXP_EXPIRE; - KEY_MODIFY(f); - return (0); -} - -/* --- @key_expired@ --- * - * - * Arguments: @key *k@ = pointer to key block - * - * Returns: Zero if the key is OK, nonzero if it's expired. - */ - -int key_expired(key *k) -{ - time_t now = time(0); - return (KEY_EXPIRED(now, k->exp) || KEY_EXPIRED(now, k->del)); -} - -/* --- @key_expire@ --- * - * - * Arguments: @key_file *f@ = pointer to file block - * @key *k@ = pointer to key block - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Immediately marks the key as expired. It may be removed - * immediately, if it is no longer required, and will be removed - * by a tidy operation when it is no longer required. The key - * file must be writable. - */ - -int key_expire(key_file *f, key *k) -{ - KEY_WRITE(f); - k->exp = KEXP_EXPIRE; - if (k->del == KEXP_FOREVER) - k->del = KEXP_EXPIRE; - KEY_MODIFY(f); - return (0); -} - -/* --- @key_used@ --- * - * - * Arguments: @key_file *f@ = pointer to key file - * @key *k@ = pointer to key block - * @time_t t@ = when key can be removed - * - * Returns: Zero if OK, nonzero on failure. - * - * Use: Marks a key as being required until a given time. Even - * though the key may expire before then (and won't be returned - * by type after that time), it will still be available when - * requested explicitly by id. The key file must be writable. - * - * The only (current) reason for failure is attempting to use - * a key which can expire for something which can't. - */ - -int key_used(key_file *f, key *k, time_t t) -{ - KEY_WRITE(f); - if (t == KEXP_FOREVER) { - if (k->exp != KEXP_FOREVER) - return (KERR_WILLEXPIRE); - } else if (k->del >= t) - return (0); - - k->del = t; - KEY_MODIFY(f); - return (0); -} - -/* --- @key_fingerprint@ --- * - * - * Arguments: @key *k@ = the key to fingerprint - * @ghash *h@ = the hash to use - * @const key_filter *kf@ = filter to apply - * - * Returns: Nonzero if the key slightly matched the filter. - * - * Use: Updates the hash context with the key contents. - */ - -static int abyname(const void *a, const void *b) { - key_attr *const *x = a, *const *y = b; - return (strcmp(SYM_NAME(*x), SYM_NAME(*y))); -} - -int key_fingerprint(key *k, ghash *h, const key_filter *kf) -{ - dstr d = DSTR_INIT; - int rc = 0; - key_attr *a, **v; - size_t n, i; - sym_iter ai; - - if (!key_encode(k->k, &d, kf)) - goto done; - rc = 1; - GH_HASHSTR(h, "catacomb-key-fingerprint:"); - GH_HASHU32(h, k->id); - GH_HASHSTR8(h, k->type); - GH_HASH(h, d.buf, d.len); - for (n = 0, sym_mkiter(&ai, &k->a); (a = sym_next(&ai)) != 0; n++); - if (n) { - v = xmalloc(n * sizeof(*v)); - for (i = 0, sym_mkiter(&ai, &k->a); (a = sym_next(&ai)) != 0; i++) - v[i] = a; - qsort(v, n, sizeof(*v), abyname); - for (i = 0; i < n; i++) { - GH_HASHSTR8(h, SYM_NAME(v[i])); - GH_HASHSTR16(h, v[i]->p); - } - xfree(v); - } -done: - dstr_destroy(&d); - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/key-moan.c b/key-moan.c deleted file mode 100644 index ebefe02..0000000 --- a/key-moan.c +++ /dev/null @@ -1,55 +0,0 @@ -/* -*-c-*- - * - * $Id: key-moan.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Standard error handling function for key loading - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "key.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @key_moan@ --- * - * - * Arguments: @const char *file@ = name of the file - * @int line@ = line number in file - * @const char *msg@ = error message - * @void *p@ = argument pointer - * - * Returns: --- - * - * Use: Reports an error message about loading a key file. - */ - -void key_moan(const char *file, int line, const char *msg, void *p) -{ - moan("%s:%i: error: %s", file, line, msg); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/key-pack.c b/key-pack.c deleted file mode 100644 index 7f79800..0000000 --- a/key-pack.c +++ /dev/null @@ -1,249 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Packing and unpacking key data - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "key-data.h" - -/*----- Generic packing and unpacking -------------------------------------*/ - -/* --- @key_pack@ --- * - * - * Arguments: @key_packdef *kp@ = pointer to packing structure - * @key_data **kd@ = where to put the key data pointer - * @dstr *d@ = pointer to tag string for the key data - * - * Returns: Error code, or zero. - * - * Use: Packs a key from a data structure. - */ - -int key_pack(key_packdef *kp, key_data **kd, dstr *d) -{ - switch (kp->e & KF_ENCMASK) { - - /* --- Binary and integer keys are easy --- */ - - case KENC_BINARY: { - key_bin *b = kp->p; - *kd = key_newbinary(kp->e, b->k, b->sz); - return (0); - } - case KENC_MP: - *kd = key_newmp(kp->e, *(mp **)kp->p); - return (0); - case KENC_STRING: - *kd = key_newstring(kp->e, *(char **)kp->p); - return (0); - case KENC_EC: - *kd = key_newec(kp->e, (ec *)kp->p); - return (0); - - /* --- Encrypted keys are a little tricky --- * - * - * This works rather differently to unpacking. - */ - - case KENC_ENCRYPT: { - key_data *kkd; - int err = key_pack(kp->p, &kkd, d); - if (!err) { - err = key_plock(kd, kkd, d->buf); - key_drop(kkd); - } - return (err); - } - - /* --- Structured keys, as ever, are a nuisance --- */ - - case KENC_STRUCT: { - int err; - key_packstruct *p; - size_t l = d->len; - - *kd = key_newstruct(); - DPUTC(d, '.'); - for (p = kp->p; p->name; p++) { - key_data *kkd; - d->len = l + 1; - DPUTS(d, p->name); - if ((err = key_pack(&p->kp, &kkd, d)) != 0) { - key_drop(*kd); - return (err); - } - key_structsteal(*kd, p->name, kkd); - } - d->len = l; - d->buf[l] = 0; - return (0); - } - default: - abort(); - } -} - -/* --- @key_unpack@ --- * - * - * Arguments: @key_packdef *kp@ = pointer to packing structure - * @key_data *kd@ = pointer to source key data - * @dstr *d@ = pointer to tag string for the key data - * - * Returns: Error code, or zero. - * - * Use: Unpacks a key into an appropriate data structure. - */ - -int key_unpack(key_packdef *kp, key_data *kd, dstr *d) -{ - unsigned e = kp->e & KF_ENCMASK; - int err; - - /* --- Decrypt the encrypted key --- */ - - if ((kd->e & KF_ENCMASK) == KENC_ENCRYPT) { - if ((err = key_punlock(&kp->kd, kd, d->buf)) != 0) - goto fail; - kd = kp->kd; - } - - /* --- Ensure that the key has the right type --- */ - - if ((kd->e & KF_ENCMASK) != e) { - err = KERR_WRONGTYPE; - goto fail; - } - - /* --- Unpack the key --- * - * - * Only three possibilities left now. - */ - - switch (e) { - - /* --- Binary and integer keys are easy --- */ - - case KENC_BINARY: - *(key_bin *)kp->p = kd->u.k; - break; - case KENC_MP: - *(mp **)kp->p = kd->u.m; - break; - case KENC_STRING: - *(char **)kp->p = kd->u.p; - break; - case KENC_EC: - *(ec *)kp->p = kd->u.e; - break; - - /* --- Structured keys take a little care --- */ - - case KENC_STRUCT: { - key_packstruct *p, *q; - size_t l = d->len; - - /* --- Iterate over the requested subparts --- */ - - DPUTC(d, '.'); - for (p = kp->p; p->name; p++) { - key_data *kkd; - - /* --- Build the name --- */ - - d->len = l + 1; - DPUTS(d, p->name); - - /* --- Find and unpack the subkey --- */ - - if ((kkd = key_structfind(kd, p->name)) == 0) { - if (!(p->kp.e & KF_OPT)) { - err = KERR_NOTFOUND; - goto tidy; - } - } else if ((err = key_unpack(&p->kp, kkd, d)) != 0) { - p++; - goto tidy; - } - } - - /* --- Done --- */ - - d->len = l; - d->buf[l] = 0; - break; - - /* --- Tidy up if something went wrong --- */ - - tidy: - for (q = kp->p; q < p; q++) - key_unpackdone(&q->kp); - goto fail; - } - - default: - abort(); - } - - return (0); - - /* --- Something went wrong --- */ - -fail: - if (kp->kd) { - key_drop(kp->kd); - kp->kd = 0; - } - return (err); -} - -/* --- @key_unpackdone@ --- * - * - * Arguments: @key_packdef *kp@ = pointer to packing definition - * - * Returns: --- - * - * Use: Frees the key components contained within a packing - * definition, created during key unpacking. - */ - -void key_unpackdone(key_packdef *kp) -{ - if (kp->kd) { - key_drop(kp->kd); - kp->kd = 0; - } - if ((kp->e & KF_ENCMASK) == KENC_STRUCT) { - key_packstruct *p; - for (p = kp->p; p->name; p++) - key_unpackdone(&p->kp); - } -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/key-pass.c b/key-pass.c deleted file mode 100644 index f303245..0000000 --- a/key-pass.c +++ /dev/null @@ -1,264 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Encrypting keys with passphrases - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "key-data.h" -#include "paranoia.h" -#include "passphrase.h" -#include "rand.h" - -#include "blowfish-cbc.h" -#include "rmd160.h" -#include "rmd160-mgf.h" -#include "rmd160-hmac.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Format --- * - * - * Choose a random 160-bit string %$R$%. Take the passphrase %$P$%, and - * the message %$m$%. Now, compute %$K_E \cat K_T = H(R \cat P)$%, - * %$y_0 = E_{K_E}(m)$% and %$\tau = T_{K_T}(y_0)$%. The ciphertext is - * %$y = N \cat \tau \cat y_0$%. - * - * This is not the original format. The original format was insecure, and - * has been replaced incompatibly. - */ - -/* --- @key_lock@ --- * - * - * Arguments: @key_data **kt@ = where to store the destination pointer - * @key_data *k@ = source key data block or null to use @*kt@ - * @const void *e@ = secret to encrypt key with - * @size_t esz@ = size of the secret - * - * Returns: --- - * - * Use: Encrypts a key data block using a secret. - */ - -void key_lock(key_data **kt, key_data *k, const void *e, size_t esz) -{ - dstr d = DSTR_INIT; - octet b[RMD160_HASHSZ * 2]; - octet *m; - size_t msz; - rmd160_mgfctx r; - blowfish_cbcctx c; - rmd160_mackey mk; - rmd160_macctx mc; - - /* --- Sanity check --- */ - - if (k) key_incref(k); else k = *kt; - assert(((void)"Key data is already encrypted", - (k->e & KF_ENCMASK) != KENC_ENCRYPT)); - - /* --- Format the stuff in the buffer --- */ - - DENSURE(&d, RMD160_HASHSZ * 2); - rand_get(RAND_GLOBAL, d.buf, RMD160_HASHSZ); - d.len += RMD160_HASHSZ * 2; - key_encode(k, &d, 0); - m = (octet *)d.buf + RMD160_HASHSZ * 2; - msz = d.len - RMD160_HASHSZ * 2; - - /* --- Hash the passphrase to make a key --- */ - - rmd160_mgfkeybegin(&r); - rmd160_mgfkeyadd(&r, d.buf, RMD160_HASHSZ); - rmd160_mgfkeyadd(&r, e, esz); - rmd160_mgfencrypt(&r, 0, b, sizeof(b)); - BURN(r); - - /* --- Encrypt the plaintext --- */ - - blowfish_cbcinit(&c, b, RMD160_HASHSZ, 0); - blowfish_cbcencrypt(&c, m, m, msz); - BURN(c); - - /* --- MAC the ciphertext --- */ - - rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ); - rmd160_macinit(&mc, &mk); - rmd160_machash(&mc, m, msz); - rmd160_macdone(&mc, d.buf + RMD160_HASHSZ); - BURN(mk); - BURN(mc); - - /* --- Done --- */ - - BURN(b); - *kt = key_newencrypted(0, d.buf, d.len); - key_drop(k); - dstr_destroy(&d); -} - -/* --- @key_unlock@ --- * - * - * Arguments: @key_data **kt@ = where to store the destination pointer - * @key_data *k@ = source key data block or null to use @*kt@ - * @const void *e@ = secret to decrypt the block with - * @size_t esz@ = size of the secret - * - * Returns: Zero for success, or a @KERR_@ error code. - * - * Use: Unlocks a key using a secret. - */ - -int key_unlock(key_data **kt, key_data *k, const void *e, size_t esz) -{ - octet b[RMD160_HASHSZ * 2]; - octet *p = 0; - int rc; - int drop = 0; - key_data *kd; - rmd160_mgfctx r; - blowfish_cbcctx c; - rmd160_mackey mk; - rmd160_macctx mc; - size_t sz; - - /* --- Sanity check --- */ - - if (!k) { k = *kt; drop = 1; } - assert(((void)"Key data isn't encrypted", - (k->e & KF_ENCMASK) == KENC_ENCRYPT)); - - /* --- Check the size --- */ - - if (k->u.k.sz < RMD160_HASHSZ * 2) - return (KERR_MALFORMED); - sz = k->u.k.sz - RMD160_HASHSZ * 2; - - /* --- Hash the passphrase to make a key --- */ - - rmd160_mgfkeybegin(&r); - rmd160_mgfkeyadd(&r, k->u.k.k, RMD160_HASHSZ); - rmd160_mgfkeyadd(&r, e, esz); - rmd160_mgfencrypt(&r, 0, b, sizeof(b)); - BURN(r); - - /* --- Verify the MAC --- */ - - rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ); - rmd160_macinit(&mc, &mk); - rmd160_machash(&mc, k->u.k.k + RMD160_HASHSZ * 2, sz); - rmd160_macdone(&mc, b + RMD160_HASHSZ); - if (memcmp(b + RMD160_HASHSZ, k->u.k.k + RMD160_HASHSZ, - RMD160_HASHSZ) != 0) { - rc = KERR_BADPASS; - goto fail; - } - BURN(mk); - BURN(mc); - - /* --- Allocate a destination buffer --- */ - - p = xmalloc(sz); - - /* --- Decrypt the key data --- */ - - blowfish_cbcinit(&c, b, RMD160_HASHSZ, 0); - blowfish_cbcdecrypt(&c, k->u.k.k + RMD160_HASHSZ * 2, p, sz); - BURN(c); - - /* --- Decode the key data into the destination buffer --- */ - - if ((kd = key_decode(p, sz)) == 0) { - rc = KERR_MALFORMED; - goto fail; - } - *kt = kd; - - /* --- Done --- */ - - xfree(p); - if (drop) key_drop(k); - return (0); - - /* --- Tidy up if things went wrong --- */ - -fail: - BURN(b); - xfree(p); - return (rc); -} - -/* --- @key_plock@ --- * - * - * Arguments: @key_data **kt@ = where to store the destination pointer - * @key_data *k@ = source key data block or null to use @*kt@ - * @const char *tag@ = tag to use for passphrase - * - * Returns: Zero if successful, a @KERR@ error code on failure. - * - * Use: Locks a key by encrypting it with a passphrase. - */ - -int key_plock(key_data **kt, key_data *k, const char *tag) -{ - char buf[256]; - - if (passphrase_read(tag, PMODE_VERIFY, buf, sizeof(buf))) - return (KERR_IO); - key_lock(kt, k, buf, strlen(buf)); - BURN(buf); - return (0); -} - -/* --- @key_punlock@ --- * - * - * Arguments: @key_data **kt@ = where to store the destination pointer - * @key_data *k@ = source key data block or null to use @*kt@ - * @const char *tag@ = tag to use for passphrase - * - * Returns: Zero if it worked, a @KERR_@ error code on failure. - * - * Use: Unlocks a passphrase-locked key. - */ - -int key_punlock(key_data **kt, key_data *k, const char *tag) -{ - char buf[256]; - int rc; - - if (passphrase_read(tag, PMODE_READ, buf, sizeof(buf))) - return (KERR_IO); - rc = key_unlock(kt, k, buf, strlen(buf)); - BURN(buf); - if (rc == KERR_BADPASS || !k) - passphrase_cancel(tag); - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/key-text.c b/key-text.c deleted file mode 100644 index ff9e705..0000000 --- a/key-text.c +++ /dev/null @@ -1,346 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Key textual encoding - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "key-data.h" -#include "mp.h" -#include "mptext.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @key_read@ --- * - * - * Arguments: @const char *p@ = pointer to textual key representation - * @char **pp@ = where to store the end pointer - * - * Returns: The newly-read key data, or null if it failed. - * - * Use: Parses a textual key description. - */ - -key_data *key_read(const char *p, char **pp) -{ - unsigned e; - key_data *kd; - - /* --- Read the encoding type --- * - * - * The key format is `[FLAGS:]DATA'. If there is no encoding type - * named, assume that it's `binary' for backwards compatibility. - */ - - if (strchr(p, ':') == 0) - e = 0; - else { - char *q; - if (key_readflags(p, &q, &e, 0)) - return (0); - p = q + 1; - } - - /* --- Now scan the data based on the encoding type --- */ - - switch (e & KF_ENCMASK) { - - /* --- Binary encoding --- * - * - * Simply read out the Base64-encoded data. Since `,' and `]' are our - * delimeter characters, and they can't appear in Base64-encoded data, I - * can just do a simple search to find the end of the encoded data. - */ - - case KENC_BINARY: - case KENC_ENCRYPT: { - dstr d = DSTR_INIT; - base64_ctx b; - size_t sz = strcspn(p, ",]"); - - base64_init(&b); - base64_decode(&b, p, sz, &d); - base64_decode(&b, 0, 0, &d); - kd = key_newbinary(e, d.buf, d.len); - dstr_destroy(&d); - p += sz; - } break; - - /* --- Multiprecision integer encoding --- * - * - * Multiprecision integers have a convenient reading function. - */ - - case KENC_MP: { - char *q; - mp *m = mp_readstring(e & KF_BURN ? MP_NEWSEC : MP_NEW, p, &q, 0); - if (!m) - return (0); - kd = key_newmp(e, m); - MP_DROP(m); - p = q; - } break; - - /* --- String encoding --- * - * - * We use form-urlencoding to ensure that evil characters don't get out. - */ - - case KENC_STRING: { - dstr d = DSTR_INIT; - size_t sz = strcspn(p, ",]"); - const char *l = p + sz; - unsigned int ch; - int x, n; - - while (p < l) { - switch (*p) { - case '+': - DPUTC(&d, ' '); break; - case '%': - x = sscanf(p + 1, "%2x%n", &ch, &n); - if (x == 1) { DPUTC(&d, ch); p += n; break; } - default: - DPUTC(&d, *p); break; - } - p++; - } - DPUTZ(&d); - kd = key_newstring(e, d.buf); - dstr_destroy(&d); - } break; - - /* --- Elliptic curve encoding --- * - * - * Again, we have a convenient function. Assume for now that points - * aren't secret. (Reasonably safe.) - */ - - case KENC_EC: { - ec pt = EC_INIT; - qd_parse qd; - qd.p = p; - qd.e = 0; - if (!ec_ptparse(&qd, &pt)) - return (0); - kd = key_newec(e, &pt); - EC_DESTROY(&pt); - p = qd.p; - } break; - - /* --- Structured information encoding --- * - * - * The format for structured key data is `[NAME=KEY,...]', where the - * brackets are part of the syntax. Structured keys have no flags apart - * from the encoding. - * - * The binary encoding only allows names up to 255 bytes long. Check for - * this here. - */ - - case KENC_STRUCT: { - dstr d = DSTR_INIT; - key_data *nkd; - char *q; - - /* --- Read the opening bracket --- */ - - kd = key_newstruct(); - if (*p != '[') - return (0); - p++; - - /* --- Read named key subparts --- */ - - for (;;) { - size_t sz; - - /* --- Stop if there's a close-bracket --- * - * - * This allows `[]' to be an empty structured key, which is good. It - * also makes `[foo=enc:bar,]' legal, and that's less good but I can - * live with it. - */ - - if (*p == ']') - break; - - /* --- Read the name out and check the length --- */ - - if ((q = strchr(p, '=')) == 0) - goto fail; - sz = q - p; - if (sz >= 256) - goto fail; - DRESET(&d); - DPUTM(&d, p, sz); - DPUTZ(&d); - - /* --- Read the key data for the subkey --- */ - - if ((nkd = key_read(q + 1, &q)) == 0) - goto fail; - key_structsteal(kd, d.buf, nkd); - p = q; - - /* --- Read the comma or close-bracket --- */ - - if (*p == ']') - break; - else if (*p == ',') - p++; - else - goto fail; - } - - /* --- Step past the close bracket --- */ - - p++; - dstr_destroy(&d); - break; - - /* --- Tidy up after a failure --- */ - - fail: - dstr_destroy(&d); - return (0); - } break; - - /* --- Anything else is unknown --- */ - - default: - return (0); - } - - /* --- Return the end pointer --- */ - - kd->e = e; - if (pp) - *pp = (char *)p; - return (kd); -} - -/* --- @key_write@ --- * - * - * Arguments: @key_data *k@ = pointer to key data - * @dstr *d@ = destination string to write on - * @const key_filter *kf@ = pointer to key selection block - * - * Returns: Nonzero if an item was actually written. - * - * Use: Writes a key in a textual encoding. - */ - -int key_write(key_data *k, dstr *d, const key_filter *kf) -{ - int rc = 0; - if (!KEY_MATCH(k, kf)) - return (0); - switch (k->e & KF_ENCMASK) { - case KENC_BINARY: - case KENC_ENCRYPT: { - base64_ctx b; - - if ((k->e & KF_ENCMASK) == KENC_BINARY) - key_writeflags(k->e, d); - else - DPUTS(d, "encrypt,secret"); - DPUTC(d, ':'); - base64_init(&b); - b.indent = ""; - b.maxline = 0; - base64_encode(&b, k->u.k.k, k->u.k.sz, d); - base64_encode(&b, 0, 0, d); - rc = 1; - } break; - case KENC_MP: - key_writeflags(k->e, d); - DPUTC(d, ':'); - mp_writedstr(k->u.m, d, 10); - rc = 1; - break; - case KENC_STRING: { - const char *p = k->u.p; - key_writeflags(k->e, d); - DPUTC(d, ':'); - while (*p) { - if (*p == ' ') DPUTC(d, '+'); - else if (!isalnum((unsigned char)*p)) dstr_putf(d, "%%%02x", *p); - else DPUTC(d, *p); - p++; - } - rc = 1; - } break; - case KENC_EC: - key_writeflags(k->e, d); - DPUTS(d, ":0x"); mp_writedstr(k->u.e.x, d, 16); - DPUTS(d, ",0x"); mp_writedstr(k->u.e.y, d, 16); - rc = 1; - break; - case KENC_STRUCT: { - key_subkeyiter i; - const char *tag; - char del = 0; - size_t n = d->len; - - DPUTS(d, "struct:["); - for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) { - size_t o = d->len; - if (del) - DPUTC(d, del); - DPUTS(d, tag); - DPUTC(d, '='); - if (!key_write(k, d, kf)) - d->len = o; - else { - del = ','; - rc = 1; - } - } - if (!rc) - d->len = n; - else - DPUTC(d, ']'); - } break; - } - DPUTZ(d); - - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/key.h b/key.h deleted file mode 100644 index dffd0eb..0000000 --- a/key.h +++ /dev/null @@ -1,702 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Simple key management - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_KEY_H -#define CATACOMB_KEY_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include -#include -#include -#include - -#ifndef CATACOMB_KEY_ERROR_H -# include "key-error.h" -#endif - -#ifndef CATACOMB_KEY_DATA_H -# include "key-data.h" -#endif - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- Key attributes --- * - * - * Each attribute is stored as a symbol in a symbol table. The value is - * the plain (not url-encoded) text to be written to the the file. If the - * value is binary data, then by this point it's base-64 encoded. - */ - -typedef struct key_attr { - sym_base _b; /* Symbol table data */ - char *p; /* Pointer to attribute value */ -} key_attr; - -/* --- Main key structure --- * - * - * Each key is stored in two symbol tables, one indexed by keyid, and the - * other indexed by type. Because many keys can have the same type, the type - * table contains a list of keys, sorted in descending order of expiry. - */ - -typedef struct key { - - /* --- Hashtable management --- */ - - hash_base _b; /* Symbol table data */ - struct key *next; /* Next key of the same type */ - - /* --- Basic key attributes --- */ - - uint32 id; /* Key id used to name it */ - char *tag; /* Textual tag name */ - char *type; /* Textual key type */ - time_t exp, del; /* Expiry times for keys */ - - /* --- The key data itself --- */ - - key_data *k; /* The actual key data */ - - /* --- Other attributes and commentary --- */ - - sym_table a; /* Hashtable of key attributes */ - char *c; /* Any additional comments */ -} key; - -/* --- The keys-by-type entries --- */ - -typedef struct key_ref { - sym_base _b; /* Symbol table data */ - key *k; /* Pointer to first key in list */ -} key_ref; - -/* --- A key file --- */ - -typedef struct key_file { - FILE *fp; /* File pointer open on file */ - char *name; /* Filename used to create it */ - unsigned f; /* Various useful flags */ - hash_table byid; /* Table of keys by keyid */ - sym_table bytype; /* Table of keys by type */ - sym_table bytag; /* Table of keys by tag */ - size_t idload; /* Loading on id table */ -} key_file; - -/* --- Key file flags --- */ - -#define KF_WRITE 1u /* File opened for writing */ -#define KF_MODIFIED 2u /* File has been modified */ - -/* --- Iterating over keys --- * - * - * Both of these are simple symbol table iterators, but they're made distinct - * types for the dubious benefits that type safety brings. - */ - -typedef struct { hash_iter i; time_t t; } key_iter; -typedef struct { sym_iter i; } key_attriter; - -/* --- Key fetching --- */ - -typedef struct key_fetchdef { - char *name; /* Name of item */ - size_t off; /* Offset into target structure */ - unsigned e; /* Flags for the item */ - const struct key_fetchdef *kf; /* Substructure pointer */ -} key_fetchdef; - -/* --- File opening options --- */ - -#define KOPEN_READ 0u -#define KOPEN_WRITE 1u -#define KOPEN_MASK 0xff -#define KOPEN_NOFILE 0x100 - -/* --- Various other magic numbers --- */ - -#define KEXP_FOREVER ((time_t)-1) /* Never expire this key */ -#define KEXP_EXPIRE ((time_t)-2) /* Expire this key when unused */ - -/* --- Write error codes --- */ - -enum { - KWRITE_OK, /* Everything went fine */ - KWRITE_FAIL = -1, /* Close attempt failed */ - KWRITE_BROKEN = -2 /* Key ring needs manual fixing */ -}; - -/* --- Error reporting functions for @key_merge@ and @key_open@ --- */ - -typedef void key_reporter(const char */*file*/, int /*line*/, - const char */*err*/, void */*p*/); - -/* --- Macros for testing expiry --- */ - -#define KEY_EXPIRED(now, exp) \ - ((exp) == KEXP_EXPIRE || ((exp) != KEXP_FOREVER && (exp) < (now))) - -/*----- Reading and writing keys and files --------------------------------*/ - -/* --- @key_merge@ --- * - * - * Arguments: @key_file *f@ = pointer to file structure - * @const char *file@ = name of file (for error messages) - * @FILE *fp@ = file handle to read from - * @key_reporter *rep@ = error reporting function - * @void *arg@ = argument for function - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Reads keys from a file, and inserts them into the file. - */ - -extern int key_merge(key_file */*f*/, const char */*file*/, FILE */*fp*/, - key_reporter */*rep*/, void */*arg*/); - -/* --- @key_extract@ --- * - * - * Arguments: @key_file *f@ = pointer to file structure - * @key *k@ = key to extract - * @FILE *fp@ = file to write on - * @const key_filter *kf@ = pointer to key selection block - * - * Returns: Zero if OK, EOF on error. - * - * Use: Extracts a key to an ouptut file. - */ - -extern int key_extract(key_file */*f*/, key */*k*/, FILE */*fp*/, - const key_filter */*kf*/); - -/* --- @key_open@ --- * - * - * Arguments: @key_file *f@ = pointer to file structure to initialize - * @const char *file@ = pointer to the file name - * @unsigned how@ = opening options (@KOPEN_*@). - * @key_reporter *rep@ = error reporting function - * @void *arg@ = argument for function - * - * Returns: Zero if it worked, nonzero otherwise. - * - * Use: Opens a key file, reads its contents, and stores them in a - * structure. The file is locked appropriately until closed - * using @key_close@. On an error, everything is cleared away - * tidily. If the file is opened with @KOPEN_WRITE@, it's - * created if necessary, with read and write permissions for its - * owner only. - */ - -extern int key_open(key_file */*f*/, const char */*file*/, unsigned /*how*/, - key_reporter */*rep*/, void */*arg*/); - -/* --- @key_discard@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * - * Returns: --- - * - * Use: Frees all the key data, without writing changes. - */ - -extern void key_discard(key_file */*f*/); - -/* --- @key_close@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * - * Returns: A @KWRITE_@ code indicating how it went. - * - * Use: Frees all the key data, writes any changes. Make sure that - * all hell breaks loose if this returns @KWRITE_BROKEN@. - */ - -extern int key_close(key_file */*f*/); - -/* --- @key_save@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * - * Returns: A @KWRITE_@ code indicating how well it worked. - * - * Use: Writes a key file's data back to the actual file. This code - * is extremely careful about error handling. It should usually - * be able to back out somewhere sensible, but it can tell when - * it's got itself into a real pickle and starts leaving well - * alone. - * - * Callers, please make sure that you ring alarm bells when this - * function returns @KWRITE_BROKEN@. - */ - -extern int key_save(key_file */*f*/); - -/* --- @key_lockfile@ --- * - * - * Arguments: @key_file *f@ = pointer to file structure to initialize - * @const char *file@ = pointer to the file name - * @unsigned how@ = opening options (@KOPEN_*@). - * - * Returns: Zero if it worked, nonzero otherwise. - * - * Use: Opens a keyfile and stores the information needed for - * continued access in the structure. - * - * If the file is opened with @KOPEN_WRITE@, it's created if - * necessary with read and write permissions for owner only, and - * locked for update while it's open. - * - * This is a system-dependent routine, and only really intended - * for the private use of @key_open@. - */ - -extern int key_lockfile(key_file */*f*/, const char */*file*/, - unsigned /*how*/); - -/*----- Creating and manipulating keys ------------------------------------*/ - -/* --- @key_new@ --- - * - * Arguments: @key_file *f@ = pointer to key file - * @uint32 id@ = keyid to set - * @const char *type@ = the type of this key - * @time_t exp@ = when the key expires - * @key *kk@ = where to put the key pointer - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Attaches a new key to a key file. You must have a writable - * key file for this to work. - * - * The type is a key type string. This interface doesn't care - * about how type strings are formatted: it just treats them as - * opaque gobs of text. Clients are advised to choose some - * standard for representing key types, though. - * - * The expiry time should either be a time in the future, or the - * magic value @KEXP_FOREVER@ which means `never expire this - * key'. Be careful with `forever' keys. If I were you, I'd - * use a more sophisticated key management system than this for - * them. - * - * You have to set the actual key yourself. - */ - -extern int key_new(key_file */*f*/, uint32 /*id*/, const char */*type*/, - time_t /*exp*/, key **/*kk*/); - -/* --- @key_delete@ --- * - * - * Arguments: @key_file *f@ = pointer to file block - * @key *k@ = key to delete - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Removes the given key from the list. The key file must be - * writable. (Due to the horridness of the data structures, - * deleted keys aren't actually removed, just marked so that - * they can't be looked up or iterated over. One upshot of - * this is that they don't get written back to the file when - * it's closed.) - */ - -extern int key_delete(key_file */*f*/, key */*k*/); - -/* --- @key_expired@ --- * - * - * Arguments: @key *k@ = pointer to key block - * - * Returns: Zero if the key is OK, nonzero if it's expired. - */ - -int key_expired(key */*k*/); - -/* --- @key_expire@ --- * - * - * Arguments: @key_file *f@ = pointer to file block - * @key *k@ = pointer to key block - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Immediately marks the key as expired. It may be removed - * immediately, if it is no longer required, and will be removed - * by a tidy operation when it is no longer required. The key - * file must be writable. - */ - -extern int key_expire(key_file */*f*/, key */*k*/); - -/* --- @key_used@ --- * - * - * Arguments: @key_file *f@ = pointer to key file - * @key *k@ = pointer to key block - * @time_t t@ = when key can be removed - * - * Returns: Zero if OK, nonzero on failure. - * - * Use: Marks a key as being required until a given time. Even - * though the key may expire before then (and won't be returned - * by type after that time), it will still be available when - * requested explicitly by id. The key file must be writable. - * - * The only (current) reason for failure is attempting to use - * a key which can expire for something which can't. - */ - -extern int key_used(key_file */*f*/, key */*k*/, time_t /*t*/); - -/* --- @key_fingerprint@ --- * - * - * Arguments: @key *k@ = the key to fingerprint - * @ghash *h@ = the hash to use - * @const key_filter *kf@ = filter to apply - * - * Returns: Nonzero if the key slightly matched the filter. - * - * Use: Updates the hash context with the key contents. - */ - -extern int key_fingerprint(key */*k*/, ghash */*h*/, - const key_filter */*kf*/); - -/*----- Setting and reading attributes ------------------------------------*/ - -/* --- @key_chkident@ --- * - * - * Arguments: @const char *p@ = pointer to a type string - * - * Returns: Zero if OK, -1 on error. - * - * Use: Checks whether an identification component string is OK. - */ - -extern int key_chkident(const char */*p*/); - -/* --- @key_chkcomment@ --- * - * - * Arguments: @const char *p@ = pointer to a comment string - * - * Returns: Zero if OK, -1 on error. - * - * Use: Checks whether a comment string is OK. - */ - -extern int key_chkcomment(const char */*p*/); - -/* --- @key_setcomment@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * @key *k@ = pointer to key block - * @const char *c@ = pointer to comment to set, or zero - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Replaces the key's current comment with a new one. - */ - -extern int key_setcomment(key_file */*f*/, key */*k*/, const char */*c*/); - -/* --- @key_settag@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * @key *k@ = pointer to key block - * @const char *tag@ = pointer to comment to set, or zero - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Replaces the key's current tag with a new one. - */ - -extern int key_settag(key_file */*f*/, key */*k*/, const char */*tag*/); - -/* --- @key_setkeydata@ --- * - * - * Arguments: @key_file *kf@ = pointer to key file - * @key *k@ = pointer to key - * @key_data *kd@ = new key data - * - * Returns: Zero on success, or a @KERR_@ error code on failure. - * - * Use: Sets the key data for a key. - */ - -extern int key_setkeydata(key_file */*kf*/, key */*k*/, key_data */*kd*/); - -/* --- @key_fulltag@ --- * - * - * Arguments: @key *k@ = pointer to key - * @dstr *d@ = pointer to destination string - * - * Returns: --- - * - * Use: Emits the key's full tag, which has the form - * `ID:TYPE[:TAG]'. This is used in the textual file format, - * and to identify passphrases for locked keys. - */ - -extern void key_fulltag(key */*k*/, dstr */*d*/); - -/* --- @key_qtag@ --- * - * - * Arguments: @key_file *f@ = key file to find a key from - * @const char *tag@ = pointer to tag string - * @dstr *d@ = pointer to string for full tag name - * @key **k@ = where to store the key pointer - * @key_data ***kd@ = where to store the key data pointer - * - * Returns: Zero if OK, nonzero if it failed. - * - * Use: Performs a full lookup on a qualified tag name. The tag is - * qualified by the names of subkeys, separated by dots. Hence, - * a qualified tag is ID|TAG[.TAG...]. The various result - * pointers can be null to indicate that the result isn't - * interesting. - */ - -extern int key_qtag(key_file */*f*/, const char */*tag*/, - dstr */*d*/, key **/*k*/, key_data ***/*kd*/); - -/* --- @key_getattr@ --- * - * - * Arguments: @key_file *f@ = pointer to file - * @key *k@ = pointer to key - * @const char *n@ = pointer to attribute name - * - * Returns: Pointer to attribute value, or null if not found. - * - * Use: Returns the value of a key attribute. - */ - -extern const char *key_getattr(key_file */*f*/, key */*k*/, - const char */*n*/); - -/* --- @key_putattr@ --- * - * - * Arguments: @key_file *f@ = pointer to file - * @key *k@ = pointer to key - * @const char *n@ = pointer to attribute name - * @const char *v@ = pointer to attribute value or null - * - * Returns: Error code (one of the @KERR@ constants). - * - * Use: Inserts an attribute on a key. If an attribute with the same - * name already exists, it is deleted. Setting a null value - * removes the attribute. - */ - -extern int key_putattr(key_file */*f*/, key */*k*/, - const char */*n*/, const char */*v*/); - -/* --- @key_mkattriter@ --- * - * - * Arguments: @key_attriter *i@ = pointer to attribute iterator - * @key *k@ = pointer to key - * - * Returns: --- - * - * Use: Initializes an attribute iterator. The attributes are - * returned by @key_nextattr@. - */ - -extern void key_mkattriter(key_attriter */*i*/, key */*k*/); - -/* --- @key_nextattr@ --- * - * - * Arguments: @key_attriter *i@ = pointer to attribute iterator - * @const char **n, **v@ = pointers to name and value - * - * Returns: Zero if no attribute available, or nonzero if returned OK. - * - * Use: Returns the next attribute. - */ - -extern int key_nextattr(key_attriter */*i*/, - const char **/*n*/, const char **/*v*/); - -/*----- Searching and iterating -------------------------------------------*/ - -/* --- @key_bytype@ --- * - * - * Arguments: @key_file *f@ = key file we want a key from - * @const char *type@ = type string for desired key - * - * Returns: Pointer to the best key to use, or null. - * - * Use: Looks up a key by its type. Returns the key with the latest - * expiry time. This function will not return an expired key. - */ - -extern key *key_bytype(key_file */*f*/, const char */*type*/); - -/* --- @key_byid@ --- * - * - * Arguments: @key_file *f@ = key file to find a key from - * @uint32 id@ = id to look for - * - * Returns: Key with matching id. - * - * Use: Returns a key given its id. This function will return an - * expired key, but not a deleted one. - */ - -extern key *key_byid(key_file */*f*/, uint32 /*id*/); - -/* --- @key_bytag@ --- * - * - * Arguments: @key_file *f@ = key file to find a key from - * @const char *tag@ = pointer to tag string - * - * Returns: Key with matching id or tag. - * - * Use: Returns a key given its tag or id. This function will return - * an expired key, but not a deleted one. - */ - -extern key *key_bytag(key_file */*f*/, const char */*tag*/); - -/* --- @key_mkiter@ --- * - * - * Arguments: @key_iter *i@ = pointer to iterator object - * @key_file *f@ = pointer to file structure - * - * Returns: --- - * - * Use: Initializes a key iterator. The keys are returned by - * @key_next@. - */ - -extern void key_mkiter(key_iter */*i*/, key_file */*f*/); - -/* --- @key_next@ --- * - * - * Arguments: @key_iter *i@ = pointer to iterator object - * - * Returns: Pointer to next key, or null. - * - * Use: Returns the next key in some arbitrary sequence. - */ - -extern key *key_next(key_iter */*i*/); - -/*----- Fetching key data conveniently ------------------------------------*/ - -/* --- @key_fetchinit@ --- * - * - * Arguments: @const key_fetchdef *kf@ = pointer to base definition - * @key_packstruct *kps@ = pointer to destination packing def - * @void *p@ = pointer to destination block - * - * Returns: Pointer to packing definition. - * - * Use: Initializes a packing definition (@key_packdef@ structure). - * If @kps@ is null on entry, an appropriately sized block is - * allocated automatically. Otherwise it must be large enough. - */ - -extern key_packdef *key_fetchinit(const key_fetchdef */*kf*/, - key_packstruct */*kp*/, void */*p*/); - -/* --- @key_fetch@ --- * - * - * Arguments: @key_packdef *kp@ = pointer to packing structure - * @key *k@ = key file containing desired key - * - * Returns: Error code, or zero. - * - * Use: Fetches an unpacked key from a packed one. - */ - -extern int key_fetch(key_packdef */*kp*/, key */*k*/); - -/* --- @key_fetchbyname@ --- * - * - * Arguments: @key_packdef *kp@ = pointer to packing structure - * @key_file *kf@ = key file containing desired key - * @const char *tag@ = user's tag describing the key - * - * Returns: Error code, or zero. - * - * Use: Fetches a named key from a key file and unpacks it - * conveniently. - */ - -extern int key_fetchbyname(key_packdef */*kp*/, - key_file */*kf*/, const char */*tag*/); - -/* --- @key_fetchdone@ --- * - * - * Arguments: @key_packdef *kp@ = pointer to packing structure - * - * Returns: --- - * - * Use: Frees a packing structure. If the structure was allocated by - * @key_fetchinit@ then it is freed. - */ - -extern void key_fetchdone(key_packdef */*kp*/); - -/*----- Other functions ---------------------------------------------------*/ - -/* --- @key_moan@ --- * - * - * Arguments: @const char *file@ = name of the file - * @int line@ = line number in file - * @const char *msg@ = error message - * @void *p@ = argument pointer - * - * Returns: --- - * - * Use: Reports an error message about loading a key file. - */ - -extern void key_moan(const char */*file*/, int /*line*/, - const char */*msg*/, void */*p*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/key/Makefile.am b/key/Makefile.am new file mode 100644 index 0000000..b73aad8 --- /dev/null +++ b/key/Makefile.am @@ -0,0 +1,65 @@ +### -*-makefile-*- +### +### Build script for key management +### +### (c) 2013 Straylight/Edgeware +### + +###----- Licensing notice --------------------------------------------------- +### +### This file is part of Catacomb. +### +### Catacomb is free software; you can redistribute it and/or modify +### it under the terms of the GNU Library General Public License as +### published by the Free Software Foundation; either version 2 of the +### License, or (at your option) any later version. +### +### Catacomb is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU Library General Public License for more details. +### +### You should have received a copy of the GNU Library General Public +### License along with Catacomb; if not, write to the Free +### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +### MA 02111-1307, USA. + +include $(top_srcdir)/vars.am + +noinst_LTLIBRARIES = libkey.la +libkey_la_SOURCES = + +###-------------------------------------------------------------------------- +### Component files. + +## Managing keys and keyring files. +pkginclude_HEADERS += key.h +libkey_la_SOURCES += key-attr.c +libkey_la_SOURCES += key-fetch.c +libkey_la_SOURCES += key-file.c +libkey_la_SOURCES += key-io.c +libkey_la_SOURCES += key-misc.c +libkey_la_SOURCES += key-moan.c + +## Managing key data. +pkginclude_HEADERS += key-data.h +libkey_la_SOURCES += key-binary.c +libkey_la_SOURCES += key-data.c +libkey_la_SOURCES += key-flags.c +libkey_la_SOURCES += key-pack.c +libkey_la_SOURCES += key-pass.c +libkey_la_SOURCES += key-text.c + +## Error reporting. +pkginclude_HEADERS += key-error.h +libkey_la_SOURCES += key-error.c + +## Reading passphrases. +pkginclude_HEADERS += passphrase.h +libkey_la_SOURCES += passphrase.c + +## Interfacing with the passphrase pixie. +pkginclude_HEADERS += pixie.h +libkey_la_SOURCES += pixie-common.c + +###----- That's all, folks -------------------------------------------------- diff --git a/key/key-attr.c b/key/key-attr.c new file mode 100644 index 0000000..e884d69 --- /dev/null +++ b/key/key-attr.c @@ -0,0 +1,306 @@ +/* -*-c-*- + * + * Key attribute manipulation + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +#include +#include + +#include "key.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @key_chkident@ --- * + * + * Arguments: @const char *p@ = pointer to a type string + * + * Returns: Zero if OK, -1 on error. + * + * Use: Checks whether an identification component string is OK. + */ + +int key_chkident(const char *p) +{ + if (!p || !*p || strlen(p) > 255) + return (-1); + while (*p) { + if (*p == ':' || *p == '.' || isspace((unsigned char)*p)) + return (-1); + p++; + } + return (0); +} + +/* --- @key_chkcomment@ --- * + * + * Arguments: @const char *p@ = pointer to a comment string + * + * Returns: Zero if OK, -1 on error. + * + * Use: Checks whether a comment string is OK. + */ + +int key_chkcomment(const char *p) +{ + if (!p) + return (0); + if (!*p) + return (-1); + while (*p) { + if (*p == '\n') + return (-1); + p++; + } + return (0); +} + +/* --- @key_mkattriter@ --- * + * + * Arguments: @key_attriter *i@ = pointer to attribute iterator + * @key *k@ = pointer to key + * + * Returns: --- + * + * Use: Initializes an attribute iterator. The attributes are + * returned by @key_nextattr@. + */ + +void key_mkattriter(key_attriter *i, key *k) +{ + sym_mkiter(&i->i, &k->a); +} + +/* --- @key_nextattr@ --- * + * + * Arguments: @key_attriter *i@ = pointer to attribute iterator + * @const char **n, **v@ = pointers to name and value + * + * Returns: Zero if no attribute available, or nonzero if returned OK. + * + * Use: Returns the next attribute. + */ + +int key_nextattr(key_attriter *i, const char **n, const char **v) +{ + key_attr *a = sym_next(&i->i); + if (!a) + return (0); + if (n) *n = SYM_NAME(a); + if (v) *v = a->p; + return (1); +} + +/* --- @key_getattr@ --- * + * + * Arguments: @key_file *f@ = pointer to file + * @key *k@ = pointer to key + * @const char *n@ = pointer to attribute name + * + * Returns: Pointer to attribute value, or null if not found. + * + * Use: Returns the value of a key attribute. + */ + +const char *key_getattr(key_file *f, key *k, const char *n) +{ + key_attr *a; + if ((a = sym_find(&k->a, n, -1, 0, 0)) == 0) + return (0); + return (a->p); +} + +/* --- @key_putattr@ --- * + * + * Arguments: @key_file *f@ = pointer to file + * @key *k@ = pointer to key + * @const char *n@ = pointer to attribute name + * @const char *v@ = pointer to attribute value or null + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Inserts an attribute on a key. If an attribute with the same + * name already exists, it is deleted. Setting a null value + * removes the attribute. + */ + +int key_putattr(key_file *f, key *k, const char *n, const char *v) +{ + key_attr *a; + unsigned found; + + if (!(f->f & KF_WRITE)) + return (KERR_READONLY); + if (strlen(n) > 255) + return (KERR_BADATTR); + + if (v) { + a = sym_find(&k->a, n, -1, sizeof(*a), &found); + if (found) + xfree(a->p); + a->p = xstrdup(v); + } else if ((a = sym_find(&k->a, n, -1, 0, 0)) != 0) { + xfree(a->p); + sym_remove(&k->a, a); + } + + f->f |= KF_MODIFIED; + return (0); +} + +/* --- @key_setkeydata@ --- * + * + * Arguments: @key_file *kf@ = pointer to key file + * @key *k@ = pointer to key + * @key_data *kd@ = new key data + * + * Returns: Zero on success, or a @KERR_@ error code on failure. + * + * Use: Sets the key data for a key. + */ + +int key_setkeydata(key_file *kf, key *k, key_data *kd) +{ + if (!(kf->f & KF_WRITE)) + return (KERR_READONLY); + key_incref(kd); + key_drop(k->k); + k->k = kd; + kf->f |= KF_MODIFIED; + return (0); +} + +/* --- @key_setcomment@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * @key *k@ = pointer to key block + * @const char *c@ = pointer to comment to set, or zero + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Replaces the key's current comment with a new one. + */ + +int key_setcomment(key_file *f, key *k, const char *c) +{ + if (!(f->f & KF_WRITE)) + return (KERR_READONLY); + if (key_chkcomment(c)) + return (KERR_BADCOMMENT); + if (k->c) + xfree(k->c); + if (c) + k->c = xstrdup(c); + else + k->c = 0; + f->f |= KF_MODIFIED; + return (0); +} + +/* --- @key_settag@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * @key *k@ = pointer to key block + * @const char *tag@ = pointer to comment to set, or zero + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Replaces the key's current tag with a new one. + */ + +int key_settag(key_file *f, key *k, const char *tag) +{ + key_ref *kr; + unsigned found; + + if (!(f->f & KF_WRITE)) + return (KERR_READONLY); + + /* --- Make sure the tag is OK --- */ + + if (tag && key_chkident(tag)) + return (KERR_BADTAG); + + /* --- See if the new tag is the same as the old one --- */ + + if ((!tag && !k->tag) || + (tag && k->tag && strcmp(tag, k->tag) == 0)) + return (0); + + /* --- Allocate an entry for the new tag --- */ + + if (tag) { + kr = sym_find(&f->bytag, tag, -1, sizeof(*kr), &found); + if (found && !KEY_EXPIRED(time(0), kr->k->del)) + return (KERR_DUPTAG); + kr->k = k; + } + + /* --- Remove any existing tag --- */ + + if (k->tag) { + kr = sym_find(&f->bytag, k->tag, -1, 0, 0); + assert(((void)"No bytag link", kr)); + sym_remove(&f->bytag, kr); + xfree(k->tag); + } + + /* --- Done --- */ + + f->f |= KF_MODIFIED; + if (tag) + k->tag = xstrdup(tag); + else + k->tag = 0; + return (0); +} + +/* --- @key_fulltag@ --- * + * + * Arguments: @key *k@ = pointer to key + * @dstr *d@ = pointer to destination string + * + * Returns: --- + * + * Use: Emits the key's full tag, which has the form + * `ID:TYPE[:TAG]'. This is used in the textual file format, + * and to identify passphrases for locked keys. + */ + +void key_fulltag(key *k, dstr *d) +{ + dstr_putf(d, "%08lx:%s", (unsigned long)k->id, k->type); + if (k->tag) + dstr_putf(d, ":%s", k->tag); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/key-binary.c b/key/key-binary.c new file mode 100644 index 0000000..046819a --- /dev/null +++ b/key/key-binary.c @@ -0,0 +1,314 @@ +/* -*-c-*- + * + * Key binary encoding + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include +#include +#include +#include + +#include "key-data.h" +#include "mp.h" +#include "mptext.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @key_decode@ --- * + * + * Arguments: @const void *p@ = pointer to buffer to read + * @size_t sz@ = size of the buffer + * + * Returns: The newly-read key data, or null if it failed. + * + * Use: Decodes a binary representation of a key. + */ + +key_data *key_decode(const void *p, size_t sz) +{ + const octet *q = p; + size_t psz; + key_data *kd; + unsigned e; + + /* --- Parse the header information --- * + * + * Make sure the size matches external reality. Security holes have been + * known to creep in without this sort of check. (No, this isn't an after- + * the-fact patch-up.) + */ + + e = LOAD16(q); + psz = LOAD16(q + 2); + if (psz + 4 > sz) + return (0); + + /* --- Now decide what to do --- */ + + switch (e & KF_ENCMASK) { + + /* --- Plain binary data --- */ + + case KENC_BINARY: + case KENC_ENCRYPT: + kd = key_newbinary(e, q + 4, psz); + break; + + /* --- Multiprecision integer data --- */ + + case KENC_MP: + kd = key_newmp(e, mp_loadb(e & KF_BURN ? MP_NEWSEC : MP_NEW, + q + 4, psz)); + break; + + /* --- String data --- */ + + case KENC_STRING: + kd = key_newraw(e); + kd->u.p = xmalloc(sz + 1); + memcpy(kd->u.p, q + 4, sz); + kd->u.p[sz] = 0; + break; + + /* --- Elliptic curve point data --- */ + + case KENC_EC: { + size_t xsz, ysz; + kd = key_newraw(e); + EC_CREATE(&kd->u.e); + if (!sz) break; + if (sz < 2) return (0); + xsz = LOAD16(q + 4); + if (sz < xsz + 4) return (0); + ysz = LOAD16(q + 6 + xsz); + if (sz < xsz + ysz + 4) return (0); + kd->u.e.x = mp_loadb(MP_NEW, q + 6, xsz); + kd->u.e.y = mp_loadb(MP_NEW, q + 8 + xsz, ysz); + } break; + + /* --- Structured key data --- */ + + case KENC_STRUCT: { + dstr d = DSTR_INIT; + key_data *nkd; + + if ((e & ~KF_ENCMASK) || (psz & 3)) + return (0); + q += 4; + kd = key_newstruct(); + + while (psz) { + + /* --- Read the tag string --- */ + + DRESET(&d); + sz = LOAD8(q); + if (sz >= psz) + goto fail; + DPUTM(&d, q + 1, sz); + DPUTZ(&d); + sz = (sz + 4) & ~3; + q += sz; psz -= sz; + + /* --- Read the encoding and size --- */ + + sz = (LOAD16(q + 2) + 7) & ~3; + if (sz > psz) + goto fail; + + /* --- Create a table node and fill it in --- */ + + if ((nkd = key_decode(q, sz)) == 0) + goto fail; + key_structsteal(kd, d.buf, nkd); + psz -= sz; + q += sz; + } + dstr_destroy(&d); + break; + + /* --- Tidy up after a failure --- */ + + fail: + dstr_destroy(&d); + key_drop(kd); + return (0); + } break; + + /* --- Everything else --- */ + + default: + return (0); + } + + /* --- OK, that was good --- */ + + kd->e = e; + return (kd); +} + +/* --- @key_encode@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @dstr *d@ = pointer to destination string + * @const key_filter *kf@ = pointer to key selection block + * + * Returns: Nonzero if an item was actually written. + * + * Use: Encodes a key block as binary data. + */ + +static int ksbyname(const void *a, const void *b) { + key_struct *const *x = a, *const *y = b; + return (strcmp(SYM_NAME(*x), SYM_NAME(*y))); +} + +int key_encode(key_data *k, dstr *d, const key_filter *kf) +{ + int rc = 0; + if (!KEY_MATCH(k, kf)) + return (0); + switch (k->e & KF_ENCMASK) { + case KENC_BINARY: + case KENC_ENCRYPT: { + char *p; + + DENSURE(d, (k->u.k.sz + 7) & ~3); + p = d->buf + d->len; + STORE16(p, k->e); + STORE16(p + 2, k->u.k.sz); + d->len += 4; + DPUTM(d, k->u.k.k, k->u.k.sz); + rc = 1; + } break; + + case KENC_MP: { + char *p; + size_t sz = mp_octets(k->u.m); + + DENSURE(d, (sz + 7) & ~3); + p = d->buf + d->len; + STORE16(p, k->e); + STORE16(p + 2, sz); + mp_storeb(k->u.m, p + 4, sz); + d->len += sz + 4; + rc = 1; + } break; + + case KENC_STRING: { + char *p; + size_t sz = strlen(k->u.p); + + DENSURE(d, (sz + 7) & ~3); + p = d->buf + d->len; + STORE16(p, k->e); + STORE16(p + 2, sz); + memcpy(p + 4, k->u.p, sz); + d->len += sz + 4; + rc = 1; + } break; + + case KENC_EC: { + char *p; + size_t xsz = 0, ysz = 0; + size_t sz; + + if (EC_ATINF(&k->u.e)) + sz = 0; + else { + xsz = mp_octets(k->u.e.x); + ysz = mp_octets(k->u.e.y); + sz = xsz + ysz + 4; + } + DENSURE(d, (sz + 7) & ~3); + p = d->buf + d->len; + STORE16(p, k->e); + STORE16(p + 2, sz); + if (!EC_ATINF(&k->u.e)) { + STORE16(p + 4, xsz); + mp_storeb(k->u.e.x, p + 6, xsz); + STORE16(p + 6 + xsz, ysz); + mp_storeb(k->u.e.y, p + 8 + xsz, ysz); + } + d->len += sz + 4; + rc = 1; + } break; + + case KENC_STRUCT: { + size_t n; + char *p; + key_struct *ks, **ksv; + size_t nks, j; + sym_iter i; + + n = d->len; + DENSURE(d, 4); + p = d->buf + n; + STORE16(p, k->e & KF_ENCMASK); + d->len += 4; + + for (nks = 0, sym_mkiter(&i, &k->u.s); + (ks = sym_next(&i)) != 0; + nks++); + if (nks) { + ksv = xmalloc(nks * sizeof(*ksv)); + for (j = 0, sym_mkiter(&i, &k->u.s); (ks = sym_next(&i)) != 0; j++) + ksv[j] = ks; + qsort(ksv, nks, sizeof(*ksv), ksbyname); + for (j = 0; j < nks; j++) { + size_t o = d->len; + ks = ksv[j]; + DENSURE(d, 1); + *(octet *)(d->buf + d->len++) = strlen(SYM_NAME(ks)); + DPUTS(d, SYM_NAME(ks)); + while (d->len & 3) + DPUTC(d, 0); + if (key_encode(ks->k, d, kf)) + rc = 1; + else + d->len = o; + } + xfree(ksv); + } + if (!rc) + d->len = n; + else { + p = d->buf + n + 2; + n = d->len - n - 4; + STORE16(p, n); + } + } break; + } + while (d->len & 3) + DPUTC(d, 0); + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/key-data.c b/key/key-data.c new file mode 100644 index 0000000..8b01d72 --- /dev/null +++ b/key/key-data.c @@ -0,0 +1,467 @@ +/* -*-c-*- + * + * Encoding and decoding of key data + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "key-data.h" +#include "mp.h" +#include "mptext.h" + +/*----- Reference counting stuff ------------------------------------------*/ + +/* --- @key_incref@ --- * + * + * Arguments: @key_data *k@ = pointer to key data + * + * Returns: --- + * + * Use: Increments the refcount on a key data block. + */ + +void key_incref(key_data *k) { KEY_INCREF(k); } + +/* --- @key_destroy@ --- * + * + * Arguments: @key_data *k@ = pointer to key data to destroy + * + * Returns: --- + * + * Use: Destroys a block of key data, regardless of reference count. + * Don't use this unless you know what you're doing. + */ + +void key_destroy(key_data *k) +{ + switch (k->e & KF_ENCMASK) { + case KENC_BINARY: + case KENC_ENCRYPT: + if (k->u.k.k) { + if (k->e & KF_BURN) + memset(k->u.k.k, 0, k->u.k.sz); + sub_free(k->u.k.k, k->u.k.sz); + } + break; + case KENC_MP: + mp_drop(k->u.m); + break; + case KENC_STRING: + xfree(k->u.p); + break; + case KENC_EC: + EC_DESTROY(&k->u.e); + break; + case KENC_STRUCT: { + key_data *kd; + key_subkeyiter i; + + for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, 0, &kd); ) + KEY_DROP(kd); + sym_destroy(&k->u.s); + } break; + default: + abort(); + } + DESTROY(k); +} + +/* --- @key_drop@ --- * + * + * Arguments: @key_data *k@ = pointer to key data to destroy + * + * Returns: --- + * + * Use: Drops a reference to key data, destroying it if necessary. + */ + +void key_drop(key_data *k) { KEY_DROP(k); } + +/* --- @key_split@ --- * + * + * Arguments: @key_data **kk@ = address of pointer to key data block + * + * Returns: --- + * + * Use: Replaces @*kk@ with a pointer to the same key data, but with + * just one reference. + */ + +void key_split(key_data **kk) +{ + key_data *k = *kk; + + if (k->ref == 1) + return; + switch (k->e & KF_ENCMASK) { + case KENC_BINARY: + *kk = key_newbinary(k->e, k->u.k.k, k->u.k.sz); + break; + case KENC_ENCRYPT: + *kk = key_newencrypted(k->e, k->u.k.k, k->u.k.sz); + break; + case KENC_MP: + *kk = key_newmp(k->e, k->u.m); + break; + case KENC_STRING: + *kk = key_newstring(k->e, k->u.p); + break; + case KENC_EC: + *kk = key_newec(k->e, &k->u.e); + break; + case KENC_STRUCT: { + key_subkeyiter i; + const char *tag; + key_data *kd; + + *kk = key_newstruct(); + for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) + key_structset(*kk, tag, kd); + } break; + default: + abort(); + } +} + +/*----- Setting new values ------------------------------------------------*/ + +/* --- @key_newraw@ --- * + * + * Arguments: @unsigned e@ = encoding type to set + * + * Returns: New key block, not filled in. + */ + +key_data *key_newraw(unsigned e) +{ + key_data *k = CREATE(key_data); + k->e = e; + k->ref = 1; + return (k); +} + +/* --- @key_newbinary@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @const void *p@ = pointer to key data + * @size_t sz@ = size of the key data + * + * Returns: New key data object. + */ + +key_data *key_newbinary(unsigned e, const void *p, size_t sz) +{ + key_data *k = key_newraw(KENC_BINARY | e); + k->u.k.k = sub_alloc(sz); + memcpy(k->u.k.k, p, sz); + k->u.k.sz = sz; + return (k); +} + +/* --- @key_newencrypted@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @const void *p@ = pointer to key data + * @size_t sz@ = size of the key data + * + * Returns: New key data object. + */ + +key_data *key_newencrypted(unsigned e, const void *p, size_t sz) +{ + key_data *k = key_newraw(KENC_ENCRYPT | e); + k->u.k.k = sub_alloc(sz); + memcpy(k->u.k.k, p, sz); + k->u.k.sz = sz; + return (k); +} + +/* --- @key_newmp@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @mp *m@ = pointer to the value to set + * + * Returns: New key data object. + */ + +key_data *key_newmp(unsigned e, mp *m) +{ + key_data *k = key_newraw(KENC_MP | e); + k->u.m = MP_COPY(m); + return (k); +} + +/* --- @key_newstring@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @const char *p@ = pointer to the value to set + * + * Returns: New key data object. + */ + +key_data *key_newstring(unsigned e, const char *p) +{ + key_data *k = key_newraw(KENC_STRING | e); + k->u.p = xstrdup(p); + return (k); +} + +/* --- @key_newec@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @const ec *pt@ = pointer to the value to set + * + * Returns: New key data object. + */ + +key_data *key_newec(unsigned e, const ec *pt) +{ + key_data *k = key_newraw(KENC_EC | e); + EC_CREATE(&k->u.e); + EC_COPY(&k->u.e, pt); + return (k); +} + +/* --- @key_newstruct@ --- * + * + * Arguments: --- + * + * Returns: New key data object. + */ + +key_data *key_newstruct(void) +{ + key_data *k = key_newraw(KENC_STRUCT); + sym_create(&k->u.s); + return (k); +} + +/* --- @key_structfind@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @const char *tag@ = pointer to tag string + * + * Returns: Pointer to key data block, or null. + * + * Use: Looks up the tag in a structured key. + */ + +key_data *key_structfind(key_data *k, const char *tag) +{ + key_struct *ks; + assert(((void)"Key is not structured", + (k->e & KF_ENCMASK) == KENC_STRUCT)); + ks = sym_find(&k->u.s, tag, -1, 0, 0); + if (!ks) + return (0); + return (ks->k); +} + +/* --- @key_mksubkeyiter@ --- * + * + * Arguments: @key_subkeyiter *i@ = pointer to iterator block + * @key_data *k@ = pointer to key data block + * + * Returns: --- + * + * Use: Initializes a subkey iterator. + */ + +void key_mksubkeyiter(key_subkeyiter *i, key_data *k) +{ + assert(((void)"Key is not structured", + (k->e & KF_ENCMASK) == KENC_STRUCT)); + sym_mkiter(&i->i, &k->u.s); +} + +/* --- @key_nextsubkey@ --- * + * + * Arguments: @key_structiter *i@ = pointer to iterator block + * @const char **tag@ = where to put the tag pointer, or null + * @key_data **kd@ = where to put the key data pointer, or null + * + * Returns: Nonzero if there was another item, zero if we hit the + * end-stop. + * + * Use: Collects the next subkey of a structured key. + */ + +int key_nextsubkey(key_subkeyiter *i, const char **tag, key_data **kd) +{ + key_struct *ks; + + if ((ks = sym_next(&i->i)) == 0) + return (0); + if (tag) *tag = SYM_NAME(ks); + if (kd) *kd = ks->k; + return (1); +} + +/* --- @key_structset@, @key_structsteal@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @const char *tag@ = pointer to tag string + * @key_data *kd@ = new key data to store + * + * Returns: --- + * + * Use: Creates a new subkey. Stealing doesn't affect @kd@'s + * refcount. If @kd@ is null, the subkey is deleted. + */ + +static void structset(key_data *k, int stealp, + const char *tag, key_data *kd) +{ + key_struct *ks; + unsigned f; + + assert(((void)"Key is not structured", k->e == KENC_STRUCT)); + assert(((void)"Key has multiple references", k->ref == 1)); + if (!kd) { + ks = sym_find(&k->u.s, tag, -1, 0, 0); + if (ks) sym_remove(&k->u.s, ks); + } else { + ks = sym_find(&k->u.s, tag, -1, sizeof(*ks), &f); + if (f) + key_drop(ks->k); + if (!stealp) KEY_INCREF(kd); + ks->k = kd; + } +} + +void key_structset(key_data *k, const char *tag, key_data *kd) + { structset(k, 0, tag, kd); } +void key_structsteal(key_data *k, const char *tag, key_data *kd) + { structset(k, 1, tag, kd); } + +/*----- Miscellaneous operations ------------------------------------------*/ + +/* --- @key_do@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @const key_filter *kf@ = pointer to filter block + * @dstr *d@ = pointer to base string + * @int (*func)(key_data *kd, dstr *d, void *p@ = function + * @void *p@ = argument to function + * + * Returns: Nonzero return code from function, or zero. + * + * Use: Runs a function over all the leaves of a key. + */ + +int key_do(key_data *k, const key_filter *kf, dstr *d, + int (*func)(key_data */*kd*/, dstr */*d*/, void */*p*/), + void *p) +{ + if (!KEY_MATCH(k, kf)) + return (0); + if ((k->e & KF_ENCMASK) != KENC_STRUCT) + return (func(k, d, p)); + else { + key_subkeyiter i; + const char *tag; + size_t n = 0; + int rc; + + if (d) + n = d->len; + for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) { + if (d) { + d->len = n; + dstr_putf(d, ".%s", tag); + } + if ((rc = key_do(k, kf, d, func, p)) != 0) + return (rc); + } + return (0); + } +} + +/* --- @key_copydata@ --- * + * + * Arguments: @key_data *k@ = key data to copy + * @const key_filter *kf@ = pointer to filter block + * + * Returns: Pointer to a copy of the data, or null if the root subkey + * didn't match the filter. + * + * Use: Copies a chunk of key data. Subkeys, whether they're + * structured or leaves, which don't match the filter aren't + * copied. The copy may or may not have structure in common + * with the original. + */ + +static int structmatchp(key_data *k, const key_filter *kf) +{ + key_subkeyiter i; + + if (!KEY_MATCH(k, kf)) return (0); + else if ((k->e & KF_ENCMASK) == KENC_STRUCT) return (1); + else { + for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, 0, &k); ) + if (!structmatchp(k, kf)) return (0); + return (1); + } +} + +key_data *key_copydata(key_data *k, const key_filter *kf) +{ + key_subkeyiter i; + const char *tag; + key_data *kd, *kkd; + + /* --- Trivial cases --- */ + + if (!KEY_MATCH(k, kf)) + return (0); + else if (structmatchp(k, kf)) { + key_incref(k); + return (k); + } + + /* --- Copy a structured key recursively --- */ + + kkd = key_newstruct(); + for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) { + if ((kd = key_copydata(kd, kf)) != 0) + key_structsteal(kkd, tag, kd); + } + + /* --- Done --- */ + + return (kkd); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/key-data.h b/key/key-data.h new file mode 100644 index 0000000..9c00908 --- /dev/null +++ b/key/key-data.h @@ -0,0 +1,592 @@ +/* -*-c-*- + * + * Manipulating key data + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_KEY_DATA_H +#define CATACOMB_KEY_DATA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include +#include +#include + +#ifndef CATACOMB_KEY_ERROR_H +# include "key-error.h" +#endif + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_EC_H +# include "ec.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- Key binary data --- */ + +typedef struct key_bin { + octet *k; /* Pointer to key data */ + size_t sz; /* Size of the key data (in bytes) */ +} key_bin; + +/* --- Key data structure --- */ + +typedef struct key_data { + unsigned e; /* Encoding type for key data */ + unsigned ref; /* Reference counter */ + union { + key_bin k; /* Binary key data */ + mp *m; /* Multiprecision integer */ + sym_table s; /* Structured key data */ + char *p; /* String pointer */ + ec e; /* Elliptic curve point */ + } u; +} key_data; + +typedef struct key_struct { + sym_base _b; + key_data *k; +} key_struct; + +typedef struct key_subkeyiter { sym_iter i; } key_subkeyiter; + +/* --- Packing and unpacking --- */ + +typedef struct key_packdef { + unsigned e; /* Key data encoding type */ + void *p; /* Pointer to the destination */ + key_data *kd; /* Key data block */ +} key_packdef; + +typedef struct key_packstruct { + char *name; /* Pointer to name string */ + key_packdef kp; /* Packing structure */ +} key_packstruct; + +/* --- Key binary encoding --- * + * + * The binary encoding consists of a header containing a 16-bit encoding type + * and a 16-bit length, followed immediately by the key data, followed by + * between zero and three zero bytes to make the total length a multiple of + * four. The format of the following data depends on the encoding type: + * + * @KENC_BINARY@ Binary data. + * + * @KENC_MP@ Octet array interpreted in big-endian byte order. + * + * @KENC_STRUCT@ An array of pairs, each containing a string (8-bit + * length followed by data and zero-padding to 4-byte + * boundary) and key binary encodings. + * + * @KENC_ENCRYPT@ Binary data, format + */ + +/* --- Key encoding methods and other flags--- */ + +enum { + + /* --- Bottom two bits are the encoding type --- */ + + KF_ENCMASK = 0x83, /* Encoding mask */ + KENC_BINARY = 0x00, /* Plain binary key (@k@) */ + KENC_MP = 0x01, /* Multiprecision integer (@i@) */ + KENC_STRUCT = 0x02, /* Structured key data (@s@) */ + KENC_ENCRYPT = 0x03, /* Encrypted key type (@k@) */ + KENC_STRING = 0x80, /* ASCII string (@p@) */ + KENC_EC = 0x81, /* Elliptic curve point (@e@) */ + + /* --- Key category bits --- */ + + KF_CATMASK = 0x0c, /* Category mask */ + KCAT_SYMM = 0x00, /* Symmetric encryption key */ + KCAT_PRIV = 0x04, /* Private (asymmetric) key */ + KCAT_PUB = 0x08, /* Public (asymmetric) key */ + KCAT_SHARE = 0x0c, /* Shared (asymmetric) key */ + KF_NONSECRET = 0x08, /* Bit flag for non-secret keys */ + + /* --- Other flags --- */ + + KF_BURN = 0x10, /* Burn key after use */ + KF_OPT = 0x20, /* Optional key (for @key_unpack@) */ + + /* --- Tag end --- */ + + KENC_MAX /* Dummy limit constant */ +}; + +/* --- Key locking return codes --- */ + +#define KL_OK 0 /* All good */ +#define KL_IOERR -1 /* I/O problem (e.g., getting pp) */ +#define KL_KEYERR -2 /* Wrong key supplied */ +#define KL_DATAERR -3 /* Data format error */ + +/* --- Key flag filtering --- */ + +typedef struct key_filter { + unsigned f; + unsigned m; +} key_filter; + +/* --- Matching aginst key selection --- */ + +#define KEY_MATCH(kd, kf) \ + (!(kf) || \ + ((kd)->e & KF_ENCMASK) == KENC_STRUCT || \ + ((kd)->e & (kf)->m) == (kf)->f) + +/*----- Key flags and filtering -------------------------------------------*/ + +/* --- @key_readflags@ --- * + * + * Arguments: @const char *p@ = pointer to string to read + * @char **pp@ = where to store the end pointer + * @unsigned *ff@ = where to store the flags + * @unsigned *mm@ = where to store the mask + * + * Returns: Zero if all went well, nonzero if there was an error. + * + * Use: Reads a flag string. + */ + +extern int key_readflags(const char */*p*/, char **/*pp*/, + unsigned */*ff*/, unsigned */*mm*/); + +/* --- @key_writeflags@ --- * + * + * Arguments: @unsigned f@ = flags to write + * @dstr *d@ = pointer to destination string + * + * Returns: --- + * + * Use: Emits a flags word as a string representation. + */ + +extern void key_writeflags(unsigned /*f*/, dstr */*d*/); + +/* --- @key_match@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @const key_filter *kf@ = pointer to filter block + * + * Returns: Nonzero if the key matches the filter. + * + * Use: Checks whether a key matches a filter. + */ + +extern int key_match(key_data */*k*/, const key_filter */*kf*/); + +/*----- Setting new key data ----------------------------------------------*/ + +/* --- @key_newraw@ --- * + * + * Arguments: @unsigned e@ = encoding type to set + * + * Returns: New key block, not filled in. + */ + +extern key_data *key_newraw(unsigned /*e*/); + +/* --- @key_newbinary@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @const void *p@ = pointer to key data + * @size_t sz@ = size of the key data + * + * Returns: New key data object. + */ + +extern key_data *key_newbinary(unsigned /*e*/, + const void */*p*/, size_t /*sz*/); + +/* --- @key_newencrypted@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @const void *p@ = pointer to key data + * @size_t sz@ = size of the key data + * + * Returns: New key data object. + */ + +extern key_data *key_newencrypted(unsigned /*e*/, + const void */*p*/, size_t /*sz*/); + +/* --- @key_newmp@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @mp *m@ = pointer to the value to set + * + * Returns: New key data object. + */ + +extern key_data *key_newmp(unsigned /*e*/, mp */*m*/); + +/* --- @key_newstring@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @const char *p@ = pointer to the value to set + * + * Returns: New key data object. + */ + +extern key_data *key_newstring(unsigned /*e*/, const char */*p*/); + +/* --- @key_newec@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @const ec *pt@ = pointer to the value to set + * + * Returns: New key data object. + */ + +extern key_data *key_newec(unsigned /*e*/, const ec */*pt*/); + +/* --- @key_newstruct@ --- * + * + * Arguments: --- + * + * Returns: New key data object. + */ + +extern key_data *key_newstruct(void); + +/* --- @key_structfind@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @const char *tag@ = pointer to tag string + * + * Returns: Pointer to key data block, or null. + * + * Use: Looks up the tag in a structured key. + */ + +extern key_data *key_structfind(key_data */*k*/, const char */*tag*/); + +/* --- @key_mksubkeyiter@ --- * + * + * Arguments: @key_subkeyiter *i@ = pointer to iterator block + * @key_data *k@ = pointer to key data block + * + * Returns: --- + * + * Use: Initializes a subkey iterator. + */ + +extern void key_mksubkeyiter(key_subkeyiter */*i*/, key_data */*k*/); + +/* --- @key_nextsubkey@ --- * + * + * Arguments: @key_structiter *i@ = pointer to iterator block + * @const char **tag@ = where to put the tag pointer, or null + * @key_data **kd@ = where to put the key data pointer, or null + * + * Returns: Nonzero if there was another item, zero if we hit the + * end-stop. + * + * Use: Collects the next subkey of a structured key. + */ + +extern int key_nextsubkey(key_subkeyiter */*i*/, + const char **/*tag*/, key_data **/*kd*/); + +/* --- @key_structset@, @key_structsteal@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @const char *tag@ = pointer to tag string + * @key_data *kd@ = new key data to store + * + * Returns: --- + * + * Use: Creates a new subkey. Stealing doesn't affect @kd@'s + * refcount. If @kd@ is null, the subkey is deleted. + */ + +extern void key_structset(key_data */*k*/, + const char */*tag*/, key_data */*kd*/); +extern void key_structsteal(key_data */*k*/, + const char */*tag*/, key_data */*kd*/); + +/* --- @key_split@ --- * + * + * Arguments: @key_data **kk@ = address of pointer to key data block + * + * Returns: --- + * + * Use: Replaces @*kk@ with a pointer to the same key data, but with + * just one reference. + */ + +extern void key_split(key_data **/*kk*/); + +/*----- Miscellaneous operations ------------------------------------------*/ + +/* --- @key_incref@ --- * + * + * Arguments: @key_data *k@ = pointer to key data + * + * Returns: --- + * + * Use: Increments the refcount on a key data block. + */ + +#define KEY_INCREF(k) ((k)->ref++) +extern void key_incref(key_data */*k*/); + +/* --- @key_destroy@ --- * + * + * Arguments: @key_data *k@ = pointer to key data to destroy + * + * Returns: --- + * + * Use: Destroys a block of key data, regardless of reference count. + * Don't use this unless you know what you're doing. + */ + +extern void key_destroy(key_data */*k*/); + +/* --- @key_drop@ --- * + * + * Arguments: @key_data *k@ = pointer to key data to destroy + * + * Returns: --- + * + * Use: Drops a reference to key data, destroying it if necessary. + */ + +#define KEY_DROP(k) do { \ + key_data *_k = k; \ + _k->ref--; \ + if (_k->ref == 0) \ + key_destroy(_k); \ +} while (0) + +extern void key_drop(key_data */*k*/); + +/* --- @key_do@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @const key_filter *kf@ = pointer to filter block + * @dstr *d@ = pointer to base string + * @int (*func)(key_data *kd, dstr *d, void *p@ = function + * @void *p@ = argument to function + * + * Returns: Nonzero return code from function, or zero. + * + * Use: Runs a function over all the leaves of a key. + */ + +extern int key_do(key_data */*k*/, const key_filter */*kf*/, dstr */*d*/, + int (*/*func*/)(key_data */*kd*/, + dstr */*d*/, void */*p*/), + void */*p*/); + +/* --- @key_copydata@ --- * + * + * Arguments: @key_data *k@ = key data to copy + * @const key_filter *kf@ = pointer to filter block + * + * Returns: Pointer to a copy of the data, or null if the root subkey + * didn't match the filter. + * + * Use: Copies a chunk of key data. Subkeys, whether they're + * structured or leaves, which don't match the filter aren't + * copied. The copy may or may not have structure in common + * with the original. + */ + +extern key_data *key_copydata(key_data */*k*/, const key_filter */*kf*/); + +/*----- Textual encoding --------------------------------------------------*/ + +/* --- @key_read@ --- * + * + * Arguments: @const char *p@ = pointer to textual key representation + * @char **pp@ = where to store the end pointer + * + * Returns: The newly-read key data, or null if it failed. + * + * Use: Parses a textual key description. + */ + +extern key_data *key_read(const char */*p*/, char **/*pp*/); + +/* --- @key_write@ --- * + * + * Arguments: @key_data *k@ = pointer to key data + * @dstr *d@ = destination string to write on + * @const key_filter *kf@ = pointer to key selection block + * + * Returns: Nonzero if any items were actually written. + * + * Use: Writes a key in a textual encoding. + */ + +extern int key_write(key_data */*k*/, dstr */*d*/, const key_filter */*kf*/); + +/*----- Key binary encoding -----------------------------------------------*/ + +/* --- @key_decode@ --- * + * + * Arguments: @const void *p@ = pointer to buffer to read + * @size_t sz@ = size of the buffer + * + * Returns: The newly-read key data, or null if it failed. + * + * Use: Decodes a binary representation of a key. + */ + +extern key_data *key_decode(const void */*p*/, size_t /*sz*/); + +/* --- @key_encode@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @dstr *d@ = pointer to destination string + * @const key_filter *kf@ = pointer to key selection block + * + * Returns: Nonzero if any items were actually written. + * + * Use: Encodes a key block as binary data. + */ + +extern int key_encode(key_data */*k*/, dstr */*d*/, + const key_filter */*kf*/); + +/*----- Packing and unpacking keys ----------------------------------------*/ + +/* --- @key_pack@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing structure + * @key_data **kd@ = where to put the key data pointer + * @dstr *d@ = pointer to tag string for the key data + * + * Returns: Error code, or zero. + * + * Use: Packs a key from a data structure. + */ + +extern int key_pack(key_packdef */*kp*/, key_data **/*kd*/, dstr */*d*/); + +/* --- @key_unpack@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing structure + * @key_data *kd@ = pointer to source key data + * @dstr *d@ = pointer to tag string for the key data + * + * Returns: Error code, or zero. + * + * Use: Unpacks a key into an appropriate data structure. + */ + +extern int key_unpack(key_packdef */*kp*/, key_data */*kd*/, dstr */*d*/); + +/* --- @key_unpackdone@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing definition + * + * Returns: --- + * + * Use: Frees the key components contained within a packing + * definition, created during key unpacking. + */ + +extern void key_unpackdone(key_packdef */*kp*/); + +/*----- Key encryption ----------------------------------------------------*/ + +/* --- @key_lock@ --- * + * + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const void *e@ = secret to encrypt key with + * @size_t esz@ = size of the secret + * + * Returns: --- + * + * Use: Encrypts a key data block using a secret. + */ + +extern void key_lock(key_data **/*kt*/, key_data */*k*/, + const void */*e*/, size_t /*esz*/); + +/* --- @key_unlock@ --- * + * + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const void *e@ = secret to decrypt the block with + * @size_t esz@ = size of the secret + * + * Returns: Zero for success, or a @KERR_@ error code. + * + * Use: Unlocks a key using a secret. + */ + +extern int key_unlock(key_data **/*kt*/, key_data */*k*/, + const void */*e*/, size_t /*esz*/); + +/* --- @key_plock@ --- * + * + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const char *tag@ = tag to use for passphrase + * + * Returns: Zero if successful, a @KERR@ error code on failure. + * + * Use: Locks a key by encrypting it with a passphrase. + */ + +extern int key_plock(key_data **/*kt*/, key_data */*k*/, + const char */*tag*/); + +/* --- @key_punlock@ --- * + * + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const char *tag@ = tag to use for passphrase + * + * Returns: Zero if successful, a @KERR@ error code on failure. + * + * Use: Unlocks a passphrase-locked key. + */ + +extern int key_punlock(key_data **/*kt*/, key_data */*k*/, + const char */*tag*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/key/key-error.c b/key/key-error.c new file mode 100644 index 0000000..a091997 --- /dev/null +++ b/key/key-error.c @@ -0,0 +1,60 @@ +/* -*-c-*- + * + * Translating key error codes into strings + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include "key-error.h" + +/*----- Error reporting ---------------------------------------------------*/ + +/* --- @key_strerror@ --- * + * + * Arguments: @int err@ = error code from @key_new@ + * + * Returns: Pointer to error string. + * + * Use: Translates a @KERR@ error code into a human-readable + * string. + */ + +const char *key_strerror(int err) +{ + static const char *const tab[] = { +#define ENTRY(tag, num, str) str, + KEY_ERRORS(ENTRY) +#undef ENTRY + "Unknown error code" + }; + + unsigned e = -err; + if (e >= N(tab)) + e = N(tab) - 1; + return (tab[e]); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/key-error.h b/key/key-error.h new file mode 100644 index 0000000..6b3131c --- /dev/null +++ b/key/key-error.h @@ -0,0 +1,81 @@ +/* -*-c-*- + * + * Key management error codes + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_KEY_ERROR_H +#define CATACOMB_KEY_ERROR_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Error codes -------------------------------------------------------*/ + +#define KEY_ERRORS(_) \ + _(OK, 0, "No error") \ + _(BADTAG, -1, "Bad tag string") \ + _(BADTYPE, -2, "Bad type string") \ + _(BADCOMMENT, -3, "Bad comment string") \ + _(DUPID, -4, "Key id already exists") \ + _(DUPTAG, -5, "Key tag already exists") \ + _(READONLY, -6, "Key file is read-only") \ + _(WILLEXPIRE, -7, "Key will eventually expire") \ + _(EXPIRED, -8, "Key has expired") \ + _(BADFLAGS, -9, "Bad key flags string") \ + _(BADPASS, -10, "Failed to unlock key") \ + _(WRONGTYPE, -11, "Unexpected key encoding type") \ + _(NOTFOUND, -12, "Key not found") \ + _(BADATTR, -13, "Bad attribute name") \ + _(MALFORMED, -14, "Malformed key data") \ + _(IO, -15, "I/O error") \ + +enum { +#define ENTRY(tag, num, str) KERR_##tag = num, + KEY_ERRORS(ENTRY) +#undef ENTRY + KERR__dummy +}; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @key_strerror@ --- * + * + * Arguments: @int err@ = error code from @key_new@ + * + * Returns: Pointer to error string. + * + * Use: Translates a @KERR@ error code into a human-readable string. + */ + +extern const char *key_strerror(int /*err*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/key/key-fetch.c b/key/key-fetch.c new file mode 100644 index 0000000..d8d6da2 --- /dev/null +++ b/key/key-fetch.c @@ -0,0 +1,206 @@ +/* -*-c-*- + * + * Higher-level key unpacking + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "key.h" +#include "key-data.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @key_fetchinit@ --- * + * + * Arguments: @const key_fetchdef *kf@ = pointer to base definition + * @key_packstruct *kps@ = pointer to destination packing def + * @void *p@ = pointer to destination block + * + * Returns: Pointer to packing definition. + * + * Use: Initializes a packing definition (@key_packdef@ structure). + * If @kps@ is null on entry, an appropriately sized block is + * allocated automatically. Otherwise it must be large enough. + */ + +static size_t kfcount(const key_fetchdef *kf) +{ + size_t n = 1; + while (kf->name) { + n++; + if (kf->kf) + n += kfcount(kf->kf); + kf++; + } + return (n); +} + +key_packdef *key_fetchinit(const key_fetchdef *kf, + key_packstruct *kp, void *p) +{ + size_t n = 1 + kfcount(kf); + key_packdef *kpd; + key_packstruct *kps; + char *cp = p; + + /* --- If @kps@ is null, count the entries and allocate --- */ + + if (kp) + kp->name = 0; + else { + kp = xmalloc(n * sizeof(*kp)); + kp->name = (char *)kp; + } + + /* --- Fill in the top part --- */ + + kp->kp.e = KENC_STRUCT; + kp->kp.p = &kp[1]; + kp->kp.kd = 0; + kpd = &kp->kp; + + /* --- Initialize for the main loop --- */ + + kps = kp + n; + n = 0; + kp++; + + /* --- Iterate over the entries in the table --- * + * + * The end of the target block is used as a stack to record where + * substructure is meant to occur. The integer @n@ is the depth of the + * stack; @kps@ is a full descending stack pointer. The @kp.p@ member of a + * stack element points back to an entry with substructure, the @kp.p@ + * member of which refers to the @kf@ table for the substructure. + * + * This should all be about as clear as mud. + */ + + for (;;) { + + /* --- Blat out a level's worth --- */ + + while (kf->name) { + kp->name = kf->name; + kp->kp.e = kf->e; + kp->kp.kd = 0; + if ((kf->e & KF_ENCMASK) != KENC_STRUCT) + kp->kp.p = cp + kf->off; + else { + (--kps)->kp.p = kp; + kp->kp.p = (void *)kf->kf; + n++; + } + kf++; + kp++; + } + (kp++)->name = 0; + if (!n) + break; + + /* --- Pop an entry from the stack --- */ + + { + key_packstruct *kkp = (kps++)->kp.p; + kf = kkp->kp.p; + kkp->kp.p = kp; + n--; + } + } + + /* --- We're done --- */ + + return (kpd); +} + +/* --- @key_fetch@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing structure + * @key *k@ = key file containing desired key + * + * Returns: Error code, or zero. + * + * Use: Fetches an unpacked key from a packed one. + */ + +int key_fetch(key_packdef *kp, key *k) +{ + dstr d = DSTR_INIT; + int e; + + key_fulltag(k, &d); + e = key_unpack(kp, k->k, &d); + dstr_destroy(&d); + return (e); +} + +/* --- @key_fetchbyname@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing structure + * @key_file *kf@ = key file containing desired key + * @const char *tag@ = user's tag describing the key + * + * Returns: Error code, or zero. + * + * Use: Fetches a named key from a key file and unpacks it + * conveniently. + */ + +int key_fetchbyname(key_packdef *kp, key_file *kf, const char *tag) +{ + dstr d = DSTR_INIT; + key_data **kd; + int e; + + if (key_qtag(kf, tag, &d, 0, &kd)) + e = KERR_NOTFOUND; + else + e = key_unpack(kp, *kd, &d); + dstr_destroy(&d); + return (e); +} + +/* --- @key_fetchdone@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing structure + * + * Returns: --- + * + * Use: Frees a packing structure. If the structure was allocated by + * @key_fetchinit@ then it is freed. + */ + +void key_fetchdone(key_packdef *kp) +{ + key_packstruct *kps = + (key_packstruct *)(((char *)kp) - offsetof(key_packstruct, kp)); + key_unpackdone(kp); + if (kps->name) + xfree(kps); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/key-file.c b/key/key-file.c new file mode 100644 index 0000000..e7f4fdd --- /dev/null +++ b/key/key-file.c @@ -0,0 +1,336 @@ +/* -*-c-*- + * + * System-dependent key filing operations + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "key.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @fdcopy@ --- * + * + * Arguments: @int source@ = source file descriptor + * @int dest@ = destination file descriptor + * + * Returns: Zero if OK, nonzero otherwise. + * + * Use: Copies data from one file descriptor to another. + */ + +static int fdcopy(int source, int dest) +{ + char buf[4096]; + char *p; + + if (lseek(source, 0, SEEK_SET) < 0|| + lseek(dest, 0, SEEK_SET) < 0 || + ftruncate(dest, 0) < 0) + return (-1); + for (;;) { + int n = read(source, buf, sizeof(buf)); + if (n < 0) + return (-1); + else if (n == 0) + break; + p = buf; + while (n) { + int nn = write(dest, p, n); + if (nn < 0) + return (-1); + p += nn; + n -= nn; + } + } + return (0); +} + +/* --- @key_save@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * + * Returns: A @KWRITE_@ code indicating how well it worked. + * + * Use: Writes a key file's data back to the actual file. This code + * is extremely careful about error handling. It should usually + * be able to back out somewhere sensible, but it can tell when + * it's got itself into a real pickle and starts leaving well + * alone. + * + * Callers, please make sure that you ring alarm bells when this + * function returns @KWRITE_BROKEN@. + */ + +int key_save(key_file *f) +{ + dstr n_older = DSTR_INIT, n_old = DSTR_INIT, n_new = DSTR_INIT; + int rc = KWRITE_FAIL; + + if (!(f->f & KF_MODIFIED)) + return (KWRITE_OK); + if (!f->fp) + return (KWRITE_FAIL); + + /* --- Write a new key file out --- * + * + * Check for an error after each key line. This ought to be enough. + * Checking after each individual byte write and @fprintf@ isn't much fun. + */ + + dstr_putf(&n_new, "%s.new", f->name); + + { + key *k; + key_iter i; + FILE *fp; + + if ((fp = fopen(n_new.buf, "w")) == 0) + goto fail_open; + + for (key_mkiter(&i, f); (k = key_next(&i)) != 0; ) { + if (key_extract(f, k, fp, 0)) { + fclose(fp); + goto fail_write; + } + } + + if (fclose(fp)) + goto fail_write; + } + + /* --- Set up the other filenames --- */ + + dstr_putf(&n_older, "%s.older", f->name); + dstr_putf(&n_old, "%s.old", f->name); + + /* --- Move the current backup on one --- * + * + * If the `older' file exists, then we're in need of attention. + */ + + { + struct stat st; + if (stat(n_older.buf, &st) == 0 || errno != ENOENT) { + errno = EEXIST; + rc = KWRITE_BROKEN; + goto fail_shift; + } + if (rename(n_old.buf, n_older.buf) && errno != ENOENT) + goto fail_shift; + } + + /* --- Copy the current file to the backup --- */ + + { + int fd; + if ((fd = open(n_old.buf, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0) + goto fail_backup; + if (fdcopy(fileno(f->fp), fd)) { + close(fd); + goto fail_backup; + } + if (close(fd)) + goto fail_backup; + } + + /* --- Copy the newly created file to the current one --- * + * + * This is the dangerous bit. + */ + + { + int fd; + if ((fd = open(n_new.buf, O_RDONLY)) < 0) + goto fail_update; + if (fdcopy(fd, fileno(f->fp))) { + close(fd); + goto fail_update; + } + close(fd); + if (fsync(fileno(f->fp))) + goto fail_update; + } + + /* --- Clean up --- * + * + * Remove the `new' file and the `older' backup. Then we're done. + */ + + unlink(n_new.buf); + unlink(n_older.buf); + dstr_destroy(&n_new); + dstr_destroy(&n_old); + dstr_destroy(&n_older); + return (KWRITE_OK); + + /* --- Failure while writing the new key file --- * + * + * I need to copy the backup back. If that fails then I'm really stuffed. + * If not, then I might as well try to get the backups sorted back out + * again. + */ + +fail_update: + { + int fd; + int e = errno; + + if ((fd = open(n_old.buf, O_RDONLY)) < 0) + rc = KWRITE_BROKEN; + else if (fdcopy(fd, fileno(f->fp))) { + close(fd); + rc = KWRITE_BROKEN; + } else { + close(fd); + if (fsync(fileno(f->fp))) + rc = KWRITE_BROKEN; + } + + errno = e; + if (rc == KWRITE_BROKEN) + goto fail_shift; + } + /* Now drop through */ + + /* --- Failure while writing the new backup --- * + * + * The new backup isn't any use. Try to recover the old one. + */ + +fail_backup: + { + int e = errno; + unlink(n_old.buf); + if (rename(n_older.buf, n_old.buf) && errno != ENOENT) + rc = KWRITE_BROKEN; + errno = e; + } + /* Now drop through */ + + /* --- Failure while demoting the current backup --- * + * + * Leave the completed output file there for the operator in case he wants + * to clean up. + */ + +fail_shift: + dstr_destroy(&n_new); + dstr_destroy(&n_old); + dstr_destroy(&n_older); + return (rc); + + /* --- Failure during write of new data --- * + * + * Clean up the new file and return. These errors can never cause + * breakage. + */ + +fail_write: + unlink(n_new.buf); +fail_open: + dstr_destroy(&n_new); + return (rc); +} + +/* --- @key_lockfile@ --- * + * + * Arguments: @key_file *f@ = pointer to file structure to initialize + * @const char *file@ = pointer to the file name + * @unsigned how@ = opening options (@KOPEN_*@). + * + * Returns: Zero if it worked, nonzero otherwise. + * + * Use: Opens a keyfile and stores the information needed for + * continued access in the structure. + * + * If the file is opened with @KOPEN_WRITE@, it's created if + * necessary with read and write permissions for owner only, and + * locked for update while it's open. + * + * This is a system-dependent routine, and only really intended + * for the private use of @key_open@. + */ + +int key_lockfile(key_file *f, const char *file, unsigned how) +{ + int of, lf; + const char *ff; + int fd; + + /* --- Handle the magic no-file option --- */ + + if (how & KOPEN_NOFILE) { + f->fp = 0; + return (0); + } + + /* --- Lots of things depend on whether we're writing --- */ + + switch (how & KOPEN_MASK) { + case KOPEN_READ: + of = O_RDONLY; + lf = LOCK_NONEXCL; + ff = "r"; + break; + case KOPEN_WRITE: + of = O_RDWR | O_CREAT; + lf = LOCK_EXCL; + ff = "r+"; + break; + default: + errno = EINVAL; + return (-1); + } + + /* --- Open and lock the file --- */ + + if ((fd = open(file, of, 0600)) < 0) + return (-1); + if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0 || + lock_file(fd, lf) < 0 || + (f->fp = fdopen(fd, ff)) == 0) { + close(fd); + return (-1); + } + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/key-flags.c b/key/key-flags.c new file mode 100644 index 0000000..169de2c --- /dev/null +++ b/key/key-flags.c @@ -0,0 +1,202 @@ +/* -*-c-*- + * + * Reading and writing key flag strings + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include +#include + +#include "key-data.h" + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct key_flags { + unsigned f; + unsigned m; +} key_flags; + +/*----- Flags table -------------------------------------------------------*/ + +typedef struct flagent { + const char *name; + unsigned f; + unsigned m; +} flagent; + +static const flagent flagtab[] = { + + /* --- Encoding types --- */ + + { "binary", KENC_BINARY, KF_ENCMASK }, + { "integer", KENC_MP, KF_ENCMASK }, + { "struct", KENC_STRUCT, KF_ENCMASK }, + { "encrypt", KENC_ENCRYPT, KF_ENCMASK }, + { "string", KENC_STRING, KF_ENCMASK }, + { "ec", KENC_EC, KF_ENCMASK }, + + /* --- Classes of keys --- */ + + { "shared", KCAT_SHARE, KF_CATMASK }, + { "public", KCAT_PUB, KF_CATMASK }, + { "private", KCAT_PRIV, KF_CATMASK }, + { "symmetric", KCAT_SYMM, KF_CATMASK }, + { "secret", 0, KF_NONSECRET }, + { "-secret", KF_NONSECRET, KF_NONSECRET }, + + /* --- Other flags --- */ + + { "burn", KF_BURN, KF_BURN }, + { "-burn", 0, KF_BURN }, + + /* --- End marker --- */ + + { 0, 0, 0 } +}; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @key_readflags@ --- * + * + * Arguments: @const char *p@ = pointer to string to read + * @char **pp@ = where to store the end pointer + * @unsigned *ff@ = where to store the flags + * @unsigned *mm@ = where to store the mask + * + * Returns: Zero if all went well, nonzero if there was an error. + * + * Use: Reads a flag string. + */ + +int key_readflags(const char *p, char **pp, unsigned *ff, unsigned *mm) +{ + unsigned f = 0, m = 0; + + for (;;) { + size_t sz = strcspn(p, ",:"); + const flagent *e, *ee = 0; + + /* --- Look up the string in the flags table --- */ + + if (sz == 4 && strncmp(p, "none", 4) == 0) + goto next; + for (e = flagtab; e->name; e++) { + if (strncmp(e->name, p, sz) == 0) { + if (e->name[sz] == 0) { + ee = e; + break; + } else if (ee) + return (KERR_BADFLAGS); + else + ee = e; + } + } + if (!ee) + return (KERR_BADFLAGS); + + /* --- Adjust the flag words --- * + * + * Ensure that the flags set are disjoint. + */ + + if (m & ee->m) + return (KERR_BADFLAGS); + m |= ee->m; + f |= ee->f; + next: + p += sz; + if (*p == 0 || *p == ':') + break; + p++; + } + + /* --- Report the results --- */ + + if (ff) *ff = f; + if (mm) *mm = m; + if (pp) *pp = (char *)p; + return (0); +} + +/* --- @key_writeflags@ --- * + * + * Arguments: @unsigned f@ = flags to write + * @dstr *d@ = pointer to destination string + * + * Returns: --- + * + * Use: Emits a flags word as a string representation. + */ + +void key_writeflags(unsigned f, dstr *d) +{ + int del = 0; + const flagent *e; + unsigned m = 0; + + for (e = flagtab; e->name; e++) { + if (m & e->m || e->name[0] == '-' || (f & e->m) != e->f) + continue; + if (del) + DPUTC(d, ','); + DPUTS(d, e->name); + m |= e->m; + del = 1; + } +} + +/* --- @key_match@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @const key_filter *kf@ = pointer to filter block + * + * Returns: Nonzero if the key matches the filter. + * + * Use: Checks whether a key matches a filter. + */ + +int key_match(key_data *k, const key_filter *kf) +{ + key_subkeyiter i; + const char *tag; + key_data *kd; + + if (!kf) + return (1); + if ((k->e & KF_ENCMASK) != KENC_STRUCT) + return ((k->e & kf->m) == kf->f); + + for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) { + if (key_match(kd, kf)) + return (1); + } + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/key-io.c b/key/key-io.c new file mode 100644 index 0000000..df7cd53 --- /dev/null +++ b/key/key-io.c @@ -0,0 +1,569 @@ +/* -*-c-*- + * + * Adding new keys to a key file + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "key.h" + +/*----- Tweakable macros --------------------------------------------------*/ + +#define KEY_INITSZ 16 + +/*----- Low-level functions -----------------------------------------------*/ + +/* --- @insert@ --- * + * + * Arguments: @key_file *f@ = pointer to file structure + * @key *k@ = pointer to key block to insert + * + * Returns: Error code (one of the @KERR@ code). + * + * Use: Links a new key block into the complicated data structure + * which is a keyring file. + */ + +static int insert(key_file *f, key *k) +{ + key_ref *kr = 0; + unsigned found; + + /* --- Sanity preservatives --- */ + + if (key_chkident(k->type)) + return (KERR_BADTYPE); + else if (k->tag && key_chkident(k->tag)) + return (KERR_BADTAG); + + /* --- Insert into the tag table --- */ + + if (k->tag) { + kr = sym_find(&f->bytag, k->tag, -1, sizeof(*kr), &found); + if (found) + return (KERR_DUPTAG); + kr->k = k; + } + + /* --- Insert into the id table --- */ + + { + hash_base **bin, *b; + + bin = HASH_BIN(&f->byid, k->id); + for (b = *bin; b; b = b->next) { + if (b->hash == k->id) { + if (kr) + sym_remove(&f->bytag, kr); + return (KERR_DUPID); + } + } + + k->_b.next = *bin; + *bin = &k->_b; + k->_b.hash = k->id; + } + + /* --- Extend the table --- */ + + if (f->idload > 0) + f->idload--; + else if (hash_extend(&f->byid)) + f->idload = SYM_LIMIT(f->byid.mask / 2); + + /* --- Insert into the type table --- */ + + kr = sym_find(&f->bytype, k->type, -1, sizeof(*kr), &found); + if (!found) { + kr->k = k; + k->next = 0; + } else { + key **p = &kr->k; + if (k->exp != KEXP_FOREVER) { + while (*p && (*p)->exp != KEXP_EXPIRE && (*p)->exp > k->exp) + p = &(*p)->next; + } + k->next = *p; + *p = k; + } + + return (KERR_OK); +} + +/*----- Reading and writing keys ------------------------------------------*/ + +/* --- @exptime@ --- * + * + * Arguments: @const char *p@ = pointer to string + * + * Returns: Time value. + * + * Use: Translates an expiry or deletion time. + */ + +time_t exptime(const char *p) +{ + size_t sz = strlen(p); + if (strncmp(p, "expired", sz) == 0) + return (KEXP_EXPIRE); + else if (strncmp(p, "forever", sz) == 0) + return (KEXP_FOREVER); + else + return (atol(p)); +} + +/* --- @key_merge@ --- * + * + * Arguments: @key_file *f@ = pointer to file structure + * @const char *file@ = name of file (for error messages) + * @FILE *fp@ = file handle to read from + * @key_reporter *rep@ = error reporting function + * @void *arg@ = argument for function + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Reads keys from a file, and inserts them into the file. + */ + +int key_merge(key_file *f, const char *file, FILE *fp, + key_reporter *rep, void *arg) +{ + int line = 0; + dstr l = DSTR_INIT; + dstr n = DSTR_INIT, v = DSTR_INIT; + + if (!(f->f & KF_WRITE)) + return (KERR_READONLY); + + for (; dstr_putline(&l, fp) != EOF; DRESET(&l)) { + char *vf[6]; + char *p = l.buf; + key *k; + + /* --- Skip blank lines and comments --- * + * + * Quite what they're doing in what ought to be an automatically- + * maintained file I don't know. + */ + + line++; + while (isspace((unsigned char)*p)) + p++; + if (!*p || *p == '#') + continue; + + /* --- Break the line into fields --- * + * + * There are currently six fields of interest: + * + * * The key's identification (id, tag and type). + * * The actual key data itself. + * * The key expiry time. + * * The key deletion time. + * * The attributes field. + * * Any further comments. + * + * All but the last field can contain no spaces. + */ + + { + int n = str_split(p, vf, 5, &vf[5]); + if (n < 4) { + if (rep) + rep(file, line, "too few fields", arg); + goto skip_0; + } + } + + /* --- Allocate a new key block --- */ + + k = CREATE(key); + + /* --- Extract the key data into the block --- */ + + if ((k->k = key_read(vf[1], 0)) == 0) { + if (rep) + rep(file, line, "bad key data", arg); + goto skip_1; + } + + /* --- Decode the identification field --- * + * + * For compatibility, derive a keyid from the key data. This can only be + * done if the key encoding is binary (and presumably old-encoding binary + * at that). + */ + + { + char *q = strchr(vf[0], ':'); + char *qq; + + if (!q) { + if (k->k->e != KENC_BINARY) { + if (rep) + rep(file, line, "new-style key encoding but no keyid", arg); + goto skip_2; + } + k->id = crc32(0, k->k->u.k.k, k->k->u.k.sz); + k->type = xstrdup(vf[0]); + k->tag = 0; + } else { + *q++ = 0; + k->id = strtoul(p, 0, 16); + if ((qq = strchr(q, ':')) == 0 || !qq[1]) { + if (qq) + *qq = 0; + k->tag = 0; + } else { + *qq++ = 0; + k->tag = xstrdup(qq); + } + k->type = xstrdup(q); + } + } + + /* --- Get a key block for the new key --- */ + + k->exp = exptime(vf[2]); + k->del = exptime(vf[3]); + + /* --- Insert the key block into the table --- */ + + { + int err; + + again: + if ((err = insert(f, k)) < 0) { + if (err == KERR_DUPTAG) { + if (rep) + rep(file, line, "duplicate key tag stripped", arg); + xfree(k->tag); + k->tag = 0; + goto again; + } + if (rep) + rep(file, line, key_strerror(err), arg); + goto skip_3; + } + } + + /* --- Parse up the attributes, if specified --- */ + + sym_create(&k->a); + if (vf[4] && strcmp(vf[4], "-") != 0) { + url_dctx uc; + for (url_initdec(&uc, vf[4]); url_dec(&uc, &n, &v); ) { + key_putattr(f, k, n.buf, v.buf); + DRESET(&n); DRESET(&v); + } + } + + /* --- Insert the comment --- */ + + if (vf[5]) + k->c = xstrdup(vf[5]); + else + k->c = 0; + continue; + + /* --- Tidy up after something going wrong --- */ + + skip_3: + if (k->tag) + xfree(k->tag); + xfree(k->type); + skip_2: + key_drop(k->k); + skip_1: + DESTROY(k); + skip_0:; + } + + /* --- Extensive tidying up now required --- */ + + dstr_destroy(&l); + dstr_destroy(&n); + dstr_destroy(&v); + f->f |= KF_MODIFIED; + return (0); +} + +/* --- @key_extract@ --- * + * + * Arguments: @key_file *f@ = pointer to file structure + * @key *k@ = key to extract + * @FILE *fp@ = file to write on + * @const key_filter *kf@ = pointer to key selection block + * + * Returns: Zero if OK, EOF on error. + * + * Use: Extracts a key to an ouptut file. + */ + +int key_extract(key_file *f, key *k, FILE *fp, const key_filter *kf) +{ + dstr d = DSTR_INIT; + time_t t = time(0); + + /* --- Skip the key if it's deleted or unselected--- */ + + if (KEY_EXPIRED(t, k->del) || !key_match(k->k, kf)) + return (0); + + /* --- Encode the key and write the easy stuff --- */ + + key_fulltag(k, &d); + DPUTC(&d, ' '); + key_write(k->k, &d, kf); + DPUTC(&d, ' '); + dstr_write(&d, fp); + DRESET(&d); + + /* --- Write out the expiry and deletion times --- */ + + if (KEY_EXPIRED(t, k->exp)) + fputs("expired ", fp); + else if (k->exp == KEXP_FOREVER) + fputs("forever ", fp); + else + fprintf(fp, "%li ", (long)k->exp); + + if (k->del == KEXP_FOREVER) + fputs("forever ", fp); + else + fprintf(fp, "%li ", (long)k->del); + + /* --- Output the attributes --- */ + + { + int none = 1; + sym_iter i; + key_attr *a; + url_ectx uc; + + url_initenc(&uc); + for (sym_mkiter(&i, &k->a); (a = sym_next(&i)) != 0; ) { + none = 0; + url_enc(&uc, &d, SYM_NAME(a), a->p); + } + if (none) + DPUTS(&d, "-"); + DWRITE(&d, fp); + } + + dstr_destroy(&d); + if (k->c) { + putc(' ', fp); + fputs(k->c, fp); + } + putc('\n', fp); + return (ferror(fp) ? EOF : 0); +} + +/*----- Opening and closing files -----------------------------------------*/ + +/* --- @key_open@ --- * + * + * Arguments: @key_file *f@ = pointer to file structure to initialize + * @const char *file@ = pointer to the file name + * @unsigned how@ = opening options (@KOPEN_*@). + * @key_reporter *rep@ = error reporting function + * @void *arg@ = argument for function + * + * Returns: Zero if it worked, nonzero otherwise. + * + * Use: Opens a key file, reads its contents, and stores them in a + * structure. The file is locked appropriately until closed + * using @key_close@. On an error, everything is cleared away + * tidily. If the file is opened with @KOPEN_WRITE@, it's + * created if necessary, with read and write permissions for its + * owner only. + */ + +int key_open(key_file *f, const char *file, unsigned how, + key_reporter *rep, void *arg) +{ + if (key_lockfile(f, file, how)) { + rep(file, 0, strerror(errno), arg); + return (-1); + } + f->f = 0; + f->name = xstrdup(file); + + hash_create(&f->byid, KEY_INITSZ); + f->idload = SYM_LIMIT(KEY_INITSZ); + sym_create(&f->bytype); + sym_create(&f->bytag); + f->f |= KF_WRITE; + if (f->fp) + key_merge(f, file, f->fp, rep, arg); + f->f &= ~KF_MODIFIED; + + if ((how & KOPEN_MASK) == KOPEN_READ) { + f->f &= ~KF_WRITE; + fclose(f->fp); + f->fp = 0; + } + + return (0); +} + +/* --- @key_discard@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * + * Returns: --- + * + * Use: Frees all the key data, without writing changes. + */ + +void key_discard(key_file *f) +{ + hash_base *b; + hash_iter i; + + /* --- Free all the individual keys --- */ + + for (hash_mkiter(&i, &f->byid); (b = hash_next(&i)) != 0; ) { + sym_iter j; + key_attr *a; + key *k = (key *)b; + + if (k->k) key_drop(k->k); + xfree(k->type); + xfree(k->tag); + if (k->c) + xfree(k->c); + for (sym_mkiter(&j, &k->a); (a = sym_next(&j)) != 0; ) + xfree(a->p); + sym_destroy(&k->a); + DESTROY(k); + } + hash_destroy(&f->byid); + sym_destroy(&f->bytype); + sym_destroy(&f->bytag); + + if (f->fp) + fclose(f->fp); + xfree(f->name); +} + +/* --- @key_close@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * + * Returns: A @KWRITE_@ code indicating how it went. + * + * Use: Frees all the key data, writes any changes. Make sure that + * all hell breaks loose if this returns @KWRITE_BROKEN@. + */ + +int key_close(key_file *f) +{ + int e; + + if (f->fp && (e = key_save(f)) != KWRITE_OK) + return (e); + key_discard(f); + return (KWRITE_OK); +} + +/* --- @key_new@ --- + * + * Arguments: @key_file *f@ = pointer to key file + * @uint32 id@ = keyid to set + * @const char *type@ = the type of this key + * @time_t exp@ = when the key expires + * @key *kk@ = where to put the key pointer + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Attaches a new key to a key file. You must have a writable + * key file for this to work. + * + * The type is a key type string. This interface doesn't care + * about how type strings are formatted: it just treats them as + * opaque gobs of text. Clients are advised to choose some + * standard for representing key types, though. + * + * The expiry time should either be a time in the future, or the + * magic value @KEXP_FOREVER@ which means `never expire this + * key'. Be careful with `forever' keys. If I were you, I'd + * use a more sophisticated key management system than this for + * them. + */ + +int key_new(key_file *f, uint32 id, const char *type, time_t exp, key **kk) +{ + key *k = 0; + time_t t = time(0); + int e = KERR_OK; + + /* --- Make sure the file is writable --- */ + + if (!(f->f & KF_WRITE)) + e = KERR_READONLY; + else if (KEY_EXPIRED(t, exp)) + e = KERR_EXPIRED; + else if (key_chkident(type)) + e = KERR_BADTYPE; + else { + k = CREATE(key); + k->id = id; + k->tag = 0; + k->exp = k->del = exp; + k->c = 0; + k->type = (char *)type; /* temporarily */ + sym_create(&k->a); + if ((e = insert(f, k)) != 0) + DESTROY(k); + else { + k->k = key_newstring(KCAT_SHARE, ""); + k->type = xstrdup(type); + *kk = k; + f->f |= KF_MODIFIED; + } + } + + return (e); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/key-misc.c b/key/key-misc.c new file mode 100644 index 0000000..80e9597 --- /dev/null +++ b/key/key-misc.c @@ -0,0 +1,405 @@ +/* -*-c-*- + * + * Simple key management + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "key.h" + +/*----- Useful macros -----------------------------------------------------*/ + +#define KEY_WRITE(f) do { \ + if (!(f)->f & KF_WRITE) \ + return (KERR_READONLY); \ + } while (0) + +#define KEY_MODIFY(f) do { (f)->f |= KF_MODIFIED; } while (0) + +#define KEY_LOAD(n) ((n) * 2) + +/*----- Iteration and iterators -------------------------------------------*/ + +/* --- @key_mkiter@ --- * + * + * Arguments: @key_iter *i@ = pointer to iterator object + * @key_file *f@ = pointer to file structure + * + * Returns: --- + * + * Use: Initializes a key iterator. The keys are returned by + * @key_next@. + */ + +void key_mkiter(key_iter *i, key_file *f) +{ + HASH_MKITER(&i->i, &f->byid); + i->t = time(0); +} + +/* --- @key_next@ --- * + * + * Arguments: @key_iter *i@ = pointer to iterator object + * + * Returns: Pointer to next key, or null. + * + * Use: Returns the next key in some arbitrary sequence. + */ + +key *key_next(key_iter *i) +{ + hash_base *b; + key *k; + do { + HASH_NEXT(&i->i, b); + k = (key *)b; + } while (k && KEY_EXPIRED(i->t, k->exp) && KEY_EXPIRED(i->t, k->del)); + return (k); +} + +/*----- Lookup ------------------------------------------------------------*/ + +/* --- @key_bytype@ --- * + * + * Arguments: @key_file *f@ = key file we want a key from + * @const char *type@ = type string for desired key + * + * Returns: Pointer to the best key to use, or null. + * + * Use: Looks up a key by its type. Returns the key with the latest + * expiry time. This function will not return an expired key. + */ + +key *key_bytype(key_file *f, const char *type) +{ + time_t now = time(0); + key *k; + key_ref *kr; + + if ((kr = sym_find(&f->bytype, type, -1, 0, 0)) == 0) + return (0); + for (k = kr->k; k && KEY_EXPIRED(now, k->exp); k = k->next) + ; + return (k); +} + +/* --- @key_byid@ --- * + * + * Arguments: @key_file *f@ = key file to find a key from + * @uint32 id@ = id to look for + * + * Returns: Key with matching id. + * + * Use: Returns a key given its id. This function will return an + * expired key, but not a deleted one. + */ + +key *key_byid(key_file *f, uint32 id) +{ + time_t t = time(0); + hash_base **bin, *b; + + bin = HASH_BIN(&f->byid, id); + for (b = *bin; b; b = b->next) { + if (b->hash == id) { + key *k = (key *)b; + if (KEY_EXPIRED(t, k->exp) && KEY_EXPIRED(t, k->del)) + return (0); + return (k); + } + } + return (0); +} + +/* --- @key_bytag@ --- * + * + * Arguments: @key_file *f@ = key file to find a key from + * @const char *tag@ = pointer to tag string + * + * Returns: Key with matching id or tag. + * + * Use: Returns a key given its tag or id. This function will return + * an expired key, but not a deleted one. + */ + +key *key_bytag(key_file *f, const char *tag) +{ + time_t t = time(0); + char *p; + uint32 id; + key_ref *kr = sym_find(&f->bytag, tag, -1, 0, 0); + + if (kr && !(KEY_EXPIRED(t, kr->k->exp) && KEY_EXPIRED(t, kr->k->del))) + return (kr->k); + id = strtoul(tag, &p, 16); + if (!*p) + return (key_byid(f, id)); + return (key_bytype(f, tag)); +} + +/* --- @key_qtag@ --- * + * + * Arguments: @key_file *f@ = key file to find a key from + * @const char *tag@ = pointer to tag string + * @dstr *d@ = pointer to string for full tag name + * @key **k@ = where to store the key pointer + * @key_data ***kd@ = where to store the key data pointer + * + * Returns: Zero if OK, nonzero if it failed. + * + * Use: Performs a full lookup on a qualified tag name. The tag is + * qualified by the names of subkeys, separated by dots. Hence, + * a qualified tag is ID|TAG[.TAG...]. The various result + * pointers can be null to indicate that the result isn't + * interesting. + */ + +int key_qtag(key_file *f, const char *tag, dstr *d, key **k, key_data ***kd) +{ + dstr dd = DSTR_INIT; + const char *q; + key *kk; + key_data **kkd; + + /* --- Find the end of the base tag --- */ + + if ((q = strchr(tag, '.')) == 0) + DPUTS(&dd, tag); + else { + DPUTM(&dd, tag, q - tag); + DPUTZ(&dd); + q++; + } + + /* --- Look up the key tag --- */ + + if ((kk = key_bytag(f, dd.buf)) == 0) { + dstr_destroy(&dd); + return (-1); + } + + /* --- Set the various initial bits of result up --- */ + + if (d) + key_fulltag(kk, d); + if (k) + *k = kk; + kkd = &kk->k; + + /* --- Now dig through the rest of the tag --- */ + + if (q) { + while (*q) { + key_struct *ks; + + /* --- Stick on the next bit of the fullqtag --- */ + + DRESET(&dd); + while (*q && *q != '.') { + DPUTC(&dd, *q); + q++; + } + DPUTZ(&dd); + if (d) { + DPUTC(d, '.'); + DPUTD(d, &dd); + } + + /* --- Look up the subkey --- */ + + if ((*kkd)->e != KENC_STRUCT) { + kkd = 0; + break; + } + if ((ks = sym_find(&(*kkd)->u.s, dd.buf, -1, 0, 0)) == 0) { + kkd = 0; + break; + } + kkd = &ks->k; + } + } + + /* --- Return the results --- */ + + dstr_destroy(&dd); + if (!kkd) + return (-1); + if (kd) + *kd = kkd; + return (0); +} + +/*----- Miscellaneous functions -------------------------------------------*/ + +/* --- @key_delete@ --- * + * + * Arguments: @key_file *f@ = pointer to file block + * @key *k@ = key to delete + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Removes the given key from the list. The key file must be + * writable. (Due to the horridness of the data structures, + * deleted keys aren't actually removed, just marked so that + * they can't be looked up or iterated over. One upshot of + * this is that they don't get written back to the file when + * it's closed.) + */ + +int key_delete(key_file *f, key *k) +{ + KEY_WRITE(f); + k->exp = KEXP_EXPIRE; + k->del = KEXP_EXPIRE; + KEY_MODIFY(f); + return (0); +} + +/* --- @key_expired@ --- * + * + * Arguments: @key *k@ = pointer to key block + * + * Returns: Zero if the key is OK, nonzero if it's expired. + */ + +int key_expired(key *k) +{ + time_t now = time(0); + return (KEY_EXPIRED(now, k->exp) || KEY_EXPIRED(now, k->del)); +} + +/* --- @key_expire@ --- * + * + * Arguments: @key_file *f@ = pointer to file block + * @key *k@ = pointer to key block + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Immediately marks the key as expired. It may be removed + * immediately, if it is no longer required, and will be removed + * by a tidy operation when it is no longer required. The key + * file must be writable. + */ + +int key_expire(key_file *f, key *k) +{ + KEY_WRITE(f); + k->exp = KEXP_EXPIRE; + if (k->del == KEXP_FOREVER) + k->del = KEXP_EXPIRE; + KEY_MODIFY(f); + return (0); +} + +/* --- @key_used@ --- * + * + * Arguments: @key_file *f@ = pointer to key file + * @key *k@ = pointer to key block + * @time_t t@ = when key can be removed + * + * Returns: Zero if OK, nonzero on failure. + * + * Use: Marks a key as being required until a given time. Even + * though the key may expire before then (and won't be returned + * by type after that time), it will still be available when + * requested explicitly by id. The key file must be writable. + * + * The only (current) reason for failure is attempting to use + * a key which can expire for something which can't. + */ + +int key_used(key_file *f, key *k, time_t t) +{ + KEY_WRITE(f); + if (t == KEXP_FOREVER) { + if (k->exp != KEXP_FOREVER) + return (KERR_WILLEXPIRE); + } else if (k->del >= t) + return (0); + + k->del = t; + KEY_MODIFY(f); + return (0); +} + +/* --- @key_fingerprint@ --- * + * + * Arguments: @key *k@ = the key to fingerprint + * @ghash *h@ = the hash to use + * @const key_filter *kf@ = filter to apply + * + * Returns: Nonzero if the key slightly matched the filter. + * + * Use: Updates the hash context with the key contents. + */ + +static int abyname(const void *a, const void *b) { + key_attr *const *x = a, *const *y = b; + return (strcmp(SYM_NAME(*x), SYM_NAME(*y))); +} + +int key_fingerprint(key *k, ghash *h, const key_filter *kf) +{ + dstr d = DSTR_INIT; + int rc = 0; + key_attr *a, **v; + size_t n, i; + sym_iter ai; + + if (!key_encode(k->k, &d, kf)) + goto done; + rc = 1; + GH_HASHSTR(h, "catacomb-key-fingerprint:"); + GH_HASHU32(h, k->id); + GH_HASHSTR8(h, k->type); + GH_HASH(h, d.buf, d.len); + for (n = 0, sym_mkiter(&ai, &k->a); (a = sym_next(&ai)) != 0; n++); + if (n) { + v = xmalloc(n * sizeof(*v)); + for (i = 0, sym_mkiter(&ai, &k->a); (a = sym_next(&ai)) != 0; i++) + v[i] = a; + qsort(v, n, sizeof(*v), abyname); + for (i = 0; i < n; i++) { + GH_HASHSTR8(h, SYM_NAME(v[i])); + GH_HASHSTR16(h, v[i]->p); + } + xfree(v); + } +done: + dstr_destroy(&d); + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/key-moan.c b/key/key-moan.c new file mode 100644 index 0000000..cc44770 --- /dev/null +++ b/key/key-moan.c @@ -0,0 +1,53 @@ +/* -*-c-*- + * + * Standard error handling function for key loading + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "key.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @key_moan@ --- * + * + * Arguments: @const char *file@ = name of the file + * @int line@ = line number in file + * @const char *msg@ = error message + * @void *p@ = argument pointer + * + * Returns: --- + * + * Use: Reports an error message about loading a key file. + */ + +void key_moan(const char *file, int line, const char *msg, void *p) +{ + moan("%s:%i: error: %s", file, line, msg); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/key-pack.c b/key/key-pack.c new file mode 100644 index 0000000..61495b9 --- /dev/null +++ b/key/key-pack.c @@ -0,0 +1,247 @@ +/* -*-c-*- + * + * Packing and unpacking key data + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "key-data.h" + +/*----- Generic packing and unpacking -------------------------------------*/ + +/* --- @key_pack@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing structure + * @key_data **kd@ = where to put the key data pointer + * @dstr *d@ = pointer to tag string for the key data + * + * Returns: Error code, or zero. + * + * Use: Packs a key from a data structure. + */ + +int key_pack(key_packdef *kp, key_data **kd, dstr *d) +{ + switch (kp->e & KF_ENCMASK) { + + /* --- Binary and integer keys are easy --- */ + + case KENC_BINARY: { + key_bin *b = kp->p; + *kd = key_newbinary(kp->e, b->k, b->sz); + return (0); + } + case KENC_MP: + *kd = key_newmp(kp->e, *(mp **)kp->p); + return (0); + case KENC_STRING: + *kd = key_newstring(kp->e, *(char **)kp->p); + return (0); + case KENC_EC: + *kd = key_newec(kp->e, (ec *)kp->p); + return (0); + + /* --- Encrypted keys are a little tricky --- * + * + * This works rather differently to unpacking. + */ + + case KENC_ENCRYPT: { + key_data *kkd; + int err = key_pack(kp->p, &kkd, d); + if (!err) { + err = key_plock(kd, kkd, d->buf); + key_drop(kkd); + } + return (err); + } + + /* --- Structured keys, as ever, are a nuisance --- */ + + case KENC_STRUCT: { + int err; + key_packstruct *p; + size_t l = d->len; + + *kd = key_newstruct(); + DPUTC(d, '.'); + for (p = kp->p; p->name; p++) { + key_data *kkd; + d->len = l + 1; + DPUTS(d, p->name); + if ((err = key_pack(&p->kp, &kkd, d)) != 0) { + key_drop(*kd); + return (err); + } + key_structsteal(*kd, p->name, kkd); + } + d->len = l; + d->buf[l] = 0; + return (0); + } + default: + abort(); + } +} + +/* --- @key_unpack@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing structure + * @key_data *kd@ = pointer to source key data + * @dstr *d@ = pointer to tag string for the key data + * + * Returns: Error code, or zero. + * + * Use: Unpacks a key into an appropriate data structure. + */ + +int key_unpack(key_packdef *kp, key_data *kd, dstr *d) +{ + unsigned e = kp->e & KF_ENCMASK; + int err; + + /* --- Decrypt the encrypted key --- */ + + if ((kd->e & KF_ENCMASK) == KENC_ENCRYPT) { + if ((err = key_punlock(&kp->kd, kd, d->buf)) != 0) + goto fail; + kd = kp->kd; + } + + /* --- Ensure that the key has the right type --- */ + + if ((kd->e & KF_ENCMASK) != e) { + err = KERR_WRONGTYPE; + goto fail; + } + + /* --- Unpack the key --- * + * + * Only three possibilities left now. + */ + + switch (e) { + + /* --- Binary and integer keys are easy --- */ + + case KENC_BINARY: + *(key_bin *)kp->p = kd->u.k; + break; + case KENC_MP: + *(mp **)kp->p = kd->u.m; + break; + case KENC_STRING: + *(char **)kp->p = kd->u.p; + break; + case KENC_EC: + *(ec *)kp->p = kd->u.e; + break; + + /* --- Structured keys take a little care --- */ + + case KENC_STRUCT: { + key_packstruct *p, *q; + size_t l = d->len; + + /* --- Iterate over the requested subparts --- */ + + DPUTC(d, '.'); + for (p = kp->p; p->name; p++) { + key_data *kkd; + + /* --- Build the name --- */ + + d->len = l + 1; + DPUTS(d, p->name); + + /* --- Find and unpack the subkey --- */ + + if ((kkd = key_structfind(kd, p->name)) == 0) { + if (!(p->kp.e & KF_OPT)) { + err = KERR_NOTFOUND; + goto tidy; + } + } else if ((err = key_unpack(&p->kp, kkd, d)) != 0) { + p++; + goto tidy; + } + } + + /* --- Done --- */ + + d->len = l; + d->buf[l] = 0; + break; + + /* --- Tidy up if something went wrong --- */ + + tidy: + for (q = kp->p; q < p; q++) + key_unpackdone(&q->kp); + goto fail; + } + + default: + abort(); + } + + return (0); + + /* --- Something went wrong --- */ + +fail: + if (kp->kd) { + key_drop(kp->kd); + kp->kd = 0; + } + return (err); +} + +/* --- @key_unpackdone@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing definition + * + * Returns: --- + * + * Use: Frees the key components contained within a packing + * definition, created during key unpacking. + */ + +void key_unpackdone(key_packdef *kp) +{ + if (kp->kd) { + key_drop(kp->kd); + kp->kd = 0; + } + if ((kp->e & KF_ENCMASK) == KENC_STRUCT) { + key_packstruct *p; + for (p = kp->p; p->name; p++) + key_unpackdone(&p->kp); + } +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/key-pass.c b/key/key-pass.c new file mode 100644 index 0000000..665030e --- /dev/null +++ b/key/key-pass.c @@ -0,0 +1,262 @@ +/* -*-c-*- + * + * Encrypting keys with passphrases + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "key-data.h" +#include "paranoia.h" +#include "passphrase.h" +#include "rand.h" + +#include "blowfish-cbc.h" +#include "rmd160.h" +#include "rmd160-mgf.h" +#include "rmd160-hmac.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- Format --- * + * + * Choose a random 160-bit string %$R$%. Take the passphrase %$P$%, and + * the message %$m$%. Now, compute %$K_E \cat K_T = H(R \cat P)$%, + * %$y_0 = E_{K_E}(m)$% and %$\tau = T_{K_T}(y_0)$%. The ciphertext is + * %$y = N \cat \tau \cat y_0$%. + * + * This is not the original format. The original format was insecure, and + * has been replaced incompatibly. + */ + +/* --- @key_lock@ --- * + * + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const void *e@ = secret to encrypt key with + * @size_t esz@ = size of the secret + * + * Returns: --- + * + * Use: Encrypts a key data block using a secret. + */ + +void key_lock(key_data **kt, key_data *k, const void *e, size_t esz) +{ + dstr d = DSTR_INIT; + octet b[RMD160_HASHSZ * 2]; + octet *m; + size_t msz; + rmd160_mgfctx r; + blowfish_cbcctx c; + rmd160_mackey mk; + rmd160_macctx mc; + + /* --- Sanity check --- */ + + if (k) key_incref(k); else k = *kt; + assert(((void)"Key data is already encrypted", + (k->e & KF_ENCMASK) != KENC_ENCRYPT)); + + /* --- Format the stuff in the buffer --- */ + + DENSURE(&d, RMD160_HASHSZ * 2); + rand_get(RAND_GLOBAL, d.buf, RMD160_HASHSZ); + d.len += RMD160_HASHSZ * 2; + key_encode(k, &d, 0); + m = (octet *)d.buf + RMD160_HASHSZ * 2; + msz = d.len - RMD160_HASHSZ * 2; + + /* --- Hash the passphrase to make a key --- */ + + rmd160_mgfkeybegin(&r); + rmd160_mgfkeyadd(&r, d.buf, RMD160_HASHSZ); + rmd160_mgfkeyadd(&r, e, esz); + rmd160_mgfencrypt(&r, 0, b, sizeof(b)); + BURN(r); + + /* --- Encrypt the plaintext --- */ + + blowfish_cbcinit(&c, b, RMD160_HASHSZ, 0); + blowfish_cbcencrypt(&c, m, m, msz); + BURN(c); + + /* --- MAC the ciphertext --- */ + + rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ); + rmd160_macinit(&mc, &mk); + rmd160_machash(&mc, m, msz); + rmd160_macdone(&mc, d.buf + RMD160_HASHSZ); + BURN(mk); + BURN(mc); + + /* --- Done --- */ + + BURN(b); + *kt = key_newencrypted(0, d.buf, d.len); + key_drop(k); + dstr_destroy(&d); +} + +/* --- @key_unlock@ --- * + * + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const void *e@ = secret to decrypt the block with + * @size_t esz@ = size of the secret + * + * Returns: Zero for success, or a @KERR_@ error code. + * + * Use: Unlocks a key using a secret. + */ + +int key_unlock(key_data **kt, key_data *k, const void *e, size_t esz) +{ + octet b[RMD160_HASHSZ * 2]; + octet *p = 0; + int rc; + int drop = 0; + key_data *kd; + rmd160_mgfctx r; + blowfish_cbcctx c; + rmd160_mackey mk; + rmd160_macctx mc; + size_t sz; + + /* --- Sanity check --- */ + + if (!k) { k = *kt; drop = 1; } + assert(((void)"Key data isn't encrypted", + (k->e & KF_ENCMASK) == KENC_ENCRYPT)); + + /* --- Check the size --- */ + + if (k->u.k.sz < RMD160_HASHSZ * 2) + return (KERR_MALFORMED); + sz = k->u.k.sz - RMD160_HASHSZ * 2; + + /* --- Hash the passphrase to make a key --- */ + + rmd160_mgfkeybegin(&r); + rmd160_mgfkeyadd(&r, k->u.k.k, RMD160_HASHSZ); + rmd160_mgfkeyadd(&r, e, esz); + rmd160_mgfencrypt(&r, 0, b, sizeof(b)); + BURN(r); + + /* --- Verify the MAC --- */ + + rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ); + rmd160_macinit(&mc, &mk); + rmd160_machash(&mc, k->u.k.k + RMD160_HASHSZ * 2, sz); + rmd160_macdone(&mc, b + RMD160_HASHSZ); + if (memcmp(b + RMD160_HASHSZ, k->u.k.k + RMD160_HASHSZ, + RMD160_HASHSZ) != 0) { + rc = KERR_BADPASS; + goto fail; + } + BURN(mk); + BURN(mc); + + /* --- Allocate a destination buffer --- */ + + p = xmalloc(sz); + + /* --- Decrypt the key data --- */ + + blowfish_cbcinit(&c, b, RMD160_HASHSZ, 0); + blowfish_cbcdecrypt(&c, k->u.k.k + RMD160_HASHSZ * 2, p, sz); + BURN(c); + + /* --- Decode the key data into the destination buffer --- */ + + if ((kd = key_decode(p, sz)) == 0) { + rc = KERR_MALFORMED; + goto fail; + } + *kt = kd; + + /* --- Done --- */ + + xfree(p); + if (drop) key_drop(k); + return (0); + + /* --- Tidy up if things went wrong --- */ + +fail: + BURN(b); + xfree(p); + return (rc); +} + +/* --- @key_plock@ --- * + * + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const char *tag@ = tag to use for passphrase + * + * Returns: Zero if successful, a @KERR@ error code on failure. + * + * Use: Locks a key by encrypting it with a passphrase. + */ + +int key_plock(key_data **kt, key_data *k, const char *tag) +{ + char buf[256]; + + if (passphrase_read(tag, PMODE_VERIFY, buf, sizeof(buf))) + return (KERR_IO); + key_lock(kt, k, buf, strlen(buf)); + BURN(buf); + return (0); +} + +/* --- @key_punlock@ --- * + * + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const char *tag@ = tag to use for passphrase + * + * Returns: Zero if it worked, a @KERR_@ error code on failure. + * + * Use: Unlocks a passphrase-locked key. + */ + +int key_punlock(key_data **kt, key_data *k, const char *tag) +{ + char buf[256]; + int rc; + + if (passphrase_read(tag, PMODE_READ, buf, sizeof(buf))) + return (KERR_IO); + rc = key_unlock(kt, k, buf, strlen(buf)); + BURN(buf); + if (rc == KERR_BADPASS || !k) + passphrase_cancel(tag); + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/key-text.c b/key/key-text.c new file mode 100644 index 0000000..98c1fba --- /dev/null +++ b/key/key-text.c @@ -0,0 +1,344 @@ +/* -*-c-*- + * + * Key textual encoding + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "key-data.h" +#include "mp.h" +#include "mptext.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @key_read@ --- * + * + * Arguments: @const char *p@ = pointer to textual key representation + * @char **pp@ = where to store the end pointer + * + * Returns: The newly-read key data, or null if it failed. + * + * Use: Parses a textual key description. + */ + +key_data *key_read(const char *p, char **pp) +{ + unsigned e; + key_data *kd; + + /* --- Read the encoding type --- * + * + * The key format is `[FLAGS:]DATA'. If there is no encoding type + * named, assume that it's `binary' for backwards compatibility. + */ + + if (strchr(p, ':') == 0) + e = 0; + else { + char *q; + if (key_readflags(p, &q, &e, 0)) + return (0); + p = q + 1; + } + + /* --- Now scan the data based on the encoding type --- */ + + switch (e & KF_ENCMASK) { + + /* --- Binary encoding --- * + * + * Simply read out the Base64-encoded data. Since `,' and `]' are our + * delimeter characters, and they can't appear in Base64-encoded data, I + * can just do a simple search to find the end of the encoded data. + */ + + case KENC_BINARY: + case KENC_ENCRYPT: { + dstr d = DSTR_INIT; + base64_ctx b; + size_t sz = strcspn(p, ",]"); + + base64_init(&b); + base64_decode(&b, p, sz, &d); + base64_decode(&b, 0, 0, &d); + kd = key_newbinary(e, d.buf, d.len); + dstr_destroy(&d); + p += sz; + } break; + + /* --- Multiprecision integer encoding --- * + * + * Multiprecision integers have a convenient reading function. + */ + + case KENC_MP: { + char *q; + mp *m = mp_readstring(e & KF_BURN ? MP_NEWSEC : MP_NEW, p, &q, 0); + if (!m) + return (0); + kd = key_newmp(e, m); + MP_DROP(m); + p = q; + } break; + + /* --- String encoding --- * + * + * We use form-urlencoding to ensure that evil characters don't get out. + */ + + case KENC_STRING: { + dstr d = DSTR_INIT; + size_t sz = strcspn(p, ",]"); + const char *l = p + sz; + unsigned int ch; + int x, n; + + while (p < l) { + switch (*p) { + case '+': + DPUTC(&d, ' '); break; + case '%': + x = sscanf(p + 1, "%2x%n", &ch, &n); + if (x == 1) { DPUTC(&d, ch); p += n; break; } + default: + DPUTC(&d, *p); break; + } + p++; + } + DPUTZ(&d); + kd = key_newstring(e, d.buf); + dstr_destroy(&d); + } break; + + /* --- Elliptic curve encoding --- * + * + * Again, we have a convenient function. Assume for now that points + * aren't secret. (Reasonably safe.) + */ + + case KENC_EC: { + ec pt = EC_INIT; + qd_parse qd; + qd.p = p; + qd.e = 0; + if (!ec_ptparse(&qd, &pt)) + return (0); + kd = key_newec(e, &pt); + EC_DESTROY(&pt); + p = qd.p; + } break; + + /* --- Structured information encoding --- * + * + * The format for structured key data is `[NAME=KEY,...]', where the + * brackets are part of the syntax. Structured keys have no flags apart + * from the encoding. + * + * The binary encoding only allows names up to 255 bytes long. Check for + * this here. + */ + + case KENC_STRUCT: { + dstr d = DSTR_INIT; + key_data *nkd; + char *q; + + /* --- Read the opening bracket --- */ + + kd = key_newstruct(); + if (*p != '[') + return (0); + p++; + + /* --- Read named key subparts --- */ + + for (;;) { + size_t sz; + + /* --- Stop if there's a close-bracket --- * + * + * This allows `[]' to be an empty structured key, which is good. It + * also makes `[foo=enc:bar,]' legal, and that's less good but I can + * live with it. + */ + + if (*p == ']') + break; + + /* --- Read the name out and check the length --- */ + + if ((q = strchr(p, '=')) == 0) + goto fail; + sz = q - p; + if (sz >= 256) + goto fail; + DRESET(&d); + DPUTM(&d, p, sz); + DPUTZ(&d); + + /* --- Read the key data for the subkey --- */ + + if ((nkd = key_read(q + 1, &q)) == 0) + goto fail; + key_structsteal(kd, d.buf, nkd); + p = q; + + /* --- Read the comma or close-bracket --- */ + + if (*p == ']') + break; + else if (*p == ',') + p++; + else + goto fail; + } + + /* --- Step past the close bracket --- */ + + p++; + dstr_destroy(&d); + break; + + /* --- Tidy up after a failure --- */ + + fail: + dstr_destroy(&d); + return (0); + } break; + + /* --- Anything else is unknown --- */ + + default: + return (0); + } + + /* --- Return the end pointer --- */ + + kd->e = e; + if (pp) + *pp = (char *)p; + return (kd); +} + +/* --- @key_write@ --- * + * + * Arguments: @key_data *k@ = pointer to key data + * @dstr *d@ = destination string to write on + * @const key_filter *kf@ = pointer to key selection block + * + * Returns: Nonzero if an item was actually written. + * + * Use: Writes a key in a textual encoding. + */ + +int key_write(key_data *k, dstr *d, const key_filter *kf) +{ + int rc = 0; + if (!KEY_MATCH(k, kf)) + return (0); + switch (k->e & KF_ENCMASK) { + case KENC_BINARY: + case KENC_ENCRYPT: { + base64_ctx b; + + if ((k->e & KF_ENCMASK) == KENC_BINARY) + key_writeflags(k->e, d); + else + DPUTS(d, "encrypt,secret"); + DPUTC(d, ':'); + base64_init(&b); + b.indent = ""; + b.maxline = 0; + base64_encode(&b, k->u.k.k, k->u.k.sz, d); + base64_encode(&b, 0, 0, d); + rc = 1; + } break; + case KENC_MP: + key_writeflags(k->e, d); + DPUTC(d, ':'); + mp_writedstr(k->u.m, d, 10); + rc = 1; + break; + case KENC_STRING: { + const char *p = k->u.p; + key_writeflags(k->e, d); + DPUTC(d, ':'); + while (*p) { + if (*p == ' ') DPUTC(d, '+'); + else if (!isalnum((unsigned char)*p)) dstr_putf(d, "%%%02x", *p); + else DPUTC(d, *p); + p++; + } + rc = 1; + } break; + case KENC_EC: + key_writeflags(k->e, d); + DPUTS(d, ":0x"); mp_writedstr(k->u.e.x, d, 16); + DPUTS(d, ",0x"); mp_writedstr(k->u.e.y, d, 16); + rc = 1; + break; + case KENC_STRUCT: { + key_subkeyiter i; + const char *tag; + char del = 0; + size_t n = d->len; + + DPUTS(d, "struct:["); + for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) { + size_t o = d->len; + if (del) + DPUTC(d, del); + DPUTS(d, tag); + DPUTC(d, '='); + if (!key_write(k, d, kf)) + d->len = o; + else { + del = ','; + rc = 1; + } + } + if (!rc) + d->len = n; + else + DPUTC(d, ']'); + } break; + } + DPUTZ(d); + + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/key.h b/key/key.h new file mode 100644 index 0000000..bed3632 --- /dev/null +++ b/key/key.h @@ -0,0 +1,700 @@ +/* -*-c-*- + * + * Simple key management + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_KEY_H +#define CATACOMB_KEY_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include +#include +#include +#include + +#ifndef CATACOMB_KEY_ERROR_H +# include "key-error.h" +#endif + +#ifndef CATACOMB_KEY_DATA_H +# include "key-data.h" +#endif + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- Key attributes --- * + * + * Each attribute is stored as a symbol in a symbol table. The value is + * the plain (not url-encoded) text to be written to the the file. If the + * value is binary data, then by this point it's base-64 encoded. + */ + +typedef struct key_attr { + sym_base _b; /* Symbol table data */ + char *p; /* Pointer to attribute value */ +} key_attr; + +/* --- Main key structure --- * + * + * Each key is stored in two symbol tables, one indexed by keyid, and the + * other indexed by type. Because many keys can have the same type, the type + * table contains a list of keys, sorted in descending order of expiry. + */ + +typedef struct key { + + /* --- Hashtable management --- */ + + hash_base _b; /* Symbol table data */ + struct key *next; /* Next key of the same type */ + + /* --- Basic key attributes --- */ + + uint32 id; /* Key id used to name it */ + char *tag; /* Textual tag name */ + char *type; /* Textual key type */ + time_t exp, del; /* Expiry times for keys */ + + /* --- The key data itself --- */ + + key_data *k; /* The actual key data */ + + /* --- Other attributes and commentary --- */ + + sym_table a; /* Hashtable of key attributes */ + char *c; /* Any additional comments */ +} key; + +/* --- The keys-by-type entries --- */ + +typedef struct key_ref { + sym_base _b; /* Symbol table data */ + key *k; /* Pointer to first key in list */ +} key_ref; + +/* --- A key file --- */ + +typedef struct key_file { + FILE *fp; /* File pointer open on file */ + char *name; /* Filename used to create it */ + unsigned f; /* Various useful flags */ + hash_table byid; /* Table of keys by keyid */ + sym_table bytype; /* Table of keys by type */ + sym_table bytag; /* Table of keys by tag */ + size_t idload; /* Loading on id table */ +} key_file; + +/* --- Key file flags --- */ + +#define KF_WRITE 1u /* File opened for writing */ +#define KF_MODIFIED 2u /* File has been modified */ + +/* --- Iterating over keys --- * + * + * Both of these are simple symbol table iterators, but they're made distinct + * types for the dubious benefits that type safety brings. + */ + +typedef struct { hash_iter i; time_t t; } key_iter; +typedef struct { sym_iter i; } key_attriter; + +/* --- Key fetching --- */ + +typedef struct key_fetchdef { + char *name; /* Name of item */ + size_t off; /* Offset into target structure */ + unsigned e; /* Flags for the item */ + const struct key_fetchdef *kf; /* Substructure pointer */ +} key_fetchdef; + +/* --- File opening options --- */ + +#define KOPEN_READ 0u +#define KOPEN_WRITE 1u +#define KOPEN_MASK 0xff +#define KOPEN_NOFILE 0x100 + +/* --- Various other magic numbers --- */ + +#define KEXP_FOREVER ((time_t)-1) /* Never expire this key */ +#define KEXP_EXPIRE ((time_t)-2) /* Expire this key when unused */ + +/* --- Write error codes --- */ + +enum { + KWRITE_OK, /* Everything went fine */ + KWRITE_FAIL = -1, /* Close attempt failed */ + KWRITE_BROKEN = -2 /* Key ring needs manual fixing */ +}; + +/* --- Error reporting functions for @key_merge@ and @key_open@ --- */ + +typedef void key_reporter(const char */*file*/, int /*line*/, + const char */*err*/, void */*p*/); + +/* --- Macros for testing expiry --- */ + +#define KEY_EXPIRED(now, exp) \ + ((exp) == KEXP_EXPIRE || ((exp) != KEXP_FOREVER && (exp) < (now))) + +/*----- Reading and writing keys and files --------------------------------*/ + +/* --- @key_merge@ --- * + * + * Arguments: @key_file *f@ = pointer to file structure + * @const char *file@ = name of file (for error messages) + * @FILE *fp@ = file handle to read from + * @key_reporter *rep@ = error reporting function + * @void *arg@ = argument for function + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Reads keys from a file, and inserts them into the file. + */ + +extern int key_merge(key_file */*f*/, const char */*file*/, FILE */*fp*/, + key_reporter */*rep*/, void */*arg*/); + +/* --- @key_extract@ --- * + * + * Arguments: @key_file *f@ = pointer to file structure + * @key *k@ = key to extract + * @FILE *fp@ = file to write on + * @const key_filter *kf@ = pointer to key selection block + * + * Returns: Zero if OK, EOF on error. + * + * Use: Extracts a key to an ouptut file. + */ + +extern int key_extract(key_file */*f*/, key */*k*/, FILE */*fp*/, + const key_filter */*kf*/); + +/* --- @key_open@ --- * + * + * Arguments: @key_file *f@ = pointer to file structure to initialize + * @const char *file@ = pointer to the file name + * @unsigned how@ = opening options (@KOPEN_*@). + * @key_reporter *rep@ = error reporting function + * @void *arg@ = argument for function + * + * Returns: Zero if it worked, nonzero otherwise. + * + * Use: Opens a key file, reads its contents, and stores them in a + * structure. The file is locked appropriately until closed + * using @key_close@. On an error, everything is cleared away + * tidily. If the file is opened with @KOPEN_WRITE@, it's + * created if necessary, with read and write permissions for its + * owner only. + */ + +extern int key_open(key_file */*f*/, const char */*file*/, unsigned /*how*/, + key_reporter */*rep*/, void */*arg*/); + +/* --- @key_discard@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * + * Returns: --- + * + * Use: Frees all the key data, without writing changes. + */ + +extern void key_discard(key_file */*f*/); + +/* --- @key_close@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * + * Returns: A @KWRITE_@ code indicating how it went. + * + * Use: Frees all the key data, writes any changes. Make sure that + * all hell breaks loose if this returns @KWRITE_BROKEN@. + */ + +extern int key_close(key_file */*f*/); + +/* --- @key_save@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * + * Returns: A @KWRITE_@ code indicating how well it worked. + * + * Use: Writes a key file's data back to the actual file. This code + * is extremely careful about error handling. It should usually + * be able to back out somewhere sensible, but it can tell when + * it's got itself into a real pickle and starts leaving well + * alone. + * + * Callers, please make sure that you ring alarm bells when this + * function returns @KWRITE_BROKEN@. + */ + +extern int key_save(key_file */*f*/); + +/* --- @key_lockfile@ --- * + * + * Arguments: @key_file *f@ = pointer to file structure to initialize + * @const char *file@ = pointer to the file name + * @unsigned how@ = opening options (@KOPEN_*@). + * + * Returns: Zero if it worked, nonzero otherwise. + * + * Use: Opens a keyfile and stores the information needed for + * continued access in the structure. + * + * If the file is opened with @KOPEN_WRITE@, it's created if + * necessary with read and write permissions for owner only, and + * locked for update while it's open. + * + * This is a system-dependent routine, and only really intended + * for the private use of @key_open@. + */ + +extern int key_lockfile(key_file */*f*/, const char */*file*/, + unsigned /*how*/); + +/*----- Creating and manipulating keys ------------------------------------*/ + +/* --- @key_new@ --- + * + * Arguments: @key_file *f@ = pointer to key file + * @uint32 id@ = keyid to set + * @const char *type@ = the type of this key + * @time_t exp@ = when the key expires + * @key *kk@ = where to put the key pointer + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Attaches a new key to a key file. You must have a writable + * key file for this to work. + * + * The type is a key type string. This interface doesn't care + * about how type strings are formatted: it just treats them as + * opaque gobs of text. Clients are advised to choose some + * standard for representing key types, though. + * + * The expiry time should either be a time in the future, or the + * magic value @KEXP_FOREVER@ which means `never expire this + * key'. Be careful with `forever' keys. If I were you, I'd + * use a more sophisticated key management system than this for + * them. + * + * You have to set the actual key yourself. + */ + +extern int key_new(key_file */*f*/, uint32 /*id*/, const char */*type*/, + time_t /*exp*/, key **/*kk*/); + +/* --- @key_delete@ --- * + * + * Arguments: @key_file *f@ = pointer to file block + * @key *k@ = key to delete + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Removes the given key from the list. The key file must be + * writable. (Due to the horridness of the data structures, + * deleted keys aren't actually removed, just marked so that + * they can't be looked up or iterated over. One upshot of + * this is that they don't get written back to the file when + * it's closed.) + */ + +extern int key_delete(key_file */*f*/, key */*k*/); + +/* --- @key_expired@ --- * + * + * Arguments: @key *k@ = pointer to key block + * + * Returns: Zero if the key is OK, nonzero if it's expired. + */ + +int key_expired(key */*k*/); + +/* --- @key_expire@ --- * + * + * Arguments: @key_file *f@ = pointer to file block + * @key *k@ = pointer to key block + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Immediately marks the key as expired. It may be removed + * immediately, if it is no longer required, and will be removed + * by a tidy operation when it is no longer required. The key + * file must be writable. + */ + +extern int key_expire(key_file */*f*/, key */*k*/); + +/* --- @key_used@ --- * + * + * Arguments: @key_file *f@ = pointer to key file + * @key *k@ = pointer to key block + * @time_t t@ = when key can be removed + * + * Returns: Zero if OK, nonzero on failure. + * + * Use: Marks a key as being required until a given time. Even + * though the key may expire before then (and won't be returned + * by type after that time), it will still be available when + * requested explicitly by id. The key file must be writable. + * + * The only (current) reason for failure is attempting to use + * a key which can expire for something which can't. + */ + +extern int key_used(key_file */*f*/, key */*k*/, time_t /*t*/); + +/* --- @key_fingerprint@ --- * + * + * Arguments: @key *k@ = the key to fingerprint + * @ghash *h@ = the hash to use + * @const key_filter *kf@ = filter to apply + * + * Returns: Nonzero if the key slightly matched the filter. + * + * Use: Updates the hash context with the key contents. + */ + +extern int key_fingerprint(key */*k*/, ghash */*h*/, + const key_filter */*kf*/); + +/*----- Setting and reading attributes ------------------------------------*/ + +/* --- @key_chkident@ --- * + * + * Arguments: @const char *p@ = pointer to a type string + * + * Returns: Zero if OK, -1 on error. + * + * Use: Checks whether an identification component string is OK. + */ + +extern int key_chkident(const char */*p*/); + +/* --- @key_chkcomment@ --- * + * + * Arguments: @const char *p@ = pointer to a comment string + * + * Returns: Zero if OK, -1 on error. + * + * Use: Checks whether a comment string is OK. + */ + +extern int key_chkcomment(const char */*p*/); + +/* --- @key_setcomment@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * @key *k@ = pointer to key block + * @const char *c@ = pointer to comment to set, or zero + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Replaces the key's current comment with a new one. + */ + +extern int key_setcomment(key_file */*f*/, key */*k*/, const char */*c*/); + +/* --- @key_settag@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * @key *k@ = pointer to key block + * @const char *tag@ = pointer to comment to set, or zero + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Replaces the key's current tag with a new one. + */ + +extern int key_settag(key_file */*f*/, key */*k*/, const char */*tag*/); + +/* --- @key_setkeydata@ --- * + * + * Arguments: @key_file *kf@ = pointer to key file + * @key *k@ = pointer to key + * @key_data *kd@ = new key data + * + * Returns: Zero on success, or a @KERR_@ error code on failure. + * + * Use: Sets the key data for a key. + */ + +extern int key_setkeydata(key_file */*kf*/, key */*k*/, key_data */*kd*/); + +/* --- @key_fulltag@ --- * + * + * Arguments: @key *k@ = pointer to key + * @dstr *d@ = pointer to destination string + * + * Returns: --- + * + * Use: Emits the key's full tag, which has the form + * `ID:TYPE[:TAG]'. This is used in the textual file format, + * and to identify passphrases for locked keys. + */ + +extern void key_fulltag(key */*k*/, dstr */*d*/); + +/* --- @key_qtag@ --- * + * + * Arguments: @key_file *f@ = key file to find a key from + * @const char *tag@ = pointer to tag string + * @dstr *d@ = pointer to string for full tag name + * @key **k@ = where to store the key pointer + * @key_data ***kd@ = where to store the key data pointer + * + * Returns: Zero if OK, nonzero if it failed. + * + * Use: Performs a full lookup on a qualified tag name. The tag is + * qualified by the names of subkeys, separated by dots. Hence, + * a qualified tag is ID|TAG[.TAG...]. The various result + * pointers can be null to indicate that the result isn't + * interesting. + */ + +extern int key_qtag(key_file */*f*/, const char */*tag*/, + dstr */*d*/, key **/*k*/, key_data ***/*kd*/); + +/* --- @key_getattr@ --- * + * + * Arguments: @key_file *f@ = pointer to file + * @key *k@ = pointer to key + * @const char *n@ = pointer to attribute name + * + * Returns: Pointer to attribute value, or null if not found. + * + * Use: Returns the value of a key attribute. + */ + +extern const char *key_getattr(key_file */*f*/, key */*k*/, + const char */*n*/); + +/* --- @key_putattr@ --- * + * + * Arguments: @key_file *f@ = pointer to file + * @key *k@ = pointer to key + * @const char *n@ = pointer to attribute name + * @const char *v@ = pointer to attribute value or null + * + * Returns: Error code (one of the @KERR@ constants). + * + * Use: Inserts an attribute on a key. If an attribute with the same + * name already exists, it is deleted. Setting a null value + * removes the attribute. + */ + +extern int key_putattr(key_file */*f*/, key */*k*/, + const char */*n*/, const char */*v*/); + +/* --- @key_mkattriter@ --- * + * + * Arguments: @key_attriter *i@ = pointer to attribute iterator + * @key *k@ = pointer to key + * + * Returns: --- + * + * Use: Initializes an attribute iterator. The attributes are + * returned by @key_nextattr@. + */ + +extern void key_mkattriter(key_attriter */*i*/, key */*k*/); + +/* --- @key_nextattr@ --- * + * + * Arguments: @key_attriter *i@ = pointer to attribute iterator + * @const char **n, **v@ = pointers to name and value + * + * Returns: Zero if no attribute available, or nonzero if returned OK. + * + * Use: Returns the next attribute. + */ + +extern int key_nextattr(key_attriter */*i*/, + const char **/*n*/, const char **/*v*/); + +/*----- Searching and iterating -------------------------------------------*/ + +/* --- @key_bytype@ --- * + * + * Arguments: @key_file *f@ = key file we want a key from + * @const char *type@ = type string for desired key + * + * Returns: Pointer to the best key to use, or null. + * + * Use: Looks up a key by its type. Returns the key with the latest + * expiry time. This function will not return an expired key. + */ + +extern key *key_bytype(key_file */*f*/, const char */*type*/); + +/* --- @key_byid@ --- * + * + * Arguments: @key_file *f@ = key file to find a key from + * @uint32 id@ = id to look for + * + * Returns: Key with matching id. + * + * Use: Returns a key given its id. This function will return an + * expired key, but not a deleted one. + */ + +extern key *key_byid(key_file */*f*/, uint32 /*id*/); + +/* --- @key_bytag@ --- * + * + * Arguments: @key_file *f@ = key file to find a key from + * @const char *tag@ = pointer to tag string + * + * Returns: Key with matching id or tag. + * + * Use: Returns a key given its tag or id. This function will return + * an expired key, but not a deleted one. + */ + +extern key *key_bytag(key_file */*f*/, const char */*tag*/); + +/* --- @key_mkiter@ --- * + * + * Arguments: @key_iter *i@ = pointer to iterator object + * @key_file *f@ = pointer to file structure + * + * Returns: --- + * + * Use: Initializes a key iterator. The keys are returned by + * @key_next@. + */ + +extern void key_mkiter(key_iter */*i*/, key_file */*f*/); + +/* --- @key_next@ --- * + * + * Arguments: @key_iter *i@ = pointer to iterator object + * + * Returns: Pointer to next key, or null. + * + * Use: Returns the next key in some arbitrary sequence. + */ + +extern key *key_next(key_iter */*i*/); + +/*----- Fetching key data conveniently ------------------------------------*/ + +/* --- @key_fetchinit@ --- * + * + * Arguments: @const key_fetchdef *kf@ = pointer to base definition + * @key_packstruct *kps@ = pointer to destination packing def + * @void *p@ = pointer to destination block + * + * Returns: Pointer to packing definition. + * + * Use: Initializes a packing definition (@key_packdef@ structure). + * If @kps@ is null on entry, an appropriately sized block is + * allocated automatically. Otherwise it must be large enough. + */ + +extern key_packdef *key_fetchinit(const key_fetchdef */*kf*/, + key_packstruct */*kp*/, void */*p*/); + +/* --- @key_fetch@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing structure + * @key *k@ = key file containing desired key + * + * Returns: Error code, or zero. + * + * Use: Fetches an unpacked key from a packed one. + */ + +extern int key_fetch(key_packdef */*kp*/, key */*k*/); + +/* --- @key_fetchbyname@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing structure + * @key_file *kf@ = key file containing desired key + * @const char *tag@ = user's tag describing the key + * + * Returns: Error code, or zero. + * + * Use: Fetches a named key from a key file and unpacks it + * conveniently. + */ + +extern int key_fetchbyname(key_packdef */*kp*/, + key_file */*kf*/, const char */*tag*/); + +/* --- @key_fetchdone@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing structure + * + * Returns: --- + * + * Use: Frees a packing structure. If the structure was allocated by + * @key_fetchinit@ then it is freed. + */ + +extern void key_fetchdone(key_packdef */*kp*/); + +/*----- Other functions ---------------------------------------------------*/ + +/* --- @key_moan@ --- * + * + * Arguments: @const char *file@ = name of the file + * @int line@ = line number in file + * @const char *msg@ = error message + * @void *p@ = argument pointer + * + * Returns: --- + * + * Use: Reports an error message about loading a key file. + */ + +extern void key_moan(const char */*file*/, int /*line*/, + const char */*msg*/, void */*p*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/key/passphrase.c b/key/passphrase.c new file mode 100644 index 0000000..6f0780f --- /dev/null +++ b/key/passphrase.c @@ -0,0 +1,164 @@ +/* -*-c-*- + * + * Reading of passphrases (Unix-specific) + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include + +#include + +#include "passphrase.h" +#include "pixie.h" + +/*----- Static variables --------------------------------------------------*/ + +static int fd = -1; +static unsigned flags = 0; + +#define f_fail 1u + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @passphrase_connect@ --- + * + * Arguments: @const char *sock@ = socket name to connect to, or null for + * default + * + * Returns: Zero if OK, nonzero if it failed + * + * Use: Attempts to connect to the passphrase pixie. + */ + +int passphrase_connect(const char *sock) +{ + if (fd != -1) + close(fd); + if ((fd = pixie_open(sock)) < 0) { + flags |= f_fail; + return (-1); + } + flags &= ~f_fail; + return (0); +} + +static int pconn(void) +{ + if (fd != -1) + return (0); + if (flags & f_fail) + return (-1); + return (passphrase_connect(0)); +} + +/* --- @passphrase_read@ --- * + * + * Arguments: @const char *tag@ = pointer to passphrase tag string + * @unsigned mode@ = reading mode + * @char *buf@ = pointer to destination buffer + * @size_t sz@ = size of destination buffer + * + * Returns: Zero if successful, nonzero on failure. + * + * Use: Reads a passphrase from the user, using some system-specific + * secure mechanism. The mechanism may keep a cache of + * passphrases, so the user may not necessarily be prompted. + */ + +int passphrase_read(const char *tag, unsigned mode, char *buf, size_t sz) +{ + dstr d = DSTR_INIT; + int rc = 1; + + /* --- Try talking to the pixie --- */ + + if (!pconn()) { + rc = pixie_read(fd, tag, mode, buf, sz); + if (rc < 0) { + close(fd); + fd = -1; + return (-1); + } + if (rc == 0) + return (0); + } + + /* --- Read from the terminal --- */ + + dstr_putf(&d, "%s %s: ", + mode == PMODE_READ ? "Passphrase" : "New passphrase", + tag); + if (pixie_getpass(d.buf, buf, sz)) + goto fail; + if (mode == PMODE_VERIFY) { + char b[1024]; + DRESET(&d); + dstr_putf(&d, "Verify passphrase %s: ", tag); + if (pixie_getpass(d.buf, b, sizeof(b)) || strcmp(b, buf) != 0) { + memset(b, 0, sizeof(b)); + goto fail; + } + } + dstr_destroy(&d); + + /* --- If the pixie is interested, tell it the new passphrase --- */ + + if (fd >= 0) + pixie_set(fd, tag, buf); + return (0); + + /* --- Tidy up after a failure --- */ + +fail: + dstr_destroy(&d); + memset(buf, 0, sz); + return (-1); +} + +/* --- @passphrase_cancel@ --- * + * + * Arguments: @const char *tag@ = pointer to passphrase tag string + * + * Returns: --- + * + * Use: Attempts to make the passphrase cache forget about a + * particular passphrase. This may be useful if the passphrase + * turns out to be wrong, or if the user is attempting to change + * the passphrase. + */ + +void passphrase_cancel(const char *tag) +{ + if (!pconn()) + pixie_cancel(fd, tag); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key/passphrase.h b/key/passphrase.h new file mode 100644 index 0000000..876df70 --- /dev/null +++ b/key/passphrase.h @@ -0,0 +1,103 @@ +/* -*-c-*- + * + * Reading passphrases + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_PASSPHRASE_H +#define CATACOMB_PASSPHRASE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +/*----- Data structures ---------------------------------------------------*/ + +/* --- Passphrase modes --- * + * + * @PMODE_VERIFY@ requests that the passphrase be repeated to make sure it's + * right. + */ + +enum { + PMODE_READ, + PMODE_VERIFY +}; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @passphrase_connect@ --- + * + * Arguments: @const char *sock@ = socket name to connect to, or null for + * default + * + * Returns: Zero if OK, nonzero if it failed + * + * Use: Attempts to connect to the passphrase pixie. + */ + +extern int passphrase_connect(const char */*sock*/); + +/* --- @passphrase_read@ --- * + * + * Arguments: @const char *tag@ = pointer to passphrase tag string + * @unsigned mode@ = reading mode + * @char *buf@ = pointer to destination buffer + * @size_t sz@ = size of destination buffer + * + * Returns: Zero if successful, nonzero on failure. + * + * Use: Reads a passphrase from the user, using some system-specific + * secure mechanism. The mechanism may keep a cache of + * passphrases, so the user may not necessarily be prompted. + */ + +extern int passphrase_read(const char */*tag*/, unsigned /*mode*/, + char */*buf*/, size_t /*sz*/); + +/* --- @passphrase_cancel@ --- * + * + * Arguments: @const char *tag@ = pointer to passphrase tag string + * + * Returns: --- + * + * Use: Attempts to make the passphrase cache forget about a + * particular passphrase. This may be useful if the passphrase + * turns out to be wrong, or if the user is attempting to change + * the passphrase. + */ + +extern void passphrase_cancel(const char */*tag*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/key/pixie-common.c b/key/pixie-common.c new file mode 100644 index 0000000..f24b576 --- /dev/null +++ b/key/pixie-common.c @@ -0,0 +1,374 @@ +/* -*-c-*- + * + * Common code for Pixie client and server (Unix-specific) + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "pixie.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @pixie_address@ --- * + * + * Arguments: @const char *sock@ = pointer to socket name + * @size_t *psz@ = where to write the address size + * + * Returns: Pointer to filled-in Unix-domain socket address. + * + * Use: Returns a Unix-domain socket address to use to find the + * passphrase pixie. + */ + +struct sockaddr_un *pixie_address(const char *sock, size_t *psz) +{ + dstr d = DSTR_INIT; + + /* --- Get the default socket path if none specified --- */ + + if (!sock) + sock = getenv("CATACOMB_PIXIE_SOCKET"); + if (!sock) + sock = "%h/.catacomb/pixie"; + + /* --- Substitute interesting sequences in the path --- */ + + { + const char *q, *qq; + + q = sock; + for (;;) { + qq = strchr(q, '%'); + if (!qq || !qq[1]) { + DPUTS(&d, q); + break; + } + DPUTM(&d, q, qq - q); + q = qq + 1; + switch (*q) { + case 'u': + qq = getenv("USER"); + if (!qq) + qq = getenv("LOGNAME"); + if (!qq) { + struct passwd *pw = getpwuid(getuid()); + if (pw) + qq = pw->pw_name; + else + qq = ""; + } + DPUTS(&d, qq); + break; + case 'h': + qq = getenv("HOME"); + if (!qq) { + struct passwd *pw = getpwuid(getuid()); + if (pw) + qq = pw->pw_dir; + else + qq = ""; + } + DPUTS(&d, qq); + break; + default: + DPUTC(&d, '%'); + DPUTC(&d, *q); + break; + } + q++; + } + DPUTZ(&d); + } + + /* --- Allocate and initialize the socket address --- */ + + { + struct sockaddr_un *sun; + size_t bsz = offsetof(struct sockaddr_un, sun_path); + *psz = bsz + d.len + 1; + sun = xmalloc(bsz + d.len + 1); + memset(sun, 0, bsz); + sun->sun_family = AF_UNIX; + memcpy(sun->sun_path, d.buf, d.len + 1); + dstr_destroy(&d); + return (sun); + } +} + +/* --- @pixie_fdline@ --- * + * + * Arguments: @int fd@ = file descriptor to read from + * @char *buf@ = pointer to buffer + * @size_t sz@ = size of buffer + * + * Returns: --- + * + * Use: Reads a line from a file descriptor. The read is done one + * character at a time. If the entire line won't fit, the end + * is truncated. The line is null terminated. + */ + +void pixie_fdline(int fd, char *buf, size_t sz) +{ + char *p = buf; + char *q = p + sz - 1; + + for (;;) { + char c; + if (read(fd, &c, 1) < 1) + break; + if (c == '\n') + break; + if (p < q) + *p++ = c; + } + *p = 0; +} + +/* --- @pixie_getpass@ --- * + * + * Arguments: @const char *prompt@ = pointer to prompt string + * @char *buf@ = pointer to buffer + * @size_t sz@ = size of buffer + * + * Returns: Zero if it worked OK, nonzero otherwise. + * + * Use: Reads a passphrase from the terminal or some other requested + * source. + */ + +int pixie_getpass(const char *prompt, char *buf, size_t sz) +{ + const char *pfd = getenv("CATACOMB_PASSPHRASE_FD"); + int fd = 0; + + /* --- See whether a terminal is what's wanted --- */ + + if (pfd) { + fd = atoi(pfd); + pixie_fdline(fd, buf, sz); + } else { + struct termios ta; + struct termios ota; + char nl = '\n'; + + if ((fd = open("/dev/tty", O_RDWR)) < 0) + goto fail_0; + if (tcgetattr(fd, &ta) < 0) + goto fail_1; + ota = ta; + ta.c_lflag &= ~(ECHO | ISIG); + if (tcsetattr(fd, TCSAFLUSH, &ta)) + goto fail_1; + write(fd, prompt, strlen(prompt)); + pixie_fdline(fd, buf, sz); + tcsetattr(fd, TCSAFLUSH, &ota); + write(fd, &nl, 1); + close(fd); + } + return (0); + + /* --- Tidy up if things went wrong --- */ + +fail_1: + close(fd); +fail_0: + return (-1); +} + +/* --- @pixie_open@ --- * + * + * Arguments: @const char *sock@ = path to pixie socket + * + * Returns: Less than zero if it failed, or file descriptor. + * + * Use: Opens a connection to a passphrase pixie. + */ + +int pixie_open(const char *sock) +{ + struct sockaddr_un *sun; + size_t sz; + int fd; + + /* --- Open the connection --- */ + + if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) + goto fail_0; + sun = pixie_address(sock, &sz); + if (connect(fd, (struct sockaddr *)sun, sz)) + goto fail_1; + xfree(sun); + return (fd); + + /* --- Tidy up if things went wrong --- */ + +fail_1: + xfree(sun); + close(fd); +fail_0: + return (-1); +} + +/* --- @pixie_read@ --- * + * + * Arguments: @int fd@ = connection to passphrase pixie + * @const char *tag@ = pointer to tag string + * @unsigned mode@ = reading mode + * @char *buf@ = pointer to destination buffer + * @size_t sz@ = size of the buffer + * + * Returns: Zero if all went well, @-1@ if the read fails, @+1@ to + * request the passphrase from the user. + * + * Use: Reads a passphrase from the pixie. + */ + +int pixie_read(int fd, const char *tag, unsigned mode, char *buf, size_t sz) +{ + dstr d = DSTR_INIT; + char *p, *q; + + /* --- Send the request --- */ + + dstr_putf(&d, "%s %s\n", mode == PMODE_READ ? "PASS" : "VERIFY", tag); + write(fd, d.buf, d.len); + dstr_destroy(&d); + + /* --- Sort out the result --- */ + +again: + pixie_fdline(fd, buf, sz); + p = buf; + if ((q = str_getword(&p)) == 0) + return (-1); + if (strcmp(q, "INFO") == 0) + goto again; + else if (strcmp(q, "MISSING") == 0) + return (+1); + else if (strcmp(q, "OK") != 0) + return (-1); + + /* --- Return the final answer --- */ + + if (p) + memmove(buf, p, strlen(p) + 1); + else + *buf = 0; + return (0); +} + +/* --- @pixie_set@ --- * + * + * Arguments: @int fd@ = pixie file descriptor + * @const char *tag@ = pointer to tag string + * @const char *phrase@ = pointer to passphrase string + * + * Returns: --- + * + * Use: Sends a passphrase to the passphrase pixie. + */ + +void pixie_set(int fd, const char *tag, const char *phrase) +{ + dstr d = DSTR_INIT; + char buf[16]; + size_t sz = strlen(phrase); + char nl = '\n'; + char *p, *q; + + /* --- Send the request --- * + * + * I didn't want to copy it out of the caller's buffer. @writev@ may + * produce a copy, too, so I didn't do that either. + */ + + dstr_putf(&d, "SET %s -- ", tag); + write(fd, d.buf, d.len); + write(fd, phrase, sz); + write(fd, &nl, 1); + dstr_destroy(&d); + + /* --- Pick up the pieces --- */ + +again: + pixie_fdline(fd, buf, sizeof(buf)); + p = buf; + if ((q = str_getword(&p)) != 0 && strcmp(q, "INFO") == 0) + goto again; +} + +/* --- @pixie_cancel@ --- * + * + * Arguments: @int fd@ = pixie file descriptor + * @const char *tag@ = pointer to tag string + * + * Returns: --- + * + * Use: Cancels a passphrase if it turns out to be bogus. + */ + +void pixie_cancel(int fd, const char *tag) +{ + dstr d = DSTR_INIT; + char buf[16]; + char *p, *q; + + /* --- Send the request --- */ + + dstr_putf(&d, "FLUSH %s\n", tag); + write(fd, d.buf, d.len); + dstr_destroy(&d); + + /* --- Sort out the result --- */ + +again: + pixie_fdline(fd, buf, sizeof(buf)); + p = buf; + if ((q = str_getword(&p)) != 0 && strcmp(q, "INFO") == 0) + goto again; +} + +/*----- That's all, folks -------------------------------------------------*/ + diff --git a/key/pixie.h b/key/pixie.h new file mode 100644 index 0000000..bfda993 --- /dev/null +++ b/key/pixie.h @@ -0,0 +1,216 @@ +/* -*-c-*- + * + * Passphrase pixie definitions (Unix-specific) + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_PIXIE_H +#define CATACOMB_PIXIE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include +#include + +#ifndef CATACOMB_PASSPHRASE_H +# include "passphrase.h" +#endif + +/*----- Protocol definition -----------------------------------------------* + * + * The protocol is simple and text-based. The client connects to the + * server's socket and sends `request lines', each of which elicits one or + * more `response lines' from the server. Request and response lines contain + * whitespace-separated fields, and are terminated by a single linefeed. The + * final field on a line may contain whitespace. The first field describes + * the type of the line. The type field is not case-sensitive, although + * writing them in uppercase is conventional. + * + * The requests are: + * + * HELP + * Provide (very) brief help with the pixie protocol. + * + * LIST + * Return a list of passphrases currently stored, together with expiry + * information. + * + * PASS tag [expire] + * Request the passphrase named `tag' from the pixie. + * + * VERIFY tag [expire] + * Request a new passphrase, which therefore requires verification. + * + * SET tag [expire] -- phrase + * Set the value of passphrase `tag'. This will usually be a follow-up + * to a MISSING response. + * + * FLUSH [tag] + * Flush the passphrase named `tag', or all passphrases, from memory. + * + * QUIT + * Requests that the pixie close down. + * + * Response lines are as follows: + * + * OK [phrase] + * Request completed successfully. If a passphrase was requested, it is + * returned by the pixie. This is the final response to a request. + * + * MISSING + * The passphrase requested is not known, and no requester mechanism is + * present. The client should request the passphrase itself and pass it + * back to the pixie. This is the final response to a request. + * + * FAIL error + * Reports an error. The message given is intended to be + * human-readable. This is the final response to a request. + * + * INFO message + * Reports a human-readable informational message. Further responses + * follow. + * + * ITEM tag expires + * Reports a passphrase in response to a LIST request. One ITEM + * response is given for each passphrase currently in memory. An OK or + * FAIL response follows the last ITEM. + * + * Expiry times in requests may be given in any format acceptable to + * `getdate'. Expiry times in responses are returned in ISO format + * (YYYY-MM-DD HH:MM:SS ZZZ) and are expressed relative to local time. + */ + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @pixie_open@ --- * + * + * Arguments: @const char *sock@ = path to pixie socket + * + * Returns: Less than zero if it failed, or file descriptor. + * + * Use: Opens a connection to a passphrase pixie. + */ + +extern int pixie_open(const char */*sock*/); + +/* --- @pixie_read@ --- * + * + * Arguments: @int fd@ = connection to passphrase pixie + * @const char *tag@ = pointer to tag string + * @unsigned mode@ = reading mode + * @char *buf@ = pointer to destination buffer + * @size_t sz@ = size of the buffer + * + * Returns: Zero if all went well, @-1@ if the read fails, @+1@ to + * request the passphrase from the user. + * + * Use: Reads a passphrase from the pixie. + */ + +extern int pixie_read(int /*fd*/, const char */*tag*/, unsigned /*mode*/, + char */*buf*/, size_t /*sz*/); + +/* --- @pixie_set@ --- * + * + * Arguments: @int fd@ = pixie file descriptor + * @const char *tag@ = pointer to tag string + * @const char *phrase@ = pointer to passphrase string + * + * Returns: --- + * + * Use: Sends a passphrase to the passphrase pixie. + */ + +extern void pixie_set(int /*fd*/, const char */*tag*/, + const char */*phrase*/); + +/* --- @pixie_cancel@ --- * + * + * Arguments: @int fd@ = pixie file descriptor + * @const char *tag@ = pointer to tag string + * + * Returns: --- + * + * Use: Cancels a passphrase if it turns out to be bogus. + */ + +extern void pixie_cancel(int /*fd*/, const char */*tag*/); + +/* --- @pixie_address@ --- * + * + * Arguments: @const char *sock@ = pointer to socket name + * @size_t *psz@ = where to write the address size + * + * Returns: Pointer to filled-in Unix-domain socket address. + * + * Use: Returns a Unix-domain socket address to use to find the + * passphrase pixie. + */ + +extern struct sockaddr_un *pixie_address(const char */*sock*/, + size_t */*psz*/); + +/* --- @pixie_fdline@ --- * + * + * Arguments: @int fd@ = file descriptor to read from + * @char *buf@ = pointer to buffer + * @size_t sz@ = size of buffer + * + * Returns: --- + * + * Use: Reads a line from a file descriptor. The read is done one + * character at a time. If the entire line won't fit, the end + * is truncated. The line is null terminated. + */ + +extern void pixie_fdline(int /*fd*/, char */*buf*/, size_t /*sz*/); + +/* --- @pixie_getpass@ --- * + * + * Arguments: @const char *prompt@ = pointer to prompt string + * @char *buf@ = pointer to buffer + * @size_t sz@ = size of buffer + * + * Returns: Zero if it worked OK, nonzero otherwise. + * + * Use: Reads a passphrase from the terminal or some other requested + * source. + */ + +extern int pixie_getpass(const char */*prompt*/, + char */*buf*/, size_t /*sz*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/keycheck-mp.c b/keycheck-mp.c deleted file mode 100644 index 580d608..0000000 --- a/keycheck-mp.c +++ /dev/null @@ -1,88 +0,0 @@ -/* -*-c-*- - * - * $Id: keycheck-mp.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Key consistency checking tools for large integers - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "fibrand.h" -#include "grand.h" -#include "keycheck.h" -#include "mp.h" -#include "mprand.h" -#include "pfilt.h" -#include "pgen.h" -#include "rabin.h" -#include "rand.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @keycheck_prime@ --- * - * - * Arguments: @keycheck *kc@ = keycheck state - * @unsigned sev@ = severity if not prime - * @mp *m@ = a number to check for primality - * @const char *name@ = name of this number - * - * Returns: Zero if OK, or return status from function. - * - * Use: Checks that a number is prime. - */ - -int keycheck_prime(keycheck *kc, unsigned sev, mp *m, const char *name) -{ - int rc; - - rc = pfilt_smallfactor(m); - if (rc == PGEN_TRY) { - rabin rn; - grand *r = fibrand_create(0); - unsigned n; - mp *x = MP_NEW; - - r->ops->misc(r, GRAND_SEEDRAND, &rand_global); - n = rabin_iters(mp_bits(m)); - rabin_create(&rn, m); - do { - x = mprand_range(x, m, r, 0); - rc = rabin_test(&rn, x); - n--; - } while (n && rc == PGEN_PASS); - rabin_destroy(&rn); - mp_drop(x); - r->ops->destroy(r); - } - if (rc != PGEN_FAIL) - rc = 0; - else - rc = keycheck_report(kc, sev, "%s not prime", name); - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/keycheck-report.c b/keycheck-report.c deleted file mode 100644 index c69a6ae..0000000 --- a/keycheck-report.c +++ /dev/null @@ -1,61 +0,0 @@ -/* -*-c-*- - * - * $Id: keycheck-report.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * A standard reporter function - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "keycheck.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @keycheck_stdreport@ --- * - * - * Arguments: @unsigned sev@ = problem severity - * @const char *msg@ = message to report - * @void *p@ = an uninteresting pointer - * - * Returns: Zero. - * - * Use: Reports a message to stderr. - */ - -int keycheck_stdreport(unsigned sev, const char *msg, void *p) -{ - static const char *const sevtab[] = { - "informational", "warning", "error" - }; - keycheck_reportctx *r = p; - if (r && sev < r->sev) - return (0); - fprintf(r ? r->fp : stderr, "keycheck: %s: %s\n", sevtab[sev], msg); - return (0); -} - -/*----- that's all, folks -------------------------------------------------*/ diff --git a/keycheck.c b/keycheck.c deleted file mode 100644 index 0025f98..0000000 --- a/keycheck.c +++ /dev/null @@ -1,110 +0,0 @@ -/* -*-c-*- - * - * $Id: keycheck.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Framework for checking consistency of keys - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#include "keycheck.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @keycheck_report@ --- * - * - * Arguments: @keycheck *kc@ = keycheck state - * @unsigned sev@ = severity of this report - * @const char *msg@ = message to send along - * @...@ = things to fill the message in with - * - * Returns: Zero to continue, or nonzero to stop and give up. - * - * Use: Reports a message to the user function. - */ - -int keycheck_report(keycheck *kc, unsigned sev, const char *msg, ...) -{ - int rc; - va_list ap; - dstr d = DSTR_INIT; - - kc->sev[sev]++; - va_start(ap, msg); - dstr_vputf(&d, msg, &ap); - va_end(ap); - rc = kc->func ? kc->func(sev, d.buf, kc->p) : 0; - dstr_destroy(&d); - return (rc); -} - -/* --- @keycheck_init@ --- * - * - * Arguments: @keycheck *kc@ = pointer to block to initialize - * @int (*func)(unsigned sev, const char *msg, void *p)@ = - * handler function for problems - * @void *p@ = pointer to give to handler - * - * Returns: --- - * - * Use: Initializes a key checking context. - */ - -void keycheck_init(keycheck *kc, - int (*func)(unsigned /*sev*/, - const char */*msg*/, - void */*p*/), - void *p) -{ - unsigned i; - kc->func = func; - kc->p = p; - for (i = 0; i < KCSEV_MAX; i++) - kc->sev[i] = 0; -} - -/* --- @keycheck_allclear@ --- * - * - * Arguments: @keycheck *kc@ = pointer to keycheck context - * @unsigned sev@ = minimum severity to care about - * - * Returns: Nonzero if no problems of @sev@ or above were noticed. - */ - -int keycheck_allclear(keycheck *kc, unsigned sev) -{ - while (sev < KCSEV_MAX) { - if (kc->sev[sev]) - return (0); - sev++; - } - return (1); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/keycheck.h b/keycheck.h deleted file mode 100644 index b80ceeb..0000000 --- a/keycheck.h +++ /dev/null @@ -1,148 +0,0 @@ -/* -*-c-*- - * - * $Id: keycheck.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Framework for checking consistency of keys - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_KEYCHECK_H -#define CATACOMB_KEYCHECK_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -enum { - KCSEV_ALL, - KCSEV_INFO = KCSEV_ALL, - KCSEV_WARN, - KCSEV_ERR, - KCSEV_MAX -}; - -typedef struct keycheck { - unsigned sev[KCSEV_MAX]; - int (*func)(unsigned /*sev*/, const char */*msg*/, void */*p*/); - void *p; -} keycheck; - -typedef struct keycheck_reportctx { - FILE *fp; - unsigned sev; -} keycheck_reportctx; - -/*----- Generic functions -------------------------------------------------*/ - -/* --- @keycheck_report@ --- * - * - * Arguments: @keycheck *kc@ = keycheck state - * @unsigned sev@ = severity of this report - * @const char *msg@ = message to send along - * @...@ = things to fill the message in with - * - * Returns: Zero to continue, or nonzero to stop and give up. - * - * Use: Reports a message to the user function. - */ - -extern int keycheck_report(keycheck */*kc*/, unsigned /*sev*/, - const char */*msg*/, ...); - -/* --- @keycheck_init@ --- * - * - * Arguments: @keycheck *kc@ = pointer to block to initialize - * @int (*func)(unsigned sev, const char *msg, void *p)@ = - * handler function for problems - * @void *p@ = pointer to give to handler - * - * Returns: --- - * - * Use: Initializes a key checking context. - */ - -extern void keycheck_init(keycheck */*kc*/, - int (*/*func*/)(unsigned /*sev*/, - const char */*msg*/, - void */*p*/), - void */*p*/); - -/* --- @keycheck_allclear@ --- * - * - * Arguments: @keycheck *kc@ = pointer to keycheck context - * @unsigned sev@ = minimum severity to care about - * - * Returns: Nonzero if no problems of @sev@ or above were noticed. - */ - -extern int keycheck_allclear(keycheck */*kc*/, unsigned /*sev*/); - -/*----- A standard report function ----------------------------------------*/ - -/* --- @keycheck_stdreport@ --- * - * - * Arguments: @unsigned sev@ = problem severity - * @const char *msg@ = message to report - * @void *p@ = pointer to a @keycheck_reportctx@ structure - * - * Returns: Zero. - * - * Use: Reports a message to stderr. - */ - -extern int keycheck_stdreport(unsigned /*sev*/, - const char */*msg*/, void */*p*/); - -/*----- Special support functions for large integers ----------------------*/ - -/* --- @keycheck_prime@ --- * - * - * Arguments: @keycheck *kc@ = keycheck state - * @unsigned sev@ = severity if not prime - * @mp *m@ = a number to check for primality - * @const char *name@ = name of this number - * - * Returns: Zero if OK, or return status from function. - * - * Use: Checks that a number is prime. - */ - -extern int keycheck_prime(keycheck */*kc*/, unsigned /*sev*/, - mp */*m*/, const char */*name*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/keysz.c b/keysz.c deleted file mode 100644 index ccc0769..0000000 --- a/keysz.c +++ /dev/null @@ -1,83 +0,0 @@ -/* -*-c-*- - * - * $Id: keysz.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * General block cipher utilities - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "gcipher.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @keysz@ --- * - * - * Arguments: @size_t sz@ = a proposed key size, or zero - * @const octet *ksz@ = pointer to key size table - * - * Returns: See below. - * - * Use: Returns a sensible key size. If @sz@ is nonzero, it is - * interpreted as an amount (in bytes) of key material which the - * caller has available, and the return value is either the - * largest allowable key size less than or equal to the caller's - * size, or zero if there is no valid key length small enough. - * If @sz@ is zero, the function returns a `recommended' key - * size. - */ - -size_t keysz(size_t sz, const octet *ksz) -{ - if (sz == 0) - return (ksz[1]); - else switch (ksz[0]) { - case KSZ_ANY: - return (sz); - case KSZ_RANGE: - if (ksz[4]) - sz -= sz % ksz[4]; - if (sz < ksz[2]) - return (0); - if (ksz[3] && sz > ksz[3]) - return (ksz[3]); - return (sz); - case KSZ_SET: { - unsigned q = 0; - for (ksz++; *ksz; ksz++) { - if (sz >= *ksz && q < *ksz) - q = *ksz; - } - return (q); - } - } - - assert(((void)"bad key size table", 0)); - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/keyutil.c b/keyutil.c deleted file mode 100644 index cca075f..0000000 --- a/keyutil.c +++ /dev/null @@ -1,2308 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Simple key manager program - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _FILE_OFFSET_BITS 64 - -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "bintab.h" -#include "bbs.h" -#include "dh.h" -#include "dsa.h" -#include "dsarand.h" -#include "ec.h" -#include "ec-keys.h" -#include "ectab.h" -#include "fibrand.h" -#include "getdate.h" -#include "gfreduce.h" -#include "key.h" -#include "mp.h" -#include "mpmont.h" -#include "mprand.h" -#include "mptext.h" -#include "pgen.h" -#include "ptab.h" -#include "rsa.h" - -#include "cc.h" -#include "sha-mgf.h" -#include "sha256-mgf.h" -#include "sha224-mgf.h" -#include "sha384-mgf.h" -#include "sha512-mgf.h" -#include "tiger-mgf.h" -#include "rmd128-mgf.h" -#include "rmd160-mgf.h" -#include "rmd256-mgf.h" -#include "rmd320-mgf.h" -#include "md5-mgf.h" -#include "dsarand.h" - -/*----- Handy global state ------------------------------------------------*/ - -static const char *keyfile = "keyring"; - -/*----- Useful shared functions -------------------------------------------*/ - -/* --- @doopen@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * @unsigned how@ = method to open file with - * - * Returns: --- - * - * Use: Opens a key file and handles errors by panicking - * appropriately. - */ - -static void doopen(key_file *f, unsigned how) -{ - if (key_open(f, keyfile, how, key_moan, 0)) - die(1, "couldn't open keyring `%s': %s", keyfile, strerror(errno)); -} - -/* --- @doclose@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * - * Returns: --- - * - * Use: Closes a key file and handles errors by panicking - * appropriately. - */ - -static void doclose(key_file *f) -{ - switch (key_close(f)) { - case KWRITE_FAIL: - die(EXIT_FAILURE, "couldn't write file `%s': %s", - keyfile, strerror(errno)); - case KWRITE_BROKEN: - die(EXIT_FAILURE, "keyring file `%s' broken: %s (repair manually)", - keyfile, strerror(errno)); - } -} - -/* --- @setattr@ --- * - * - * Arguments: @key_file *f@ = pointer to key file block - * @key *k@ = pointer to key block - * @char *v[]@ = array of assignments (overwritten!) - * - * Returns: --- - * - * Use: Applies the attribute assignments to the key. - */ - -static void setattr(key_file *f, key *k, char *v[]) -{ - while (*v) { - int err; - char *p = *v; - size_t eq = strcspn(p, "="); - if (!p[eq]) { - moan("invalid assignment: `%s' (ignored)", p); - v++; - continue; - } - p[eq] = 0; - p += eq + 1; - if ((err = key_putattr(f, k, *v, *p ? p : 0)) != 0) - die(EXIT_FAILURE, "couldn't set attributes: %s", key_strerror(err)); - v++; - } -} - -/*----- Seeding -----------------------------------------------------------*/ - -const struct seedalg { const char *p; grand *(*gen)(const void *, size_t); } -seedtab[] = { - { "dsarand", dsarand_create }, - { "rmd128-mgf", rmd128_mgfrand }, - { "rmd160-mgf", rmd160_mgfrand }, - { "rmd256-mgf", rmd256_mgfrand }, - { "rmd320-mgf", rmd320_mgfrand }, - { "sha-mgf", sha_mgfrand }, - { "sha224-mgf", sha224_mgfrand }, - { "sha256-mgf", sha256_mgfrand }, - { "sha384-mgf", sha384_mgfrand }, - { "sha512-mgf", sha512_mgfrand }, - { "tiger-mgf", tiger_mgfrand }, - { 0, 0 } -}; - -#define SEEDALG_DEFAULT (seedtab + 2) - -/*----- Key generation ----------------------------------------------------*/ - -/* --- Key generation parameters --- */ - -typedef struct keyopts { - key_file *kf; /* Pointer to key file */ - key *k; /* Pointer to the actual key */ - dstr tag; /* Full tag name for the key */ - unsigned f; /* Flags for the new key */ - unsigned bits, qbits; /* Bit length for the new key */ - const char *curve; /* Elliptic curve name/info */ - grand *r; /* Random number source */ - key *p; /* Parameters key-data */ -} keyopts; - -#define f_bogus 1u /* Error in parsing */ -#define f_lock 2u /* Passphrase-lock private key */ -#define f_quiet 4u /* Don't show a progress indicator */ -#define f_limlee 8u /* Generate Lim-Lee primes */ -#define f_subgroup 16u /* Generate a subgroup */ -#define f_retag 32u /* Remove any existing tag */ -#define f_kcdsa 64u /* Generate KCDSA primes */ - -/* --- @dolock@ --- * - * - * Arguments: @keyopts *k@ = key generation options - * @key_data **kd@ = pointer to key data to lock - * @const char *t@ = tag suffix or null - * - * Returns: --- - * - * Use: Does passphrase locking on new keys. - */ - -static void dolock(keyopts *k, key_data **kd, const char *t) -{ - if (!(k->f & f_lock)) - return; - if (t) - dstr_putf(&k->tag, ".%s", t); - if (key_plock(kd, 0, k->tag.buf)) - die(EXIT_FAILURE, "couldn't lock key"); -} - -/* --- @copyparam@ --- * - * - * Arguments: @keyopts *k@ = pointer to key options - * @const char **pp@ = checklist of parameters - * - * Returns: Nonzero if parameters copied; zero if you have to generate - * them. - * - * Use: Copies parameters from a source key to the current one. - */ - -static int copyparam(keyopts *k, const char **pp) -{ - key_filter kf; - key_attriter i; - key_data *kd; - const char *n, *v; - - kf.f = KCAT_SHARE; - kf.m = KF_CATMASK; - - /* --- Quick check if no parameters supplied --- */ - - if (!k->p) - return (0); - - /* --- Run through the checklist --- */ - - while (*pp) { - key_data *kd = key_structfind(k->p->k, *pp); - if (!kd) - die(EXIT_FAILURE, "bad parameter key: parameter `%s' not found", *pp); - if (!KEY_MATCH(kd, &kf)) - die(EXIT_FAILURE, "bad parameter key: subkey `%s' is not shared", *pp); - pp++; - } - - /* --- Copy over the parameters --- */ - - kd = key_copydata(k->p->k, &kf); - assert(kd); - key_setkeydata(k->kf, k->k, kd); - key_drop(kd); - - /* --- Copy over attributes --- */ - - for (key_mkattriter(&i, k->p); key_nextattr(&i, &n, &v); ) - key_putattr(k->kf, k->k, n, v); - - /* --- Done --- */ - - return (1); -} - -/* --- @getmp@ --- * - * - * Arguments: @key_data *k@ = pointer to key data block - * @const char *tag@ = tag string to use - * - * Returns: Pointer to multiprecision integer key item. - * - * Use: Fetches an MP key component. - */ - -static mp *getmp(key_data *k, const char *tag) -{ - k = key_structfind(k, tag); - if (!k) - die(EXIT_FAILURE, "unexpected failure looking up subkey `%s'", tag); - if ((k->e & KF_ENCMASK) != KENC_MP) - die(EXIT_FAILURE, "subkey `%s' has an incompatible type"); - return (k->u.m); -} - -/* --- @keyrand@ --- * - * - * Arguments: @key_file *kf@ = pointer to key file - * @const char *id@ = pointer to key id (or null) - * - * Returns: --- - * - * Use: Keys the random number generator. - */ - -static void keyrand(key_file *kf, const char *id) -{ - key *k; - - /* --- Find the key --- */ - - if (id) { - if ((k = key_bytag(kf, id)) == 0) - die(EXIT_FAILURE, "key `%s' not found", id); - } else - k = key_bytype(kf, "catacomb-rand"); - - if (k) { - key_data *kd = k->k, *kkd; - key_incref(kd); - - again: - switch (kd->e & KF_ENCMASK) { - case KENC_BINARY: - break; - case KENC_ENCRYPT: { - dstr d = DSTR_INIT; - key_fulltag(k, &d); - if (key_punlock(&kkd, kd, d.buf)) - die(EXIT_FAILURE, "error unlocking key `%s'", d.buf); - dstr_destroy(&d); - key_drop(kd); - kd = kkd; - } goto again; - default: { - dstr d = DSTR_INIT; - key_fulltag(k, &d); - die(EXIT_FAILURE, "bad encoding type for key `%s'", d.buf); - } break; - } - - /* --- Key the generator --- */ - - rand_key(RAND_GLOBAL, kd->u.k.k, kd->u.k.sz); - key_drop(kd); - } -} - -/* --- Key generation algorithms --- */ - -static void alg_binary(keyopts *k) -{ - unsigned sz; - unsigned m; - key_data *kd; - octet *p; - - if (!k->bits) - k->bits = 128; - if (k->p) - die(EXIT_FAILURE, "no shared parameters for binary keys"); - - sz = (k->bits + 7) >> 3; - p = sub_alloc(sz); - m = (1 << (((k->bits - 1) & 7) + 1)) - 1; - k->r->ops->fill(k->r, p, sz); - *p &= m; - kd = key_newbinary(KCAT_SYMM | KF_BURN, p, sz); - memset(p, 0, sz); - dolock(k, &kd, 0); - key_setkeydata(k->kf, k->k, kd); - key_drop(kd); - sub_free(p, sz); -} - -static void alg_des(keyopts *k) -{ - unsigned sz; - octet *p; - key_data *kd; - int i; - - if (!k->bits) - k->bits = 168; - if (k->p) - die(EXIT_FAILURE, "no shared parameters for DES keys"); - if (k->bits % 56 || k->bits > 168) - die(EXIT_FAILURE, "DES keys must be 56, 112 or 168 bits long"); - - sz = k->bits / 7; - p = sub_alloc(sz); - k->r->ops->fill(k->r, p, sz); - for (i = 0; i < sz; i++) { - octet x = p[i] | 0x01; - x = x ^ (x >> 4); - x = x ^ (x >> 2); - x = x ^ (x >> 1); - p[i] = (p[i] & 0xfe) | (x & 0x01); - } - kd = key_newbinary(KCAT_SYMM | KF_BURN, p, sz); - memset(p, 0, sz); - dolock(k, &kd, 0); - key_setkeydata(k->kf, k->k, kd); - key_drop(kd); - sub_free(p, sz); -} - -static void alg_rsa(keyopts *k) -{ - rsa_priv rp; - key_data *kd, *kkd; - - /* --- Sanity checking --- */ - - if (k->p) - die(EXIT_FAILURE, "no shared parameters for RSA keys"); - if (!k->bits) - k->bits = 1024; - - /* --- Generate the RSA parameters --- */ - - if (rsa_gen(&rp, k->bits, k->r, 0, - (k->f & f_quiet) ? 0 : pgen_ev, 0)) - die(EXIT_FAILURE, "RSA key generation failed"); - - /* --- Run a test encryption --- */ - - { - grand *g = fibrand_create(k->r->ops->word(k->r)); - rsa_pub rpp; - mp *m = mprand_range(MP_NEW, rp.n, g, 0); - mp *c; - - rpp.n = rp.n; - rpp.e = rp.e; - c = rsa_qpubop(&rpp, MP_NEW, m); - c = rsa_qprivop(&rp, c, c, g); - - if (!MP_EQ(c, m)) - die(EXIT_FAILURE, "test encryption failed"); - mp_drop(c); - mp_drop(m); - g->ops->destroy(g); - } - - /* --- Allrighty then --- */ - - kd = key_newstruct(); - key_structsteal(kd, "n", key_newmp(KCAT_PUB, rp.n)); - key_structsteal(kd, "e", key_newmp(KCAT_PUB, rp.e)); - - kkd = key_newstruct(); - key_structsteal(kkd, "d", key_newmp(KCAT_PRIV | KF_BURN, rp.d)); - key_structsteal(kkd, "p", key_newmp(KCAT_PRIV | KF_BURN, rp.p)); - key_structsteal(kkd, "q", key_newmp(KCAT_PRIV | KF_BURN, rp.q)); - key_structsteal(kkd, "q-inv", key_newmp(KCAT_PRIV | KF_BURN, rp.q_inv)); - key_structsteal(kkd, "d-mod-p", key_newmp(KCAT_PRIV | KF_BURN, rp.dp)); - key_structsteal(kkd, "d-mod-q", key_newmp(KCAT_PRIV | KF_BURN, rp.dq)); - dolock(k, &kkd, "private"); - key_structsteal(kd, "private", kkd); - key_setkeydata(k->kf, k->k, kd); - key_drop(kd); - rsa_privfree(&rp); -} - -static void alg_dsaparam(keyopts *k) -{ - static const char *pl[] = { "q", "p", "g", 0 }; - if (!copyparam(k, pl)) { - dsa_param dp; - octet *p; - size_t sz; - dstr d = DSTR_INIT; - base64_ctx c; - key_data *kd; - dsa_seed ds; - - /* --- Choose appropriate bit lengths if necessary --- */ - - if (!k->qbits) - k->qbits = 160; - if (!k->bits) - k->bits = 1024; - - /* --- Allocate a seed block --- */ - - sz = (k->qbits + 7) >> 3; - p = sub_alloc(sz); - k->r->ops->fill(k->r, p, sz); - - /* --- Allocate the parameters --- */ - - if (dsa_gen(&dp, k->qbits, k->bits, 0, p, sz, &ds, - (k->f & f_quiet) ? 0 : pgen_ev, 0)) - die(EXIT_FAILURE, "DSA parameter generation failed"); - - /* --- Store the parameters --- */ - - kd = key_newstruct(); - key_structsteal(kd, "q", key_newmp(KCAT_SHARE, dp.q)); - key_structsteal(kd, "p", key_newmp(KCAT_SHARE, dp.p)); - key_structsteal(kd, "g", key_newmp(KCAT_SHARE, dp.g)); - mp_drop(dp.q); - mp_drop(dp.p); - mp_drop(dp.g); - key_setkeydata(k->kf, k->k, kd); - key_drop(kd); - - /* --- Store the seed for future verification --- */ - - base64_init(&c); - c.maxline = 0; - c.indent = ""; - base64_encode(&c, ds.p, ds.sz, &d); - base64_encode(&c, 0, 0, &d); - DPUTZ(&d); - key_putattr(k->kf, k->k, "seed", d.buf); - DRESET(&d); - dstr_putf(&d, "%u", ds.count); - key_putattr(k->kf, k->k, "count", d.buf); - xfree(ds.p); - sub_free(p, sz); - dstr_destroy(&d); - } -} - -static void alg_dsa(keyopts *k) -{ - mp *q, *p, *g; - mp *x, *y; - mpmont mm; - key_data *kd, *kkd; - - /* --- Get the shared parameters --- */ - - alg_dsaparam(k); - key_split(&k->k->k); kd = k->k->k; - q = getmp(kd, "q"); - p = getmp(kd, "p"); - g = getmp(kd, "g"); - - /* --- Choose a private key --- */ - - x = mprand_range(MP_NEWSEC, q, k->r, 0); - mpmont_create(&mm, p); - y = mpmont_exp(&mm, MP_NEW, g, x); - - /* --- Store everything away --- */ - - key_structsteal(kd, "y", key_newmp(KCAT_PUB, y)); - - kkd = key_newstruct(); - key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x)); - dolock(k, &kkd, "private"); - key_structsteal(kd, "private", kkd); - - mp_drop(x); mp_drop(y); -} - -static void alg_dhparam(keyopts *k) -{ - static const char *pl[] = { "p", "q", "g", 0 }; - key_data *kd; - if (!copyparam(k, pl)) { - dh_param dp; - int rc; - - if (k->curve) { - qd_parse qd; - group *g; - const char *e; - - if (strcmp(k->curve, "list") == 0) { - unsigned i, w; - LIST("Built-in prime fields", stdout, ptab[i].name, ptab[i].name); - exit(0); - } - qd.p = k->curve; - if (dh_parse(&qd, &dp)) - die(EXIT_FAILURE, "error in field spec: %s", qd.e); - if (!qd_eofp(&qd)) - die(EXIT_FAILURE, "junk at end of field spec"); - if ((g = group_prime(&dp)) == 0) - die(EXIT_FAILURE, "invalid prime field"); - if (!(k->f & f_quiet) && (e = G_CHECK(g, &rand_global)) != 0) - moan("WARNING! group check failed: %s", e); - G_DESTROYGROUP(g); - goto done; - } - - if (!k->bits) - k->bits = 1024; - - /* --- Choose a large safe prime number --- */ - - if (k->f & f_limlee) { - mp **f; - size_t nf; - if (!k->qbits) - k->qbits = 256; - rc = dh_limlee(&dp, k->qbits, k->bits, - (k->f & f_subgroup) ? DH_SUBGROUP : 0, - 0, k->r, (k->f & f_quiet) ? 0 : pgen_ev, 0, - (k->f & f_quiet) ? 0 : pgen_evspin, 0, &nf, &f); - if (!rc) { - dstr d = DSTR_INIT; - size_t i; - for (i = 0; i < nf; i++) { - if (i) - dstr_puts(&d, ", "); - mp_writedstr(f[i], &d, 10); - mp_drop(f[i]); - } - key_putattr(k->kf, k->k, "factors", d.buf); - dstr_destroy(&d); - } - } else if (k->f & f_kcdsa) { - if (!k->qbits) - k->qbits = 256; - rc = dh_kcdsagen(&dp, k->qbits, k->bits, 0, - 0, k->r, (k->f & f_quiet) ? 0 : pgen_ev, 0); - if (!rc) { - dstr d = DSTR_INIT; - mp *v = MP_NEW; - - mp_writedstr(dp.q, &d, 10); - mp_div(&v, 0, dp.p, dp.q); - v = mp_lsr(v, v, 1); - dstr_puts(&d, ", "); - mp_writedstr(v, &d, 10); - mp_drop(v); - key_putattr(k->kf, k->k, "factors", d.buf); - dstr_destroy(&d); - } - } else - rc = dh_gen(&dp, k->qbits, k->bits, 0, k->r, - (k->f & f_quiet) ? 0 : pgen_ev, 0); - - if (rc) - die(EXIT_FAILURE, "Diffie-Hellman parameter generation failed"); - - done: - kd = key_newstruct(); - key_structsteal(kd, "p", key_newmp(KCAT_SHARE, dp.p)); - key_structsteal(kd, "q", key_newmp(KCAT_SHARE, dp.q)); - key_structsteal(kd, "g", key_newmp(KCAT_SHARE, dp.g)); - mp_drop(dp.q); - mp_drop(dp.p); - mp_drop(dp.g); - key_setkeydata(k->kf, k->k, kd); - key_drop(kd); - } -} - -static void alg_dh(keyopts *k) -{ - mp *x, *y; - mp *p, *q, *g; - mpmont mm; - key_data *kd, *kkd; - - /* --- Get the shared parameters --- */ - - alg_dhparam(k); - key_split(&k->k->k); kd = k->k->k; - p = getmp(kd, "p"); - q = getmp(kd, "q"); - g = getmp(kd, "g"); - - /* --- Choose a suitable private key --- * - * - * Since %$g$% has order %$q$%, choose %$x < q$%. - */ - - x = mprand_range(MP_NEWSEC, q, k->r, 0); - - /* --- Compute the public key %$y = g^x \bmod p$% --- */ - - mpmont_create(&mm, p); - y = mpmont_exp(&mm, MP_NEW, g, x); - mpmont_destroy(&mm); - - /* --- Store everything away --- */ - - key_structsteal(kd, "y", key_newmp(KCAT_PUB, y)); - - kkd = key_newstruct(); - key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x)); - dolock(k, &kkd, "private"); - key_structsteal(kd, "private", kkd); - - mp_drop(x); mp_drop(y); -} - -static void alg_bbs(keyopts *k) -{ - bbs_priv bp; - key_data *kd, *kkd; - - /* --- Sanity checking --- */ - - if (k->p) - die(EXIT_FAILURE, "no shared parameters for Blum-Blum-Shub keys"); - if (!k->bits) - k->bits = 1024; - - /* --- Generate the BBS parameters --- */ - - if (bbs_gen(&bp, k->bits, k->r, 0, - (k->f & f_quiet) ? 0 : pgen_ev, 0)) - die(EXIT_FAILURE, "Blum-Blum-Shub key generation failed"); - - /* --- Allrighty then --- */ - - kd = key_newstruct(); - key_structsteal(kd, "n", key_newmp(KCAT_PUB, bp.n)); - - kkd = key_newstruct(); - key_structsteal(kkd, "p", key_newmp(KCAT_PRIV | KF_BURN, bp.p)); - key_structsteal(kkd, "q", key_newmp(KCAT_PRIV | KF_BURN, bp.q)); - dolock(k, &kkd, "private"); - key_structsteal(kd, "private", kkd); - key_setkeydata(k->kf, k->k, kd); - key_drop(kd); - - bbs_privfree(&bp); -} - -static void alg_binparam(keyopts *k) -{ - static const char *pl[] = { "p", "q", "g", 0 }; - if (!copyparam(k, pl)) { - gbin_param gb; - qd_parse qd; - group *g; - const char *e; - key_data *kd; - - /* --- Decide on a field --- */ - - if (!k->bits) k->bits = 128; - if (k->curve && strcmp(k->curve, "list") == 0) { - unsigned i, w; - LIST("Built-in binary fields", stdout, - bintab[i].name, bintab[i].name); - exit(0); - } - if (!k->curve) { - if (k->bits <= 40) k->curve = "p1363-40"; - else if (k->bits <= 56) k->curve = "p1363-56"; - else if (k->bits <= 64) k->curve = "p1363-64"; - else if (k->bits <= 80) k->curve = "p1363-80"; - else if (k->bits <= 112) k->curve = "p1363-112"; - else if (k->bits <= 128) k->curve = "p1363-128"; - else { - die(EXIT_FAILURE, - "no built-in binary fields provide %u-bit security", - k->bits); - } - } - - /* --- Check it --- */ - - qd.e = 0; - qd.p = k->curve; - if (dhbin_parse(&qd, &gb)) - die(EXIT_FAILURE, "error in field spec: %s", qd.e); - if (!qd_eofp(&qd)) - die(EXIT_FAILURE, "junk at end of field spec"); - if ((g = group_binary(&gb)) == 0) - die(EXIT_FAILURE, "invalid binary field"); - if (!(k->f & f_quiet) && (e = G_CHECK(g, &rand_global)) != 0) - moan("WARNING! group check failed: %s", e); - G_DESTROYGROUP(g); - - /* --- Write out the answer --- */ - - kd = key_newstruct(); - key_structsteal(kd, "p", key_newmp(KCAT_SHARE, gb.p)); - key_structsteal(kd, "q", key_newmp(KCAT_SHARE, gb.q)); - key_structsteal(kd, "g", key_newmp(KCAT_SHARE, gb.g)); - mp_drop(gb.q); - mp_drop(gb.p); - mp_drop(gb.g); - key_setkeydata(k->kf, k->k, kd); - key_drop(kd); - } -} - -static void alg_bin(keyopts *k) -{ - mp *x, *y; - mp *p, *q, *g; - gfreduce r; - key_data *kd, *kkd; - - /* --- Get the shared parameters --- */ - - alg_binparam(k); - key_split(&k->k->k); kd = k->k->k; - p = getmp(kd, "p"); - q = getmp(kd, "q"); - g = getmp(kd, "g"); - - /* --- Choose a suitable private key --- * - * - * Since %$g$% has order %$q$%, choose %$x < q$%. - */ - - x = mprand_range(MP_NEWSEC, q, k->r, 0); - - /* --- Compute the public key %$y = g^x \bmod p$% --- */ - - gfreduce_create(&r, p); - y = gfreduce_exp(&r, MP_NEW, g, x); - gfreduce_destroy(&r); - - /* --- Store everything away --- */ - - key_structsteal(kd, "y", key_newmp(KCAT_PUB, y)); - - kkd = key_newstruct(); - key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x)); - dolock(k, &kkd, "private"); - key_structsteal(kd, "private", kkd); - - mp_drop(x); mp_drop(y); -} - -static void alg_ecparam(keyopts *k) -{ - static const char *pl[] = { "curve", 0 }; - if (!copyparam(k, pl)) { - ec_info ei; - const char *e; - key_data *kd; - - /* --- Decide on a curve --- */ - - if (!k->bits) k->bits = 256; - if (k->curve && strcmp(k->curve, "list") == 0) { - unsigned i, w; - LIST("Built-in elliptic curves", stdout, - ectab[i].name, ectab[i].name); - exit(0); - } - if (!k->curve) { - if (k->bits <= 56) k->curve = "secp112r1"; - else if (k->bits <= 64) k->curve = "secp128r1"; - else if (k->bits <= 80) k->curve = "secp160r1"; - else if (k->bits <= 96) k->curve = "secp192r1"; - else if (k->bits <= 112) k->curve = "secp224r1"; - else if (k->bits <= 128) k->curve = "secp256r1"; - else if (k->bits <= 192) k->curve = "secp384r1"; - else if (k->bits <= 256) k->curve = "secp521r1"; - else - die(EXIT_FAILURE, "no built-in curves provide %u-bit security", - k->bits); - } - - /* --- Check it --- */ - - if ((e = ec_getinfo(&ei, k->curve)) != 0) - die(EXIT_FAILURE, "error in curve spec: %s", e); - if (!(k->f & f_quiet) && (e = ec_checkinfo(&ei, k->r)) != 0) - moan("WARNING! curve check failed: %s", e); - ec_freeinfo(&ei); - - /* --- Write out the answer --- */ - - kd = key_newstruct(); - key_structsteal(kd, "curve", key_newstring(KCAT_SHARE, k->curve)); - key_setkeydata(k->kf, k->k, kd); - key_drop(kd); - } -} - -static void alg_ec(keyopts *k) -{ - key_data *kd; - key_data *kkd; - mp *x = MP_NEW; - ec p = EC_INIT; - const char *e; - ec_info ei; - - /* --- Get the curve --- */ - - alg_ecparam(k); - key_split(&k->k->k); kd = k->k->k; - if ((kkd = key_structfind(kd, "curve")) == 0) - die(EXIT_FAILURE, "unexpected failure looking up subkey `curve')"); - if ((kkd->e & KF_ENCMASK) != KENC_STRING) - die(EXIT_FAILURE, "subkey `curve' is not a string"); - if ((e = ec_getinfo(&ei, kkd->u.p)) != 0) - die(EXIT_FAILURE, "error in curve spec: %s", e); - - /* --- Invent a private exponent and compute the public key --- */ - - x = mprand_range(MP_NEWSEC, ei.r, k->r, 0); - ec_mul(ei.c, &p, &ei.g, x); - - /* --- Store everything away --- */ - - key_structsteal(kd, "p", key_newec(KCAT_PUB, &p)); - - kkd = key_newstruct(); - key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x)); - dolock(k, &kkd, "private"); - key_structsteal(kd, "private", kkd); - - /* --- Done --- */ - - ec_freeinfo(&ei); - mp_drop(x); -} - -/* --- The algorithm tables --- */ - -typedef struct keyalg { - const char *name; - void (*proc)(keyopts *o); - const char *help; -} keyalg; - -static keyalg algtab[] = { - { "binary", alg_binary, "Plain binary data" }, - { "des", alg_des, "Binary with DES-style parity" }, - { "rsa", alg_rsa, "RSA public-key encryption" }, - { "bbs", alg_bbs, "Blum-Blum-Shub generator" }, - { "dsa", alg_dsa, "DSA digital signatures" }, - { "dsa-param", alg_dsaparam, "DSA shared parameters" }, - { "dh", alg_dh, "Diffie-Hellman key exchange" }, - { "dh-param", alg_dhparam, "Diffie-Hellman parameters" }, - { "bindh", alg_bin, "DH over a binary field" }, - { "bindh-param", alg_binparam, "Binary-field DH parameters" }, - { "ec-param", alg_ecparam, "Elliptic curve parameters" }, - { "ec", alg_ec, "Elliptic curve crypto" }, - { 0, 0 } -}; - -/* --- @cmd_add@ --- */ - -static int cmd_add(int argc, char *argv[]) -{ - key_file f; - time_t exp = KEXP_EXPIRE; - uint32 kid = rand_global.ops->word(&rand_global); - const char *tag = 0, *ptag = 0; - const char *c = 0; - keyalg *alg = algtab; - const char *rtag = 0; - const struct seedalg *sa = SEEDALG_DEFAULT; - keyopts k = { 0, 0, DSTR_INIT, 0, 0, 0, 0, 0 }; - const char *seed = 0; - k.r = &rand_global; - - /* --- Parse options for the subcommand --- */ - - for (;;) { - static struct option opt[] = { - { "algorithm", OPTF_ARGREQ, 0, 'a' }, - { "bits", OPTF_ARGREQ, 0, 'b' }, - { "qbits", OPTF_ARGREQ, 0, 'B' }, - { "parameters", OPTF_ARGREQ, 0, 'p' }, - { "expire", OPTF_ARGREQ, 0, 'e' }, - { "comment", OPTF_ARGREQ, 0, 'c' }, - { "tag", OPTF_ARGREQ, 0, 't' }, - { "rand-id", OPTF_ARGREQ, 0, 'R' }, - { "key-id", OPTF_ARGREQ, 0, 'I' }, - { "curve", OPTF_ARGREQ, 0, 'C' }, - { "seedalg", OPTF_ARGREQ, 0, 'A' }, - { "seed", OPTF_ARGREQ, 0, 's' }, - { "newseed", OPTF_ARGREQ, 0, 'n' }, - { "lock", 0, 0, 'l' }, - { "quiet", 0, 0, 'q' }, - { "lim-lee", 0, 0, 'L' }, - { "subgroup", 0, 0, 'S' }, - { "kcdsa", 0, 0, 'K' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+a:b:B:p:e:c:t:R:I:C:A:s:n:lqrLKS", - opt, 0, 0, 0); - if (i < 0) - break; - - /* --- Handle the various options --- */ - - switch (i) { - - /* --- Read an algorithm name --- */ - - case 'a': { - keyalg *a; - size_t sz = strlen(optarg); - - if (strcmp(optarg, "list") == 0) { - for (a = algtab; a->name; a++) - printf("%-10s %s\n", a->name, a->help); - return (0); - } - - alg = 0; - for (a = algtab; a->name; a++) { - if (strncmp(optarg, a->name, sz) == 0) { - if (a->name[sz] == 0) { - alg = a; - break; - } else if (alg) - die(EXIT_FAILURE, "ambiguous algorithm name `%s'", optarg); - else - alg = a; - } - } - if (!alg) - die(EXIT_FAILURE, "unknown algorithm name `%s'", optarg); - } break; - - /* --- Bits must be nonzero and a multiple of 8 --- */ - - case 'b': { - char *p; - k.bits = strtoul(optarg, &p, 0); - if (k.bits == 0 || *p != 0) - die(EXIT_FAILURE, "bad bitlength `%s'", optarg); - } break; - - case 'B': { - char *p; - k.qbits = strtoul(optarg, &p, 0); - if (k.qbits == 0 || *p != 0) - die(EXIT_FAILURE, "bad bitlength `%s'", optarg); - } break; - - /* --- Parameter selection --- */ - - case 'p': - ptag = optarg; - break; - - /* --- Expiry dates get passed to @get_date@ for parsing --- */ - - case 'e': - if (strcmp(optarg, "forever") == 0) - exp = KEXP_FOREVER; - else { - exp = get_date(optarg, 0); - if (exp == -1) - die(EXIT_FAILURE, "bad expiry date `%s'", optarg); - } - break; - - /* --- Store comments without interpretation --- */ - - case 'c': - if (key_chkcomment(optarg)) - die(EXIT_FAILURE, "bad comment string `%s'", optarg); - c = optarg; - break; - - /* --- Elliptic curve parameters --- */ - - case 'C': - k.curve = optarg; - break; - - /* --- Store tags --- */ - - case 't': - if (key_chkident(optarg)) - die(EXIT_FAILURE, "bad tag string `%s'", optarg); - tag = optarg; - break; - case 'r': - k.f |= f_retag; - break; - - /* --- Seeding --- */ - - case 'A': { - const struct seedalg *ss; - if (strcmp(optarg, "list") == 0) { - printf("Seed algorithms:\n"); - for (ss = seedtab; ss->p; ss++) - printf(" %s\n", ss->p); - exit(0); - } - if (seed) die(EXIT_FAILURE, "seed already set -- put -A first"); - sa = 0; - for (ss = seedtab; ss->p; ss++) { - if (strcmp(optarg, ss->p) == 0) - sa = ss; - } - if (!sa) - die(EXIT_FAILURE, "seed algorithm `%s' not known", optarg); - } break; - - case 's': { - base64_ctx b; - dstr d = DSTR_INIT; - if (seed) die(EXIT_FAILURE, "seed already set"); - base64_init(&b); - base64_decode(&b, optarg, strlen(optarg), &d); - base64_decode(&b, 0, 0, &d); - k.r = sa->gen(d.buf, d.len); - seed = optarg; - dstr_destroy(&d); - } break; - - case 'n': { - base64_ctx b; - dstr d = DSTR_INIT; - char *p; - unsigned n = strtoul(optarg, &p, 0); - if (n == 0 || *p != 0 || n % 8 != 0) - die(EXIT_FAILURE, "bad seed length `%s'", optarg); - if (seed) die(EXIT_FAILURE, "seed already set"); - n /= 8; - p = xmalloc(n); - rand_get(RAND_GLOBAL, p, n); - base64_init(&b); - base64_encode(&b, p, n, &d); - base64_encode(&b, 0, 0, &d); - seed = d.buf; - k.r = sa->gen(p, n); - } break; - - /* --- Key id --- */ - - case 'I': { - char *p; - unsigned long id; - - errno = 0; - id = strtoul(optarg, &p, 16); - if (errno || *p || id > MASK32) - die(EXIT_FAILURE, "bad key-id `%s'", optarg); - kid = id; - } break; - - /* --- Other flags --- */ - - case 'R': - rtag = optarg; - break; - case 'l': - k.f |= f_lock; - break; - case 'q': - k.f |= f_quiet; - break; - case 'L': - k.f |= f_limlee; - break; - case 'K': - k.f |= f_kcdsa; - break; - case 'S': - k.f |= f_subgroup; - break; - - /* --- Other things are bogus --- */ - - default: - k.f |= f_bogus; - break; - } - } - - /* --- Various sorts of bogosity --- */ - - if ((k.f & f_bogus) || optind + 1 > argc) { - die(EXIT_FAILURE, - "Usage: add [OPTIONS] TYPE [ATTR...]"); - } - if (key_chkident(argv[optind])) - die(EXIT_FAILURE, "bad key type `%s'", argv[optind]); - - /* --- Set up various bits of the state --- */ - - if (exp == KEXP_EXPIRE) - exp = time(0) + 14 * 24 * 60 * 60; - - /* --- Open the file and create the basic key block --- * - * - * Keep on generating keyids until one of them doesn't collide. - */ - - doopen(&f, KOPEN_WRITE); - k.kf = &f; - - /* --- Key the generator --- */ - - keyrand(&f, rtag); - - for (;;) { - int err; - if ((err = key_new(&f, kid, argv[optind], exp, &k.k)) == 0) - break; - else if (err != KERR_DUPID) - die(EXIT_FAILURE, "error adding new key: %s", key_strerror(err)); - } - - /* --- Set various simple attributes --- */ - - if (tag) { - int err; - key *kk; - if (k.f & f_retag) { - if ((kk = key_bytag(&f, tag)) != 0 && - kk->tag && - strcmp(kk->tag, tag) == 0) - key_settag(&f, kk, 0); - } - if ((err = key_settag(&f, k.k, tag)) != 0) - die(EXIT_FAILURE, "error setting key tag: %s", key_strerror(err)); - } - - if (c) { - int err = key_setcomment(&f, k.k, c); - if (err) - die(EXIT_FAILURE, "error setting key comment: %s", key_strerror(err)); - } - - setattr(&f, k.k, argv + optind + 1); - if (seed) { - key_putattr(&f, k.k, "genseed", seed); - key_putattr(&f, k.k, "seedalg", sa->p); - } - - key_fulltag(k.k, &k.tag); - - /* --- Find the parameter key --- */ - - if (ptag) { - if ((k.p = key_bytag(&f, ptag)) == 0) - die(EXIT_FAILURE, "parameter key `%s' not found", ptag); - if ((k.p->k->e & KF_ENCMASK) != KENC_STRUCT) - die(EXIT_FAILURE, "parameter key `%s' is not structured", ptag); - } - - /* --- Now generate the actual key data --- */ - - alg->proc(&k); - - /* --- Done --- */ - - dstr_destroy(&k.tag); - doclose(&f); - return (0); -} - -/*----- Key listing -------------------------------------------------------*/ - -/* --- Listing options --- */ - -typedef struct listopts { - const char *tfmt; /* Date format (@strftime@-style) */ - int v; /* Verbosity level */ - unsigned f; /* Various flags */ - time_t t; /* Time now (for key expiry) */ - key_filter kf; /* Filter for matching keys */ -} listopts; - -/* --- Listing flags --- */ - -#define f_newline 2u /* Write newline before next entry */ -#define f_attr 4u /* Written at least one attribute */ -#define f_utc 8u /* Emit UTC time, not local time */ - -/* --- @showkeydata@ --- * - * - * Arguments: @key_data *k@ = pointer to key to write - * @int ind@ = indentation level - * @listopts *o@ = listing options - * @dstr *d@ = tag string for this subkey - * - * Returns: --- - * - * Use: Emits a piece of key data in a human-readable format. - */ - -static void showkeydata(key_data *k, int ind, listopts *o, dstr *d) -{ -#define INDENT(i) do { \ - int _i; \ - for (_i = 0; _i < (i); _i++) { \ - putchar(' '); \ - } \ -} while (0) - - switch (k->e & KF_ENCMASK) { - - /* --- Binary key data --- * - * - * Emit as a simple hex dump. - */ - - case KENC_BINARY: { - const octet *p = k->u.k.k; - const octet *l = p + k->u.k.sz; - size_t sz = 0; - - fputs(" {", stdout); - while (p < l) { - if (sz % 16 == 0) { - putchar('\n'); - INDENT(ind + 2); - } else if (sz % 8 == 0) - fputs(" ", stdout); - else - putc(' ', stdout); - printf("%02x", *p++); - sz++; - } - putchar('\n'); - INDENT(ind); - fputs("}\n", stdout); - } break; - - /* --- Encrypted data --- * - * - * If the user is sufficiently keen, ask for a passphrase and decrypt the - * key. Otherwise just say that it's encrypted and move on. - */ - - case KENC_ENCRYPT: - if (o->v <= 3) - fputs(" encrypted\n", stdout); - else { - key_data *kd; - if (key_punlock(&kd, k, d->buf)) - printf(" \n", d->buf); - else { - fputs(" encrypted", stdout); - showkeydata(kd, ind, o, d); - key_drop(kd); - } - } - break; - - /* --- Integer keys --- * - * - * Emit as a large integer in decimal. This makes using the key in - * `calc' or whatever easier. - */ - - case KENC_MP: - putchar(' '); - mp_writefile(k->u.m, stdout, 10); - putchar('\n'); - break; - - /* --- Strings --- */ - - case KENC_STRING: - printf(" `%s'\n", k->u.p); - break; - - /* --- Elliptic curve points --- */ - - case KENC_EC: - if (EC_ATINF(&k->u.e)) - fputs(" inf\n", stdout); - else { - fputs(" 0x", stdout); mp_writefile(k->u.e.x, stdout, 16); - fputs(", 0x", stdout); mp_writefile(k->u.e.y, stdout, 16); - putchar('\n'); - } - break; - - /* --- Structured keys --- * - * - * Just iterate over the subkeys. - */ - - case KENC_STRUCT: { - key_subkeyiter i; - const char *tag; - size_t n = d->len; - - fputs(" {\n", stdout); - for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) { - if (!key_match(k, &o->kf)) - continue; - INDENT(ind + 2); - printf("%s =", tag); - d->len = n; - dstr_putf(d, ".%s", tag); - showkeydata(k, ind + 2, o, d); - } - INDENT(ind); - fputs("}\n", stdout); - } break; - } - -#undef INDENT -} - -/* --- @showkey@ --- * - * - * Arguments: @key *k@ = pointer to key to show - * @listopts *o@ = pointer to listing options - * - * Returns: --- - * - * Use: Emits a listing of a particular key. - */ - -static void showkey(key *k, listopts *o) -{ - char ebuf[24], dbuf[24]; - struct tm *tm; - - /* --- Skip the key if the filter doesn't match --- */ - - if (!key_match(k->k, &o->kf)) - return; - - /* --- Sort out the expiry and deletion times --- */ - - if (KEY_EXPIRED(o->t, k->exp)) - strcpy(ebuf, "expired"); - else if (k->exp == KEXP_FOREVER) - strcpy(ebuf, "forever"); - else { - tm = (o->f & f_utc) ? gmtime(&k->exp) : localtime(&k->exp); - strftime(ebuf, sizeof(ebuf), o->tfmt, tm); - } - - if (KEY_EXPIRED(o->t, k->del)) - strcpy(dbuf, "deleted"); - else if (k->del == KEXP_FOREVER) - strcpy(dbuf, "forever"); - else { - tm = (o->f & f_utc) ? gmtime(&k->del) : localtime(&k->del); - strftime(dbuf, sizeof(dbuf), o->tfmt, tm); - } - - /* --- If in compact format, just display and quit --- */ - - if (!o->v) { - if (!(o->f & f_newline)) { - printf("%8s %-20s %-20s %-10s %s\n", - "Id", "Tag", "Type", "Expire", "Delete"); - } - printf("%08lx %-20s %-20s %-10s %s\n", - (unsigned long)k->id, k->tag ? k->tag : "", - k->type, ebuf, dbuf); - o->f |= f_newline; - return; - } - - /* --- Display the standard header --- */ - - if (o->f & f_newline) - fputc('\n', stdout); - printf("keyid: %08lx\n", (unsigned long)k->id); - printf("tag: %s\n", k->tag ? k->tag : ""); - printf("type: %s\n", k->type); - printf("expiry: %s\n", ebuf); - printf("delete: %s\n", dbuf); - printf("comment: %s\n", k->c ? k->c : ""); - - /* --- Display the attributes --- */ - - if (o->v > 1) { - key_attriter i; - const char *av, *an; - - o->f &= ~f_attr; - printf("attributes:"); - for (key_mkattriter(&i, k); key_nextattr(&i, &an, &av); ) { - printf("\n %s = %s", an, av); - o->f |= f_attr; - } - if (o->f & f_attr) - fputc('\n', stdout); - else - puts(" "); - } - - /* --- If dumping requested, dump the raw key data --- */ - - if (o->v > 2) { - dstr d = DSTR_INIT; - fputs("key:", stdout); - key_fulltag(k, &d); - showkeydata(k->k, 0, o, &d); - dstr_destroy(&d); - } - - o->f |= f_newline; -} - -/* --- @cmd_list@ --- */ - -static int cmd_list(int argc, char *argv[]) -{ - key_file f; - key *k; - listopts o = { 0, 0, 0, 0, { 0, 0 } }; - - /* --- Parse subcommand options --- */ - - for (;;) { - static struct option opt[] = { - { "quiet", 0, 0, 'q' }, - { "verbose", 0, 0, 'v' }, - { "utc", 0, 0, 'u' }, - { "filter", OPTF_ARGREQ, 0, 'f' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+uqvf:", opt, 0, 0, 0); - if (i < 0) - break; - - switch (i) { - case 'u': - o.f |= f_utc; - break; - case 'q': - if (o.v) - o.v--; - break; - case 'v': - o.v++; - break; - case 'f': { - char *p; - int e = key_readflags(optarg, &p, &o.kf.f, &o.kf.m); - if (e || *p) - die(EXIT_FAILURE, "bad filter string `%s'", optarg); - } break; - default: - o.f |= f_bogus; - break; - } - } - - if (o.f & f_bogus) - die(EXIT_FAILURE, "Usage: list [-uqv] [-f FILTER] [TAG...]"); - - /* --- Open the key file --- */ - - doopen(&f, KOPEN_READ); - o.t = time(0); - - /* --- Set up the time format --- */ - - if (!o.v) - o.tfmt = "%Y-%m-%d"; - else if (o.f & f_utc) - o.tfmt = "%Y-%m-%d %H:%M:%S UTC"; - else - o.tfmt = "%Y-%m-%d %H:%M:%S %Z"; - - /* --- If specific keys were requested use them, otherwise do all --- * - * - * Some day, this might turn into a wildcard match. - */ - - if (optind < argc) { - do { - if ((k = key_bytag(&f, argv[optind])) != 0) - showkey(k, &o); - else { - moan("key `%s' not found", argv[optind]); - o.f |= f_bogus; - } - optind++; - } while (optind < argc); - } else { - key_iter i; - for (key_mkiter(&i, &f); (k = key_next(&i)) != 0; ) - showkey(k, &o); - } - - /* --- Done --- */ - - doclose(&f); - if (o.f & f_bogus) - return (EXIT_FAILURE); - else - return (0); -} - -/*----- Command implementation --------------------------------------------*/ - -/* --- @cmd_expire@ --- */ - -static int cmd_expire(int argc, char *argv[]) -{ - key_file f; - key *k; - int i; - int rc = 0; - - if (argc < 2) - die(EXIT_FAILURE, "Usage: expire TAG..."); - doopen(&f, KOPEN_WRITE); - for (i = 1; i < argc; i++) { - if ((k = key_bytag(&f, argv[i])) != 0) - key_expire(&f, k); - else { - moan("key `%s' not found", argv[i]); - rc = 1; - } - } - doclose(&f); - return (rc); -} - -/* --- @cmd_delete@ --- */ - -static int cmd_delete(int argc, char *argv[]) -{ - key_file f; - key *k; - int i; - int rc = 0; - - if (argc < 2) - die(EXIT_FAILURE, "Usage: delete TAG..."); - doopen(&f, KOPEN_WRITE); - for (i = 1; i < argc; i++) { - if ((k = key_bytag(&f, argv[i])) != 0) - key_delete(&f, k); - else { - moan("key `%s' not found", argv[i]); - rc = 1; - } - } - doclose(&f); - return (rc); -} - -/* --- @cmd_setattr@ --- */ - -static int cmd_setattr(int argc, char *argv[]) -{ - key_file f; - key *k; - - if (argc < 3) - die(EXIT_FAILURE, "Usage: setattr TAG ATTR..."); - doopen(&f, KOPEN_WRITE); - if ((k = key_bytag(&f, argv[1])) == 0) - die(EXIT_FAILURE, "key `%s' not found", argv[1]); - setattr(&f, k, argv + 2); - doclose(&f); - return (0); -} - -/* --- @cmd_getattr@ --- */ - -static int cmd_getattr(int argc, char *argv[]) -{ - key_file f; - key *k; - dstr d = DSTR_INIT; - const char *p; - - if (argc != 3) - die(EXIT_FAILURE, "Usage: getattr TAG ATTR"); - doopen(&f, KOPEN_READ); - if ((k = key_bytag(&f, argv[1])) == 0) - die(EXIT_FAILURE, "key `%s' not found", argv[1]); - key_fulltag(k, &d); - if ((p = key_getattr(&f, k, argv[2])) == 0) - die(EXIT_FAILURE, "no attribute `%s' for key `%s'", argv[2], d.buf); - puts(p); - dstr_destroy(&d); - doclose(&f); - return (0); -} - -/* --- @cmd_finger@ --- */ - -static void fingerprint(key *k, const gchash *ch, const key_filter *kf) -{ - ghash *h; - dstr d = DSTR_INIT; - const octet *p; - size_t i; - - h = GH_INIT(ch); - if (key_fingerprint(k, h, kf)) { - p = GH_DONE(h, 0); - key_fulltag(k, &d); - for (i = 0; i < ch->hashsz; i++) { - if (i && i % 4 == 0) - putchar('-'); - printf("%02x", p[i]); - } - printf(" %s\n", d.buf); - } - dstr_destroy(&d); - GH_DESTROY(h); -} - -static int cmd_finger(int argc, char *argv[]) -{ - key_file f; - int rc = 0; - const gchash *ch = &rmd160; - key_filter kf = { KF_NONSECRET, KF_NONSECRET }; - - for (;;) { - static struct option opt[] = { - { "filter", OPTF_ARGREQ, 0, 'f' }, - { "algorithm", OPTF_ARGREQ, 0, 'a' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+f:a:", opt, 0, 0, 0); - if (i < 0) - break; - switch (i) { - case 'f': { - char *p; - int err = key_readflags(optarg, &p, &kf.f, &kf.m); - if (err || *p) - die(EXIT_FAILURE, "bad filter string `%s'", optarg); - } break; - case 'a': - if ((ch = ghash_byname(optarg)) == 0) - die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg); - break; - default: - rc = 1; - break; - } - } - - argv += optind; argc -= optind; - if (rc) - die(EXIT_FAILURE, "Usage: fingerprint [-f FILTER] [TAG...]"); - - doopen(&f, KOPEN_READ); - - if (argc) { - int i; - for (i = 0; i < argc; i++) { - key *k = key_bytag(&f, argv[i]); - if (k) - fingerprint(k, ch, &kf); - else { - rc = 1; - moan("key `%s' not found", argv[i]); - } - } - } else { - key_iter i; - key *k; - for (key_mkiter(&i, &f); (k = key_next(&i)) != 0; ) - fingerprint(k, ch, &kf); - } - return (rc); -} - -/* --- @cmd_verify@ --- */ - -static unsigned xdigit(char c) -{ - if ('A' <= c && c <= 'Z') return (c + 10 - 'A'); - if ('a' <= c && c <= 'z') return (c + 10 - 'a'); - if ('0' <= c && c <= '9') return (c - '0'); - return (~0u); -} - -static void unhexify(octet *q, char *p, size_t n) -{ - unsigned a = 0; - int i = 0; - - for (;;) { - if (*p == '-' || *p == ':' || isspace((unsigned char)*p)) { - p++; - continue; - } - if (!n && !*p) - break; - if (!*p) - die(EXIT_FAILURE, "hex string too short"); - if (!isxdigit((unsigned char)*p)) - die(EXIT_FAILURE, "bad hex string"); - if (!n) - die(EXIT_FAILURE, "hex string too long"); - a = (a << 4) | xdigit(*p++); - i++; - if (i == 2) { - *q++ = U8(a); - a = 0; - i = 0; - n--; - } - } -} - -static int cmd_verify(int argc, char *argv[]) -{ - key_file f; - int rc = 0; - const gchash *ch = &rmd160; - ghash *h; - key *k; - octet *buf; - const octet *fpr; - key_filter kf = { KF_NONSECRET, KF_NONSECRET }; - - for (;;) { - static struct option opt[] = { - { "filter", OPTF_ARGREQ, 0, 'f' }, - { "algorithm", OPTF_ARGREQ, 0, 'a' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+f:a:", opt, 0, 0, 0); - if (i < 0) - break; - switch (i) { - case 'f': { - char *p; - int err = key_readflags(optarg, &p, &kf.f, &kf.m); - if (err || *p) - die(EXIT_FAILURE, "bad filter string `%s'", optarg); - } break; - case 'a': - if ((ch = ghash_byname(optarg)) == 0) - die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg); - break; - default: - rc = 1; - break; - } - } - - argv += optind; argc -= optind; - if (rc || argc != 2) - die(EXIT_FAILURE, "Usage: verify [-f FILTER] TAG FINGERPRINT"); - - doopen(&f, KOPEN_READ); - - if ((k = key_bytag(&f, argv[0])) == 0) - die(EXIT_FAILURE, "key `%s' not found", argv[0]); - buf = xmalloc(ch->hashsz); - unhexify(buf, argv[1], ch->hashsz); - h = GH_INIT(ch); - if (!key_fingerprint(k, h, &kf)) - die(EXIT_FAILURE, "key has no fingerprintable components (as filtered)"); - fpr = GH_DONE(h, 0); - if (memcmp(fpr, buf, ch->hashsz) != 0) - die(EXIT_FAILURE, "key fingerprint mismatch"); - doclose(&f); - return (0); -} - -/* --- @cmd_comment@ --- */ - -static int cmd_comment(int argc, char *argv[]) -{ - key_file f; - key *k; - int err; - - if (argc < 2 || argc > 3) - die(EXIT_FAILURE, "Usage: comment TAG [COMMENT]"); - doopen(&f, KOPEN_WRITE); - if ((k = key_bytag(&f, argv[1])) == 0) - die(EXIT_FAILURE, "key `%s' not found", argv[1]); - if ((err = key_setcomment(&f, k, argv[2])) != 0) - die(EXIT_FAILURE, "bad comment `%s': %s", argv[2], key_strerror(err)); - doclose(&f); - return (0); -} - -/* --- @cmd_tag@ --- */ - -static int cmd_tag(int argc, char *argv[]) -{ - key_file f; - key *k; - int err; - unsigned flags = 0; - int rc = 0; - - for (;;) { - static struct option opt[] = { - { "retag", 0, 0, 'r' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+r", opt, 0, 0, 0); - if (i < 0) - break; - switch (i) { - case 'r': - flags |= f_retag; - break; - default: - rc = 1; - break; - } - } - - argv += optind; argc -= optind; - if (argc < 1 || argc > 2 || rc) - die(EXIT_FAILURE, "Usage: tag [-r] TAG [NEW-TAG]"); - doopen(&f, KOPEN_WRITE); - if (flags & f_retag) { - if ((k = key_bytag(&f, argv[1])) != 0 && strcmp(k->tag, argv[1]) == 0) - key_settag(&f, k, 0); - } - if ((k = key_bytag(&f, argv[0])) == 0) - die(EXIT_FAILURE, "key `%s' not found", argv[0]); - if ((err = key_settag(&f, k, argv[1])) != 0) - die(EXIT_FAILURE, "bad tag `%s': %s", argv[1], key_strerror(err)); - doclose(&f); - return (0); -} - -/* --- @cmd_lock@ --- */ - -static int cmd_lock(int argc, char *argv[]) -{ - key_file f; - key *k; - key_data **kd; - dstr d = DSTR_INIT; - - if (argc != 2) - die(EXIT_FAILURE, "Usage: lock QTAG"); - doopen(&f, KOPEN_WRITE); - if (key_qtag(&f, argv[1], &d, &k, &kd)) - die(EXIT_FAILURE, "key `%s' not found", argv[1]); - if ((*kd)->e == KENC_ENCRYPT && key_punlock(kd, 0, d.buf)) - die(EXIT_FAILURE, "couldn't unlock key `%s'", d.buf); - if (key_plock(kd, 0, d.buf)) - die(EXIT_FAILURE, "failed to lock key `%s'", d.buf); - f.f |= KF_MODIFIED; - doclose(&f); - return (0); -} - -/* --- @cmd_unlock@ --- */ - -static int cmd_unlock(int argc, char *argv[]) -{ - key_file f; - key *k; - key_data **kd; - dstr d = DSTR_INIT; - - if (argc != 2) - die(EXIT_FAILURE, "Usage: unlock QTAG"); - doopen(&f, KOPEN_WRITE); - if (key_qtag(&f, argv[1], &d, &k, &kd)) - die(EXIT_FAILURE, "key `%s' not found", argv[1]); - if ((*kd)->e != KENC_ENCRYPT) - die(EXIT_FAILURE, "key `%s' is not encrypted", d.buf); - if (key_punlock(kd, 0, d.buf)) - die(EXIT_FAILURE, "couldn't unlock key `%s'", d.buf); - f.f |= KF_MODIFIED; - doclose(&f); - return (0); -} - -/* --- @cmd_extract@ --- */ - -static int cmd_extract(int argc, char *argv[]) -{ - key_file f; - key *k; - int i; - int rc = 0; - key_filter kf = { 0, 0 }; - dstr d = DSTR_INIT; - const char *outfile = 0; - FILE *fp; - - for (;;) { - static struct option opt[] = { - { "filter", OPTF_ARGREQ, 0, 'f' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "f:", opt, 0, 0, 0); - if (i < 0) - break; - switch (i) { - case 'f': { - char *p; - int err = key_readflags(optarg, &p, &kf.f, &kf.m); - if (err || *p) - die(EXIT_FAILURE, "bad filter string `%s'", optarg); - } break; - default: - rc = 1; - break; - } - } - - argv += optind; argc -= optind; - if (rc || argc < 1) - die(EXIT_FAILURE, "Usage: extract [-f FILTER] FILE [TAG...]"); - if (strcmp(*argv, "-") == 0) - fp = stdout; - else { - outfile = *argv; - dstr_putf(&d, "%s.new", outfile); - if (!(fp = fopen(d.buf, "w"))) { - die(EXIT_FAILURE, "couldn't open `%s' for writing: %s", - d.buf, strerror(errno)); - } - } - - doopen(&f, KOPEN_READ); - if (argc < 2) { - key_iter i; - key *k; - for (key_mkiter(&i, &f); (k = key_next(&i)) != 0; ) - key_extract(&f, k, fp, &kf); - } else { - for (i = 1; i < argc; i++) { - if ((k = key_bytag(&f, argv[i])) != 0) - key_extract(&f, k, fp, &kf); - else { - moan("key `%s' not found", argv[i]); - rc = 1; - } - } - } - if (fclose(fp) || (outfile && rename(d.buf, outfile))) - die(EXIT_FAILURE, "error writing file: %s", strerror(errno)); - dstr_destroy(&d); - doclose(&f); - return (rc); -} - -/* --- @cmd_tidy@ --- */ - -static int cmd_tidy(int argc, char *argv[]) -{ - key_file f; - if (argc != 1) - die(EXIT_FAILURE, "Usage: tidy"); - doopen(&f, KOPEN_WRITE); - f.f |= KF_MODIFIED; /* Nasty hack */ - doclose(&f); - return (0); -} - -/* --- @cmd_merge@ --- */ - -static int cmd_merge(int argc, char *argv[]) -{ - key_file f; - FILE *fp; - - if (argc != 2) - die(EXIT_FAILURE, "Usage: merge FILE"); - if (strcmp(argv[1], "-") == 0) - fp = stdin; - else if (!(fp = fopen(argv[1], "r"))) { - die(EXIT_FAILURE, "couldn't open `%s' for reading: %s", - argv[1], strerror(errno)); - } - - doopen(&f, KOPEN_WRITE); - key_merge(&f, argv[1], fp, key_moan, 0); - doclose(&f); - return (0); -} - -/* --- @cmd_show@ --- */ - -#define LISTS(LI) \ - LI("Lists", list, \ - listtab[i].name, listtab[i].name) \ - LI("Hash functions", hash, \ - ghashtab[i], ghashtab[i]->name) \ - LI("Elliptic curves", ec, \ - ectab[i].name, ectab[i].name) \ - LI("Prime Diffie-Hellman groups", dh, \ - ptab[i].name, ptab[i].name) \ - LI("Binary Diffie-Hellman groups", bindh, \ - bintab[i].name, bintab[i].name) \ - LI("Key-generation algorithms", keygen, \ - algtab[i].name, algtab[i].name) \ - LI("Random seeding algorithms", seed, \ - seedtab[i].p, seedtab[i].p) - -MAKELISTTAB(listtab, LISTS) - -static int cmd_show(int argc, char *argv[]) -{ - return (displaylists(listtab, argv + 1)); -} - -/*----- Main command table ------------------------------------------------*/ - -static int cmd_help(int argc, char *argv[]); - -static cmd cmds[] = { - { "help", cmd_help, "help [COMMAND...]" }, - { "show", cmd_show, "show [ITEM...]" }, - { "list", cmd_list, "list [-uqv] [-f FILTER] [TAG...]", "\ -Options:\n\ -\n\ --u, --utc Display expiry times etc. in UTC, not local time.\n\ --q, --quiet Show less information.\n\ --v, --verbose Show more information.\n\ -" }, - { "fingerprint", cmd_finger, "fingerprint [-f FILTER] [TAG...]", "\ -Options:\n\ -\n\ --f, --filter=FILT Only hash key components matching FILT.\n\ --a, --algorithm=HASH Use the named HASH algorithm.\n\ - ($ show hash for list.)\n\ -" }, - { "verify", cmd_verify, "verify [-f FILTER] TAG FINGERPRINT", "\ -Options:\n\ -\n\ --f, --filter=FILT Only hash key components matching FILT.\n\ --a, --algorithm=HASH Use the named HASH algorithm.\n\ - ($ show hash for list.)\n\ -" }, - { "extract", cmd_extract, "extract [-f FILTER] FILE [TAG...]", "\ -Options:\n\ -\n\ --f, --filter=FILT Only extract key components matching FILT.\n\ -" }, - { "merge", cmd_merge, "merge FILE" }, - { "expire", cmd_expire, "expire TAG..." }, - { "delete", cmd_delete, "delete TAG..." }, - { "setattr", cmd_setattr, "setattr TAG ATTR..." }, - { "getattr", cmd_getattr, "getattr TAG ATTR" }, - { "comment", cmd_comment, "comment TAG [COMMENT]" }, - { "lock", cmd_lock, "lock QTAG" }, - { "unlock", cmd_unlock, "unlock QTAG" }, - { "tag", cmd_tag, "tag [-r] TAG [NEW-TAG]", "\ -Options:\n\ -\n\ --r, --retag Untag any key currently called new-tag.\n\ -" }, - { "tidy", cmd_tidy, "tidy" }, - { "add", cmd_add, - "add [-OPTIONS] TYPE [ATTR...]\n\ - Options: [-lqrLKS] [-a ALG] [-bB BITS] [-p PARAM] [-R TAG]\n\ - [-A SEEDALG] [-s SEED] [-n BITS] [-I KEYID]\n\ - [-e EXPIRE] [-t TAG] [-c COMMENT]", "\ -Options:\n\ -\n\ --a, --algorithm=ALG Generate keys suitable for ALG.\n\ - ($ show keygen for list.)\n\ --b, --bits=N Generate an N-bit key.\n\ --B, --qbits=N Use an N-bit subgroup or factors.\n\ --p, --parameters=TAG Get group parameters from TAG.\n\ --C, --curve=NAME Use elliptic curve or DH group NAME.\n\ - ($ show ec or $ show dh for list.)\n\ --A, --seedalg=ALG Use pseudorandom generator ALG to generate key.\n\ - ($ show seed for list.)\n\ --s, --seed=BASE64 Use Base64-encoded string BASE64 as seed.\n\ --n, --newseed=COUNT Generate new COUNT-bit seed.\n\ --e, --expire=TIME Make the key expire after TIME.\n\ --c, --comment=STRING Attach the command STRING to the key.\n\ --t, --tag=TAG Tag the key with the name TAG.\n\ --r, --retag Untag any key currently with that tag.\n\ --R, --rand-id=TAG Use key named TAG for the random number generator.\n\ --I, --key-id=ID Force the key-id for the new key.\n\ --l, --lock Lock the generated key with a passphrase.\n\ --q, --quiet Don't give progress indicators while working.\n\ --L, --lim-lee Generate Lim-Lee primes for Diffie-Hellman groups.\n\ --K, --kcdsa Generate KCDSA-style Lim-Lee primes for DH groups.\n\ --S, --subgroup Use a prime-order subgroup for Diffie-Hellman.\n\ -" }, - { 0, 0, 0 } -}; - -static int cmd_help(int argc, char *argv[]) -{ - sc_help(cmds, stdout, argv + 1); - return (0); -} - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Helpful GNUy functions --- */ - -static void usage(FILE *fp) -{ - pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n"); -} - -void version(FILE *fp) -{ - pquis(fp, "$, Catacomb version " VERSION "\n"); -} - -void help_global(FILE *fp) -{ - usage(fp); - fputs("\n\ -Performs various simple key management operations.\n\ -\n\ -Global command line options:\n\ -\n\ --h, --help [COMMAND...] Display this help text (or help for COMMANDs).\n\ --v, --version Display version number.\n\ --u, --usage Display short usage summary.\n\ -\n\ --k, --keyring=FILE Read and write keys in FILE.\n", - fp); -} - -/* --- @main@ --- * - * - * Arguments: @int argc@ = number of command line arguments - * @char *argv[]@ = array of command line arguments - * - * Returns: Nonzero on failure. - * - * Use: Main program. Performs simple key management functions. - */ - -int main(int argc, char *argv[]) -{ - unsigned f = 0; - -#define f_bogus 1u - - /* --- Initialization --- */ - - ego(argv[0]); - sub_init(); - - /* --- Parse command line options --- */ - - for (;;) { - static struct option opt[] = { - - /* --- Standard GNUy help options --- */ - - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'v' }, - { "usage", 0, 0, 'u' }, - - /* --- Real live useful options --- */ - - { "keyring", OPTF_ARGREQ, 0, 'k' }, - - /* --- Magic terminator --- */ - - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "+hvu k:", opt, 0, 0, 0); - - if (i < 0) - break; - switch (i) { - - /* --- GNU help options --- */ - - case 'h': - sc_help(cmds, stdout, argv + optind); - exit(0); - case 'v': - version(stdout); - exit(0); - case 'u': - usage(stdout); - exit(0); - - /* --- Real useful options --- */ - - case 'k': - keyfile = optarg; - break; - - /* --- Bogosity --- */ - - default: - f |= f_bogus; - break; - } - } - - /* --- Complain about excessive bogons --- */ - - if (f & f_bogus || optind == argc) { - usage(stderr); - exit(1); - } - - /* --- Initialize the Catacomb random number generator --- */ - - rand_noisesrc(RAND_GLOBAL, &noise_source); - rand_seed(RAND_GLOBAL, 160); - - /* --- Dispatch to appropriate command handler --- */ - - argc -= optind; - argv += optind; - optind = 0; - return (findcmd(cmds, argv[0])->cmd(argc, argv)); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/lcrand.c b/lcrand.c deleted file mode 100644 index a108f13..0000000 --- a/lcrand.c +++ /dev/null @@ -1,306 +0,0 @@ -/* -*-c-*- - * - * $Id: lcrand.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Simple linear congruential generator - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include -#include - -#include "grand.h" -#include "lcrand.h" - -/*----- Magic numbers -----------------------------------------------------*/ - -/* --- The generator parameters --- */ - -#define P LCRAND_P /* Modulus */ -#define A LCRAND_A /* Multiplier (primitive mod @p@) */ -#define C LCRAND_C /* Additive constant */ - -/* --- Precomputed values for modular reduction --- */ - -#define D 5 /* %$p = 2^{32} - d$% */ - -/* --- Other useful bits --- */ - -#define P256 4294967040u /* Highest multiple of 256 < %$p$% */ - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @lcrand@ --- * - * - * Arguments: @uint32 x@ = seed value - * - * Returns: New state of the generator. - * - * Use: Steps the generator. Returns %$ax + c \bmod p$%. - */ - -uint32 lcrand(uint32 x) -{ - uint32 a[2], xx[2]; - uint32 yy[2]; - - /* --- Unpack things into the arrays --- */ - - a[0] = U16(A); a[1] = U16(A >> 16); - xx[0] = U16(x); xx[1] = U16(x >> 16); - - /* --- Multiply everything together --- * - * - * This is plain old long multiplication, although it looks a bit strange. - * I set up the top and bottom partial products directly where they're - * supposed to be. The cross terms I add together, with the low 16 bits in - * @q@ and the high 32 bits in @p@. These I then add into the product. - */ - - { - uint32 p, q; - - yy[0] = a[0] * xx[0]; - yy[1] = a[1] * xx[1]; - - p = a[0] * xx[1]; - q = p + a[1] * xx[0]; - p = ((q < p) << 16) + (q >> 16); - q = U16(q) << 16; - - q += yy[0]; - if (q < yy[0]) - p++; - else - p += (q >> 16) >> 16; - yy[0] = q; - - yy[1] += p; - } - - /* --- Now reduce mod p --- * - * - * I'm using shifts and adds to do the multiply step here. This needs to - * be changed if @D@ ever becomes something other than 5. - */ - -#if D != 5 -# error "Change shift sequence!" -#endif - - { - uint32 q; - - q = yy[1]; - x = yy[0]; - - while (q) { - uint32 y, z; - y = q >> 30; - z = q << 2; - z += q; - if (z < q) - y++; - else - y += (q >> 16) >> 16; - q = y; - x += z; - if (x < z || x > P) - x -= P; - } - } - - /* --- Now add on the constant --- */ - - x += C; - if (x < C || x >= P) - x -= P; - - /* --- Done --- */ - - return (x); -} - -/* --- @lcrand_range@ --- * - * - * Arguments: @uint32 *x@ = pointer to seed value (updated) - * @uint32 m@ = limit allowable - * - * Returns: A uniformly distributed pseudorandom integer in the interval - * %$[0, m)$%. - */ - -uint32 lcrand_range(uint32 *x, uint32 m) -{ - uint32 xx = *x; - uint32 r = P - P % m; - do xx = lcrand(xx); while (xx >= r); - *x = xx; - return (xx % m); -} - -/*----- Generic interface -------------------------------------------------*/ - -typedef struct gctx { - grand r; - uint32 x; -} gctx; - -static void gdestroy(grand *r) -{ - gctx *g = (gctx *)r; - DESTROY(g); -} - -static int gmisc(grand *r, unsigned op, ...) -{ - gctx *g = (gctx *)r; - va_list ap; - int rc = 0; - va_start(ap, op); - - switch (op) { - case GRAND_CHECK: - switch (va_arg(ap, unsigned)) { - case GRAND_CHECK: - case GRAND_SEEDINT: - case GRAND_SEEDUINT32: - case GRAND_SEEDRAND: - rc = 1; - break; - default: - rc = 0; - break; - } - break; - case GRAND_SEEDINT: - g->x = va_arg(ap, unsigned); - break; - case GRAND_SEEDUINT32: - g->x = va_arg(ap, uint32); - break; - case GRAND_SEEDRAND: { - grand *rr = va_arg(ap, grand *); - uint32 x; - do x = rr->ops->word(rr); while (x >= P || x == LCRAND_FIXEDPT); - g->x = x; - } break; - default: - GRAND_BADOP; - break; - } - - va_end(ap); - return (rc); -} - -static uint32 graw(grand *r) -{ - gctx *g = (gctx *)r; - g->x = lcrand(g->x); - return (g->x); -} - -static octet gbyte(grand *r) -{ - gctx *g = (gctx *)r; - uint32 x = g->x; - do x = lcrand(x); while (x >= P256); - g->x = x; - return (x / (P256 / 256)); -} - -static uint32 grange(grand *r, uint32 l) -{ - gctx *g = (gctx *)r; - return (lcrand_range(&g->x, l)); -} - -static const grand_ops gops = { - "lcrand", - LCRAND_P, 0, - gmisc, gdestroy, - graw, gbyte, grand_word, grange, grand_fill -}; - -/* --- @lcrand_create@ --- * - * - * Arguments: @uint32 x@ = initial seed - * - * Returns: Pointer to a generic generator. - * - * Use: Constructs a generic generator interface over a linear - * congruential generator. - */ - -grand *lcrand_create(uint32 x) -{ - gctx *g = CREATE(gctx); - g->r.ops = &gops; - g->x = x; - return (&g->r); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -static int verify(dstr *v) -{ - uint32 x = *(uint32 *)v[0].buf; - uint32 y = *(uint32 *)v[1].buf; - uint32 z = lcrand(x); - int ok = 1; - if (y != z) { - fprintf(stderr, - "\n*** lcrand failed. lcrand(%lu) = %lu, expected %lu\n", - (unsigned long)x, (unsigned long)z, (unsigned long)y); - ok = 0; - } - return (ok); -} - -static test_chunk tests[] = { - { "lcrand", verify, { &type_uint32, &type_uint32, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, tests, SRCDIR"/tests/lcrand"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/lcrand.h b/lcrand.h deleted file mode 100644 index 080370c..0000000 --- a/lcrand.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -*-c-*- - * - * $Id: lcrand.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Simple linear congruential generator - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the linear congruential generator ------------------------* - * - * This pseudorandom number generator is simple, but has absolutely no - * cryptographic strength whatever. It may be used whenever random numbers - * are required but cryptographic strength is not, for example when - * generating numbers for use in primality tests. To be honest, it's not - * even particularly fast, although a certain amount of effort has been - * expended on making it better than awfully slow. To put things in - * perspective, it can't quite spit bytes out as fast as OFB DES. (Then - * again, bytes aren't its natural output format.) Its main use is probably - * seeding a Fibonacci generator. - * - * There exists a fixed-point input @LCRAND_FIXEDPT@ -- when fed to the - * generator it comes straight back out again. All other inputs less than - * the modulus are part of the same sequence of period %$p - 1$%. - * - * The generator has been tested for its statistical properties. George - * Marsaglia's Diehard tests give it a reasonably clean bill of health. - * - * The modulus %$p$% is chosen as the largest prime number less than - * %$2^{32}$%. The multiplier %$a$% and additive constant %$c$% are based on - * the decimal expansions of %$\pi$% and %$e$%, with the additional - * restriction that the multiplier must be a primitive element modulo %$p$%. - * The fixed point value is determined as %$c / (1 - a) \bmod p$%. - */ - -#ifndef CATACOMB_LCRAND_H -#define CATACOMB_LCRAND_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -/*----- Constants ---------------------------------------------------------*/ - -#define LCRAND_P 4294967291u /* Modulus for the generator */ -#define LCRAND_A 314159265u /* Multiplier (primitive mod @p@) */ -#define LCRAND_C 271828183u /* Additive constant */ - -#define LCRAND_FIXEDPT 3223959250u /* Fixed point (only bad input) */ - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @lcrand@ --- * - * - * Arguments: @uint32 x@ = seed value - * - * Returns: New state of the generator. - * - * Use: Steps the generator. Returns %$ax + c \bmod p$%. - */ - -extern uint32 lcrand(uint32 /*x*/); - -/* --- @lcrand_range@ --- * - * - * Arguments: @uint32 *x@ = pointer to seed value (updated) - * @uint32 m@ = limit allowable - * - * Returns: A uniformly distributed pseudorandom integer in the interval - * %$[0, m)$%. - */ - -extern uint32 lcrand_range(uint32 */*x*/, uint32 /*m*/); - -/* --- @lcrand_create@ --- * - * - * Arguments: @uint32 x@ = initial seed - * - * Returns: Pointer to a generic generator. - * - * Use: Constructs a generic generator interface over a linear - * congruential generator. - */ - -extern grand *lcrand_create(uint32 /*x*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/limlee.c b/limlee.c deleted file mode 100644 index b6fc4d6..0000000 --- a/limlee.c +++ /dev/null @@ -1,398 +0,0 @@ -/* -*-c-*- - * - * $Id: limlee.c,v 1.9 2004/04/08 01:36:15 mdw Exp $ - * - * Generate Lim-Lee primes - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include "limlee.h" -#include "mpmul.h" -#include "mprand.h" -#include "pgen.h" -#include "rabin.h" - -/*----- Stepping through combinations -------------------------------------*/ - -/* --- @comb_init@ --- * - * - * Arguments: @octet *c@ = pointer to byte-flag array - * @unsigned n@ = number of items in the array - * @unsigned r@ = number of desired items - * - * Returns: --- - * - * Use: Initializes a byte-flag array which, under the control of - * @comb_next@, will step through all combinations of @r@ chosen - * elements. - */ - -static void comb_init(octet *c, unsigned n, unsigned r) -{ - memset(c, 0, n - r); - memset(c + (n - r), 1, r); -} - -/* --- @comb_next@ --- * - * - * Arguments: @octet *c@ = pointer to byte-flag array - * @unsigned n@ = number of items in the array - * @unsigned r@ = number of desired items - * - * Returns: Nonzero if another combination was returned, zero if we've - * reached the end. - * - * Use: Steps on to the next combination in sequence. - */ - -static int comb_next(octet *c, unsigned n, unsigned r) -{ - unsigned g = 0; - - /* --- How the algorithm works --- * - * - * Set bits start at the end and work their way towards the start. - * Excepting bits already at the start, we scan for the lowest set bit, and - * move it one place nearer the start. A group of bits at the start are - * counted and reset just below the `moved' bit. If there is no moved bit - * then we're done. - */ - - /* --- Count the group at the start --- */ - - for (; *c; c++) { - g++; - *c = 0; - } - if (g == r) - return (0); - - /* --- Move the next bit down one --- * - * - * There must be one, because otherwise we'd have counted %$r$% bits - * earlier. - */ - - for (; !*c; c++) - ; - *c = 0; - g++; - for (; g; g--) - *--c = 1; - return (1); -} - -/*----- Default prime generator -------------------------------------------*/ - -static void llgen(limlee_factor *f, unsigned pl, limlee_stepctx *l) -{ - pgen_filterctx pf; - rabin r; - mp *p; - -again: - p = mprand(l->newp, pl, l->r, 1); - pf.step = 2; - p = pgen(l->d.buf, p, p, l->iev, l->iec, 0, pgen_filter, &pf, - rabin_iters(pl), pgen_test, &r); - if (!p) - goto again; - f->p = p; -} - -static void llfree(limlee_factor *f, limlee_stepctx *l) -{ - mp_drop(f->p); -} - -static const limlee_primeops primeops_simple = { llgen, llfree }; - -/*----- Lim-Lee stepper ---------------------------------------------------*/ - -/* --- @init@ --- * - * - * Arguments: @pgen_event *ev@ = pointer to event block - * @limlee_stepctx *l@ = pointer to Lim-Lee context - * - * Returns: A @PGEN@ result code. - * - * Use: Initializes the stepper. - */ - -static int init(pgen_event *ev, limlee_stepctx *l) -{ - size_t i; - unsigned qql; - - /* --- First of all, decide on a number of factors to make --- */ - - l->nf = l->pl / l->ql; - qql = l->pl % l->ql; - if (!l->nf) - return (PGEN_ABORT); - else if (qql && l->nf > 1) { - l->nf--; - qql += l->ql; - } - - /* --- Now decide on how many primes I'll actually generate --- * - * - * The formula %$m = \max(3 n + 5, 25)$% comes from GPG's prime generation - * library. - */ - - l->poolsz = l->nf * 3 + 5; - if (l->poolsz < 25) - l->poolsz = 25; - - /* --- Allocate and initialize the various tables --- */ - - l->c = xmalloc(l->poolsz); - l->v = xmalloc(l->poolsz * sizeof(limlee_factor)); - comb_init(l->c, l->poolsz, l->nf); - for (i = 0; i < l->poolsz; i++) - l->v[i].p = 0; - - /* --- Other bits of initialization --- */ - - l->seq = 0; - dstr_create(&l->d); - if (!l->pops) { - l->pops = &primeops_simple; - l->pc = 0; - } - - /* --- Find a big prime --- */ - - if (!qql) - l->qq.p = 0; - else { - dstr_putf(&l->d, "%s*", ev->name); - l->pops->pgen(&l->qq, qql, l); - } - - return (PGEN_TRY); -} - -/* --- @next@ --- * - * - * Arguments: @int rq@ = request which triggered this call - * @pgen_event *ev@ = pointer to event block - * @limlee_stepctx *l@ = pointer to Lim-Lee context - * - * Returns: A @PGEN@ result code. - * - * Use: Initializes the stepper. - */ - -static int next(int rq, pgen_event *ev, limlee_stepctx *l) -{ - mp *p; - int rc; - - mp_drop(ev->m); - - for (;;) { - size_t i; - mpmul mm = MPMUL_INIT; - - /* --- Step on to next combination --- */ - - if (rq == PGEN_TRY && !comb_next(l->c, l->poolsz, l->nf)) { - for (i = 0; i < l->poolsz; i++) { - l->pops->pfree(&l->v[i], l); - l->v[i].p = 0; - } - } - rq = PGEN_TRY; /* For next time through */ - - /* --- Gather up some factors --- */ - - if (l->qq.p) - mpmul_add(&mm, l->qq.p); - for (i = 0; i < l->poolsz; i++) { - if (!l->c[i]) - continue; - if (!l->v[i].p) { - DRESET(&l->d); - dstr_putf(&l->d, "%s_%lu", ev->name, l->seq++); - l->pops->pgen(&l->v[i], l->ql, l); - } - mpmul_add(&mm, l->v[i].p); - } - - /* --- Check it for small factors --- */ - - p = mpmul_done(&mm); - p = mp_lsl(p, p, 1); - p->v[0] |= 1; - if ((rc = pfilt_smallfactor(p)) != PGEN_FAIL) - break; - mp_drop(p); - } - - ev->m = p; - return (rc); -} - -/* --- @done@ --- * - * - * Arguments: @pgen_event *ev@ = pointer to event block - * @limlee_stepctx *l@ = pointer to Lim-Lee context - * - * Returns: A @PGEN@ result code. - * - * Use: Finalizes the stepper. The output values in the context - * take on their final results; other resources are discarded. - */ - -static int done(pgen_event *ev, limlee_stepctx *l) -{ - size_t i, j; - limlee_factor *v; - - /* --- If an output vector of factors is wanted, produce one --- */ - - if (!(l->f & LIMLEE_KEEPFACTORS)) - v = 0; - else { - if (l->qq.p) - l->nf++; - v = xmalloc(l->nf * sizeof(limlee_factor)); - } - - for (i = 0, j = 0; i < l->poolsz; i++) { - if (v && l->c[i]) - v[j++] = l->v[i]; - else if (l->v[i].p) - l->pops->pfree(&l->v[i], l); - } - - if (l->qq.p) { - if (v) - v[j++] = l->qq; - else - l->pops->pfree(&l->qq, l); - } - - xfree(l->v); - l->v = v; - - /* --- Free other resources --- */ - - xfree(l->c); - dstr_destroy(&l->d); - - /* --- Done --- */ - - return (PGEN_DONE); -} - -/* --- @limlee_step@ --- */ - -int limlee_step(int rq, pgen_event *ev, void *p) -{ - limlee_stepctx *l = p; - int rc; - - switch (rq) { - case PGEN_BEGIN: - if ((rc = init(ev, l)) != PGEN_TRY) - return (rc); - case PGEN_TRY: - return (next(rq, ev, l)); - case PGEN_DONE: - return (done(ev, l)); - } - return (PGEN_ABORT); -} - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @limlee@ --- * - * - * Arguments: @const char *name@ = pointer to name root - * @mp *d@ = pointer to destination integer - * @mp *newp@ = how to generate factor primes - * @unsigned ql@ = size of individual factors - * @unsigned pl@ = size of large prime - * @grand *r@ = a random number source - * @unsigned on@ = number of outer attempts to make - * @pgen_proc *oev@ = outer event handler function - * @void *oec@ = argument for the outer event handler - * @pgen_proc *iev@ = inner event handler function - * @void *iec@ = argument for the inner event handler - * @size_t *nf@, @mp ***f@ = output array for factors - * - * Returns: A Lim-Lee prime, or null if generation failed. - * - * Use: Generates Lim-Lee primes. A Lim-Lee prime %$p$% is one which - * satisfies %$p = 2 \prod_i q_i + 1$%, where all of the %$q_i$% - * are large enough to resist square-root discrete log - * algorithms. - * - * If we succeed, and @f@ is non-null, we write the array of - * factors chosen to @f@ for the benefit of the caller. - */ - -mp *limlee(const char *name, mp *d, mp *newp, - unsigned ql, unsigned pl, grand *r, - unsigned on, pgen_proc *oev, void *oec, - pgen_proc *iev, void *iec, - size_t *nf, mp ***f) -{ - limlee_stepctx l; - rabin rr; - - l.f = 0; if (f) l.f |= LIMLEE_KEEPFACTORS; - l.newp = newp; - l.pl = pl; l.ql = ql; - l.pops = 0; - l.iev = iev; - l.iec = iec; - l.r = r; - - d = pgen(name, d, 0, oev, oec, on, limlee_step, &l, - rabin_iters(pl), pgen_test, &rr); - - if (d && f) { - mp **v; - size_t i; - v = xmalloc(l.nf * sizeof(mp *)); - for (i = 0; i < l.nf; i++) - v[i] = l.v[i].p; - xfree(l.v); - *f = v; - *nf = l.nf; - } - - return (d); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/limlee.h b/limlee.h deleted file mode 100644 index 8b03bc3..0000000 --- a/limlee.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -*-c-*- - * - * $Id: limlee.h,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Generate Lim-Lee primes - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_LIMLEE_H -#define CATACOMB_LIMLEE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_PGEN_H -# include "pgen.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct limlee_factor { - mp *p; /* The actual prime */ - unsigned tag; /* A tag, usable by the generator */ - void *more; /* Pointer to more data */ -} limlee_factor; - -typedef struct limlee_stepctx { - - /* --- To be initialized by the caller --- */ - - unsigned f; /* Various useful flags */ - mp *newp; /* Initial valid for new primes */ - unsigned ql, pl; /* Size of factors and result */ - const struct limlee_primeops *pops; /* Pointer to generator ops */ - void *pc; /* Context ptr for generator ops */ - pgen_proc *iev; /* Event handler for inner @pgen@ */ - void *iec; /* Context for inner @pgen@ */ - grand *r; /* Random number generator */ - - /* --- Output values --- */ - - size_t nf; /* Number of factors wanted */ - limlee_factor *v; /* Vector of factors */ - - /* --- Maintained internally --- */ - - octet *c; /* Combination byte-flag vector */ - unsigned long seq; /* Sequence number for primes */ - size_t poolsz; /* Size of the small-prime pool */ - dstr d; /* String for subprime name */ - limlee_factor qq; /* Big prime to pick up slack */ - -} limlee_stepctx; - -typedef struct limlee_primeops { - void (*pgen)(limlee_factor */*f*/, unsigned /*pl*/, limlee_stepctx */*l*/); - void (*pfree)(limlee_factor */*f*/, limlee_stepctx */*l*/); -} limlee_primeops; - -/* --- Flags --- */ - -#define LIMLEE_KEEPFACTORS 1u - -/*----- The Lim-Lee stepper function --------------------------------------*/ - -extern pgen_proc limlee_step; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @limlee@ --- * - * - * Arguments: @const char *name@ = pointer to name root - * @mp *d@ = pointer to destination integer - * @mp *newp@ = how to generate factor primes - * @unsigned ql@ = size of individual factors - * @unsigned pl@ = size of large prime - * @grand *r@ = a random number source - * @unsigned on@ = number of outer attempts to make - * @pgen_proc *oev@ = outer event handler function - * @void *oec@ = argument for the outer event handler - * @pgen_proc *iev@ = inner event handler function - * @void *iec@ = argument for the inner event handler - * @size_t *nf@, @mp ***f@ = output array for factors - * - * Returns: A Lim-Lee prime, or null if generation failed. - * - * Use: Generates Lim-Lee primes. A Lim-Lee prime %$p$% is one which - * satisfies %$p = 2 \prod_i q_i + 1$%, where all of the %$q_i$% - * are large enough to resist square-root discrete log - * algorithms. - * - * If we succeed, and @f@ is non-null, we write the array of - * factors chosen to @f@ for the benefit of the caller. - */ - -extern mp *limlee(const char */*name*/, mp */*d*/, mp */*newp*/, - unsigned /*ql*/, unsigned /*pl*/, grand */*r*/, - unsigned /*on*/, pgen_proc */*oev*/, void */*oec*/, - pgen_proc */*iev*/, void */*iec*/, - size_t */*nf*/, mp ***/*f*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/lmem.c b/lmem.c deleted file mode 100644 index a7033d0..0000000 --- a/lmem.c +++ /dev/null @@ -1,346 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Locked memory allocation (Unix-specific) - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "config.h" - -#include -#include -#include -#include -#include - -#include -#include - -#ifdef HAVE_MLOCK -# include -#endif - -#include -#include -#include - -#include "lmem.h" - -/*----- Arena operations --------------------------------------------------*/ - -static void *aalloc(arena *a, size_t sz) { return l_alloc((lmem *)a, sz); } -static void afree(arena *a, void *p) { l_free((lmem *)a, p); } -static void apurge(arena *a) { l_purge((lmem *)a); } - -static const arena_ops l_ops = { aalloc, arena_fakerealloc, afree, apurge }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @l_init@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * @size_t sz@ = size of locked memory area requested - * - * Returns: Zero if everything is fine, @+1@ if some insecure memory was - * allocated, and @-1@ if everything went horribly wrong. - * - * Use: Initializes the locked memory manager. This function is safe - * to call in a privileged program; privileges should usually be - * dropped after allocating the locked memory block. - * - * You must call @sub_init@ before allocating locked memory - * buffers. - */ - -int l_init(lmem *lm, size_t sz) -{ - char *p; - int rc = 0; - l_node *l; - - /* --- Preliminaries --- */ - - lm->a.ops = &l_ops; - lm->err = 0; - lm->f = 0; - - /* --- Try making a secure locked passphrase buffer --- * - * - * Drop privileges before emitting diagnostic messages. - */ - -#ifdef HAVE_MLOCK - - /* --- Memory-map a page from somewhere --- */ - -# ifdef MAP_ANON - p = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); -# else - { - int fd; - if ((fd = open("/dev/zero", O_RDWR)) >= 0) { - p = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - close(fd); - } - } -# endif - - /* --- Lock the page in memory --- * - * - * Why does @mmap@ return such a stupid result if it fails? - */ - - if (p == 0 || p == MAP_FAILED) { - lm->emsg = "couldn't map locked memory area: %s"; - lm->err = errno; - p = 0; - } else if (mlock(p, sz)) { - lm->emsg = "error locking memory area: %s"; - lm->err = errno; - munmap(p, sz); - p = 0; - } else - lm->f |= LF_LOCKED; - -#endif - - /* --- Make a standard passphrase buffer --- */ - -#ifdef HAVE_MLOCK - if (!p) -#else - lm->err = 0; - lm->emsg = "locked memory not available on this system"; -#endif - { - if ((p = malloc(sz)) == 0) { - lm->emsg = "not enough standard memory!"; - lm->err = ENOMEM; - return (-1); - } - rc = +1; - } - - /* --- Initialize the buffer --- */ - - lm->sz = lm->free = sz; - lm->p = p; - - /* --- Initialize the free list --- */ - - l = CREATE(l_node); - l->next = 0; - l->p = p; - l->sz = sz; - l->f = 0; - lm->l = l; - - /* --- Done --- */ - - return (rc); -} - -/* --- @l_alloc@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * @size_t sz@ = size requested - * - * Returns: Pointer to allocated memory. - * - * Use: Allocates @sz@ bytes of locked memory. - */ - -void *l_alloc(lmem *lm, size_t sz) -{ - l_node *l; - - sz = (sz + 3u) & ~3u; - for (l = lm->l; l; l = l->next) { - if (l->f & LF_ALLOC) - continue; - if (l->sz < sz) - continue; - l->f |= LF_ALLOC; - if (l->sz > sz) { - l_node *n = CREATE(l_node); - n->next = l->next; - n->p = l->p + sz; - n->sz = l->sz - sz; - l->sz = sz; - n->f = 0; - l->next = n; - } - assert(((void)"Locked buffer space has vanished", lm->free >= sz)); - lm->free -= sz; - return (l->p); - } - return (0); -} - -/* --- @l_free@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * @void *p@ = pointer to block - * - * Returns: --- - * - * Use: Releases a block of locked memory. - */ - -void l_free(lmem *lm, void *p) -{ - l_node *l; - l_node *ll = 0; - - for (l = lm->l; l; l = l->next) { - size_t sz; - - /* --- If this isn't the block, skip it --- */ - - if (l->p != p) { - ll = l; - continue; - } - assert(((void)"Block is already free", l->f & LF_ALLOC)); - - /* --- Coalesce with adjacent free blocks --- */ - - l->f &= ~LF_ALLOC; - sz = l->sz; - memset(p, 0, sz); - - if (ll && !(ll->f & LF_ALLOC)) { - assert(((void)"Previous block doesn't fit", ll->p + ll->sz == p)); - ll->sz += sz; - ll->next = l->next; - DESTROY(l); - l = ll; - } - - ll = l->next; - if (ll && !(ll->f & LF_ALLOC)) { - assert(((void)"Next block doesn't fit", ll->p == l->p + l->sz)); - l->sz += ll->sz; - l->next = ll->next; - DESTROY(ll); - } - - lm->free += sz; - assert(((void)"Free lunch", lm->free <= lm->sz)); - return; - } - assert(((void)"Not a locked block", 0)); -} - -/* --- @l_purge@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * - * Returns: --- - * - * Use: Purges all the free blocks in the buffer, and clears all of - * the locked memory. Memory is not freed back to the system. - */ - -void l_purge(lmem *lm) -{ - l_node *l; - - l = lm->l; - while (l) { - l_node *ll = l->next; - DESTROY(l); - l = ll; - } - memset(lm->p, 0, lm->sz); - l = CREATE(l_node); - l->next = 0; - l->p = lm->p; - l->sz = lm->sz; - l->f = 0; - lm->l = l; - lm->free = l->sz; -} - -/* --- @l_destroy@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * - * Returns: --- - * - * Use: Disposes of a locked memory arena permanently. - */ - -void l_destroy(lmem *lm) -{ - l_node *l; - - l = lm->l; - while (l) { - l_node *ll = l->next; - DESTROY(l); - l = ll; - } - memset(lm->p, 0, lm->sz); - -#ifdef HAVE_MLOCK - if (lm->f & LF_LOCKED) - munmap(lm->p, lm->sz); - else -#endif - free(lm->p); /*sic*/ -} - -/* --- @l_report@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * @dstr *d@ = string to write the error message on - * - * Returns: Zero if the buffer is fine, @+1@ if there was a problem - * getting locked memory but insecure stuff could be allocated, - * and @-1@ if not even insecure memory could be found. - * - * Use: Returns a user-digestable explanation for the state of a - * locked memory buffer. If the return code is zero, no message - * is emitted to the string @d@. - */ - -int l_report(lmem *lm, dstr *d) -{ - int rc; - if (lm->err) - dstr_putf(d, lm->emsg, strerror(lm->err)); - if (!lm->p) - rc = -1; - else if (lm->err) - rc = +1; - else - rc = 0; - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/lmem.h b/lmem.h deleted file mode 100644 index 65a31a8..0000000 --- a/lmem.h +++ /dev/null @@ -1,166 +0,0 @@ -/* -*-c-*- - * - * $Id: lmem.h,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Locked memory allocation - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_LMEM_H -#define CATACOMB_LMEM_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include -#include - -/*----- Data structures ---------------------------------------------------*/ - -/* --- Block list --- * - * - * The block list is kept in normal memory, to avoid wasting precious locked - * memory. Entries are sorted into ascending address order to make - * coalescing free blocks easier. All blocks, free or not, are included in - * the list. - */ - -typedef struct l_node { - struct l_node *next; /* Next free block in chain */ - char *p; /* Pointer to the block */ - size_t sz; /* Size of the block */ - unsigned f; /* Various flags */ -} l_node; - -#define LF_ALLOC 1u - -/* --- Locked memory buffer state --- */ - -typedef struct lmem { - arena a; /* Arena header block */ - unsigned f; /* Various flags */ - char *p; /* Pointer to locked buffer */ - l_node *l; /* Pointer to block list */ - size_t sz; /* Size of locked buffer */ - size_t free; /* Size of free area */ - int err; char *emsg; /* Error indicators */ -} lmem; - -#define LF_LOCKED 1u - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @l_init@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * @size_t sz@ = size of locked memory area requested - * - * Returns: Zero if everything is fine, @+1@ if some insecure memory was - * allocated, and @-1@ if everything went horribly wrong. - * - * Use: Initializes the locked memory manager. This function is safe - * to call in a privileged program; privileges should usually be - * dropped after allocating the locked memory block. - * - * You must call @sub_init@ before allocating locked memory - * buffers. - */ - -extern int l_init(lmem */*lm*/, size_t /*sz*/); - -/* --- @l_alloc@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * @size_t sz@ = size requested - * - * Returns: Pointer to allocated memory. - * - * Use: Allocates @sz@ bytes of locked memory. - */ - -extern void *l_alloc(lmem */*lm*/, size_t /*sz*/); - -/* --- @l_free@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * @void *p@ = pointer to block - * - * Returns: --- - * - * Use: Releases a block of locked memory. - */ - -extern void l_free(lmem */*lm*/, void */*p*/); - -/* --- @l_purge@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * - * Returns: --- - * - * Use: Purges all the free blocks in the buffer, and clears all of - * the locked memory. Memory is not freed back to the system. - */ - -extern void l_purge(lmem */*lm*/); - -/* --- @l_destroy@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * - * Returns: --- - * - * Use: Disposes of a locked memory arena permanently. - */ - -extern void l_destroy(lmem */*lm*/); - -/* --- @l_report@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * @dstr *d@ = string to write the error message on - * - * Returns: Zero if the buffer is fine, @+1@ if there was a problem - * getting locked memory but insecure stuff could be allocated, - * and @-1@ if not even insecure memory could be found. - * - * Use: Returns a user-digestable explanation for the state of a - * locked memory buffer. If the return code is zero, no message - * is emitted to the string @d@. - */ - -extern int l_report(lmem */*lm*/, dstr */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/manual/catacomb.tex b/manual/catacomb.tex index f13c7c1..a811331 100644 --- a/manual/catacomb.tex +++ b/manual/catacomb.tex @@ -1,7 +1,5 @@ %%% -*-latex-*- %%% -%%% $Id: catacomb.tex,v 1.3 2004/04/08 01:36:15 mdw Exp $ -%%% %%% Catacomb manual %%% %%% (c) 1999 Straylight/Edgeware diff --git a/mars-mktab.c b/mars-mktab.c deleted file mode 100644 index 9726ed9..0000000 --- a/mars-mktab.c +++ /dev/null @@ -1,317 +0,0 @@ -/* -*-c-*- - * - * $Id: mars-mktab.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Generate the MARS S-box table - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include - -#include "sha.h" - -/*----- SHA-1 (quick version) ---------------------------------------------*/ - -/* --- @sha_compress@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: SHA-1 compression function. - */ - -void sha_compress(sha_ctx *ctx, const void *sbuf) -{ - uint32 a, b, c, d, e; - uint32 buf[80]; - - /* --- Fetch the chaining variables --- */ - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - e = ctx->e; - - /* --- Fetch and expand the buffer contents --- */ - - { - int i; - const octet *p; - - for (i = 0, p = sbuf; i < 16; i++, p += 4) - buf[i] = LOAD32(p); - for (i = 16; i < 80; i++) { - uint32 x = buf[i - 3] ^ buf[i - 8] ^ buf[i - 14] ^ buf[i - 16]; - buf[i] = ROL32(x, 1); - } - } - - /* --- Definitions for round functions --- */ - -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define G(x, y, z) ((x) ^ (y) ^ (z)) -#define H(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) - -#define T(v, w, x, y, z, i, f, k) do { \ - uint32 _x; \ - z = ROL32(v, 5) + f(w, x, y) + z + buf[i] + k; \ - w = ROR32(w, 2); \ - _x = v; v = z; z = y; y = x; x = w; w = _x; \ -} while (0) - -#define FF(v, w, x, y, z, i) T(v, w, x, y, z, i, F, 0x5a827999) -#define GG(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0x6ed9eba1) -#define HH(v, w, x, y, z, i) T(v, w, x, y, z, i, H, 0x8f1bbcdc) -#define II(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0xca62c1d6) - - /* --- The main compression function --- */ - - { - unsigned i; - for (i = 0; i < 20; i++) - FF(a, b, c, d, e, i); - for (i = 20; i < 40; i++) - GG(a, b, c, d, e, i); - for (i = 40; i < 60; i++) - HH(a, b, c, d, e, i); - for (i = 60; i < 80; i++) - II(a, b, c, d, e, i); - } - - ctx->a += a; - ctx->b += b; - ctx->c += c; - ctx->d += d; - ctx->e += e; -} - -/* --- @sha_init@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void sha_init(sha_ctx *ctx) -{ - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; - ctx->e = 0xc3d2e1f0; - ctx->off = 0; - ctx->nl = ctx->nh = 0; -} - -/* --- @sha_hash@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void sha_hash(sha_ctx *ctx, const void *buf, size_t sz) -{ - sha_ctx *_bctx = (ctx); - size_t _bsz = (sz); - const octet *_bbuf = (octet *) (buf); - - { - uint32 _l = ((uint32) ((_bsz) & MASK32)); - uint32 _h = ((_bsz & ~MASK32) >> 16) >> 16; - _bctx->nh += _h; - _bctx->nl += _l; - if (_bctx->nl < _l || _bctx->nl & ~MASK32) - _bctx->nh++; - } - if (_bctx->off + _bsz < SHA_BUFSZ) { - memcpy(_bctx->buf + _bctx->off, _bbuf, _bsz); - _bctx->off += _bsz; - } else { - if (_bctx->off) { - size_t s = SHA_BUFSZ - _bctx->off; - memcpy(_bctx->buf + _bctx->off, _bbuf, s); - sha_compress(_bctx, _bctx->buf); - _bsz -= s; - _bbuf += s; - } - while (_bsz >= SHA_BUFSZ) { - sha_compress(_bctx, _bbuf); - _bsz -= SHA_BUFSZ; - _bbuf += SHA_BUFSZ; - } - if (_bsz) - memcpy(_bctx->buf, _bbuf, _bsz); - _bctx->off = _bsz; - } -} - -/* --- @sha_done@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -void sha_done(sha_ctx *ctx, void *hash) -{ - octet *p = hash; - { - sha_ctx *_pctx = (ctx); - _pctx->buf[_pctx->off] = 0x80; - _pctx->off++; - if (_pctx->off > SHA_BUFSZ - 8) { - if (_pctx->off < SHA_BUFSZ) - memset(_pctx->buf + _pctx->off, 0, SHA_BUFSZ - _pctx->off); - sha_compress(_pctx, _pctx->buf); - memset(_pctx->buf, 0, SHA_BUFSZ - 8); - } else - memset(_pctx->buf + _pctx->off, 0, SHA_BUFSZ - _pctx->off - 8); - } - STORE32(ctx->buf + SHA_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3)); - STORE32(ctx->buf + SHA_BUFSZ - 4, ctx->nl << 3); - sha_compress(ctx, ctx->buf); - STORE32(p + 0, ctx->a); - STORE32(p + 4, ctx->b); - STORE32(p + 8, ctx->c); - STORE32(p + 12, ctx->d); - STORE32(p + 16, ctx->e); -} - -/*----- Main code ---------------------------------------------------------*/ - -static void mks(uint32 c3, uint32 *s) -{ - octet ibuf[16], obuf[20]; - sha_ctx h; - unsigned i, j; - - STORE32_L(ibuf + 4, 0xb7e15162); - STORE32_L(ibuf + 8, 0x243f6a88); - STORE32_L(ibuf + 12, c3); - - for (i = 0; i < 510; i += 5) { - STORE32_L(ibuf, i); - sha_init(&h); - sha_hash(&h, ibuf, sizeof(ibuf)); - sha_done(&h, obuf); - for (j = 0; j < 5; j++) - *s++ = LOAD32_L(obuf + (4 * j)); - } - STORE32_L(ibuf, i); - sha_init(&h); - sha_hash(&h, ibuf, sizeof(ibuf)); - sha_done(&h, obuf); - for (j = 0; i < 512; j++, i++) - *s++ = LOAD32_L(obuf + (4 * j)); -} - -static void fix(uint32 *s) -{ - unsigned i, j, n; - uint32 d; - - for (i = 0; i < 512; i++) { - for (j = i & ~255u; j < ((i + 255) & ~255u); j++) { - if (i == j) - continue; - d = s[i] ^ s[j]; - n = 0; - if (!(d & 0xff000000)) n++; - if (!(d & 0x00ff0000)) n++; - if (!(d & 0x0000ff00)) n++; - if (!(d & 0x000000ff)) n++; - if (n >= 2) { - s[i] = U32(s[i] * 3); - goto fixed; - } - } - fixed:; - } -} - -int main(void) -{ - uint32 s[512]; - unsigned i; - - mks(0x02917d59, s); - fix(s); - - puts("\ -/* -*-c-*-\n\ - *\n\ - * MARS tables [generated]\n\ - */\n\ -\n\ -#ifndef CATACOMB_MARS_TAB_H\n\ -#define CATACOMB_MARS_TAB_H\n\ -"); - - fputs("\ -/* --- The S-box --- */\n\ -\n\ -#define MARS_S { \\\n\ - ", stdout); - for (i = 0; i < 512; i++) { - printf("0x%08lx", (unsigned long)s[i]); - if (i == 511) - fputs(" \\\n}\n\n", stdout); - else if (i % 4 == 3) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - puts("#endif"); - - if (fclose(stdout)) { - fprintf(stderr, "error writing data\n"); - exit(EXIT_FAILURE); - } - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mars.c b/mars.c deleted file mode 100644 index 9240083..0000000 --- a/mars.c +++ /dev/null @@ -1,266 +0,0 @@ -/* -*-c-*- - * - * $Id: mars.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The MARS block cipher - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "mars.h" -#include "mars-tab.h" -#include "paranoia.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet mars_keysz[] = { KSZ_RANGE, MARS_KEYSZ, 0, 56, 4 }; - -/*----- Useful tables -----------------------------------------------------*/ - -static const uint32 s[512] = MARS_S; -#define s0 (s + 0) -#define s1 (s + 256) -#define bb (s + 265) - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mars_init@ --- * - * - * Arguments: @mars_ctx *k@ = pointer to key block to fill in - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a MARS key buffer. MARS accepts key sizes - * between 128 and 448 bits which are a multiple of 32 bits. - */ - -void mars_init(mars_ctx *k, const void *buf, size_t sz) -{ - uint32 t[15]; - uint32 *kk = k->k; - const octet *p; - unsigned i, j, ii; - - KSZ_ASSERT(mars, sz); - - /* --- Copy the key into the temporary buffer --- */ - - p = buf; - for (i = 0; i < sz/4; i++) { - t[i] = LOAD32_L(p); - p += 4; - } - t[i++] = sz/4; - for (; i < 15; i++) - t[i] = 0; - - /* --- Now spit out the actual key material --- */ - - for (j = 0; j < 4; j++) { - uint32 x; - - /* --- Do the linear mixing stage --- */ - - for (i = 0; i < 15; i++) { - x = t[(i + 8)%15] ^ t[(i + 13)%15]; - t[i] ^= ROL32(x, 3) ^ ((i << 2) | j); - } - - /* --- Now do the Feistel stirring stage --- */ - - x = t[14]; - for (ii = 0; ii < 4; ii++) { - for (i = 0; i < 15; i++) { - x = t[i] + s[x & 511u]; - t[i] = x = ROL32(x, 9); - } - } - - /* --- And spit out the key material --- */ - - for (i = 0; i < 10; i++) - *kk++ = t[(4 * i)%15]; - } - - /* --- Finally, fix up the multiplicative entries --- */ - - for (i = 5; i < 37; i += 2) { - uint32 w, m, x; - j = k->k[i] & 3u; - w = k->k[i] | 3u; - - /* --- Compute the magic mask value --- */ - - m = 0; - for (ii = 0; ii <= 22; ii++) { - x = w >> ii; - if ((x & 0x3ff) == 0x3ff || (x & 0x3ff) == 0) - m |= 0x3ff << ii; - } - m &= ~(((w ^ (w << 1)) | (w ^ (w >> 1))) | 0x80000003); - - /* --- Add in the bias entry to fix up the key --- */ - - x = ROL32(bb[j], k->k[i - 1]); - k->k[i] = w ^ (x & m); - } -} - -/* --- @mars_eblk@, @mars_dblk@ --- * - * - * Arguments: @const mars_ctx *k@ = pointer to key block - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -#define KADD(k, a, b, c, d) a += *k++, b += *k++, c += *k++, d += *k++ -#define KSUB(k, a, b, c, d) a -= *k++, b -= *k++, c -= *k++, d -= *k++ -#define IKADD(k, a, b, c, d) d += *--k, c += *--k, b += *--k, a += *--k -#define IKSUB(k, a, b, c, d) d -= *--k, c -= *--k, b -= *--k, a -= *--k - -#define MIX(a, b, c, d) do { \ - b ^= s0[(a >> 0) & 0xff]; \ - b += s1[(a >> 8) & 0xff]; \ - c += s0[(a >> 16) & 0xff]; \ - d ^= s1[(a >> 24) & 0xff]; \ - a = ROL32(a, 8); \ -} while (0) - -#define IMIX(a, b, c, d) do { \ - a = ROR32(a, 8); \ - d ^= s1[(a >> 24) & 0xff]; \ - c -= s0[(a >> 16) & 0xff]; \ - b -= s1[(a >> 8) & 0xff]; \ - b ^= s0[(a >> 0) & 0xff]; \ -} while (0) - -#define E(x, y, z, k, a) do { \ - uint32 kx = *k++, ky = *k++; \ - y = a + kx; \ - a = ROL32(a, 13); z = a * ky; z = ROL32(z, 5); \ - x = s[y & 511u] ^ z; y = ROL32(y, z); \ - z = ROL32(z, 5); x ^= z; x = ROL32(x, z); \ -} while (0) - -#define IE(x, y, z, k, a) do { \ - uint32 ky = *--k, kx = *--k; \ - z = a * ky; \ - a = ROR32(a, 13); y = a + kx; z = ROL32(z, 5); \ - x = s[y & 511u] ^ z; y = ROL32(y, z); \ - z = ROL32(z, 5); x ^= z; x = ROL32(x, z); \ -} while (0) - -#define ROUND(k, a, b, c, d) do { \ - uint32 x, y, z; \ - E(x, y, z, k, a); \ - b += x; c += y; d ^= z; \ -} while (0) - -#define IROUND(k, a, b, c, d) do { \ - uint32 x, y, z; \ - IE(x, y, z, k, a); \ - b -= x; c -= y; d ^= z; \ -} while (0) - -void mars_eblk(const mars_ctx *k, const uint32 *src, uint32 *dst) -{ - uint32 a, b, c, d; - const uint32 *kk = k->k; - - a = src[0], b = src[1], c = src[2], d = src[3]; - KADD(kk, a, b, c, d); - - MIX(a, b, c, d); a += d; MIX(b, c, d, a); b += c; - MIX(c, d, a, b); MIX(d, a, b, c); - MIX(a, b, c, d); a += d; MIX(b, c, d, a); b += c; - MIX(c, d, a, b); MIX(d, a, b, c); - - ROUND(kk, a, b, c, d); ROUND(kk, b, c, d, a); - ROUND(kk, c, d, a, b); ROUND(kk, d, a, b, c); - ROUND(kk, a, b, c, d); ROUND(kk, b, c, d, a); - ROUND(kk, c, d, a, b); ROUND(kk, d, a, b, c); - - ROUND(kk, a, d, c, b); ROUND(kk, b, a, d, c); - ROUND(kk, c, b, a, d); ROUND(kk, d, c, b, a); - ROUND(kk, a, d, c, b); ROUND(kk, b, a, d, c); - ROUND(kk, c, b, a, d); ROUND(kk, d, c, b, a); - - IMIX(a, d, c, b); IMIX(b, a, d, c); - c -= b; IMIX(c, b, a, d); d -= a; IMIX(d, c, b, a); - IMIX(a, d, c, b); IMIX(b, a, d, c); - c -= b; IMIX(c, b, a, d); d -= a; IMIX(d, c, b, a); - - KSUB(kk, a, b, c, d); - dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; -} - -void mars_dblk(const mars_ctx *k, const uint32 *src, uint32 *dst) -{ - uint32 a, b, c, d; - const uint32 *kk = k->k + 40; - - a = src[0], b = src[1], c = src[2], d = src[3]; - IKADD(kk, a, b, c, d); - - MIX(d, c, b, a); d += a; MIX(c, b, a, d); c += b; - MIX(b, a, d, c); MIX(a, d, c, b); - MIX(d, c, b, a); d += a; MIX(c, b, a, d); c += b; - MIX(b, a, d, c); MIX(a, d, c, b); - - IROUND(kk, d, c, b, a); IROUND(kk, c, b, a, d); - IROUND(kk, b, a, d, c); IROUND(kk, a, d, c, b); - IROUND(kk, d, c, b, a); IROUND(kk, c, b, a, d); - IROUND(kk, b, a, d, c); IROUND(kk, a, d, c, b); - - IROUND(kk, d, a, b, c); IROUND(kk, c, d, a, b); - IROUND(kk, b, c, d, a); IROUND(kk, a, b, c, d); - IROUND(kk, d, a, b, c); IROUND(kk, c, d, a, b); - IROUND(kk, b, c, d, a); IROUND(kk, a, b, c, d); - - IMIX(d, a, b, c); IMIX(c, d, a, b); - b -= c; IMIX(b, c, d, a); a -= d; IMIX(a, b, c, d); - IMIX(d, a, b, c); IMIX(c, d, a, b); - b -= c; IMIX(b, c, d, a); a -= d; IMIX(a, b, c, d); - - IKSUB(kk, a, b, c, d); - dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; -} - -BLKC_TEST(MARS, mars) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mars.h b/mars.h deleted file mode 100644 index f32f9f4..0000000 --- a/mars.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -*-c-*- - * - * $Id: mars.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The MARS block cipher - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the MARS block cipher ------------------------------------* - * - * MARS was IBM's submission to the AES contest. It was designed by a number - * of clever people at the T. J. Watson labs, and made it to the second round - * of the contest. Unfortunately, MARS is rather messy. There are some - * awkward corner cases in the key schedule algorithm, for example, that show - * up very rarely. - */ - -#ifndef CATACOMB_MARS_H -#define CATACOMB_MARS_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magical numbers ---------------------------------------------------*/ - -#define MARS_BLKSZ 16 -#define MARS_KEYSZ 32 -#define MARS_CLASS (N, L, 128) - -extern const octet mars_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct mars_ctx { - uint32 k[40]; -} mars_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @mars_init@ --- * - * - * Arguments: @mars_ctx *k@ = pointer to key block to fill in - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a MARS key buffer. MARS accepts key sizes - * between 128 and 448 bits which are a multiple of 32 bits. - */ - -extern void mars_init(mars_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @mars_eblk@, @mars_dblk@ --- * - * - * Arguments: @const mars_ctx *k@ = pointer to key block - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void mars_eblk(const mars_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -extern void mars_dblk(const mars_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/math/Makefile.am b/math/Makefile.am new file mode 100644 index 0000000..5bb546c --- /dev/null +++ b/math/Makefile.am @@ -0,0 +1,392 @@ +### -*-makefile-*- +### +### Build script for mathematical infrastructure +### +### (c) 2013 Straylight/Edgeware +### + +###----- Licensing notice --------------------------------------------------- +### +### This file is part of Catacomb. +### +### Catacomb is free software; you can redistribute it and/or modify +### it under the terms of the GNU Library General Public License as +### published by the Free Software Foundation; either version 2 of the +### License, or (at your option) any later version. +### +### Catacomb is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU Library General Public License for more details. +### +### You should have received a copy of the GNU Library General Public +### License along with Catacomb; if not, write to the Free +### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +### MA 02111-1307, USA. + +include $(top_srcdir)/vars.am + +noinst_LTLIBRARIES = libmath.la +libmath_la_SOURCES = +nodist_libmath_la_SOURCES = +libmath_la_LIBADD = + +TEST_LIBS = libmath.la + +###-------------------------------------------------------------------------- +### Main multiprecision integer library. + +## This library is unfortunately intertwined with some of the code generation +## programs, so we must be rather careful. The important bits of the maths +## library needed by these programs is separated out into `libmpbase'. There +## is work going on to fix this unpleasant situation by generating the +## relevant files from Python scripts rather than C programs, using +## information gathered by `configure'. +noinst_LTLIBRARIES += libmpbase.la +libmath_la_LIBADD += libmpbase.la +libmpbase_la_LIBADD = $(mLib_LIBS) +libmpbase_la_SOURCES = +$(libmpbase_la_OBJECTS): mptypes.h + +## Additional buffer I/O functions for mathematical objects. +pkginclude_HEADERS += buf.h +libmath_la_SOURCES += buf.c + +## Infrastructure for fast exponentiation. +pkginclude_HEADERS += exp.h +libmath_la_SOURCES += exp.c + +## Main user-visible multiprecision arithmetic. +pkginclude_HEADERS += mp.h +libmpbase_la_SOURCES += mp-arith.c +TESTS += mp-arith.$t +libmpbase_la_SOURCES += mp-const.c +libmath_la_SOURCES += mp-exp.c mp-exp.h +libmath_la_SOURCES += mp-gcd.c +TESTS += mp-gcd.$t +libmpbase_la_SOURCES += mp-io.c +libmath_la_SOURCES += mp-jacobi.c +TESTS += mp-jacobi.$t +libmpbase_la_SOURCES += mp-mem.c +libmpbase_la_SOURCES += mp-misc.c +libmath_la_SOURCES += mp-modexp.c +TESTS += mp-modexp.$t +libmath_la_SOURCES += mp-modsqrt.c +TESTS += mp-modsqrt.$t +libmath_la_SOURCES += mp-sqrt.c +TESTS += mp-sqrt.$t +libmath_la_SOURCES += mp-test.c +EXTRA_DIST += t/mp + +## Computing Fibonacci numbers. +pkginclude_HEADERS += mp-fibonacci.h +libmath_la_SOURCES += mp-fibonacci.c +TESTS += mp-fibonacci.$t + +## Special memory allocation for multiprecision integers. +pkginclude_HEADERS += mparena.h +libmpbase_la_SOURCES += mparena.c + +## Barrett reduction, an efficient method for modular reduction. +pkginclude_HEADERS += mpbarrett.h +libmath_la_SOURCES += mpbarrett.c +TESTS += mpbarrett.$t +libmath_la_SOURCES += mpbarrett-exp.c mpbarrett-mexp.c mpbarrett-exp.h +TESTS += mpbarrett-exp.$t mpbarrett-mexp.$t +TESTS += mpbarrett.$t +EXTRA_DIST += t/mpbarrett + +## Solving congruences using the Chinese Remainder Theorem. +pkginclude_HEADERS += mpcrt.h +libmath_la_SOURCES += mpcrt.c +TESTS += mpcrt.$t +EXTRA_DIST += t/mpcrt + +## Conversions between machine-native and multiprecision integers. +pkginclude_HEADERS += mpint.h +libmath_la_SOURCES += mpint.c +TESTS += mpint.$t +EXTRA_DIST += t/mpint + +## Table of upper and lower limits of various types of machine integers, as +## multiprecision integers. +nodist_archinclude_HEADERS += mplimits.h +nodist_libmath_la_SOURCES += mplimits.c +CLEANFILES += mplimits.h mplimits.c +noinst_PROGRAMS += genlimits +genlimits_LDADD = libmpbase.la +mplimits.c: genlimits$e + $(AM_V_GEN)./genlimits c >mplimits.c.new && \ + mv mplimits.c.new mplimits.c +mplimits.h: genlimits$e + $(AM_V_GEN)./genlimits h >mplimits.h.new && \ + mv mplimits.h.new mplimits.h +$(genlimits_OBJECTS): mptypes.h +mplimits.lo: mplimits.h + +## Montgomery reduction, a clever method for modular arithmetic. +pkginclude_HEADERS += mpmont.h +libmath_la_SOURCES += mpmont.c +TESTS += mpmont.$t +libmath_la_SOURCES += mpmont-exp.c mpmont-mexp.c mpmont-exp.h +TESTS += mpmont-exp.$t mpmont-mexp.$t +EXTRA_DIST += t/mpmont + +## Efficient multiplication of many small numbers. +pkginclude_HEADERS += mpmul.h +libmath_la_SOURCES += mpmul.c +TESTS += mpmul.$t + +## Generating random numbers. +pkginclude_HEADERS += mprand.h +libmath_la_SOURCES += mprand.c + +## Efficient reduction modulo numbers with conveninent binary +## representations. +pkginclude_HEADERS += mpreduce.h +libmath_la_SOURCES += mpreduce.c mpreduce-exp.h +TESTS += mpreduce.$t +EXTRA_DIST += t/mpreduce + +## Iteratiion over the bianry representation of multiprecision integers. +pkginclude_HEADERS += mpscan.h +libmpbase_la_SOURCES += mpscan.c + +## Conversion between multiprecision integers and their textual +## representations. +pkginclude_HEADERS += mptext.h +libmpbase_la_SOURCES += mptext.c +TESTS += mptext.$t +libmath_la_SOURCES += mptext-dstr.c +libmath_la_SOURCES += mptext-file.c +libmath_la_SOURCES += mptext-len.c +libmpbase_la_SOURCES += mptext-string.c +EXTRA_DIST += t/mptext + +## Basic types used in the representation of multiprecision integers. +nodist_archinclude_HEADERS += mptypes.h +BUILT_SOURCES += mptypes.h +CLEANFILES += mptypes.h +noinst_PROGRAMS += mptypes +mptypes.h: mptypes$e + $(AM_V_GEN)./mptypes >mptypes.h.new && mv mptypes.h.new mptypes.h + +## Low-level multiprecision arithmetic. +pkginclude_HEADERS += mpx.h bitops.h mpw.h +libmpbase_la_SOURCES += mpx.c +TESTS += mpx.$t +libmpbase_la_SOURCES += karatsuba.h mpx-kmul.c mpx-ksqr.c +TESTS += mpx-kmul.$t mpx-ksqr.$t +noinst_PROGRAMS += bittest +TESTS += bittest +EXTRA_DIST += t/mpx + +## A quick-and-dirty parser, used for parsing descriptions of groups, fields, +## etc. +pkginclude_HEADERS += qdparse.h +libmath_la_SOURCES += qdparse.c + +## Pollard's `rho' algorithm for determining discrete logarithms. +pkginclude_HEADERS += rho.h +libmath_la_SOURCES += rho.c +TESTS += rho.$t + +###-------------------------------------------------------------------------- +### Prime number checking, searching, and related jobs. + +## Generating Lim--Lee groups, i.e., unit groups of finite fields without +## small subgroups (except for the obvious ones). +pkginclude_HEADERS += limlee.h +libmath_la_SOURCES += limlee.c + +## A table of small prime numbers. +nodist_pkginclude_HEADERS += primetab.h +nodist_libmath_la_SOURCES += primetab.c +CLEANFILES += primetab.h primetab.c +BUILT_SOURCES += primetab.h primetab.c +noinst_PROGRAMS += genprimes +genprimes_LDADD = $(mLib_LIBS) +primetab.h: primetab.c +primetab.c: genprimes$e + $(AM_V_GEN)./genprimes -hprimetab.h -cprimetab.c \ + -sCATACOMB_PRIMETAB_H \ + -n256 -t"unsigned short" -iprimetab + +## Filtering candidate prime numbers by checking for small factors +## efficiently. +pkginclude_HEADERS += pfilt.h +libmath_la_SOURCES += pfilt.c + +## Generating prime numbers (and other kinds of numbers which need searching +## for). +pkginclude_HEADERS += pgen.h +libmath_la_SOURCES += pgen.c +libmath_la_SOURCES += pgen-gcd.c +libmath_la_SOURCES += pgen-simul.c +libmath_la_SOURCES += pgen-stdev.c +TESTS += pgen.$t +EXTRA_DIST += t/pgen + +## Finding primitive elements in finite fields. +pkginclude_HEADERS += prim.h +libmath_la_SOURCES += prim.c + +## Iterating over all prime numbers from a given starting point. +pkginclude_HEADERS += primeiter.h +libmath_la_SOURCES += primeiter.c +TESTS += primeiter.$t +primeiter.lo: wheel.h + +## The Miller--Rabin primality test. +pkginclude_HEADERS += rabin.h +libmath_la_SOURCES += rabin.c + +## Finding `strong' primes, using Gordon's algorithm. Once upon a time, +## products of these kinds of numbers were harder to factor. +pkginclude_HEADERS += strongprime.h +libmath_la_SOURCES += strongprime.c + +## A `wheel', used by the prime iteration machinery. +nodist_pkginclude_HEADERS += wheel.h +nodist_libmath_la_SOURCES += wheel.c +CLEANFILES += wheel.h wheel.c +noinst_PROGRAMS += genwheel +genwheel_LDADD = $(mLib_LIBS) +wheel.h: wheel.c +wheel.c: genwheel$e + $(AM_V_GEN)./genwheel -hwheel.h -cwheel.c \ + -sCATACOMB_WHEEL_H \ + -n5 -t"unsigned char" -iwheel + +###-------------------------------------------------------------------------- +### Binary polynomial arithmetic. + +## User-visible binary polynomial arithmetic. +pkginclude_HEADERS += gf.h +libmath_la_SOURCES += gf-arith.c +TESTS += gf-arith.$t +libmath_la_SOURCES += gf-exp.c gf-exp.h +libmath_la_SOURCES += gf-gcd.c +TESTS += gf-gcd.$t +EXTRA_DIST += t/gf + +## Low-level binary polynomial arithmetic. +pkginclude_HEADERS += gfx.h +libmath_la_SOURCES += gfx.c +TESTS += gfx.$t +libmath_la_SOURCES += gfx-kmul.c +TESTS += gfx-kmul.$t +libmath_la_SOURCES += gfx-sqr.c +gfx-sqr.lo: gfx-sqr-tab.h +TESTS += gfx-sqr.$t +CLEANFILES += gfx-sqr-tab.h +noinst_PROGRAMS += gfx-sqr-mktab +gfx-sqr-tab.h: gfx-sqr-mktab$e + $(AM_V_GEN)./gfx-sqr-mktab >gfx-sqr-tab.h.in && \ + mv gfx-sqr-tab.h.in gfx-sqr-tab.h +EXTRA_DIST += t/gfx + +## Conversions between normal and polynomial basis representations for binary +## fields. +pkginclude_HEADERS += gfn.h +libmath_la_SOURCES += gfn.c +TESTS += gfn.$t +EXTRA_DIST += t/gfn + +## Efficient reduction modulo sparse polynomials. +pkginclude_HEADERS += gfreduce.h +libmath_la_SOURCES += gfreduce.c gfreduce-exp.h +TESTS += gfreduce.$t +EXTRA_DIST += t/gfreduce + +###-------------------------------------------------------------------------- +### Abstractions for various kinds of algebraic objects. + +## Abstract cyclic groups. +pkginclude_HEADERS += group.h group-guts.h +libmath_la_SOURCES += group-dstr.c +libmath_la_SOURCES += group-exp.c group-exp.h +libmath_la_SOURCES += group-file.c +libmath_la_SOURCES += group-parse.c +libmath_la_SOURCES += group-stdops.c +libmath_la_SOURCES += group-string.c +libmath_la_SOURCES += g-bin.c +libmath_la_SOURCES += g-prime.c +libmath_la_SOURCES += g-ec.c +EXTRA_DIST += group-test.c +TESTS += group-test.$t +EXTRA_DIST += t/group + +## Abstract finite fields. +pkginclude_HEADERS += field.h field-guts.h +libmath_la_SOURCES += field.c +libmath_la_SOURCES += field-exp.c field-exp.h +libmath_la_SOURCES += field-parse.c +libmath_la_SOURCES += f-binpoly.c +libmath_la_SOURCES += f-niceprime.c +libmath_la_SOURCES += f-prime.c + +## Table of built-in binary fields. +pkginclude_HEADERS += bintab.h +libmath_la_SOURCES += bintab.c +CLEANFILES += bintab.c +EXTRA_DIST += bintab.in bin-gentab.awk +bintab.c: bintab.in bin-gentab.awk mpdump$e + $(AM_V_GEN)awk -f $(srcdir)/bin-gentab.awk \ + <$(srcdir)/bintab.in >bintab.c.new && \ + mv bintab.c.new bintab.c + +## Table of built-in prime fields. +pkginclude_HEADERS += ptab.h +libmath_la_SOURCES += ptab.c +CLEANFILES += ptab.c +EXTRA_DIST += ptab.in p-gentab.awk +ptab.c: ptab.in p-gentab.awk mpdump$e + $(AM_V_GEN)awk -f $(srcdir)/p-gentab.awk \ + <$(srcdir)/ptab.in >ptab.c.new && \ + mv ptab.c.new ptab.c + +## A utility for building multiprecision integer constants. +noinst_PROGRAMS += mpdump +mpdump_LDADD = libmpbase.la +$(mpdump_OBJECTS): mptypes.h + +###-------------------------------------------------------------------------- +### Elliptic curve arithmetic. + +## Basic elliptic curve arithmetic. +pkginclude_HEADERS += ec.h ec-guts.h +libmath_la_SOURCES += ec.c +libmath_la_SOURCES += ec-exp.c ec-exp.h +libmath_la_SOURCES += ec-info.c +TESTS += ec-info.$t +libmath_la_SOURCES += ec-bin.c +TESTS += ec-bin.$t +libmath_la_SOURCES += ec-prime.c +TESTS += ec-prime.$t +EXTRA_DIST += t/ec + +## The standard `raw' encoding (`EC2OSP') of elliptic curve points. +pkginclude_HEADERS += ec-raw.h +libmath_la_SOURCES += ec-raw.c + +## Assistance for elliptic-curve keys. +pkginclude_HEADERS += ec-keys.h +libmath_la_SOURCES += ec-fetch.c + +## Test infrastructure for elliptic curves. +pkginclude_HEADERS += ec-test.h +libmath_la_SOURCES += ec-test.c +TESTS += ec-test.$t + +## A table of built-in elliptic curves. +pkginclude_HEADERS += ectab.h +libmath_la_SOURCES += ectab.c +CLEANFILES += ectab.c +EXTRA_DIST += ectab.in ec-gentab.awk +ectab.c: ectab.in ec-gentab.awk mpdump$e + $(AM_V_GEN)awk -f $(srcdir)/ec-gentab.awk \ + <$(srcdir)/ectab.in >ectab.c.new && \ + mv ectab.c.new ectab.c + +###----- That's all, folks -------------------------------------------------- diff --git a/math/bin-gentab.awk b/math/bin-gentab.awk new file mode 100755 index 0000000..a848aed --- /dev/null +++ b/math/bin-gentab.awk @@ -0,0 +1,100 @@ +#! /usr/bin/awk -f + +function banner(name, s, i) +{ + s = "/*----- " name " "; + while (length(s) < 75) s = s "-"; + return (s "*/"); +} + +function fix(name) +{ + gsub(/[^0-9A-Za-z_]+/, "_", name); + return (name); +} + +BEGIN { + print "/* -*-c-*-"; + print " *"; + print " * Table of binary groups [generated]"; + print " */"; + print ""; + print "#include \"bintab.h\""; + print ""; + print "#define N(x) (sizeof(x)/sizeof(*x))"; + print "#define MP(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }"; + print "#define NOMP { 0, 0, 0, 0, 0 }"; + print ""; + print banner("Binary group data"); + print ""; + + d_i = 0; + name = ""; +} + +function putmp(x, d) +{ + if (!(x in data)) { + print "group " name ": missing " x >"/dev/stderr"; + exit 1; + } + d = data[x]; + if (!(d in cache)) { + n = "p_" fix(name) "_" x; + print "static mpw " n "[] = {"; + system("./mpdump " d); + print "};"; + print ""; + cache[d] = n; + } + mp[x] = cache[d]; +} + +function flush() +{ + if (name == "") return; + print "/* --- Group " name " --- */"; + delete mp; + print ""; + putmp("p"); + putmp("q"); + putmp("g"); + print "static bindata bin_" fix(name) " = {"; + print " MP(" mp["p"] ")," + print " MP(" mp["q"] ")," + print " MP(" mp["g"] ")" + print "};"; + print ""; + dname[d_i++] = name; + d[name] = name; + r[name] = "bin_" fix(name); + name = ""; +} + +/^[ \t]*(#|$)/ { next; } + +$1 == "alias" { flush(); dname[d_i++] = $2; d[$2] = $3; next; } + +$1 == "group" { flush(); delete data; name = $2; next; } + +{ data[$1] = $2; next; } + +END { + flush(); + print banner("Main table"); + print ""; + print "const binentry bintab[] = {"; + for (i = 0; i < d_i; i++) { + name = dname[i]; + rname = d[name]; + if (!rname in r) { + print "group " rname " not found (alias from " name ")" >"/dev/stderr"; + exit 1; + } + print " { \"" name "\", &" r[rname] " },"; + } + print " { 0, 0 }"; + print "};" + print ""; + print banner("That's all, folks"); +} diff --git a/math/bintab.h b/math/bintab.h new file mode 100644 index 0000000..dba336c --- /dev/null +++ b/math/bintab.h @@ -0,0 +1,55 @@ +/* -*-c-*- + * + * Table of standard (ish) binary groups + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_BINTAB_H +#define CATACOMB_BINTAB_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "ptab.h" + +/*----- Data structures ---------------------------------------------------*/ + +typedef pdata bindata; +typedef pentry binentry; + +/*----- Global variables --------------------------------------------------*/ + +extern const binentry bintab[]; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/bintab.in b/math/bintab.in new file mode 100644 index 0000000..a33badf --- /dev/null +++ b/math/bintab.in @@ -0,0 +1,35 @@ +# Standard binary groups + +#----- From P1363 annex A --------------------------------------------------- + +group p1363-40 + p 0x200000000000000000000000000000000000000000000065 + q 0xabbcb671934086d21ff5f7 + g 0x66704fca38d7962439e5f9bdab4d9ac6f0dd745c72f822e + +group p1363-56 + p 0x100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100d + q 0x5538ed0653399777d80d50e508fd01 + g 0x44e2fd3317b4a1968ce65b7e72f8d64262987d0a818a5a5189a6d588b67317c9ee05a38e3e5691e34933e3e050543d8b + +group p1363-64 + p 0x4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800001 + q 0x84b73a6a902299c1aeeb8b537f1ea87c1 + g 0xce10e3ae38cacb7c1076723b80be855c629c03abef26d2a5ca898f75d2bd794daa9e21781f063ab2785a8c402f976d73e5c8d66072cd950dee1ea722bb8f3d + +group p1363-80 + p 0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080043 + q 0x519f0cb14cf36cfcda7d08fab2b578314c9542801 + g 0xd0f0d0046d995f82b1599c7bceb20010b2ec0d27748d113c532657584c9ea11ab6be6b7236cfafc2a087503e1ad108e559206d559e7c30f4a516da71fa3e08fc50e03084f18af4a59e9c6835beb67dfd2b47ef8d0ea30d8f65e378e9ba82819ffc0ade685fa6cb346dcecca7134893db0a6950c2beab89ee38508f03f2f1f186 + +group p1363-112 + p 0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040481 + q 0x399ac734bd00a6f622bdd00c5f930dcf2ae5d7c521755f7b664f104e423bddd + g 0x40154611e5cd5d4826382b23d4ba28fa9d050bb4db5e81b90816fa2823b62328798b70c061734b327e7e3221002a08554e4902f26c476a152380f49e7e2624066de81ef26ddabf4b2c4cc9374f60189e4e5446e04c39d1de05947c54eb6d8c63e498a83d5025ea9fcf2ff3195fb76d76cc2df73918268b72f693a28a01c14622351cc53546bdaacfc95ad19aee16d3d88fbb5fe8143a8a3dcf3d48525be95bef28921edcee081b5269d0b5307ed97f55e5d0218dd17a39f393e017fcfe999626f1fc6ae9a485395a62a3e969d2e0cce55755cc0e22c4356741313d762505c9a2594af3e94d8f913798d92ccf6a73d2447c474ed2924a29856c5c2feeb178a35b15545 + +group p1363-128 + p 0x1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002441 + q 0xa5c52c0d53fc1f43b2cbfd7447d53d55c37004338502dfda0f31b7df76bde74081 + g 0x9447bb7ca087a37a5268c9e4cd3b9c3eb752272af39657d616181d28f18634368ba972a26b93b2980b391e23d7a9313785a5a17adfd9f810a3677cc20342965e09afc81b8413c5b3054c3adffec6411f088942d5877eef220b2a01cd7c48e8bae8f394b2a0893eb293f6355fc3ea962e503ae1d6fd0c3d718de374100cf89cb9c72e125fac9f930abb9959d03ef18354dd16f3a51e42e2c43ef100a8c3ca9523e6decbdf1f67db454df5781d16d55e94663f9633985d2f76b71a9bb10a985a8c6e8cb4190bef038798e9f402ea8027698e9d28a4ee14f0a6724f38dab82578a0e9600fa5717f40d8f107cb148c896c3061945318b25436c04f84a1b0fa043417bf7904915fa6afaed5fd24c73a5a1328973f39e8bc930ccc3099d7f715f8738b13d0b113899200b2293cdba34a46d22c0fab4d8ed33a71c691ba90687000030ad2fe05b5668520e24edb37edcf43827d9cf0b96ff776f88a2041eadd6902e12428716b46533d765d + +#----- That's all, folks ---------------------------------------------------- diff --git a/math/bitops.h b/math/bitops.h new file mode 100644 index 0000000..941f71a --- /dev/null +++ b/math/bitops.h @@ -0,0 +1,60 @@ +/* -*-c-*- + * + * Bit operations by truth table + * + * (c) 2002 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_BITOPS_H +#define CATACOMB_BITOPS_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Macros ------------------------------------------------------------*/ + +#define B0000(x, y) (0u) +#define B0001(x, y) ((x) & (y)) +#define B0010(x, y) ((x) & ~(y)) +#define B0011(x, y) (x) +#define B0100(x, y) (~(x) & (y)) +#define B0101(x, y) (y) +#define B0110(x, y) ((x) ^ (y)) +#define B0111(x, y) ((x) | (y)) +#define B1000(x, y) (~((x) | (y))) +#define B1001(x, y) (~((x) ^ (y))) +#define B1010(x, y) (~(y)) +#define B1011(x, y) ((x) | ~(y)) +#define B1100(x, y) (~(x)) +#define B1101(x, y) (~(x) | (y)) +#define B1110(x, y) (~((x) & (y))) +#define B1111(x, y) (~0u) + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/bittest.c b/math/bittest.c new file mode 100644 index 0000000..5f7b1d7 --- /dev/null +++ b/math/bittest.c @@ -0,0 +1,56 @@ +/* -*-c-*- + * + * Check the bit operations work + * + * (c) 2002 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include "bitops.h" +#include "mpx.h" + +/*----- Main code ---------------------------------------------------------*/ + +int main(void) +{ + int rc = 0; +#define CHECK(string) do { \ + const char *ref = #string; \ + char buf[5]; \ + buf[0] = B##string(0u, 0u) & 1u? '1' : '0'; \ + buf[1] = B##string(0u, 1u) & 1u? '1' : '0'; \ + buf[2] = B##string(1u, 0u) & 1u? '1' : '0'; \ + buf[3] = B##string(1u, 1u) & 1u? '1' : '0'; \ + buf[4] = 0; \ + if (strcmp(buf, ref) != 0) { \ + fprintf(stderr, "mismatch ref `%s' != buf `%s'\n", ref, buf); \ + rc = 1; \ + } \ +} while (0); + MPX_DOBIN(CHECK) + return (rc); +} +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/buf.c b/math/buf.c new file mode 100644 index 0000000..01b6a35 --- /dev/null +++ b/math/buf.c @@ -0,0 +1,127 @@ +/* -*-c-*- + * + * Buffer handling + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "mp.h" +#include "ec.h" +#include "buf.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @buf_getmp@ --- * + * + * Arguments: @buf *b@ = pointer to a buffer block + * + * Returns: A multiprecision integer, or null if there wasn't one there. + * + * Use: Gets a multiprecision integer from a buffer. + */ + +mp *buf_getmp(buf *b) +{ + uint16 sz; + size_t n; + mp *m; + if (buf_getu16(b, &sz) || buf_ensure(b, sz)) + return (0); + m = mp_loadb(MP_NEW, BCUR(b), sz); + n = mp_octets(m); + if (n != sz && n != 0 && sz != 1) { + mp_drop(m); + return (0); + } + BSTEP(b, sz); + return (m); +} + +/* --- @buf_putmp@ --- * + * + * Arguments: @buf *b@ = pointer to a buffer block + * @mp *m@ = a multiprecision integer + * + * Returns: Zero if it worked, nonzero if there wasn't enough space. + * + * Use: Puts a multiprecision integer to a buffer. + */ + +int buf_putmp(buf *b, mp *m) +{ + size_t sz = mp_octets(m); + assert(sz < MASK16); + if (!sz) sz = 1; + if (buf_putu16(b, sz) || buf_ensure(b, sz)) + return (-1); + mp_storeb(m, BCUR(b), sz); + BSTEP(b, sz); + return (0); +} + +/* --- @buf_getec@ --- * + * + * Arguments: @buf *b@ = pointer to a buffer block + * @ec *p@ = where to put the point + * + * Returns: Zero if it worked, nonzero if it failed. + * + * Use: Gets a multiprecision integer from a buffer. The point must + * be initialized. + */ + +int buf_getec(buf *b, ec *p) +{ + mp *x = 0, *y = 0; + uint16 n; + if (buf_ensure(b, 2)) return (-1); + n = LOAD16(BCUR(b)); if (!n) { BSTEP(b, 2); EC_SETINF(p); return (0); } + if ((x = buf_getmp(b)) == 0 || (y = buf_getmp(b)) == 0) { + mp_drop(x); mp_drop(y); return (-1); + } + EC_DESTROY(p); p->x = x; p->y = y; p->z = 0; + return (0); +} + +/* --- @buf_putec@ --- * + * + * Arguments: @buf *b@ = pointer to a buffer block + * @ec *p@ = an elliptic curve point + * + * Returns: Zero if it worked, nonzero if there wasn't enough space. + * + * Use: Puts an elliptic curve point to a buffer. + */ + +int buf_putec(buf *b, ec *p) +{ + if (EC_ATINF(p)) return (buf_putu16(b, 0)); + if (buf_putmp(b, p->x) || buf_putmp(b, p->y)) return (-1); + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/buf.h b/math/buf.h new file mode 100644 index 0000000..d619416 --- /dev/null +++ b/math/buf.h @@ -0,0 +1,104 @@ +/* -*-c-*- + * + * Reading and writing packet buffers + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_BUF_H +#define CATACOMB_BUF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_EC_H +# include "ec.h" +#endif + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @buf_getmp@ --- * + * + * Arguments: @buf *b@ = pointer to a buffer block + * + * Returns: A multiprecision integer, or null if there wasn't one there. + * + * Use: Gets a multiprecision integer from a buffer. + */ + +extern mp *buf_getmp(buf */*b*/); + +/* --- @buf_putmp@ --- * + * + * Arguments: @buf *b@ = pointer to a buffer block + * @mp *m@ = a multiprecision integer + * + * Returns: Zero if it worked, nonzero if there wasn't enough space. + * + * Use: Puts a multiprecision integer to a buffer. + */ + +extern int buf_putmp(buf */*b*/, mp */*m*/); + +/* --- @buf_getec@ --- * + * + * Arguments: @buf *b@ = pointer to a buffer block + * @ec *p@ = where to put the point + * + * Returns: Zero if it worked, nonzero if it failed. + * + * Use: Gets a multiprecision integer from a buffer. The point must + * be initialized. + */ + +extern int buf_getec(buf */*b*/, ec */*p*/); + +/* --- @buf_putec@ --- * + * + * Arguments: @buf *b@ = pointer to a buffer block + * @ec *p@ = an elliptic curve point + * + * Returns: Zero if it worked, nonzero if there wasn't enough space. + * + * Use: Puts an elliptic curve point to a buffer. + */ + +extern int buf_putec(buf */*b*/, ec */*p*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/ec-bin.c b/math/ec-bin.c new file mode 100644 index 0000000..d91b034 --- /dev/null +++ b/math/ec-bin.c @@ -0,0 +1,445 @@ +/* -*-c-*- + * + * Arithmetic for elliptic curves over binary fields + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ec.h" +#include "ec-guts.h" + +/*----- Main code ---------------------------------------------------------*/ + +static const ec_ops ec_binops, ec_binprojops; + +static ec *ecneg(ec_curve *c, ec *d, const ec *p) +{ + EC_COPY(d, p); + if (d->x) + d->y = F_ADD(c->f, d->y, d->y, d->x); + return (d); +} + +static ec *ecprojneg(ec_curve *c, ec *d, const ec *p) +{ + EC_COPY(d, p); + if (d->x) { + mp *t = F_MUL(c->f, MP_NEW, d->x, d->z); + d->y = F_ADD(c->f, d->y, d->y, t); + MP_DROP(t); + } + return (d); +} + +static ec *ecfind(ec_curve *c, ec *d, mp *x) +{ + field *f = c->f; + mp *y, *u, *v; + + if (F_ZEROP(f, x)) + y = F_SQRT(f, MP_NEW, c->b); + else { + u = F_SQR(f, MP_NEW, x); /* %$x^2$% */ + y = F_MUL(f, MP_NEW, u, c->a); /* %$a x^2$% */ + y = F_ADD(f, y, y, c->b); /* %$a x^2 + b$% */ + v = F_MUL(f, MP_NEW, u, x); /* %$x^3$% */ + y = F_ADD(f, y, y, v); /* %$A = x^3 + a x^2 + b$% */ + if (!F_ZEROP(f, y)) { + u = F_INV(f, u, u); /* %$x^{-2}$% */ + v = F_MUL(f, v, u, y); /* %$B = A x^{-2} = x + a + b x^{-2}$% */ + y = F_QUADSOLVE(f, y, v); /* %$z^2 + z = B$% */ + if (y) y = F_MUL(f, y, y, x); /* %$y = z x$% */ + } + MP_DROP(u); + MP_DROP(v); + } + if (!y) return (0); + EC_DESTROY(d); + d->x = MP_COPY(x); + d->y = y; + d->z = MP_COPY(f->one); + return (d); +} + +static ec *ecdbl(ec_curve *c, ec *d, const ec *a) +{ + if (EC_ATINF(a) || F_ZEROP(c->f, a->x)) + EC_SETINF(d); + else { + field *f = c->f; + mp *lambda; + mp *dx, *dy; + + dx = F_INV(f, MP_NEW, a->x); /* %$x^{-1}$% */ + dy = F_MUL(f, MP_NEW, dx, a->y); /* %$y/x$% */ + lambda = F_ADD(f, dy, dy, a->x); /* %$\lambda = x + y/x$% */ + + dx = F_SQR(f, dx, lambda); /* %$\lambda^2$% */ + dx = F_ADD(f, dx, dx, lambda); /* %$\lambda^2 + \lambda$% */ + dx = F_ADD(f, dx, dx, c->a); /* %$x' = a + \lambda^2 + \lambda$% */ + + dy = F_ADD(f, MP_NEW, a->x, dx); /* %$ x + x' $% */ + dy = F_MUL(f, dy, dy, lambda); /* %$ (x + x') \lambda$% */ + dy = F_ADD(f, dy, dy, a->y); /* %$ (x + x') \lambda + y$% */ + dy = F_ADD(f, dy, dy, dx); /* %$ y' = (x + x') \lambda + y + x'$% */ + + EC_DESTROY(d); + d->x = dx; + d->y = dy; + d->z = 0; + MP_DROP(lambda); + } + return (d); +} + +static ec *ecprojdbl(ec_curve *c, ec *d, const ec *a) +{ + if (EC_ATINF(a) || F_ZEROP(c->f, a->x)) + EC_SETINF(d); + else { + field *f = c->f; + ecctx_bin *cc = (ecctx_bin *)c; + mp *dx, *dy, *dz, *u, *v; + + dy = F_SQR(f, MP_NEW, a->z); /* %$z^2$% */ + dx = F_MUL(f, MP_NEW, dy, cc->bb); /* %$c z^2$% */ + dx = F_ADD(f, dx, dx, a->x); /* %$x + c z^2$% */ + dz = F_SQR(f, MP_NEW, dx); /* %$(x + c z^2)^2$% */ + dx = F_SQR(f, dx, dz); /* %$x' = (x + c z^2)^4$% */ + + dz = F_MUL(f, dz, dy, a->x); /* %$z' = x z^2$% */ + + dy = F_SQR(f, dy, a->x); /* %$x^2$% */ + u = F_MUL(f, MP_NEW, a->y, a->z); /* %$y z$% */ + u = F_ADD(f, u, u, dz); /* %$z' + y z$% */ + u = F_ADD(f, u, u, dy); /* %$u = z' + x^2 + y z$% */ + + v = F_SQR(f, MP_NEW, dy); /* %$x^4$% */ + dy = F_MUL(f, dy, v, dz); /* %$x^4 z'$% */ + v = F_MUL(f, v, u, dx); /* %$u x'$% */ + dy = F_ADD(f, dy, dy, v); /* %$y' = x^4 z' + u x'$% */ + + EC_DESTROY(d); + d->x = dx; + d->y = dy; + d->z = dz; + MP_DROP(u); + MP_DROP(v); + } + return (d); +} + +static ec *ecadd(ec_curve *c, ec *d, const ec *a, const ec *b) +{ + if (a == b) + ecdbl(c, d, a); + else if (EC_ATINF(a)) + EC_COPY(d, b); + else if (EC_ATINF(b)) + EC_COPY(d, a); + else { + field *f = c->f; + mp *lambda; + mp *dx, *dy; + + if (!MP_EQ(a->x, b->x)) { + dx = F_ADD(f, MP_NEW, a->x, b->x); /* %$x_0 + x_1$% */ + dy = F_INV(f, MP_NEW, dx); /* %$(x_0 + x_1)^{-1}$% */ + dx = F_ADD(f, dx, a->y, b->y); /* %$y_0 + y_1$% */ + lambda = F_MUL(f, MP_NEW, dy, dx); + /* %$\lambda = (y_0 + y_1)/(x_0 + x_1)$% */ + + dx = F_SQR(f, dx, lambda); /* %$\lambda^2$% */ + dx = F_ADD(f, dx, dx, lambda); /* %$\lambda^2 + \lambda$% */ + dx = F_ADD(f, dx, dx, c->a); /* %$a + \lambda^2 + \lambda$% */ + dx = F_ADD(f, dx, dx, a->x); /* %$a + \lambda^2 + \lambda + x_0$% */ + dx = F_ADD(f, dx, dx, b->x); + /* %$x' = a + \lambda^2 + \lambda + x_0 + x_1$% */ + } else if (!MP_EQ(a->y, b->y) || F_ZEROP(f, a->x)) { + EC_SETINF(d); + return (d); + } else { + dx = F_INV(f, MP_NEW, a->x); /* %$x^{-1}$% */ + dy = F_MUL(f, MP_NEW, dx, a->y); /* %$y/x$% */ + lambda = F_ADD(f, dy, dy, a->x); /* %$\lambda = x + y/x$% */ + + dx = F_SQR(f, dx, lambda); /* %$\lambda^2$% */ + dx = F_ADD(f, dx, dx, lambda); /* %$\lambda^2 + \lambda$% */ + dx = F_ADD(f, dx, dx, c->a); /* %$x' = a + \lambda^2 + \lambda$% */ + dy = MP_NEW; + } + + dy = F_ADD(f, dy, a->x, dx); /* %$ x + x' $% */ + dy = F_MUL(f, dy, dy, lambda); /* %$ (x + x') \lambda$% */ + dy = F_ADD(f, dy, dy, a->y); /* %$ (x + x') \lambda + y$% */ + dy = F_ADD(f, dy, dy, dx); /* %$ y' = (x + x') \lambda + y + x'$% */ + + EC_DESTROY(d); + d->x = dx; + d->y = dy; + d->z = 0; + MP_DROP(lambda); + } + return (d); +} + +static ec *ecprojadd(ec_curve *c, ec *d, const ec *a, const ec *b) +{ + if (a == b) + c->ops->dbl(c, d, a); + else if (EC_ATINF(a)) + EC_COPY(d, b); + else if (EC_ATINF(b)) + EC_COPY(d, a); + else { + field *f = c->f; + mp *dx, *dy, *dz, *u, *uu, *v, *t, *s, *ss, *r, *w, *l; + + dz = F_SQR(f, MP_NEW, b->z); /* %$z_1^2$% */ + u = F_MUL(f, MP_NEW, dz, a->x); /* %$u_0 = x_0 z_1^2$% */ + t = F_MUL(f, MP_NEW, dz, b->z); /* %$z_1^3$% */ + s = F_MUL(f, MP_NEW, t, a->y); /* %$s_0 = y_0 z_1^3$% */ + + dz = F_SQR(f, dz, a->z); /* %$z_0^2$% */ + uu = F_MUL(f, MP_NEW, dz, b->x); /* %$u_1 = x_1 z_0^2$% */ + t = F_MUL(f, t, dz, a->z); /* %$z_0^3$% */ + ss = F_MUL(f, MP_NEW, t, b->y); /* %$s_1 = y_1 z_0^3$% */ + + w = F_ADD(f, u, u, uu); /* %$r = u_0 + u_1$% */ + r = F_ADD(f, s, s, ss); /* %$w = s_0 + s_1$% */ + if (F_ZEROP(f, w)) { + MP_DROP(w); + MP_DROP(uu); + MP_DROP(ss); + MP_DROP(t); + MP_DROP(dz); + if (F_ZEROP(f, r)) { + MP_DROP(r); + return (c->ops->dbl(c, d, a)); + } else { + MP_DROP(r); + EC_SETINF(d); + return (d); + } + } + + l = F_MUL(f, t, a->z, w); /* %$l = z_0 w$% */ + + dz = F_MUL(f, dz, l, b->z); /* %$z' = l z_1$% */ + + ss = F_MUL(f, ss, r, b->x); /* %$r x_1$% */ + t = F_MUL(f, uu, l, b->y); /* %$l y_1$% */ + v = F_ADD(f, ss, ss, t); /* %$v = r x_1 + l y_1$% */ + + t = F_ADD(f, t, r, dz); /* %$t = r + z'$% */ + + uu = F_SQR(f, MP_NEW, dz); /* %$z'^2$% */ + dx = F_MUL(f, MP_NEW, uu, c->a); /* %$a z'^2$% */ + uu = F_MUL(f, uu, t, r); /* %$t r$% */ + dx = F_ADD(f, dx, dx, uu); /* %$a z'^2 + t r$% */ + r = F_SQR(f, r, w); /* %$w^2$% */ + uu = F_MUL(f, uu, r, w); /* %$w^3$% */ + dx = F_ADD(f, dx, dx, uu); /* %$x' = a z'^2 + t r + w^3$% */ + + r = F_SQR(f, r, l); /* %$l^2$% */ + dy = F_MUL(f, uu, v, r); /* %$v l^2$% */ + l = F_MUL(f, l, t, dx); /* %$t x'$% */ + dy = F_ADD(f, dy, dy, l); /* %$y' = t x' + v l^2$% */ + + EC_DESTROY(d); + d->x = dx; + d->y = dy; + d->z = dz; + MP_DROP(l); + MP_DROP(r); + MP_DROP(w); + MP_DROP(t); + MP_DROP(v); + } + return (d); +} + +static int eccheck(ec_curve *c, const ec *p) +{ + field *f = c->f; + int rc; + mp *u, *v; + + if (EC_ATINF(p)) return (0); + v = F_SQR(f, MP_NEW, p->x); + u = F_MUL(f, MP_NEW, v, p->x); + v = F_MUL(f, v, v, c->a); + u = F_ADD(f, u, u, v); + u = F_ADD(f, u, u, c->b); + v = F_MUL(f, v, p->x, p->y); + u = F_ADD(f, u, u, v); + v = F_SQR(f, v, p->y); + u = F_ADD(f, u, u, v); + rc = F_ZEROP(f, u) ? 0 : -1; + mp_drop(u); + mp_drop(v); + return (rc); +} + +static int ecprojcheck(ec_curve *c, const ec *p) +{ + ec t = EC_INIT; + int rc; + + c->ops->fix(c, &t, p); + rc = eccheck(c, &t); + EC_DESTROY(&t); + return (rc); +} + +static void ecdestroy(ec_curve *c) +{ + ecctx_bin *cc = (ecctx_bin *)c; + MP_DROP(cc->c.a); + MP_DROP(cc->c.b); + if (cc->bb) MP_DROP(cc->bb); + DESTROY(cc); +} + +/* --- @ec_bin@, @ec_binproj@ --- * + * + * Arguments: @field *f@ = the underlying field for this elliptic curve + * @mp *a, *b@ = the coefficients for this curve + * + * Returns: A pointer to the curve, or null. + * + * Use: Creates a curve structure for an elliptic curve defined over + * a binary field. The @binproj@ variant uses projective + * coordinates, which can be a win. + */ + +ec_curve *ec_bin(field *f, mp *a, mp *b) +{ + ecctx_bin *cc = CREATE(ecctx_bin); + cc->c.ops = &ec_binops; + cc->c.f = f; + cc->c.a = F_IN(f, MP_NEW, a); + cc->c.b = F_IN(f, MP_NEW, b); + cc->bb = 0; + return (&cc->c); +} + +ec_curve *ec_binproj(field *f, mp *a, mp *b) +{ + ecctx_bin *cc = CREATE(ecctx_bin); + int i; + mp *c, *d; + + cc->c.ops = &ec_binprojops; + cc->c.f = f; + cc->c.a = F_IN(f, MP_NEW, a); + cc->c.b = F_IN(f, MP_NEW, b); + + c = MP_COPY(cc->c.b); + for (i = 0; i < f->nbits - 2; i++) + c = F_SQR(f, c, c); + d = F_SQR(f, MP_NEW, c); d = F_SQR(f, d, d); + if (!MP_EQ(d, cc->c.b)) { + MP_DROP(c); + MP_DROP(d); + MP_DROP(cc->c.a); + MP_DROP(cc->c.b); + DESTROY(cc); + return (0); + } + cc->bb = c; + MP_DROP(d); + return (&cc->c); +} + +static const ec_ops ec_binops = { + "bin", + ecdestroy, ec_stdsamep, ec_idin, ec_idout, ec_idfix, + ecfind, ecneg, ecadd, ec_stdsub, ecdbl, eccheck +}; + +static const ec_ops ec_binprojops = { + "binproj", + ecdestroy, ec_stdsamep, ec_projin, ec_projout, ec_projfix, + ecfind, ecprojneg, ecprojadd, ec_stdsub, ecprojdbl, ecprojcheck +}; + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#define MP(x) mp_readstring(MP_NEW, #x, 0, 0) + +int main(int argc, char *argv[]) +{ + field *f; + ec_curve *c; + ec g = EC_INIT, d = EC_INIT; + mp *p, *a, *b, *r, *beta; + int i, n = argc == 1 ? 1 : atoi(argv[1]); + + printf("ec-bin: "); + fflush(stdout); + a = MP(0x7ffffffffffffffffffffffffffffffffffffffff); + b = MP(0x6645f3cacf1638e139c6cd13ef61734fbc9e3d9fb); + p = MP(0x800000000000000000000000000000000000000c9); + beta = MP(0x715169c109c612e390d347c748342bcd3b02a0bef); + r = MP(0x040000000000000000000292fe77e70c12a4234c32); + + f = field_binnorm(p, beta); + c = ec_binproj(f, a, b); + g.x = MP(0x0311103c17167564ace77ccb09c681f886ba54ee8); + g.y = MP(0x333ac13c6447f2e67613bf7009daf98c87bb50c7f); + + for (i = 0; i < n; i++) { + ec_mul(c, &d, &g, r); + if (EC_ATINF(&d)) { + fprintf(stderr, "zero too early\n"); + return (1); + } + ec_add(c, &d, &d, &g); + if (!EC_ATINF(&d)) { + fprintf(stderr, "didn't reach zero\n"); + MP_EPRINTX("d.x", d.x); + MP_EPRINTX("d.y", d.y); + return (1); + } + ec_destroy(&d); + } + + ec_destroy(&g); + ec_destroycurve(c); + F_DESTROY(f); + MP_DROP(p); MP_DROP(a); MP_DROP(b); MP_DROP(r); MP_DROP(beta); + assert(!mparena_count(&mparena_global)); + printf("ok\n"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/ec-exp.c b/math/ec-exp.c new file mode 100644 index 0000000..b2f1ceb --- /dev/null +++ b/math/ec-exp.c @@ -0,0 +1,141 @@ +/* -*-c-*- + * + * Point multiplication for elliptic curves + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "ec.h" +#include "ec-exp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @ec_imul@, @ec_mul@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @const ec *p@ = pointer to the generator point + * @mp *n@ = integer multiplier + * + * Returns: The destination @d@. + * + * Use: Multiplies a point by a scalar, returning %$n p$%. The + * @imul@ variant uses internal representations for argument + * and result. + */ + +ec *ec_imul(ec_curve *c, ec *d, const ec *p, mp *n) +{ + ec t = EC_INIT; + + EC_COPY(&t, p); + if (t.x && (n->f & MP_BURN)) + t.x->f |= MP_BURN; + MP_SHRINK(n); + EC_SETINF(d); + if (MP_ZEROP(n)) + ; + else { + if (MP_NEGP(n)) + EC_NEG(c, &t, &t); + if (MP_LEN(n) < EXP_THRESH) + EXP_SIMPLE(*d, t, n); + else + EXP_WINDOW(*d, t, n); + } + EC_DESTROY(&t); + return (d); +} + +ec *ec_mul(ec_curve *c, ec *d, const ec *p, mp *n) +{ + EC_IN(c, d, p); + ec_imul(c, d, d, n); + return (EC_OUT(c, d, d)); +} + +/* --- @ec_mmul@, @ec_immul@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @const ec_mulfactor *f@ = pointer to vector of factors + * @size_t n@ = number of factors + * + * Returns: The destination @d@. + * + * Use: Does simultaneous point multiplication. The @immul@ variant + * uses internal representations for arguments and result. + */ + +#undef EXP_WINSZ +#define EXP_WINSZ 3 + +static ec *immul(ec_curve *c, ec *d, ec_mulfactor *f, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) { + MP_SHRINK(f[i].exp); + if (MP_NEGP(f[i].exp)) + EC_NEG(c, &f[i].base, &f[i].base); + if (f[i].base.x && f[i].exp->f & MP_BURN) + f[i].base.x->f |= MP_BURN; + } + EC_SETINF(d); + EXP_SIMUL(*d, f, n); + for (i = 0; i < n; i++) + EC_DESTROY(&f[i].base); + xfree(f); + return (d); +} + +ec *ec_immul(ec_curve *c, ec *d, const ec_mulfactor *f, size_t n) +{ + ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor)); + size_t i; + + for (i = 0; i < n; i++) { + EC_CREATE(&ff[i].base); + EC_COPY(&ff[i].base, &f[i].base); + ff[i].exp = f[i].exp; + } + return (immul(c, d, ff, n)); +} + +ec *ec_mmul(ec_curve *c, ec *d, const ec_mulfactor *f, size_t n) +{ + ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor)); + size_t i; + + for (i = 0; i < n; i++) { + EC_CREATE(&ff[i].base); + EC_IN(c, &ff[i].base, &f[i].base); + ff[i].exp = f[i].exp; + } + immul(c, d, ff, n); + return (EC_OUT(c, d, d)); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/ec-exp.h b/math/ec-exp.h new file mode 100644 index 0000000..6cad753 --- /dev/null +++ b/math/ec-exp.h @@ -0,0 +1,67 @@ +/* -*-c-*- + * + * Exponentiation operations for elliptic curves + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_EC_EXP_H +#define CATACOMB_EC_EXP_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Exponentation definitions -----------------------------------------*/ + +#define EXP_TYPE ec + +#define EXP_COPY(d, p) do { \ + (d).x = MP_COPY((p).x); \ + (d).y = MP_COPY((p).y); \ + (d).z = (p).z ? MP_COPY((p).z) : MP_NEW; \ +} while (0) +#define EXP_DROP(x) EC_DESTROY(&(x)) + +#define EXP_MUL(a, x) EC_ADD(c, &(a), &(a), &(x)) +#define EXP_SQR(a) EC_DBL(c, &(a), &(a)) +#define EXP_FIX(x) + +#define EXP_SETMUL(d, x, y) do { \ + EC_CREATE(&(d)); \ + EC_ADD(c, &(d), &(x), &(y)); \ +} while (0) +#define EXP_SETSQR(d, x) do { \ + EC_CREATE(&(d)); \ + EC_DBL(c, &(d), &(x)); \ +} while (0) + +#include "exp.h" + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/ec-fetch.c b/math/ec-fetch.c new file mode 100644 index 0000000..3484d52 --- /dev/null +++ b/math/ec-fetch.c @@ -0,0 +1,89 @@ +/* -*-c-*- + * + * Key fetching for elliptic curve public and private keys + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "ec-keys.h" +#include "key.h" + +/*----- Key fetching ------------------------------------------------------*/ + +const key_fetchdef ec_paramfetch[] = { + { "curve", offsetof(ec_pub, cstr), KENC_STRING, 0 }, + { 0, 0, 0, 0 } +}; + +const key_fetchdef ec_pubfetch[] = { + { "curve", offsetof(ec_pub, cstr), KENC_STRING, 0 }, + { "p", offsetof(ec_pub, p), KENC_EC, 0 }, + { 0, 0, 0, 0 } +}; + +static const key_fetchdef priv[] = { + { "x", offsetof(ec_priv, x), KENC_MP, 0 }, + { 0, 0, 0, 0 } +}; + +const key_fetchdef ec_privfetch[] = { + { "curve", offsetof(ec_pub, cstr), KENC_STRING, 0 }, + { "p", offsetof(ec_pub, p), KENC_EC, 0 }, + { "private", 0, KENC_STRUCT, priv }, + { 0, 0, 0, 0 } +}; + +/* --- @ec_paramfree@, @ec_pubfree@, @ec_privfree@ --- * + * + * Arguments: @ec_param *ep@, @ec_pub *ep@, @ec_priv *ep@ = pointer to + * key block to free + * + * Returns: --- + * + * Use: Frees an elliptic curve key block + */ + +void ec_paramfree(ec_param *ep) +{ + if (ep->ei.c) ec_freeinfo(&ep->ei); + xfree(ep->cstr); +} + +void ec_pubfree(ec_pub *ep) +{ + if (ep->ei.c) ec_freeinfo(&ep->ei); + xfree(ep->cstr); + EC_DESTROY(&ep->p); +} + +void ec_privfree(ec_priv *ep) +{ + if (ep->ei.c) ec_freeinfo(&ep->ei); + xfree(ep->cstr); + EC_DESTROY(&ep->p); + mp_drop(ep->x); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/ec-gentab.awk b/math/ec-gentab.awk new file mode 100755 index 0000000..37ccacc --- /dev/null +++ b/math/ec-gentab.awk @@ -0,0 +1,114 @@ +#! /usr/bin/awk -f + +function banner(name, s, i) +{ + s = "/*----- " name " "; + while (length(s) < 75) s = s "-"; + return (s "*/"); +} + +function fix(name) +{ + gsub(/[^0-9A-Za-z_]+/, "_", name); + return (name); +} + +BEGIN { + print "/* -*-c-*-"; + print " *"; + print " * Table of elliptic curves [generated]"; + print " */"; + print ""; + print "#include \"ectab.h\""; + print ""; + print "#define N(x) (sizeof(x)/sizeof(*x))"; + print "#define MP(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }"; + print "#define NOMP { 0, 0, 0, 0, 0 }"; + print ""; + print banner("Curve data"); + print ""; + + d_i = 0; + name = ""; +} + +function putmp(x, d) +{ + if (!(x in data)) { + print "curve " name ": missing " x >"/dev/stderr"; + exit 1; + } + d = data[x]; + if (!(d in cache)) { + n = "c_" fix(name) "_" x; + print "static mpw " n "[] = {"; + system("./mpdump " d); + print "};"; + print ""; + cache[d] = n; + } + mp[x] = cache[d]; +} + +function flush() +{ + if (name == "") return; + print "/* --- Curve " name " --- */"; + delete mp; + print ""; + putmp("p"); + if (type == "binnorm") putmp("beta"); + putmp("a"); + putmp("b"); + putmp("r"); + putmp("h"); + putmp("gx"); + putmp("gy"); + print "static ecdata c_" fix(name) " = {"; + print " FTAG_" toupper(type) ","; + print " MP(" mp["p"] ")," + if (type == "binnorm") + print " MP(" mp["beta"] "),"; + else + print " NOMP,"; + print " MP(" mp["a"] ")," + print " MP(" mp["b"] ")," + print " MP(" mp["r"] ")," + print " MP(" mp["h"] ")," + print " MP(" mp["gx"] ")," + print " MP(" mp["gy"] ")" + print "};"; + print ""; + dname[d_i++] = name; + d[name] = name; + r[name] = "c_" fix(name); + name = ""; +} + +/^[ \t]*(#|$)/ { next; } + +$1 == "alias" { flush(); dname[d_i++] = $2; d[$2] = $3; next; } + +$1 == "curve" { flush(); delete data; name = $2; type = $3; next; } + +{ data[$1] = $2; next; } + +END { + flush(); + print banner("Main table"); + print ""; + print "const ecentry ectab[] = {"; + for (i = 0; i < d_i; i++) { + name = dname[i]; + rname = d[name]; + if (!rname in r) { + print "curve " rname " not found (alias from " name ")" >"/dev/stderr"; + exit 1; + } + print " { \"" name "\", &" r[rname] " },"; + } + print " { 0, 0 }"; + print "};" + print ""; + print banner("That's all, folks"); +} diff --git a/math/ec-guts.h b/math/ec-guts.h new file mode 100644 index 0000000..8568e62 --- /dev/null +++ b/math/ec-guts.h @@ -0,0 +1,58 @@ +/* -*-c-*- + * + * Internal structures for built-in elliptic curve types + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_EC_GUTS_H +#define CATACOMB_EC_GUTS_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_EC_H +# include "ec.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct ecctx_bin { + ec_curve c; + mp *bb; +} ecctx_bin; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/ec-info.c b/math/ec-info.c new file mode 100644 index 0000000..21d21fd --- /dev/null +++ b/math/ec-info.c @@ -0,0 +1,779 @@ +/* -*-c-*- + * + * Elliptic curve information management + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ec.h" +#include "ectab.h" +#include "gf.h" +#include "keysz.h" +#include "mpbarrett.h" +#include "pgen.h" +#include "primeiter.h" +#include "mprand.h" +#include "mpint.h" +#include "rabin.h" + +/*----- Embedding degree checking -----------------------------------------* + * + * Let %$q = p^m$% be a prime power, and let %$E$% be an elliptic curve over + * %$\gf{q}$% with %$n = \#E(\gf{q}) = r h$% where %$r$% is prime. Then the + * Weil and Tate pairings can be used to map %$r$%-torsion points on + * %$E(\gf{q})$% onto the %$r$%-th roots of unity (i.e., the order-%$r$% + * subgroup) in an extension field %$\gf{p^k}$% of %$\gf{p}$% (%%\emph{not}%% + * of %$\gf{q}$% -- see [Hitt]). We call the smallest such %$k$% the + * %%\emph{embedding degree}%% of the curve %$E$%. The + * Menezes-Okamoto-Vanstone (MOV) attack solves the discrete log problem in + * %$E(\gf{q})$% by using the pairing and then applying index calculus to + * extract a discrete log in %$\gf{p^k}$%; obviously this only works if %$k$% + * is small enough. + * + * The usual check, suggested in, e.g., [P1363] or [SEC1], only covers + * extension fields %$\gf{q^\ell}$% of %$\gf{q}$%, which is fine when %$q$% + * is prime, but when we're dealing with binary fields it works less well. + * Indeed, as [Hitt] demonstrates, the embedding field can actually be + * %%\emph{smaller}%% than %$\gf{q}$%, and choosing %$m$% prime doesn't help + * (even though I previously thought it did). + * + * Define the %%\emph{embedding degree bound}%% %$B$% to be the smallest + * %$i$% such that discrete logs in %$\gf{p^i}$% are about as hard as in + * %$E(\gf{q})$%. + * + * The embedding group is a subgroup of the multiplicative group + * %$\gf{p^k}^*$% which contains %$p^k - 1$% elements; therefore we must have + * %$r \mid p^k - 1$%, or, equivalently, %$p^k \equiv 1 \pmod{r}$%. + * + * The recommended checking procedure, e.g., in [P1363], is just to check + * %$q^i \not\equiv 1 \pmod{r}$% for each %$0 < i < B$%. This is fast when + * you only consider extension fields of %$\gf{q}$%, since %$B$% is at most + * about 27. However, as noted above, this is inadequate when %$q$% is a + * prime power, and we must check all the extension fields of %$p$%. Now + * %$B$% can be about 15000, which is rather scarier -- we need a better + * algorithm. + * + * As noted, we must have %$p^k \equiv 1 \pmod{r}$%; but by minimality of + * %$k$%, we must have %$p^i \not\equiv 1 \pmod{r}$% for %$0 < i < k$%. + * Therefore %$p$% generates an order-%$k$% subgroup in %$\gf{r}^*$%, so we + * must have %$k \mid r - 1$%. + * + * Of course, factoring %$r - 1$% is a mug's game; but we're not interested + * in the complete factorization -- just the %$B$%-smooth portion. An + * algorithm suggests itself: + * + * 1. Extract the factors of %$r - 1$% which are less than %$B$%. + * + * 2. For each divisor %$d$% of %$r - 1$% less than %$B$% (which we can + * construct using this factorization), make sure that + * %$p^d \not\equiv 1 \pmod{r}$%. + * + * This takes a little while but not ever-so long. + * + * This is enough for cryptosystems based on the computational Diffie- + * Hellman problem to be secure. However, it's %%\emph{not}%% enough for the + * %%\emph{decisional}%% Diffie-Hellman problem to be hard; it appears we + * also need to hope that there aren't any suitable distortion maps with + * which one can solve the DDH problem. I don't know how to check for those + * at the moment. + * + * We'll take the subgroup order as indicative of the security level actually + * wanted. Then, to ensure security against the MOV attack, we must ensure + * that the embedding degree is sufficiently large that discrete logs in + * %$\gf{q^m}$% are at least as hard as discrete logs over the curve. + * + * We actually allow a small amount of slop in the conversions, in order to + * let people pick nice round numbers for their key lengths. + * + * References: + * + * [Hitt] L. Hitt, On an improved definition of embedding degree; + * http://eprint.iacr.org/2006/415 + * + * [P1363] IEEE 1363-2000: Standard Specifications for Public Key + * Cryptography; http://grouper.ieee.org/groups/1363/P1363/index.html + * + * [SEC1] SEC 1: Elliptic Curve Cryptography; + * http://www.secg.org/download/aid-385/sec1_final.pdf + */ + +/* --- @movcheck@ --- * + * + * Arguments: @mp *r@ = curve subgroup order + * @mp *p@ = field characteristic + * @unsigned long B@ = embedding degree bound + * + * Returns: Zero if OK, nonzero if an embedding was found. + * + * Use: Checks a curve for embeddings with degree less than the + * stated bound %$B$%. See above for explanation and a + * description of the algorithm. + */ + +static int movcheck(mp *r, mp *p, unsigned long B) +{ + mpmont mm; + mp *r1, *pp = MP_NEW, *t = MP_NEW, *u = MP_NEW, *v = MP_NEW, *tt; + struct factor { + unsigned long f; + unsigned c, e; + }; + DA_DECL(factor_v, struct factor); + factor_v fv = DA_INIT; + size_t nf; + struct factor *ff; + primeiter pi; + mp *BB; + unsigned long d, f; + unsigned i, j; + int rc = 0; + + /* --- Special case --- * + * + * If %$r = 2$% then (a) Montgomery reduction won't work, and (b) we have + * no security worth checking anyway. Otherwise we're guaranteed that + * %$r$% is a prime, so it must be odd. + */ + + if (MP_EQ(r, MP_TWO)) + return (0); + + /* --- First factor the %$B%-smooth portion of %$r - 1$% --- * + * + * We can generate prime numbers up to %$B$% efficiently, so trial division + * it is. + */ + + BB = mp_fromulong(MP_NEW, B); + r1 = mp_sub(MP_NEW, r, MP_ONE); + primeiter_create(&pi, 0); + for (;;) { + pp = primeiter_next(&pi, pp); + if (MP_CMP(pp, >, BB)) + break; + mp_div(&u, &v, r1, pp); + if (!MP_ZEROP(v)) + continue; + i = 0; + do { + tt = r1; r1 = u; u = tt; i++; + mp_div(&u, &v, r1, pp); + } while (MP_ZEROP(v)); + DA_ENSURE(&fv, 1); + DA_UNSAFE_EXTEND(&fv, 1); + DA_LAST(&fv).f = mp_toulong(pp); + DA_LAST(&fv).e = i; + DA_LAST(&fv).c = 0; + } + MP_DROP(BB); MP_DROP(pp); primeiter_destroy(&pi); + nf = DA_LEN(&fv); ff = DA(&fv); + + /* --- Now generate divisors of %$r - 1$% less than %$B$% --- * + * + * For each divisor %$d$%, check whether %$p^d \equiv 1 \pmod{r}$%. + */ + + mpmont_create(&mm, r); + u = mpmont_mul(&mm, u, p, mm.r2); + for (;;) { + + /* --- Construct the divisor --- */ + + d = 1; + for (i = 0; i < nf; i++) { + f = ff[i].f; j = ff[i].c; if (!j) continue; + for (;;) { + if (f >= (B + d - 1)/d) goto toobig; + if (j & 1) d *= f; + j >>= 1; if (!j) break; + f *= f; + } + } + v = mp_fromulong(v, d); + + /* --- Compute %$p^k \bmod r$% and check --- */ + + t = mpmont_expr(&mm, t, u, v); + if (MP_EQ(t, mm.r)) { + rc = -1; + break; + } + + /* --- Step the divisors along --- */ + + toobig: + for (i = 0; i < nf; i++) { + if (ff[i].c < ff[i].e) { + ff[i].c++; + goto more; + } + ff[i].c = 0; + } + break; + more:; + } + + /* --- Clear away the debris --- */ + + mpmont_destroy(&mm); + MP_DROP(t); MP_DROP(u); MP_DROP(v); MP_DROP(r1); + DA_DESTROY(&fv); + return (rc); +} + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @ec_curveparse@ --- * + * + * Arguments: @qd_parse *qd@ = parser context + * + * Returns: Elliptic curve pointer if OK, or null. + * + * Use: Parses an elliptic curve description, which has the form + * + * * a field description + * * an optional `;' + * * `prime', `primeproj', `bin', or `binproj' + * * an optional `:' + * * the %$a$% parameter + * * an optional `,' + * * the %$b$% parameter + */ + +ec_curve *ec_curveparse(qd_parse *qd) +{ + mp *a = MP_NEW, *b = MP_NEW; + ec_curve *c; + field *f; + + if ((f = field_parse(qd)) == 0) goto fail; + qd_delim(qd, ';'); + switch (qd_enum(qd, "prime,primeproj,bin,binproj")) { + case 0: + if (F_TYPE(f) != FTY_PRIME) { + qd->e = "field not prime"; + goto fail; + } + qd_delim(qd, ':'); + if ((a = qd_getmp(qd)) == 0) goto fail; + qd_delim(qd, ','); + if ((b = qd_getmp(qd)) == 0) goto fail; + c = ec_prime(f, a, b); + break; + case 1: + if (F_TYPE(f) != FTY_PRIME) { + qd->e = "field not prime"; + goto fail; + } + qd_delim(qd, ':'); + if ((a = qd_getmp(qd)) == 0) goto fail; + qd_delim(qd, ','); + if ((b = qd_getmp(qd)) == 0) goto fail; + c = ec_primeproj(f, a, b); + break; + case 2: + if (F_TYPE(f) != FTY_BINARY) { + qd->e = "field not binary"; + goto fail; + } + qd_delim(qd, ':'); + if ((a = qd_getmp(qd)) == 0) goto fail; + qd_delim(qd, ','); + if ((b = qd_getmp(qd)) == 0) goto fail; + c = ec_bin(f, a, b); + break; + case 3: + if (F_TYPE(f) != FTY_BINARY) { + qd->e = "field not binary"; + goto fail; + } + qd_delim(qd, ':'); + if ((a = qd_getmp(qd)) == 0) goto fail; + qd_delim(qd, ','); + if ((b = qd_getmp(qd)) == 0) goto fail; + c = ec_binproj(f, a, b); + break; + default: + goto fail; + } + if (!c) { + qd->e = "bad curve parameters"; + goto fail; + } + if (a) MP_DROP(a); + if (b) MP_DROP(b); + return (c); + +fail: + if (f) F_DESTROY(f); + if (a) MP_DROP(a); + if (b) MP_DROP(b); + return (0); +} + +/* --- @ec_ptparse@ --- * + * + * Arguments: @qd_parse *qd@ = parser context + * @ec *p@ = where to put the point + * + * Returns: The point address, or null. + * + * Use: Parses an elliptic curve point. This has the form + * + * * %$x$%-coordinate + * * optional `,' + * * %$y$%-coordinate + */ + +ec *ec_ptparse(qd_parse *qd, ec *p) +{ + mp *x = MP_NEW, *y = MP_NEW; + + if (qd_enum(qd, "inf") >= 0) { + EC_SETINF(p); + return (p); + } + if ((x = qd_getmp(qd)) == 0) goto fail; + qd_delim(qd, ','); + if ((y = qd_getmp(qd)) == 0) goto fail; + EC_DESTROY(p); + p->x = x; + p->y = y; + p->z = 0; + return (p); + +fail: + if (x) MP_DROP(x); + if (y) MP_DROP(y); + return (0); +} + +/* --- @ec_infofromdata@ --- * + * + * Arguments: @ec_info *ei@ = where to write the information + * @ecdata *ed@ = raw data + * + * Returns: --- + * + * Use: Loads elliptic curve information about one of the standard + * curves. + */ + +void ec_infofromdata(ec_info *ei, ecdata *ed) +{ + field *f; + + switch (ed->ftag) { + case FTAG_PRIME: + f = field_prime(&ed->p); + ei->c = ec_primeproj(f, &ed->a, &ed->b); + break; + case FTAG_NICEPRIME: + f = field_niceprime(&ed->p); + ei->c = ec_primeproj(f, &ed->a, &ed->b); + break; + case FTAG_BINPOLY: + f = field_binpoly(&ed->p); + ei->c = ec_binproj(f, &ed->a, &ed->b); + break; + case FTAG_BINNORM: + f = field_binnorm(&ed->p, &ed->beta); + ei->c = ec_binproj(f, &ed->a, &ed->b); + break; + default: + abort(); + } + + assert(f); assert(ei->c); + EC_CREATE(&ei->g); ei->g.x = &ed->gx; ei->g.y = &ed->gy; ei->g.z = 0; + ei->r = &ed->r; ei->h = &ed->h; +} + +/* --- @ec_infoparse@ --- * + * + * Arguments: @qd_parse *qd@ = parser context + * @ec_info *ei@ = curve information block, currently + * uninitialized + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Parses an elliptic curve information string, and stores the + * information in @ei@. This is either the name of a standard + * curve, or it has the form + * + * * elliptic curve description + * * optional `;' + * * common point + * * optional `:' + * * group order + * * optional `*' + * * cofactor + */ + +int ec_infoparse(qd_parse *qd, ec_info *ei) +{ + ec_curve *c = 0; + field *f; + ec g = EC_INIT; + const ecentry *ee; + mp *r = MP_NEW, *h = MP_NEW; + + for (ee = ectab; ee->name; ee++) { + if (qd_enum(qd, ee->name) >= 0) { + ec_infofromdata(ei, ee->data); + goto found; + } + } + + if ((c = ec_curveparse(qd)) == 0) goto fail; + qd_delim(qd, ';'); if (!ec_ptparse(qd, &g)) goto fail; + qd_delim(qd, ':'); if ((r = qd_getmp(qd)) == 0) goto fail; + qd_delim(qd, '*'); if ((h = qd_getmp(qd)) == 0) goto fail; + ei->c = c; ei->g = g; ei->r = r; ei->h = h; + +found: + return (0); + +fail: + EC_DESTROY(&g); + if (r) MP_DROP(r); + if (h) MP_DROP(h); + if (c) { f = c->f; ec_destroycurve(c); F_DESTROY(f); } + return (-1); +} + +/* --- @ec_getinfo@ --- * + * + * Arguments: @ec_info *ei@ = where to write the information + * @const char *p@ = string describing a curve + * + * Returns: Null on success, or a pointer to an error message. + * + * Use: Parses out information about a curve. The string is either a + * standard curve name, or a curve info string. + */ + +const char *ec_getinfo(ec_info *ei, const char *p) +{ + qd_parse qd; + + qd.p = p; + qd.e = 0; + if (ec_infoparse(&qd, ei)) + return (qd.e); + if (!qd_eofp(&qd)) { + ec_freeinfo(ei); + return ("junk found at end of string"); + } + return (0); +} + +/* --- @ec_sameinfop@ --- * + * + * Arguments: @ec_info *ei, *ej@ = two elliptic curve parameter sets + * + * Returns: Nonzero if the curves are identical (not just isomorphic). + * + * Use: Checks for sameness of curve parameters. + */ + +int ec_sameinfop(ec_info *ei, ec_info *ej) +{ + return (ec_samep(ei->c, ej->c) && + MP_EQ(ei->r, ej->r) && MP_EQ(ei->h, ej->h) && + EC_EQ(&ei->g, &ej->g)); +} + +/* --- @ec_freeinfo@ --- * + * + * Arguments: @ec_info *ei@ = elliptic curve information block to free + * + * Returns: --- + * + * Use: Frees the information block. + */ + +void ec_freeinfo(ec_info *ei) +{ + field *f; + + EC_DESTROY(&ei->g); + MP_DROP(ei->r); + MP_DROP(ei->h); + f = ei->c->f; ec_destroycurve(ei->c); F_DESTROY(f); +} + +/* --- @ec_checkinfo@ --- * + * + * Arguments: @const ec_info *ei@ = elliptic curve information block + * + * Returns: Null if OK, or pointer to error message. + * + * Use: Checks an elliptic curve according to the rules in SEC1. + */ + +static const char *gencheck(const ec_info *ei, grand *gr, mp *q, mp *ch) +{ + ec_curve *c = ei->c; + unsigned long qmbits, rbits, cbits, B; + mp *qq; + mp *nn; + mp *x, *y; + ec p; + int rc; + + /* --- Check curve isn't anomalous --- */ + + if (MP_EQ(ei->r, q)) return ("curve is anomalous"); + + /* --- Check %$G \in E \setminus \{ 0 \}$% --- */ + + if (EC_ATINF(&ei->g)) return ("generator at infinity"); + if (ec_check(c, &ei->g)) return ("generator not on curve"); + + /* --- Check %$r$% is prime --- */ + + if (!pgen_primep(ei->r, gr)) return ("generator order not prime"); + + /* --- Check that the cofactor is correct --- * + * + * Let %$q$% be the size of the field, and let %$n = h r = \#E(\gf{q})$% be + * the number of %$\gf{q}$%-rational points on our curve. Hasse's theorem + * tells us that + * + * %$|q + 1 - n| \le 2\sqrt{q}$% + * + * or, if we square both sides, + * + * %$(q + 1 - n)^2 \le 4 q$%. + * + * We'd like the cofactor to be uniquely determined by this equation, which + * is possible as long as it's not too big. (If it is, we have to mess + * about with Weil pairings, which is no fun.) For this, we need the + * following inequalities: + * + * * %$A = (q + 1 - n)^2 \le 4 q$% (both lower and upper bounds from + * Hasse's theorem); + * + * * %$B = (q + 1 - n - r)^2 > 4 q$% (check %$h - 1$% isn't possible); + * and + * + * * %$C = (q + 1 - n + r)^2 > 4 q$% (check %$h + 1$% isn't possible). + */ + + rc = 1; + qq = mp_add(MP_NEW, q, MP_ONE); + nn = mp_mul(MP_NEW, ei->r, ei->h); + nn = mp_sub(nn, qq, nn); + qq = mp_lsl(qq, q, 2); + + y = mp_sqr(MP_NEW, nn); + if (MP_CMP(y, >, qq)) rc = 0; + + x = mp_sub(MP_NEW, nn, ei->r); + y = mp_sqr(y, x); + if (MP_CMP(y, <=, qq)) rc = 0; + + x = mp_add(x, nn, ei->r); + y = mp_sqr(y, x); + if (MP_CMP(y, <=, qq)) rc = 0; + + MP_DROP(x); + MP_DROP(y); + MP_DROP(nn); + MP_DROP(qq); + if (!rc) return ("incorrect or ambiguous cofactor"); + + /* --- Check %$n G = 0$% --- */ + + EC_CREATE(&p); + ec_mul(c, &p, &ei->g, ei->r); + rc = EC_ATINF(&p); + EC_DESTROY(&p); + if (!rc) return ("incorrect group order"); + + /* --- Check the embedding degree --- */ + + rbits = mp_bits(ei->r); + cbits = mp_bits(ch); + qmbits = keysz_todl(keysz_fromec(rbits * 7/8)); + B = (qmbits + cbits - 1)/cbits; + if (movcheck(ei->r, ch, B)) + return("curve embedding degree too low"); + + /* --- Done --- */ + + return (0); +} + +static int primeeltp(mp *x, field *f) + { return (!MP_NEGP(x) && MP_CMP(x, <, f->m)); } + +static const char *primecheck(const ec_info *ei, grand *gr) +{ + ec_curve *c = ei->c; + field *f = c->f; + mp *x, *y; + int rc; + const char *err; + + /* --- Check %$p$% is an odd prime --- */ + + if (!pgen_primep(f->m, gr)) return ("p not prime"); + + /* --- Check %$a$%, %$b$%, %$G_x$% and %$G_y$% are in %$[0, p)$% --- */ + + if (!primeeltp(c->a, f)) return ("a out of range"); + if (!primeeltp(c->b, f)) return ("b out of range"); + if (!primeeltp(ei->g.x, f)) return ("G_x out of range"); + if (!primeeltp(ei->g.x, f)) return ("G_y out of range"); + + /* --- Check %$4 a^3 + 27 b^2 \not\equiv 0 \pmod{p}$% --- */ + + x = F_SQR(f, MP_NEW, c->a); + x = F_MUL(f, x, x, c->a); + x = F_QDL(f, x, x); + y = F_SQR(f, MP_NEW, c->b); + y = F_TPL(f, y, y); + y = F_TPL(f, y, y); + y = F_TPL(f, y, y); + x = F_ADD(f, x, x, y); + rc = F_ZEROP(f, x); + MP_DROP(x); + MP_DROP(y); + if (rc) return ("not an elliptic curve"); + + /* --- Now do the general checks --- */ + + err = gencheck(ei, gr, f->m, f->m); + return (err); +} + +static const char *bincheck(const ec_info *ei, grand *gr) +{ + ec_curve *c = ei->c; + field *f = c->f; + mp *x; + int rc; + const char *err; + + /* --- Check that %$m$% is prime --- */ + + x = mp_fromuint(MP_NEW, f->nbits); + rc = pfilt_smallfactor(x); + mp_drop(x); + if (rc != PGEN_DONE) return ("degree not prime"); + + /* --- Check that %$p$% is irreducible --- */ + + if (!gf_irreduciblep(f->m)) return ("p not irreducible"); + + /* --- Check that %$a, b, G_x, G_y$% have degree less than %$p$% --- */ + + if (mp_bits(c->a) > f->nbits) return ("a out of range"); + if (mp_bits(c->b) > f->nbits) return ("a out of range"); + if (mp_bits(ei->g.x) > f->nbits) return ("G_x out of range"); + if (mp_bits(ei->g.y) > f->nbits) return ("G_y out of range"); + + /* --- Check that %$b \ne 0$% --- */ + + if (F_ZEROP(f, c->b)) return ("b is zero"); + + /* --- Now do the general checks --- */ + + x = mp_lsl(MP_NEW, MP_ONE, f->nbits); + err = gencheck(ei, gr, x, MP_TWO); + mp_drop(x); + return (err); +} + +const char *ec_checkinfo(const ec_info *ei, grand *gr) +{ + switch (F_TYPE(ei->c->f)) { + case FTY_PRIME: return (primecheck(ei, gr)); break; + case FTY_BINARY: return (bincheck(ei, gr)); break; + } + return ("unknown curve type"); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include "fibrand.h" + +int main(int argc, char *argv[]) +{ + const ecentry *ee; + const char *e; + int ok = 1; + int i; + grand *gr; + + gr = fibrand_create(0); + if (argc > 1) { + for (i = 1; i < argc; i++) { + ec_info ei; + if ((e = ec_getinfo(&ei, argv[i])) != 0) + fprintf(stderr, "bad curve spec `%s': %s\n", argv[i], e); + else { + e = ec_checkinfo(&ei, gr); + ec_freeinfo(&ei); + if (!e) + printf("OK %s\n", argv[i]); + else { + printf("BAD %s: %s\n", argv[i], e); + ok = 0; + } + } + assert(mparena_count(MPARENA_GLOBAL) == 0); + } + } else { + fputs("checking standard curves:", stdout); + fflush(stdout); + for (ee = ectab; ee->name; ee++) { + ec_info ei; + ec_infofromdata(&ei, ee->data); + e = ec_checkinfo(&ei, gr); + ec_freeinfo(&ei); + if (e) { + printf(" [%s fails: %s]", ee->name, e); + ok = 0; + } else + printf(" %s", ee->name); + fflush(stdout); + assert(mparena_count(MPARENA_GLOBAL) == 0); + } + fputs(ok ? " ok\n" : " failed\n", stdout); + } + gr->ops->destroy(gr); + return (!ok); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/ec-keys.h b/math/ec-keys.h new file mode 100644 index 0000000..f4a304d --- /dev/null +++ b/math/ec-keys.h @@ -0,0 +1,96 @@ +/* -*-c-*- + * + * Elliptic curve key-fetching + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_EC_KEYS_H +#define CATACOMB_EC_KEYS_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_EC_H +# include "ec.h" +#endif + +#ifndef CATACOMB_KEY_H +# include "key.h" +#endif + +/*----- Key structures ----------------------------------------------------*/ + +typedef struct ec_param { + ec_info ei; /* Curve information */ + char *cstr; /* Curve definition string */ +} ec_param; + +typedef struct ec_pub { + ec_info ei; /* Curve information */ + char *cstr; /* Curve definition string */ + ec p; /* Public point */ +} ec_pub; + +typedef struct ec_priv { + ec_info ei; /* Curve information */ + char *cstr; /* Curve definition string */ + ec p; /* Public point */ + mp *x; /* Secret exponent */ +} ec_priv; + +extern const key_fetchdef ec_paramfetch[]; +#define EC_PARAMFETCHSZ 3 + +extern const key_fetchdef ec_pubfetch[]; +#define EC_PUBFETCHSZ 4 + +extern const key_fetchdef ec_privfetch[]; +#define EC_PRIVFETCHSZ 7 + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @ec_paramfree@, @ec_pubfree@, @ec_privfree@ --- * + * + * Arguments: @ec_param *ep@, @ec_pub *ep@, @ec_priv *ep@ = pointer to + * key block to free + * + * Returns: --- + * + * Use: Frees an elliptic curve key block + */ + +extern void ec_paramfree(ec_param */*ep*/); +extern void ec_pubfree(ec_pub */*ep*/); +extern void ec_privfree(ec_priv */*ep*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/ec-prime.c b/math/ec-prime.c new file mode 100644 index 0000000..f6a7f96 --- /dev/null +++ b/math/ec-prime.c @@ -0,0 +1,449 @@ +/* -*-c-*- + * + * Elliptic curves over prime fields + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ec.h" + +/*----- Simple prime curves -----------------------------------------------*/ + +static const ec_ops ec_primeops, ec_primeprojops, ec_primeprojxops; + +static ec *ecneg(ec_curve *c, ec *d, const ec *p) +{ + EC_COPY(d, p); + if (d->y) + d->y = F_NEG(c->f, d->y, d->y); + return (d); +} + +static ec *ecfind(ec_curve *c, ec *d, mp *x) +{ + mp *p, *q; + field *f = c->f; + + q = F_SQR(f, MP_NEW, x); + p = F_MUL(f, MP_NEW, x, q); + q = F_MUL(f, q, x, c->a); + p = F_ADD(f, p, p, q); + p = F_ADD(f, p, p, c->b); + MP_DROP(q); + p = F_SQRT(f, p, p); + if (!p) + return (0); + EC_DESTROY(d); + d->x = MP_COPY(x); + d->y = p; + d->z = MP_COPY(f->one); + return (d); +} + +static ec *ecdbl(ec_curve *c, ec *d, const ec *a) +{ + if (EC_ATINF(a) || F_ZEROP(c->f, a->y)) + EC_SETINF(d); + else { + field *f = c->f; + mp *lambda; + mp *dy, *dx; + + dx = F_SQR(f, MP_NEW, a->x); /* %$x^2$% */ + dy = F_DBL(f, MP_NEW, a->y); /* %$2 y$% */ + dx = F_TPL(f, dx, dx); /* %$3 x^2$% */ + dx = F_ADD(f, dx, dx, c->a); /* %$3 x^2 + A$% */ + dy = F_INV(f, dy, dy); /* %$(2 y)^{-1}$% */ + lambda = F_MUL(f, MP_NEW, dx, dy); /* %$\lambda = (3 x^2 + A)/(2 y)$% */ + + dx = F_SQR(f, dx, lambda); /* %$\lambda^2$% */ + dy = F_DBL(f, dy, a->x); /* %$2 x$% */ + dx = F_SUB(f, dx, dx, dy); /* %$x' = \lambda^2 - 2 x */ + dy = F_SUB(f, dy, a->x, dx); /* %$x - x'$% */ + dy = F_MUL(f, dy, lambda, dy); /* %$\lambda (x - x')$% */ + dy = F_SUB(f, dy, dy, a->y); /* %$y' = \lambda (x - x') - y$% */ + + EC_DESTROY(d); + d->x = dx; + d->y = dy; + d->z = 0; + MP_DROP(lambda); + } + return (d); +} + +static ec *ecprojdbl(ec_curve *c, ec *d, const ec *a) +{ + if (EC_ATINF(a) || F_ZEROP(c->f, a->y)) + EC_SETINF(d); + else { + field *f = c->f; + mp *p, *q, *m, *s, *dx, *dy, *dz; + + p = F_SQR(f, MP_NEW, a->z); /* %$z^2$% */ + q = F_SQR(f, MP_NEW, p); /* %$z^4$% */ + p = F_MUL(f, p, q, c->a); /* %$A z^4$% */ + m = F_SQR(f, MP_NEW, a->x); /* %$x^2$% */ + m = F_TPL(f, m, m); /* %$3 x^2$% */ + m = F_ADD(f, m, m, p); /* %$m = 3 x^2 + A z^4$% */ + + q = F_DBL(f, q, a->y); /* %$2 y$% */ + dz = F_MUL(f, MP_NEW, q, a->z); /* %$z' = 2 y z$% */ + + p = F_SQR(f, p, q); /* %$4 y^2$% */ + s = F_MUL(f, MP_NEW, p, a->x); /* %$s = 4 x y^2$% */ + q = F_SQR(f, q, p); /* %$16 y^4$% */ + q = F_HLV(f, q, q); /* %$t = 8 y^4$% */ + + p = F_DBL(f, p, s); /* %$2 s$% */ + dx = F_SQR(f, MP_NEW, m); /* %$m^2$% */ + dx = F_SUB(f, dx, dx, p); /* %$x' = m^2 - 2 s$% */ + + s = F_SUB(f, s, s, dx); /* %$s - x'$% */ + dy = F_MUL(f, p, m, s); /* %$m (s - x')$% */ + dy = F_SUB(f, dy, dy, q); /* %$y' = m (s - x') - t$% */ + + EC_DESTROY(d); + d->x = dx; + d->y = dy; + d->z = dz; + MP_DROP(m); + MP_DROP(q); + MP_DROP(s); + } + return (d); +} + +static ec *ecprojxdbl(ec_curve *c, ec *d, const ec *a) +{ + if (EC_ATINF(a) || F_ZEROP(c->f, a->y)) + EC_SETINF(d); + else { + field *f = c->f; + mp *p, *q, *m, *s, *dx, *dy, *dz; + + m = F_SQR(f, MP_NEW, a->z); /* %$z^2$% */ + p = F_SUB(f, MP_NEW, a->x, m); /* %$x - z^2$% */ + q = F_ADD(f, MP_NEW, a->x, m); /* %$x + z^2$% */ + m = F_MUL(f, m, p, q); /* %$x^2 - z^4$% */ + m = F_TPL(f, m, m); /* %$m = 3 x^2 - 3 z^4$% */ + + q = F_DBL(f, q, a->y); /* %$2 y$% */ + dz = F_MUL(f, MP_NEW, q, a->z); /* %$z' = 2 y z$% */ + + p = F_SQR(f, p, q); /* %$4 y^2$% */ + s = F_MUL(f, MP_NEW, p, a->x); /* %$s = 4 x y^2$% */ + q = F_SQR(f, q, p); /* %$16 y^4$% */ + q = F_HLV(f, q, q); /* %$t = 8 y^4$% */ + + p = F_DBL(f, p, s); /* %$2 s$% */ + dx = F_SQR(f, MP_NEW, m); /* %$m^2$% */ + dx = F_SUB(f, dx, dx, p); /* %$x' = m^2 - 2 s$% */ + + s = F_SUB(f, s, s, dx); /* %$s - x'$% */ + dy = F_MUL(f, p, m, s); /* %$m (s - x')$% */ + dy = F_SUB(f, dy, dy, q); /* %$y' = m (s - x') - t$% */ + + EC_DESTROY(d); + d->x = dx; + d->y = dy; + d->z = dz; + MP_DROP(m); + MP_DROP(q); + MP_DROP(s); + } + return (d); +} + +static ec *ecadd(ec_curve *c, ec *d, const ec *a, const ec *b) +{ + if (a == b) + ecdbl(c, d, a); + else if (EC_ATINF(a)) + EC_COPY(d, b); + else if (EC_ATINF(b)) + EC_COPY(d, a); + else { + field *f = c->f; + mp *lambda; + mp *dy, *dx; + + if (!MP_EQ(a->x, b->x)) { + dy = F_SUB(f, MP_NEW, a->y, b->y); /* %$y_0 - y_1$% */ + dx = F_SUB(f, MP_NEW, a->x, b->x); /* %$x_0 - x_1$% */ + dx = F_INV(f, dx, dx); /* %$(x_0 - x_1)^{-1}$% */ + lambda = F_MUL(f, MP_NEW, dy, dx); + /* %$\lambda = (y_0 - y1)/(x_0 - x_1)$% */ + } else if (F_ZEROP(c->f, a->y) || !MP_EQ(a->y, b->y)) { + EC_SETINF(d); + return (d); + } else { + dx = F_SQR(f, MP_NEW, a->x); /* %$x_0^2$% */ + dx = F_TPL(f, dx, dx); /* %$3 x_0^2$% */ + dx = F_ADD(f, dx, dx, c->a); /* %$3 x_0^2 + A$% */ + dy = F_DBL(f, MP_NEW, a->y); /* %$2 y_0$% */ + dy = F_INV(f, dy, dy); /* %$(2 y_0)^{-1}$% */ + lambda = F_MUL(f, MP_NEW, dx, dy); + /* %$\lambda = (3 x_0^2 + A)/(2 y_0)$% */ + } + + dx = F_SQR(f, dx, lambda); /* %$\lambda^2$% */ + dx = F_SUB(f, dx, dx, a->x); /* %$\lambda^2 - x_0$% */ + dx = F_SUB(f, dx, dx, b->x); /* %$x' = \lambda^2 - x_0 - x_1$% */ + dy = F_SUB(f, dy, b->x, dx); /* %$x_1 - x'$% */ + dy = F_MUL(f, dy, lambda, dy); /* %$\lambda (x_1 - x')$% */ + dy = F_SUB(f, dy, dy, b->y); /* %$y' = \lambda (x_1 - x') - y_1$% */ + + EC_DESTROY(d); + d->x = dx; + d->y = dy; + d->z = 0; + MP_DROP(lambda); + } + return (d); +} + +static ec *ecprojadd(ec_curve *c, ec *d, const ec *a, const ec *b) +{ + if (a == b) + c->ops->dbl(c, d, a); + else if (EC_ATINF(a)) + EC_COPY(d, b); + else if (EC_ATINF(b)) + EC_COPY(d, a); + else { + field *f = c->f; + mp *p, *q, *r, *w, *u, *uu, *s, *ss, *dx, *dy, *dz; + + q = F_SQR(f, MP_NEW, a->z); /* %$z_0^2$% */ + u = F_MUL(f, MP_NEW, q, b->x); /* %$u = x_1 z_0^2$% */ + p = F_MUL(f, MP_NEW, q, b->y); /* %$y_1 z_0^2$% */ + s = F_MUL(f, q, p, a->z); /* %$s = y_1 z_0^3$% */ + + q = F_SQR(f, MP_NEW, b->z); /* %$z_1^2$% */ + uu = F_MUL(f, MP_NEW, q, a->x); /* %$uu = x_0 z_1^2$%*/ + p = F_MUL(f, p, q, a->y); /* %$y_0 z_1^2$% */ + ss = F_MUL(f, q, p, b->z); /* %$ss = y_0 z_1^3$% */ + + w = F_SUB(f, p, uu, u); /* %$w = uu - u$% */ + r = F_SUB(f, MP_NEW, ss, s); /* %$r = ss - s$% */ + if (F_ZEROP(f, w)) { + MP_DROP(w); + MP_DROP(u); + MP_DROP(s); + MP_DROP(uu); + MP_DROP(ss); + if (F_ZEROP(f, r)) { + MP_DROP(r); + return (c->ops->dbl(c, d, a)); + } else { + MP_DROP(r); + EC_SETINF(d); + return (d); + } + } + u = F_ADD(f, u, u, uu); /* %$t = uu + u$% */ + s = F_ADD(f, s, s, ss); /* %$m = ss + r$% */ + + uu = F_MUL(f, uu, a->z, w); /* %$z_0 w$% */ + dz = F_MUL(f, ss, uu, b->z); /* %$z' = z_0 z_1 w$% */ + + p = F_SQR(f, uu, w); /* %$w^2$% */ + q = F_MUL(f, MP_NEW, p, u); /* %$t w^2$% */ + u = F_MUL(f, u, p, w); /* %$w^3$% */ + p = F_MUL(f, p, u, s); /* %$m w^3$% */ + + dx = F_SQR(f, u, r); /* %$r^2$% */ + dx = F_SUB(f, dx, dx, q); /* %$x' = r^2 - t w^2$% */ + + s = F_DBL(f, s, dx); /* %$2 x'$% */ + q = F_SUB(f, q, q, s); /* %$v = t w^2 - 2 x'$% */ + dy = F_MUL(f, s, q, r); /* %$v r$% */ + dy = F_SUB(f, dy, dy, p); /* %$v r - m w^3$% */ + dy = F_HLV(f, dy, dy); /* %$y' = (v r - m w^3)/2$% */ + + EC_DESTROY(d); + d->x = dx; + d->y = dy; + d->z = dz; + MP_DROP(p); + MP_DROP(q); + MP_DROP(r); + MP_DROP(w); + } + return (d); +} + +static int eccheck(ec_curve *c, const ec *p) +{ + field *f = c->f; + mp *l, *x, *r; + int rc; + if (EC_ATINF(p)) return (0); + l = F_SQR(f, MP_NEW, p->y); + x = F_SQR(f, MP_NEW, p->x); + r = F_MUL(f, MP_NEW, x, p->x); + x = F_MUL(f, x, c->a, p->x); + r = F_ADD(f, r, r, x); + r = F_ADD(f, r, r, c->b); + rc = MP_EQ(l, r) ? 0 : -1; + mp_drop(l); + mp_drop(x); + mp_drop(r); + return (rc); +} + +static int ecprojcheck(ec_curve *c, const ec *p) +{ + ec t = EC_INIT; + int rc; + + c->ops->fix(c, &t, p); + rc = eccheck(c, &t); + EC_DESTROY(&t); + return (rc); +} + +static void ecdestroy(ec_curve *c) +{ + MP_DROP(c->a); + MP_DROP(c->b); + DESTROY(c); +} + +/* --- @ec_prime@, @ec_primeproj@ --- * + * + * Arguments: @field *f@ = the underlying field for this elliptic curve + * @mp *a, *b@ = the coefficients for this curve + * + * Returns: A pointer to the curve, or null. + * + * Use: Creates a curve structure for an elliptic curve defined over + * a prime field. The @primeproj@ variant uses projective + * coordinates, which can be a win. + */ + +extern ec_curve *ec_prime(field *f, mp *a, mp *b) +{ + ec_curve *c = CREATE(ec_curve); + c->ops = &ec_primeops; + c->f = f; + c->a = F_IN(f, MP_NEW, a); + c->b = F_IN(f, MP_NEW, b); + return (c); +} + +extern ec_curve *ec_primeproj(field *f, mp *a, mp *b) +{ + ec_curve *c = CREATE(ec_curve); + mp *ax; + + ax = mp_add(MP_NEW, a, MP_THREE); + ax = F_IN(f, ax, ax); + if (F_ZEROP(f, ax)) + c->ops = &ec_primeprojxops; + else + c->ops = &ec_primeprojops; + MP_DROP(ax); + c->f = f; + c->a = F_IN(f, MP_NEW, a); + c->b = F_IN(f, MP_NEW, b); + return (c); +} + +static const ec_ops ec_primeops = { + "prime", + ecdestroy, ec_stdsamep, ec_idin, ec_idout, ec_idfix, + ecfind, ecneg, ecadd, ec_stdsub, ecdbl, eccheck +}; + +static const ec_ops ec_primeprojops = { + "primeproj", + ecdestroy, ec_stdsamep, ec_projin, ec_projout, ec_projfix, + ecfind, ecneg, ecprojadd, ec_stdsub, ecprojdbl, ecprojcheck +}; + +static const ec_ops ec_primeprojxops = { + "primeproj", + ecdestroy, ec_stdsamep, ec_projin, ec_projout, ec_projfix, + ecfind, ecneg, ecprojadd, ec_stdsub, ecprojxdbl, ecprojcheck +}; + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#define MP(x) mp_readstring(MP_NEW, #x, 0, 0) + +int main(int argc, char *argv[]) +{ + field *f; + ec_curve *c; + ec g = EC_INIT, d = EC_INIT; + mp *p, *a, *b, *r; + int i, n = argc == 1 ? 1 : atoi(argv[1]); + + printf("ec-prime: "); + fflush(stdout); + a = MP(-3); + b = MP(0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef); + p = MP(39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319); + r = MP(39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942642); + + f = field_niceprime(p); + c = ec_primeproj(f, a, b); + + g.x = MP(0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7); + g.y = MP(0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f); + + for (i = 0; i < n; i++) { + ec_mul(c, &d, &g, r); + if (EC_ATINF(&d)) { + fprintf(stderr, "zero too early\n"); + return (1); + } + ec_add(c, &d, &d, &g); + if (!EC_ATINF(&d)) { + fprintf(stderr, "didn't reach zero\n"); + MP_EPRINT("d.x", d.x); + MP_EPRINT("d.y", d.y); + return (1); + } + ec_destroy(&d); + } + ec_destroy(&g); + ec_destroycurve(c); + F_DESTROY(f); + MP_DROP(p); MP_DROP(a); MP_DROP(b); MP_DROP(r); + assert(!mparena_count(&mparena_global)); + printf("ok\n"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/ec-raw.c b/math/ec-raw.c new file mode 100644 index 0000000..54310c8 --- /dev/null +++ b/math/ec-raw.c @@ -0,0 +1,94 @@ +/* -*-c-*- + * + * Raw formatting of elliptic curve points + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "ec.h" +#include "ec-raw.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @ec_putraw@ --- * + * + * Arguments: @ec_curve *c@ = elliptic curve + * @buf *b@ = pointer to a buffer + * @const ec *p@ = an elliptic curve point + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Puts an elliptic curve point to the given buffer using the + * standard uncompressed format described in P1383 and SEC1. + * This requires at most @1 + 2 * c->f->noctets@ space in the + * buffer. We don't do point compression. + */ + +int ec_putraw(ec_curve *c, buf *b, const ec *p) +{ + octet *q; + size_t n; + + if (EC_ATINF(p)) return (buf_putbyte(b, 0)); + buf_putbyte(b, 4); + n = c->f->noctets; + if ((q = buf_get(b, n * 2)) == 0) return (-1); + mp_storeb(p->x, q, n); + mp_storeb(p->y, q + n, n); + return (0); +} + +/* --- @ec_getraw@ --- * + * + * Arguments: @ec_curve *c@ = elliptic curve + * @buf *b@ = pointer to a buffer + * @ec *d@ = an elliptic curve point + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Reads an elliptic curve point from the given buffer using the + * standard uncompressed format described in P1383 and SEC1. + * We don't do point compression. + */ + +int ec_getraw(ec_curve *c, buf *b, ec *d) +{ + const octet *q; + size_t n; + int u; + + if ((u = buf_getbyte(b)) < 0) return (-1); + if (!u) { EC_SETINF(d); return (0); } + if (!(u & 4)) return (-1); + n = c->f->noctets; + if ((q = buf_get(b, n * 2)) == 0) return (-1); + EC_DESTROY(d); + d->x = mp_loadb(MP_NEW, q, n); + d->y = mp_loadb(MP_NEW, q + n, n); + d->z = 0; + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/ec-raw.h b/math/ec-raw.h new file mode 100644 index 0000000..4792bd7 --- /dev/null +++ b/math/ec-raw.h @@ -0,0 +1,83 @@ +/* -*-c-*- + * + * Raw formatting of elliptic curve points + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_EC_RAW_H +#define CATACOMB_EC_RAW_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_BUF_H +# include "buf.h" +#endif + +#ifndef CATACOMB_EC_H +# include "ec.h" +#endif + +/*----- Data formatting ---------------------------------------------------*/ + +/* --- @ec_putraw@ --- * + * + * Arguments: @ec_curve *c@ = elliptic curve + * @buf *b@ = pointer to a buffer + * @const ec *p@ = an elliptic curve point + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Puts an elliptic curve point to the given buffer using the + * standard uncompressed format described in P1383 and SEC1. + * We don't do point compression. + */ + +extern int ec_putraw(ec_curve */*c*/, buf */*b*/, const ec */*p*/); + +/* --- @ec_getraw@ --- * + * + * Arguments: @ec_curve *c@ = elliptic curve + * @buf *b@ = pointer to a buffer + * @ec *d@ = an elliptic curve point + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Reads an elliptic curve point from the given buffer using the + * standard uncompressed format described in P1383 and SEC1. + * We don't do point compression. + */ + +extern int ec_getraw(ec_curve */*c*/, buf */*b*/, ec */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/ec-test.c b/math/ec-test.c new file mode 100644 index 0000000..db59294 --- /dev/null +++ b/math/ec-test.c @@ -0,0 +1,345 @@ +/* -*-c-*- + * + * Code for testing elliptic-curve stuff + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ec.h" +#include "ec-test.h" + +/*----- Cardboard cut-out elliptic curve ----------------------------------*/ + +typedef struct ecctx { + ec_curve c; + unsigned long magic; + char *name; + ec_curve *real; +} ecctx; + +#define MAGIC 0x3a1f0b07 + +static void ecDESTROY(ec_curve *cc) +{ + ecctx *c = (ecctx *)cc; + xfree(c->name); + ec_destroycurve(c->real); + DESTROY(c); +} + +#define UNOP(OP) \ + static ec *ec##OP(ec_curve *cc, ec *d, const ec *p) { \ + ecctx *c = (ecctx *)cc; \ + return (EC_##OP(c->real, d, p)); \ + } + +#define BINOP(OP) \ + static ec *ec##OP(ec_curve *cc, ec *d, const ec *p, const ec *q) { \ + ecctx *c = (ecctx *)cc; \ + return (EC_##OP(c->real, d, p, q)); \ + } + +UNOP(IN) +UNOP(OUT) +UNOP(FIX) +UNOP(NEG) +UNOP(DBL) +BINOP(ADD) +BINOP(SUB) + +#undef UNOP +#undef BINOP + +static ec *ecFIND(ec_curve *cc, ec *d, mp *x) +{ + ecctx *c = (ecctx *)cc; + return (EC_FIND(c->real, d, x)); +} + +static int ecCHECK(ec_curve *cc, const ec *p) +{ + ecctx *c = (ecctx *)cc; + return (EC_CHECK(c->real, p)); +} + +static int ecSAMEP(ec_curve *cc, ec_curve *dd) +{ + ecctx *c = (ecctx *)cc, *d = (ecctx *)dd; + return (ec_samep(c->real, d->real)); +} + +static const ec_ops ecops = { + "cardboard", + ecDESTROY, ecSAMEP, ecIN, ecOUT, ecFIX, + ecFIND, ecNEG, ecADD, ecSUB, ecDBL, ecCHECK +}; + +static ec_curve *ec_cutout(ec_curve *real, const char *name) +{ + ecctx *c = CREATE(ecctx); + c->c.f = real->f; + c->c.ops = &ecops; + c->c.a = real->a; + c->c.b = real->b; + c->magic = MAGIC; + c->name = xstrdup(name); + c->real = real; + return (&c->c); +} + +static const char *ec_name(ec_curve *cc) +{ + ecctx *c = (ecctx *)cc; + assert(c->magic == MAGIC); + return (c->name); +} + +/*----- Test field types --------------------------------------------------*/ + +static void ecvcvt(const char *buf, dstr *d) +{ + ec_curve *v; + qd_parse qd; + + qd.p = buf; + qd.e = 0; + if ((v = ec_curveparse(&qd)) == 0) { + fprintf(stderr, "bad curve `%.*s|%s': %s\n", + qd.p - buf, buf, qd.p, qd.e); + exit(1); + } + dstr_ensure(d, sizeof(v)); + *(ec_curve **)d->buf = ec_cutout(v, buf); + d->len += sizeof(v); +} + +static void ecvdump(dstr *d, FILE *fp) +{ + ec_curve *v = *(ec_curve **)d->buf; + fprintf(fp, "%s", ec_name(v)); +} + +const test_type type_ecurve = { ecvcvt, ecvdump }; + +static void eccvt(const char *p, dstr *d) +{ + ec *a; + qd_parse qd; + + qd.p = p; + qd.e = 0; + dstr_ensure(d, sizeof(ec)); + a = (ec *)d->buf; + d->len += sizeof(ec); + ec_create(a); + if (!ec_ptparse(&qd, a)) { + fprintf(stderr, "bad point `%.*s|%s': %s\n", qd.p - p, p, qd.p, qd.e); + exit(1); + } +} + +static void ecdodump(ec *a, FILE *fp) +{ + if (EC_ATINF(a)) + fputs("inf", fp); + else { + fputs("0x", fp); + mp_writefile(a->x, fp, 16); + fputs(", 0x", fp); + mp_writefile(a->y, fp, 16); + } +} + +static void ecdump(dstr *d, FILE *fp) +{ + ec *a = (ec *)d->buf; + ecdodump(a, fp); +} + +const test_type type_ec = { eccvt, ecdump }; + +/*----- Testing elliptic curve functionality ------------------------------*/ + +#ifdef TEST_RIG + +static void ecdestroy(ec_curve *c) +{ + field *f = c->f; + ec_destroycurve(c); + F_DESTROY(f); +} + +#define UNOP(op) \ + static int v##op(dstr v[]) \ + { \ + ec_curve *e = *(ec_curve **)v[0].buf; \ + ec *a = (ec *)v[1].buf; \ + ec *r = (ec *)v[2].buf; \ + ec c = EC_INIT; \ + int ok = 1; \ + ec_##op(e, &c, a); \ + if (!EC_EQ(r, &c)) { \ + fprintf(stderr, #op "failed"); \ + fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); \ + fprintf(stderr, "\n a = "); ecdodump(a, stderr); \ + fprintf(stderr, "\n r = "); ecdodump(r, stderr); \ + fprintf(stderr, "\n c = "); ecdodump(&c, stderr); \ + fprintf(stderr, "\n"); \ + ok = 0; \ + } \ + EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); \ + ecdestroy(e); \ + return (ok); \ + } + +#define BINOP(op) \ + static int v##op(dstr v[]) \ + { \ + ec_curve *e = *(ec_curve **)v[0].buf; \ + ec *a = (ec *)v[1].buf; \ + ec *b = (ec *)v[2].buf; \ + ec *r = (ec *)v[3].buf; \ + ec c = EC_INIT; \ + int ok = 1; \ + ec_##op(e, &c, a, b); \ + if (!EC_EQ(r, &c)) { \ + fprintf(stderr, #op "failed"); \ + fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); \ + fprintf(stderr, "\n a = "); ecdodump(a, stderr); \ + fprintf(stderr, "\n b = "); ecdodump(b, stderr); \ + fprintf(stderr, "\n r = "); ecdodump(r, stderr); \ + fprintf(stderr, "\n c = "); ecdodump(&c, stderr); \ + fprintf(stderr, "\n"); \ + ok = 0; \ + } \ + EC_DESTROY(a); EC_DESTROY(b); EC_DESTROY(r); EC_DESTROY(&c); \ + ecdestroy(e); \ + return (ok); \ + } + +UNOP(neg) +UNOP(dbl) +BINOP(add) +BINOP(sub) + +static int vcheck(dstr v[]) +{ + ec_curve *e = *(ec_curve **)v[0].buf; + ec *a = (ec *)v[1].buf; + int r = *(int *)v[2].buf; + int c; + int ok = 1; + c = ec_check(e, a); + if (r != c) { + fprintf(stderr, "check failed"); + fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); + fprintf(stderr, "\n a = "); ecdodump(a, stderr); + fprintf(stderr, "\n r = %d", r); + fprintf(stderr, "\n c = %d", c); + fprintf(stderr, "\n"); + ok = 0; + } + EC_DESTROY(a); + ecdestroy(e); + return (ok); +} + +static int vmul(dstr v[]) +{ + ec_curve *e = *(ec_curve **)v[0].buf; + ec *a = (ec *)v[1].buf; + mp *n = *(mp **)v[2].buf; + ec *r = (ec *)v[3].buf; + ec c = EC_INIT; + int ok = 1; + ec_mul(e, &c, a, n); + if (!EC_EQ(r, &c)) { + fprintf(stderr, "mul failed"); + fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); + fprintf(stderr, "\n a = "); ecdodump(a, stderr); + fprintf(stderr, "\n n = "); mp_writefile(n, stderr, 10); + fprintf(stderr, "\n r = "); ecdodump(r, stderr); + fprintf(stderr, "\n c = "); ecdodump(&c, stderr); + fprintf(stderr, "\n"); + ok = 0; + } + EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); MP_DROP(n); + ecdestroy(e); + return (ok); +} + +static int vfind(dstr v[]) +{ + ec_curve *e = *(ec_curve **)v[0].buf; + mp *x = *(mp **)v[1].buf; + ec *r = (ec *)v[2].buf; + ec c = EC_INIT; + int ok = 1; + if (!ec_find(e, &c, x)) EC_SETINF(&c); + if (!EC_EQ(r, &c)) { + fprintf(stderr, "find failed"); + fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); + fprintf(stderr, "\n x = "); mp_writefile(x, stderr, 16); + fprintf(stderr, "\n r = "); ecdodump(r, stderr); + fprintf(stderr, "\n c = "); ecdodump(&c, stderr); + fprintf(stderr, "\n"); + ok = 0; + } + MP_DROP(x); EC_DESTROY(r); EC_DESTROY(&c); + ecdestroy(e); + return (ok); +} + +static test_chunk tests[] = { + { "neg", vneg, { &type_ecurve, &type_ec, &type_ec } }, + { "dbl", vdbl, { &type_ecurve, &type_ec, &type_ec } }, + { "add", vadd, { &type_ecurve, &type_ec, &type_ec, &type_ec } }, + { "sub", vsub, { &type_ecurve, &type_ec, &type_ec, &type_ec } }, + { "mul", vmul, { &type_ecurve, &type_ec, &type_mp, &type_ec } }, + { "check", vcheck, { &type_ecurve, &type_ec, &type_int } }, + { "find", vfind, { &type_ecurve, &type_mp, &type_ec } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/ec"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/ec-test.h b/math/ec-test.h new file mode 100644 index 0000000..4fd71e1 --- /dev/null +++ b/math/ec-test.h @@ -0,0 +1,53 @@ +/* -*-c-*- + * + * Elliptic curve test functions + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_EC_TEST_H +#define CATACOMB_EC_TEST_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_EC_H +# include "ec.h" +#endif + +/*----- Test vector types -------------------------------------------------*/ + +extern const test_type type_ecurve, type_ec; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/ec.c b/math/ec.c new file mode 100644 index 0000000..f8b77f5 --- /dev/null +++ b/math/ec.c @@ -0,0 +1,422 @@ +/* -*-c-*- + * + * Elliptic curve definitions + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "ec.h" + +/*----- Trivial wrappers --------------------------------------------------*/ + +/* --- @ec_samep@ --- * + * + * Arguments: @ec_curve *c, *d@ = two elliptic curves + * + * Returns: Nonzero if the curves are identical (not just isomorphic). + * + * Use: Checks for sameness of curves. This function does the full + * check, not just the curve-type-specific check done by the + * @sampep@ field operation. + */ + +int ec_samep(ec_curve *c, ec_curve *d) +{ + return (c == d || (field_samep(c->f, d->f) && + c->ops == d->ops && EC_SAMEP(c, d))); +} + +/* --- @ec_create@ --- * + * + * Arguments: @ec *p@ = pointer to an elliptic-curve point + * + * Returns: The argument @p@. + * + * Use: Initializes a new point. The initial value is the additive + * identity (which is universal for all curves). + */ + +ec *ec_create(ec *p) { EC_CREATE(p); return (p); } + +/* --- @ec_destroy@ --- * + * + * Arguments: @ec *p@ = pointer to an elliptic-curve point + * + * Returns: --- + * + * Use: Destroys a point, making it invalid. + */ + +void ec_destroy(ec *p) { EC_DESTROY(p); } + +/* --- @ec_atinf@ --- * + * + * Arguments: @const ec *p@ = pointer to a point + * + * Returns: Nonzero if %$p = O$% is the point at infinity, zero + * otherwise. + */ + +int ec_atinf(const ec *p) { return (EC_ATINF(p)); } + +/* --- @ec_setinf@ --- * + * + * Arguments: @ec *p@ = pointer to a point + * + * Returns: The argument @p@. + * + * Use: Sets the given point to be the point %$O$% at infinity. + */ + +ec *ec_setinf(ec *p) { EC_SETINF(p); return (p); } + +/* --- @ec_copy@ --- * + * + * Arguments: @ec *d@ = pointer to destination point + * @const ec *p@ = pointer to source point + * + * Returns: The destination @d@. + * + * Use: Creates a copy of an elliptic curve point. + */ + +ec *ec_copy(ec *d, const ec *p) { EC_COPY(d, p); return (d); } + +/* --- @ec_eq@ --- * + * + * Arguments: @const ec *p, *q@ = two points + * + * Returns: Nonzero if the points are equal. Compares external-format + * points. + */ + +int ec_eq(const ec *p, const ec *q) { return (EC_EQ(p, q)); } + +/*----- Standard curve operations -----------------------------------------*/ + +/* --- @ec_stdsamep@ --- * + * + * Arguments: @ec_curve *c, *d@ = two elliptic curves + * + * Returns: Nonzero if the curves are identical (not just isomorphic). + * + * Use: Simple sameness check on @a@ and @b@ curve members. + */ + +int ec_stdsamep(ec_curve *c, ec_curve *d) + { return (MP_EQ(c->a, d->a) && MP_EQ(c->b, d->b)); } + +/* --- @ec_idin@, @ec_idout@, @ec_idfix@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination + * @const ec *p@ = pointer to a source point + * + * Returns: The destination @d@. + * + * Use: An identity operation if your curve has no internal + * representation. (The field internal representation is still + * used.) + */ + +ec *ec_idin(ec_curve *c, ec *d, const ec *p) +{ + if (EC_ATINF(p)) + EC_SETINF(d); + else { + field *f = c->f; + d->x = F_IN(f, d->x, p->x); + d->y = F_IN(f, d->y, p->y); + mp_drop(d->z); d->z = 0; + } + return (d); +} + +ec *ec_idout(ec_curve *c, ec *d, const ec *p) +{ + if (EC_ATINF(p)) + EC_SETINF(d); + else { + field *f = c->f; + d->x = F_OUT(f, d->x, p->x); + d->y = F_OUT(f, d->y, p->y); + mp_drop(d->z); d->z = 0; + } + return (d); +} + +ec *ec_idfix(ec_curve *c, ec *d, const ec *p) + { EC_COPY(d, p); return (d); } + +/* --- @ec_projin@, @ec_projout@, @ec_projfix@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination + * @const ec *p@ = pointer to a source point + * + * Returns: The destination @d@. + * + * Use: Conversion functions if your curve operations use a + * projective representation. + */ + +ec *ec_projin(ec_curve *c, ec *d, const ec *p) +{ + if (EC_ATINF(p)) + EC_SETINF(d); + else { + field *f = c->f; + d->x = F_IN(f, d->x, p->x); + d->y = F_IN(f, d->y, p->y); + mp_drop(d->z); d->z = MP_COPY(f->one); + } + return (d); +} + +ec *ec_projout(ec_curve *c, ec *d, const ec *p) +{ + if (EC_ATINF(p)) + EC_SETINF(d); + else { + mp *x, *y, *z, *zz; + field *f = c->f; + if (p->z == f->one) { + d->x = F_OUT(f, d->x, p->x); + d->y = F_OUT(f, d->y, p->y); + } else { + z = F_INV(f, MP_NEW, p->z); + zz = F_SQR(f, MP_NEW, z); + z = F_MUL(f, z, zz, z); + x = F_MUL(f, d->x, p->x, zz); + y = F_MUL(f, d->y, p->y, z); + mp_drop(z); + mp_drop(zz); + d->x = F_OUT(f, x, x); + d->y = F_OUT(f, y, y); + } + mp_drop(d->z); + d->z = 0; + } + return (d); +} + +ec *ec_projfix(ec_curve *c, ec *d, const ec *p) +{ + if (EC_ATINF(p)) + EC_SETINF(d); + else if (p->z == c->f->one) + EC_COPY(d, p); + else { + mp *z, *zz; + field *f = c->f; + z = F_INV(f, MP_NEW, p->z); + zz = F_SQR(f, MP_NEW, z); + z = F_MUL(f, z, zz, z); + d->x = F_MUL(f, d->x, p->x, zz); + d->y = F_MUL(f, d->y, p->y, z); + mp_drop(z); + mp_drop(zz); + mp_drop(d->z); + d->z = MP_COPY(f->one); + } + return (d); +} + +/* --- @ec_stdsub@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination + * @const ec *p, *q@ = the operand points + * + * Returns: The destination @d@. + * + * Use: Standard point subtraction operation, in terms of negation + * and addition. This isn't as efficient as a ready-made + * subtraction operator. + */ + +ec *ec_stdsub(ec_curve *c, ec *d, const ec *p, const ec *q) +{ + ec t = EC_INIT; + EC_NEG(c, &t, q); + EC_FIX(c, &t, &t); + EC_ADD(c, d, p, &t); + EC_DESTROY(&t); + return (d); +} + +/*----- Creating curves ---------------------------------------------------*/ + +/* --- @ec_destroycurve@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an ellptic curve + * + * Returns: --- + * + * Use: Destroys a description of an elliptic curve. + */ + +void ec_destroycurve(ec_curve *c) { c->ops->destroy(c); } + +/*----- Real arithmetic ---------------------------------------------------*/ + +/* --- @ec_find@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @mp *x@ = a possible x-coordinate + * + * Returns: Zero if OK, nonzero if there isn't a point there. + * + * Use: Finds a point on an elliptic curve with a given x-coordinate. + */ + +ec *ec_find(ec_curve *c, ec *d, mp *x) +{ + x = F_IN(c->f, MP_NEW, x); + if ((d = EC_FIND(c, d, x)) != 0) + EC_OUT(c, d, d); + MP_DROP(x); + return (d); +} + +/* --- @ec_neg@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @const ec *p@ = pointer to the operand point + * + * Returns: The destination point. + * + * Use: Computes the negation of the given point. + */ + +ec *ec_neg(ec_curve *c, ec *d, const ec *p) + { EC_IN(c, d, p); EC_NEG(c, d, d); return (EC_OUT(c, d, d)); } + +/* --- @ec_add@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @const ec *p, *q@ = pointers to the operand points + * + * Returns: --- + * + * Use: Adds two points on an elliptic curve. + */ + +ec *ec_add(ec_curve *c, ec *d, const ec *p, const ec *q) +{ + ec pp = EC_INIT, qq = EC_INIT; + EC_IN(c, &pp, p); + EC_IN(c, &qq, q); + EC_ADD(c, d, &pp, &qq); + EC_OUT(c, d, d); + EC_DESTROY(&pp); + EC_DESTROY(&qq); + return (d); +} + +/* --- @ec_sub@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @const ec *p, *q@ = pointers to the operand points + * + * Returns: The destination @d@. + * + * Use: Subtracts one point from another on an elliptic curve. + */ + +ec *ec_sub(ec_curve *c, ec *d, const ec *p, const ec *q) +{ + ec pp = EC_INIT, qq = EC_INIT; + EC_IN(c, &pp, p); + EC_IN(c, &qq, q); + EC_SUB(c, d, &pp, &qq); + EC_OUT(c, d, d); + EC_DESTROY(&pp); + EC_DESTROY(&qq); + return (d); +} + +/* --- @ec_dbl@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @const ec *p@ = pointer to the operand point + * + * Returns: --- + * + * Use: Doubles a point on an elliptic curve. + */ + +ec *ec_dbl(ec_curve *c, ec *d, const ec *p) + { EC_IN(c, d, p); EC_DBL(c, d, d); return (EC_OUT(c, d, d)); } + +/* --- @ec_check@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @const ec *p@ = pointer to the point + * + * Returns: Zero if OK, nonzero if this is an invalid point. + * + * Use: Checks that a point is actually on an elliptic curve. + */ + +int ec_check(ec_curve *c, const ec *p) +{ + ec t = EC_INIT; + int rc; + + if (EC_ATINF(p)) + return (0); + EC_IN(c, &t, p); + rc = EC_CHECK(c, &t); + EC_DESTROY(&t); + return (rc); +} + +/* --- @ec_rand@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @grand *r@ = random number source + * + * Returns: The destination @d@. + * + * Use: Finds a random point on the given curve. + */ + +ec *ec_rand(ec_curve *c, ec *d, grand *r) +{ + mp *x = MP_NEW; + do x = F_RAND(c->f, x, r); while (!EC_FIND(c, d, x)); + mp_drop(x); + if (grand_range(r, 2)) EC_NEG(c, d, d); + return (EC_OUT(c, d, d)); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/ec.h b/math/ec.h new file mode 100644 index 0000000..cc7649d --- /dev/null +++ b/math/ec.h @@ -0,0 +1,616 @@ +/* -*-c-*- + * + * Elliptic curve definitions + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_EC_H +#define CATACOMB_EC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_FIELD_H +# include "field.h" +#endif + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_QDPARSE_H +# include "qdparse.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- An elliptic curve representation --- */ + +typedef struct ec_curve { + const struct ec_ops *ops; /* Curve operations */ + field *f; /* Underlying field structure */ + mp *a, *b; /* Standard params (internal form) */ +} ec_curve; + +/* --- An elliptic curve point --- */ + +typedef struct ec { + mp *x, *y; /* Point coordinates */ + mp *z; /* Common denominator (or null) */ +} ec; + +/* --- A factor for simultaneous multiplication --- */ + +typedef struct ec_mulfactor { + ec base; /* The point */ + mp *exp; /* The exponent */ +} ec_mulfactor; + +/* --- Elliptic curve operations --- * + * + * All operations (apart from @destroy@ and @in@) are guaranteed to be + * performed on internal representations of points. + * + * (Historical note. We used to guarantee that the second to @add@ and @mul@ + * was the output of @in@ or @fix@, but this canonification turned out to + * make the precomputation in @ec_exp@ too slow. Projective implementations + * must therefore cope with a pair of arbitrary points.) + */ + +typedef struct ec_ops { + const char *name; + void (*destroy)(ec_curve */*c*/); + int (*samep)(ec_curve */*c*/, ec_curve */*d*/); + ec *(*in)(ec_curve */*c*/, ec */*d*/, const ec */*p*/); + ec *(*out)(ec_curve */*c*/, ec */*d*/, const ec */*p*/); + ec *(*fix)(ec_curve */*c*/, ec */*d*/, const ec */*p*/); + ec *(*find)(ec_curve */*c*/, ec */*d*/, mp */*x*/); + ec *(*neg)(ec_curve */*c*/, ec */*d*/, const ec */*p*/); + ec *(*add)(ec_curve */*c*/, ec */*d*/, const ec */*p*/, const ec */*q*/); + ec *(*sub)(ec_curve */*c*/, ec */*d*/, const ec */*p*/, const ec */*q*/); + ec *(*dbl)(ec_curve */*c*/, ec */*d*/, const ec */*p*/); + int (*check)(ec_curve */*c*/, const ec */*p*/); +} ec_ops; + +#define EC_NAME(c) (c)->ops->name + +#define EC_SAMEP(c, d) (c)->ops->samep((c), (d)) +#define EC_IN(c, d, p) (c)->ops->in((c), (d), (p)) +#define EC_OUT(c, d, p) (c)->ops->out((c), (d), (p)) +#define EC_FIX(c, d, p) (c)->ops->fix((c), (d), (p)) + +#define EC_FIND(c, d, x) (c)->ops->find((c), (d), (x)) +#define EC_NEG(c, d, x) (c)->ops->neg((c), (d), (x)) +#define EC_ADD(c, d, p, q) (c)->ops->add((c), (d), (p), (q)) +#define EC_SUB(c, d, p, q) (c)->ops->sub((c), (d), (p), (q)) +#define EC_DBL(c, d, p) (c)->ops->dbl((c), (d), (p)) +#define EC_CHECK(c, p) (c)->ops->check((c), (p)) + +/* --- Elliptic curve parameters --- */ + +typedef struct ec_info { + ec_curve *c; /* The actual curve */ + ec g; /* The common point */ + mp *r; /* Order of %$g$% */ + mp *h; /* Cofactor %$h = \#E/r$% */ +} ec_info; + +/*----- Simple memory management things -----------------------------------*/ + +/* --- @ec_create@ --- * + * + * Arguments: @ec *p@ = pointer to an elliptic-curve point + * + * Returns: The argument @p@. + * + * Use: Initializes a new point. The initial value is the additive + * identity (which is universal for all curves). + */ + +#define EC_INIT { MP_NEW, MP_NEW, MP_NEW } + +#define EC_CREATE(p) do { \ + ec *_p = (p); \ + _p->x = _p->y = _p->z = MP_NEW; \ +} while (0) + +extern ec *ec_create(ec */*p*/); + +/* --- @ec_destroy@ --- * + * + * Arguments: @ec *p@ = pointer to an elliptic-curve point + * + * Returns: --- + * + * Use: Destroys a point, making it invalid. + */ + +#define EC_DESTROY(p) do { \ + ec *_p = (p); \ + if (!EC_ATINF(_p)) { \ + MP_DROP(_p->x); \ + MP_DROP(_p->y); \ + if (_p->z) MP_DROP(_p->z); \ + } \ +} while (0) + +extern void ec_destroy(ec */*p*/); + +/* --- @ec_atinf@ --- * + * + * Arguments: @const ec *p@ = pointer to a point + * + * Returns: Nonzero if %$p = O$% is the point at infinity, zero + * otherwise. + */ + +#define EC_ATINF(p) ((p)->x == MP_NEW || (p)->x == MP_NEWSEC) + +extern int ec_atinf(const ec */*p*/); + +/* --- @ec_setinf@ --- * + * + * Arguments: @ec *p@ = pointer to a point + * + * Returns: The argument @p@. + * + * Use: Sets the given point to be the point %$O$% at infinity. + */ + +#define EC_SETINF(p) do { \ + ec *_p = (p); \ + if (!EC_ATINF(_p)) { \ + MP_DROP(_p->x); \ + MP_DROP(_p->y); \ + if (_p->z) MP_DROP(_p->z); \ + _p->x = _p->y = _p->z = MP_NEW; \ + _p->y = MP_NEW; \ + _p->z = MP_NEW; \ + } \ +} while (0) + +extern ec *ec_setinf(ec */*p*/); + +/* --- @ec_copy@ --- * + * + * Arguments: @ec *d@ = pointer to destination point + * @const ec *p@ = pointer to source point + * + * Returns: The destination @d@. + * + * Use: Creates a copy of an elliptic curve point. + */ + +#define EC_COPY(d, p) do { \ + ec *_d = (d); \ + const ec *_p = (p); \ + if (d != p) { \ + EC_DESTROY(d); \ + if (EC_ATINF(p)) \ + _d->x = _d->y = _d->z = MP_NEW; \ + else { \ + _d->x = MP_COPY(_p->x); \ + _d->y = MP_COPY(_p->y); \ + _d->z = _p->z ? MP_COPY(_p->z) : MP_NEW; \ + } \ + } \ +} while (0) + +extern ec *ec_copy(ec */*d*/, const ec */*p*/); + +/* --- @ec_eq@ --- * + * + * Arguments: @const ec *p, *q@ = two points + * + * Returns: Nonzero if the points are equal. Compares external-format + * points. + */ + +#define EC_EQ(p, q) \ + ((EC_ATINF(p) && EC_ATINF(q)) || \ + (!EC_ATINF(p) && !EC_ATINF(q) && \ + MP_EQ((p)->x, (q)->x) && \ + MP_EQ((p)->y, (q)->y))) + +extern int ec_eq(const ec *p, const ec *q); + +/*----- Interesting arithmetic --------------------------------------------*/ + +/* --- @ec_samep@ --- * + * + * Arguments: @ec_curve *c, *d@ = two elliptic curves + * + * Returns: Nonzero if the curves are identical (not just isomorphic). + * + * Use: Checks for sameness of curves. This function does the full + * check, not just the curve-type-specific check done by the + * @sampep@ field operation. + */ + +extern int ec_samep(ec_curve */*c*/, ec_curve */*d*/); + +/* --- @ec_find@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @mp *x@ = a possible x-coordinate + * + * Returns: The destination if OK, or null if no point was found. + * + * Use: Finds a point on an elliptic curve with a given + * x-coordinate. If there is no point with the given + * %$x$%-coordinate, a null pointer is returned and the + * destination is left invalid. + */ + +extern ec *ec_find(ec_curve */*c*/, ec */*d*/, mp */*x*/); + +/* --- @ec_rand@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @grand *r@ = random number source + * + * Returns: The destination @d@. + * + * Use: Finds a random point on the given curve. + */ + +extern ec *ec_rand(ec_curve */*c*/, ec */*d*/, grand */*r*/); + +/* --- @ec_neg@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @const ec *p@ = pointer to the operand point + * + * Returns: The destination point. + * + * Use: Computes the negation of the given point. + */ + +extern ec *ec_neg(ec_curve */*c*/, ec */*d*/, const ec */*p*/); + +/* --- @ec_add@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @const ec *p, *q@ = pointers to the operand points + * + * Returns: The destination @d@. + * + * Use: Adds two points on an elliptic curve. + */ + +extern ec *ec_add(ec_curve */*c*/, ec */*d*/, + const ec */*p*/, const ec */*q*/); + +/* --- @ec_sub@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @const ec *p, *q@ = pointers to the operand points + * + * Returns: The destination @d@. + * + * Use: Subtracts one point from another on an elliptic curve. + */ + +extern ec *ec_sub(ec_curve */*c*/, ec */*d*/, + const ec */*p*/, const ec */*q*/); + +/* --- @ec_dbl@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @const ec *p@ = pointer to the operand point + * + * Returns: The destination @d@. + * + * Use: Doubles a point on an elliptic curve. + */ + +extern ec *ec_dbl(ec_curve */*c*/, ec */*d*/, const ec */*p*/); + +/* --- @ec_check@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @const ec *p@ = pointer to the point + * + * Returns: Zero if OK, nonzero if this is an invalid point. + * + * Use: Checks that a point is actually on an elliptic curve. + */ + +extern int ec_check(ec_curve */*c*/, const ec */*p*/); + +/* --- @ec_mul@, @ec_imul@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @const ec *p@ = pointer to the generator point + * @mp *n@ = integer multiplier + * + * Returns: The destination @d@. + * + * Use: Multiplies a point by a scalar, returning %$n p$%. The + * @imul@ variant uses internal representations for argument + * and result. + */ + +extern ec *ec_mul(ec_curve */*c*/, ec */*d*/, const ec */*p*/, mp */*n*/); +extern ec *ec_imul(ec_curve */*c*/, ec */*d*/, const ec */*p*/, mp */*n*/); + +/* --- @ec_mmul@, @ec_immul@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination point + * @const ec_mulfactor *f@ = pointer to vector of factors + * @size_t n@ = number of factors + * + * Returns: The destination @d@. + * + * Use: Does simultaneous point multiplication. The @immul@ variant + * uses internal representations for arguments and result. + */ + +extern ec *ec_mmul(ec_curve */*c*/, ec */*d*/, + const ec_mulfactor */*f*/, size_t /*n*/); +extern ec *ec_immul(ec_curve */*c*/, ec */*d*/, + const ec_mulfactor */*f*/, size_t /*n*/); + +/*----- Standard curve operations -----------------------------------------*/ + +/* --- @ec_stdsamep@ --- * + * + * Arguments: @ec_curve *c, *d@ = two elliptic curves + * + * Returns: Nonzero if the curves are identical (not just isomorphic). + * + * Use: Simple sameness check on @a@ and @b@ curve members. + */ + +extern int ec_stdsamep(ec_curve */*c*/, ec_curve */*d*/); + +/* --- @ec_idin@, @ec_idout@, @ec_idfix@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination + * @const ec *p@ = pointer to a source point + * + * Returns: The destination @d@. + * + * Use: An identity operation if your curve has no internal + * representation. (The field internal representation is still + * used.) + */ + +extern ec *ec_idin(ec_curve */*c*/, ec */*d*/, const ec */*p*/); +extern ec *ec_idout(ec_curve */*c*/, ec */*d*/, const ec */*p*/); +extern ec *ec_idfix(ec_curve */*c*/, ec */*d*/, const ec */*p*/); + +/* --- @ec_projin@, @ec_projout@, @ec_projfix@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination + * @const ec *p@ = pointer to a source point + * + * Returns: The destination @d@. + * + * Use: Conversion functions if your curve operations use a + * projective representation. + */ + +extern ec *ec_projin(ec_curve */*c*/, ec */*d*/, const ec */*p*/); +extern ec *ec_projout(ec_curve */*c*/, ec */*d*/, const ec */*p*/); +extern ec *ec_projfix(ec_curve */*c*/, ec */*d*/, const ec */*p*/); + +/* --- @ec_stdsub@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an elliptic curve + * @ec *d@ = pointer to the destination + * @const ec *p, *q@ = the operand points + * + * Returns: The destination @d@. + * + * Use: Standard point subtraction operation, in terms of negation + * and addition. This isn't as efficient as a ready-made + * subtraction operator. + */ + +extern ec *ec_stdsub(ec_curve */*c*/, ec */*d*/, + const ec */*p*/, const ec */*q*/); + +/*----- Creating curves ---------------------------------------------------*/ + +/* --- @ec_destroycurve@ --- * + * + * Arguments: @ec_curve *c@ = pointer to an ellptic curve + * + * Returns: --- + * + * Use: Destroys a description of an elliptic curve. + */ + +extern void ec_destroycurve(ec_curve */*c*/); + +/* --- @ec_prime@, @ec_primeproj@ --- * + * + * Arguments: @field *f@ = the underlying field for this elliptic curve + * @mp *a, *b@ = the coefficients for this curve + * + * Returns: A pointer to the curve, or null. + * + * Use: Creates a curve structure for an elliptic curve defined over + * a prime field. The @primeproj@ variant uses projective + * coordinates, which can be a win. + */ + +extern ec_curve *ec_prime(field */*f*/, mp */*a*/, mp */*b*/); +extern ec_curve *ec_primeproj(field */*f*/, mp */*a*/, mp */*b*/); + +/* --- @ec_bin@, @ec_binproj@ --- * + * + * Arguments: @field *f@ = the underlying field for this elliptic curve + * @mp *a, *b@ = the coefficients for this curve + * + * Returns: A pointer to the curve, or null. + * + * Use: Creates a curve structure for an elliptic curve defined over + * a binary field. The @binproj@ variant uses projective + * coordinates, which can be a win. + */ + +extern ec_curve *ec_bin(field */*f*/, mp */*a*/, mp */*b*/); +extern ec_curve *ec_binproj(field */*f*/, mp */*a*/, mp */*b*/); + +/*----- Curve parameter sets ----------------------------------------------*/ + +/* --- @ec_curveparse@ --- * + * + * Arguments: @qd_parse *qd@ = parser context + * + * Returns: Elliptic curve pointer if OK, or null. + * + * Use: Parses an elliptic curve description, which has the form + * + * * a field description + * * an optional `;' + * * `prime', `primeproj', `bin', or `binproj' + * * an optional `:' + * * the %$a$% parameter + * * an optional `,' + * * the %$b$% parameter + */ + +extern ec_curve *ec_curveparse(qd_parse */*qd*/); + +/* --- @ec_ptparse@ --- * + * + * Arguments: @qd_parse *qd@ = parser context + * @ec *p@ = where to put the point + * + * Returns: The point address, or null. + * + * Use: Parses an elliptic curve point. This has the form + * + * * %$x$%-coordinate + * * optional `,' + * * %$y$%-coordinate + */ + +extern ec *ec_ptparse(qd_parse */*qd*/, ec */*p*/); + +/* --- @ec_infoparse@ --- * + * + * Arguments: @qd_parse *qd@ = parser context + * @ec_info *ei@ = curve information block, currently + * uninitialized + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Parses an elliptic curve information string, and stores the + * information in @ei@. This has the form + * + * * elliptic curve description + * * optional `;' + * * common point + * * optional `:' + * * group order + * * optional `*' + * * cofactor + */ + +extern int ec_infoparse(qd_parse */*qd*/, ec_info */*ei*/); + +/* --- @ec_infofromdata@ --- * + * + * Arguments: @ec_info *ei@ = where to write the information + * @ecdata *ed@ = raw data + * + * Returns: --- + * + * Use: Loads elliptic curve information about one of the standard + * curves. + */ + +struct ecdata; +extern void ec_infofromdata(ec_info */*ei*/, struct ecdata */*ed*/); + +/* --- @ec_getinfo@ --- * + * + * Arguments: @ec_info *ei@ = where to write the information + * @const char *p@ = string describing a curve + * + * Returns: Null on success, or a pointer to an error message. + * + * Use: Parses out information about a curve. The string is either a + * standard curve name, or a curve info string. + */ + +extern const char *ec_getinfo(ec_info */*ei*/, const char */*p*/); + +/* --- @ec_sameinfop@ --- * + * + * Arguments: @ec_info *ei, *ej@ = two elliptic curve parameter sets + * + * Returns: Nonzero if the curves are identical (not just isomorphic). + * + * Use: Checks for sameness of curve parameters. + */ + +extern int ec_sameinfop(ec_info */*ei*/, ec_info */*ej*/); + +/* --- @ec_freeinfo@ --- * + * + * Arguments: @ec_info *ei@ = elliptic curve information block to free + * + * Returns: --- + * + * Use: Frees the information block. + */ + +extern void ec_freeinfo(ec_info */*ei*/); + +/* --- @ec_checkinfo@ --- * + * + * Arguments: @const ec_info *ei@ = elliptic curve information block + * + * Returns: Null if OK, or pointer to error message. + * + * Use: Checks an elliptic curve according to the rules in SEC1. + */ + +extern const char *ec_checkinfo(const ec_info */*ei*/, grand */*gr*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/ectab.h b/math/ectab.h new file mode 100644 index 0000000..38d3b30 --- /dev/null +++ b/math/ectab.h @@ -0,0 +1,72 @@ +/* -*-c-*- + * + * Table of standard elliptic curves + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_ECTAB_H +#define CATACOMB_ECTAB_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include "ec.h" + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct ecdata { + unsigned ftag; /* The kind of curve this is */ + mp p, beta; /* Modulus, and conversion magic */ + mp a, b; /* Elliptic curve parameters */ + mp r; /* Order of common point %$g$% */ + mp h; /* Cofactor %$h = \#E/r$% */ + mp gx, gy; /* Common point */ +} ecdata; + +enum { + FTAG_PRIME, /* Prime but not nice */ + FTAG_NICEPRIME, /* Nice prime field */ + FTAG_BINPOLY, /* Binary field, poly basis */ + FTAG_BINNORM /* Binary field, normal basis */ +}; + +typedef struct ecentry { + const char *name; + ecdata *data; +} ecentry; + +/*----- Global variables --------------------------------------------------*/ + +extern const ecentry ectab[]; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/ectab.in b/math/ectab.in new file mode 100644 index 0000000..0e7c8cb --- /dev/null +++ b/math/ectab.in @@ -0,0 +1,634 @@ +# Standard ellipic curves + +#----- Curves from SEC2 ----------------------------------------------------- + +curve secp112r1 prime + p 0xdb7c2abf62e35e668076bead208b + a 0xdb7c2abf62e35e668076bead2088 + b 0x659ef8ba043916eede8911702b22 + r 0xdb7c2abf62e35e7628dfac6561c5 + h 1 + gx 0x09487239995a5ee76b55f9c2f098 + gy 0xa89ce5af8724c0a23e0e0ff77500 +curve secp112r2 prime + p 0xdb7c2abf62e35e668076bead208b + a 0x6127c24c05f38a0aaaf65c0ef02c + b 0x51def1815db5ed74fcc34c85d709 + r 0x36df0aafd8b8d7597ca10520d04b + h 4 + gx 0x4ba30ab5e892b4e1649dd0928643 + gy 0xadcd46f5882e3747def36e956e97 + +curve secp128r1 niceprime + p 0xfffffffdffffffffffffffffffffffff + a 0xfffffffdfffffffffffffffffffffffc + b 0xe87579c11079f43dd824993c2cee5ed3 + r 0xfffffffe0000000075a30d1b9038a115 + h 1 + gx 0x161ff7528b899b2d0c28607ca52c5b86 + gy 0xcf5ac8395bafeb13c02da292dded7a83 +curve secp128r2 niceprime + p 0xfffffffdffffffffffffffffffffffff + a 0xd6031998d1b3bbfebf59cc9bbff9aee1 + b 0x5eeefca380d02919dc2c6558bb6d8a5d + r 0x3fffffff7fffffffbe0024720613b5a3 + h 4 + gx 0x7b6aa5d85e572983e6fb32a7cdebc140 + gy 0x27b6916a894d3aee7106fe805fc34b44 + +curve secp160k1 niceprime + p 0xfffffffffffffffffffffffffffffffeffffac73 + a 0 + b 7 + r 0x0100000000000000000001b8fa16dfab9aca16b6b3 + h 1 + gx 0x3b4c382ce37aa192a4019e763036f4f5dd4d7ebb + gy 0x938cf935318fdced6bc28286531733c3f03c4fee +curve secp160r1 niceprime + p 0xffffffffffffffffffffffffffffffff7fffffff + a 0xffffffffffffffffffffffffffffffff7ffffffc + b 0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45 + r 0x0100000000000000000001f4c8f927aed3ca752257 + h 1 + gx 0x4a96b5688ef573284664698968c38bb913cbfc82 + gy 0x23a628553168947d59dcc912042351377ac5fb32 +curve secp160r2 niceprime + p 0xfffffffffffffffffffffffffffffffeffffac73 + a 0xfffffffffffffffffffffffffffffffeffffac70 + b 0xb4e134d3fb59eb8bab57274904664d5af50388ba + r 0x0100000000000000000000351ee786a818f3a1a16b + h 1 + gx 0x52dcb034293a117e1f4ff11b30f7199d3144ce6d + gy 0xfeaffef2e331f296e071fa0df9982cfea7d43f2e + +curve secp192k1 niceprime + p 0xfffffffffffffffffffffffffffffffffffffffeffffee37 + a 0 + b 3 + r 0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d + h 1 + gx 0xdb4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d + gy 0x9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d +curve secp192r1 niceprime + p 0xfffffffffffffffffffffffffffffffeffffffffffffffff + a 0xfffffffffffffffffffffffffffffffefffffffffffffffc + b 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1 + r 0xffffffffffffffffffffffff99def836146bc9b1b4d22831 + h 1 + gx 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012 + gy 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811 + +curve secp224k1 niceprime + p 0xfffffffffffffffffffffffffffffffffffffffffffffffeffffe56d + a 0 + b 5 + r 0x010000000000000000000000000001dce8d2ec6184caf0a971769fb1f7 + h 1 + gx 0xa1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c + gy 0x7e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5 +curve secp224r1 niceprime + p 0xffffffffffffffffffffffffffffffff000000000000000000000001 + a 0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe + b 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4 + r 0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d + h 1 + gx 0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21 + gy 0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34 + +curve secp256k1 niceprime + p 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f + a 0 + b 7 + r 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 + h 1 + gx 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 + gy 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 +curve secp256r1 niceprime + p 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff + a 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc + b 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b + r 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 + h 1 + gx 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296 + gy 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 + +curve secp384r1 niceprime + p 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff + a 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc + b 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef + r 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973 + h 1 + gx 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7 + gy 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f + +curve secp521r1 niceprime + p 0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + a 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc + b 0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00 + r 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409 + h 1 + gx 0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66 + gy 0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650 + +curve sect113r1 binpoly + p 0x20000000000000000000000000201 + a 0x003088250ca6e7c7fe649ce85820f7 + b 0x00e8bee4d3e2260744188be0e9c723 + r 0x0100000000000000d9ccec8a39e56f + h 2 + gx 0x009d73616f35f4ab1407d73562c10f + gy 0x00a52830277958ee84d1315ed31886 +curve sect113r2 binpoly + p 0x20000000000000000000000000201 + a 0x00689918dbec7e5a0dd6dfc0aa55c7 + b 0x0095e9a9ec9b297bd4bf36e059184f + r 0x010000000000000108789b2496af93 + h 2 + gx 0x01a57a6a7b26ca5ef52fcdb8164797 + gy 0x00b3adc94ed1fe674c06e695baba1d + +curve sect131r1 binpoly + p 0x80000000000000000000000000000010d + a 0x07a11b09a76b562144418ff3ff8c2570b8 + b 0x0217c05610884b63b9c6c7291678f9d341 + r 0x0400000000000000023123953a9464b54d + h 2 + gx 0x0081baf91fdf9833c40f9c181343638399 + gy 0x078c6e7ea38c001f73c8134b1b4ef9e150 +curve sect131r2 binpoly + p 0x80000000000000000000000000000010d + a 0x03e5a88919d7cafcbf415f07c2176573b2 + b 0x04b8266a46c55657ac734ce38f018f2192 + r 0x0400000000000000016954a233049ba98f + h 2 + gx 0x0356dcd8f2f95031ad652d23951bb366a8 + gy 0x0648f06d867940a5366d9e265de9eb240f + +curve sect163k1 binpoly + p 0x800000000000000000000000000000000000000c9 + a 1 + b 1 + r 0x04000000000000000000020108a2e0cc0d99f8a5ef + h 2 + gx 0x02fe13c0537bbc11acaa07d793de4e6d5e5c94eee8 + gy 0x0289070fb05d38ff58321f2e800536d538ccdaa3d9 +curve sect163r1 binpoly + p 0x800000000000000000000000000000000000000c9 + a 0x07b6882caaefa84f9554ff8428bd88e246d2782ae2 + b 0x0713612dcddcb40aab946bda29ca91f73af958afd9 + r 0x03ffffffffffffffffffff48aab689c29ca710279b + h 2 + gx 0x0369979697ab43897789566789567f787a7876a654 + gy 0x00435edb42efafb2989d51fefce3c80988f41ff883 +curve sect163r2 binpoly + p 0x800000000000000000000000000000000000000c9 + a 1 + b 0x020a601907b8c953ca1481eb10512f78744a3205fd + r 0x040000000000000000000292fe77e70c12a4234c33 + h 2 + gx 0x03f0eba16286a2d57ea0991168d4994637e8343e36 + gy 0x00d51fbc6c71a0094fa2cdd545b11c5c0c797324f1 + +curve sect193r1 binpoly + p 0x2000000000000000000000000000000000000000000008001 + a 0x0017858feb7a98975169e171f77b4087de098ac8a911df7b01 + b 0x00fdfb49bfe6c3a89facadaa7a1e5bbc7cc1c2e5d831478814 + r 0x01000000000000000000000000c7f34a778f443acc920eba49 + h 2 + gx 0x01f481bc5f0ff84a74ad6cdf6fdef4bf6179625372d8c0c5e1 + gy 0x0025e399f2903712ccf3ea9e3a1ad17fb0b3201b6af7ce1b05 +curve sect193r2 binpoly + p 0x2000000000000000000000000000000000000000000008001 + a 0x0163f35a5137c2ce3ea6ed8667190b0bc43ecd69977702709b + b 0x00c9bb9e8927d4d64c377e2ab2856a5b16e3efb7f61d4316ae + r 0x010000000000000000000000015aab561b005413ccd4ee99d5 + h 2 + gx 0x00d9b67d192e0367c803f39e1a7e82ca14a651350aae617e8f + gy 0x01ce94335607c304ac29e7defbd9ca01f596f927224cdecf6c + +curve sect233k1 binpoly + p 0x20000000000000000000000000000000000000004000000000000000001 + a 0 + b 1 + r 0x8000000000000000000000000000069d5bb915bcd46efb1ad5f173abdf + h 4 + gx 0x017232ba853a7e731af129f22ff4149563a419c26bf50a4c9d6eefad6126 + gy 0x01db537dece819b7f70f555a67c427a8cd9bf18aeb9b56e0c11056fae6a3 +curve sect233r1 binpoly + p 0x20000000000000000000000000000000000000004000000000000000001 + a 1 + b 0x0066647ede6c332c7f8c0923bb58213b333b20e9ce4281fe115f7d8f90ad + r 0x01000000000000000000000000000013e974e72f8a6922031d2603cfe0d7 + h 2 + gx 0x00fac9dfcbac8313bb2139f1bb755fef65bc391f8b36f8f8eb7371fd558b + gy 0x01006a08a41903350678e58528bebf8a0beff867a7ca36716f7e01f81052 + +curve sect239k1 binpoly + p 0x800000000000000000004000000000000000000000000000000000000001 + a 0 + b 1 + r 0x2000000000000000000000000000005a79fec67cb6e91f1c1da800e478a5 + h 4 + gx 0x29a0b6a887a983e9730988a68727a8b2d126c44cc2cc7b2a6555193035dc + gy 0x76310804f12e549bdb011c103089e73510acb275fc312a5dc6b76553f0ca + +curve sect283k1 binpoly + p 0x800000000000000000000000000000000000000000000000000000000000000000010a1 + a 0 + b 1 + r 0x01ffffffffffffffffffffffffffffffffffe9ae2ed07577265dff7f94451e061e163c61 + h 4 + gx 0x0503213f78ca44883f1a3b8162f188e553cd265f23c1567a16876913b0c2ac2458492836 + gy 0x01ccda380f1c9e318d90f95d07e5426fe87e45c0e8184698e45962364e34116177dd2259 +curve sect283r1 binpoly + p 0x800000000000000000000000000000000000000000000000000000000000000000010a1 + a 1 + b 0x027b680ac8b8596da5a4af8a19a0303fca97fd7645309fa2a581485af6263e313b79a2f5 + r 0x03ffffffffffffffffffffffffffffffffffef90399660fc938a90165b042a7cefadb307 + h 2 + gx 0x05f939258db7dd90e1934f8c70b0dfec2eed25b8557eac9c80e2e198f8cdbecd86b12053 + gy 0x03676854fe24141cb98fe6d4b20d02b4516ff702350eddb0826779c813f0df45be8112f4 + +curve sect409k1 binpoly + p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001 + a 0 + b 1 + r 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffe5f83b2d4ea20400ec4557d5ed3e3e7ca5b4b5c83b8e01e5fcf + h 4 + gx 0x0060f05f658f49c1ad3ab1890f7184210efd0987e307c84c27accfb8f9f67cc2c460189eb5aaaa62ee222eb1b35540cfe9023746 + gy 0x01e369050b7c4e42acba1dacbf04299c3460782f918ea427e6325165e9ea10e3da5f6c42e9c55215aa9ca27a5863ec48d8e0286b +curve sect409r1 binpoly + p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001 + a 1 + b 0x0021a5c2c8ee9feb5c4b9a753b7b476b7fd6422ef1f3dd674761fa99d6ac27c8a9a197b272822f6cd57a55aa4f50ae317b13545f + r 0x010000000000000000000000000000000000000000000000000001e2aad6a612f33307be5fa47c3c9e052f838164cd37d9a21173 + h 2 + gx 0x015d4860d088ddb3496b0c6064756260441cde4af1771d4db01ffe5b34e59703dc255a868a1180515603aeab60794e54bb7996a7 + gy 0x0061b1cfab6be5f32bbfa78324ed106a7636b9c5a7bd198d0158aa4f5488d08f38514f1fdf4b4f40d2181b3681c364ba0273c706 + +curve sect571k1 binpoly + p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425 + a 0 + b 1 + r 0x020000000000000000000000000000000000000000000000000000000000000000000000131850e1f19a63e4b391a8db917f4138b630d84be5d639381e91deb45cfe778f637c1001 + h 4 + gx 0x026eb7a859923fbc82189631f8103fe4ac9ca2970012d5d46024804801841ca44370958493b205e647da304db4ceb08cbbd1ba39494776fb988b47174dca88c7e2945283a01c8972 + gy 0x0349dc807f4fbf374f4aeade3bca95314dd58cec9f307a54ffc61efc006d8a2c9d4979c0ac44aea74fbebbb9f772aedcb620b01a7ba7af1b320430c8591984f601cd4c143ef1c7a3 +curve sect571r1 binpoly + p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425 + a 1 + b 0x02f40e7e2221f295de297117b7f3d62f5c6a97ffcb8ceff1cd6ba8ce4a9a18ad84ffabbd8efa59332be7ad6756a66e294afd185a78ff12aa520e4de739baca0c7ffeff7f2955727a + r 0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47 + h 2 + gx 0x0303001d34b856296c16c0d40d3cd7750a93d1d2955fa80aa5f40fc8db7b2abdbde53950f4c0d293cdd711a35b67fb1499ae60038614f1394abfa3b4c850d927e1e7769c8eec2d19 + gy 0x037bf27342da639b6dccfffeb73d69d78c6c27a6009cbbca1980f8533921e8a684423e43bab08a576291af8f461bb2a8b3531d2f0485c19b16e2f1516e23dd3c1a4827af1b8ac15b + +#----- Curves from ANSI X9.62 ----------------------------------------------- +# +# The conversion factors for the normal basis representations were generated +# because none were given in the document. + +curve ansi-c2pnb163v1 binpoly + p 0x080000000000000000000000000000000000000107 + a 0x072546b5435234a422e0789675f432c89435de5242 + b 0x00c9517d06d5240d3cff38c74b20b6cd4d6f9dd4d9 + r 0x0400000000000000000001e60fc8821cc74daeafc1 + h 2 + gx 0x07af69989546103d79329fcc3d74880f33bbe803cb + gy 0x01ec23211b5966adea1d3f87f7ea5848aef0b7ca9f +curve ansi-c2pnb163v2 binpoly + p 0x080000000000000000000000000000000000000107 + a 0x0108b39e77c4b108bed981ed0e890e117c511cf072 + b 0x0667aceb38af4e488c407433ffae4f1c811638df20 + r 0x03fffffffffffffffffffdf64de1151adbb78f10a7 + h 2 + gx 0x0024266e4eb5106d0a964d92c4860e2671db9b6cc5 + gy 0x079f684ddf6684c5cd258b3890021b2386dfd19fc5 +curve ansi-c2pnb163v3 binpoly + p 0x080000000000000000000000000000000000000107 + a 0x07a526c63d3e25a256a007699f5447e32ae456b50e + b 0x03f7061798eb99e238fd6f1bf95b48feeb4854252b + r 0x03fffffffffffffffffffe1aee140f110aff961309 + h 2 + gx 0x02f9f87b7c574d0bdecf8a22e6524775f98cdebdcb + gy 0x05b935590c155e17ea48eb3ff3718b893df59a05d0 + +curve ansi-c2tnb191v1 binpoly + p 0x800000000000000000000000000000000000000000000201 + a 0x2866537b676752636a68f56554e12640276b649ef7526267 + b 0x2e45ef571f00786f67b0081b9495a3d95462f5de0aa185ec + r 0x40000000000000000000000004a20e90c39067c893bbb9a5 + h 2 + gx 0x36b3daf8a23206f9c4f299d7b21a9c369137f2c84ae1aa0d + gy 0x765be73433b3f95e332932e70ea245ca2418ea0ef98018fb +curve ansi-c2tnb191v2 binpoly + p 0x800000000000000000000000000000000000000000000201 + a 0x401028774d7777c7b7666d1366ea432071274f89ff01e718 + b 0x0620048d28bcbd03b6249c99182b7c8cd19700c362c46a01 + r 0x20000000000000000000000050508cb89f652824e06b8173 + h 4 + gx 0x3809b2b7cc1b28cc5a87926aad83fd28789e81e2c9e3bf10 + gy 0x17434386626d14f3dbf01760d9213a3e1cf37aec437d668a +curve ansi-c2tnb191v3 binpoly + p 0x800000000000000000000000000000000000000000000201 + a 0x6c01074756099122221056911c77d77e77a777e7e7e77fcb + b 0x71fe1af926cf847989efef8db459f66394d90f32ad3f15e8 + r 0x155555555555555555555555610c0b196812bfb6288a3ea3 + h 6 + gx 0x375d4ce24fde434489de8746e71786015009e66e38a926dd + gy 0x545a39176196575d985999366e6ad34ce0a77cd7127b06be +curve ansi-c2onb191v1 binnorm + p 0x800000000000000000000000000000000000000000000201 + beta 0x19c409a7f85383bf0ef72b097a5c7398013a2dba6269292d + a 0x65903e04e1e4924253e26a3c9ac28c758bd8184a3fb680e8 + b 0x54678621b190cfce282ade219d5b3a065e3f4b3ffdebb29b + r 0x4000000000000000000000009cf2d6e3901dac4c32eec65d + h 2 + gx 0x5a2c69a32e8638e51ccefaad05350a978457cb5fb6df994a + gy 0x0f32fe0fa0e902f19b17d363c269f4f5cfe8087618569954 +curve ansi-c2onb191v2 binnorm + p 0x800000000000000000000000000000000000000000000201 + beta 0x19c409a7f85383bf0ef72b097a5c7398013a2dba6269292d + a 0x25f8d06c97c822536d469cd5170cdd7bb9f500bd6db110fb + b 0x75ff570e35ca94fb3780c2619d081c17aa59fbd5e591c1c4 + r 0x0fffffffffffffffffffffffeeb354b7270b2992b7818627 + h 8 + gx 0x2a16910e8f6c4b199be24213857abc9c992edfb2471f3c68 + gy 0x1592dbfebeb81a7c071b744d5e2f9e242ea65b81138a3468 + +curve ansi-c2tnb239v1 binpoly + p 0x800000000000000000000000000000000000000000000000001000000001 + a 0x32010857077c5431123a46b808906756f543423e8d27877578125778ac76 + b 0x790408f2eedaf392b012edefb3392f30f4327c0ca3f31fc383c422aa8c16 + r 0x2000000000000000000000000000000f4d42ffe1492a4993f1cad666e447 + h 4 + gx 0x57927098fa932e7c0a96d3fd5b706ef7e5f5c156e16b7e7c86038552e91d + gy 0x61d8ee5077c33fecf6f1a16b268de469c3c7744ea9a971649fc7a9616305 +curve ansi-c2tnb239v2 binpoly + p 0x800000000000000000000000000000000000000000000000001000000001 + a 0x4230017757a767fae42398569b746325d45313af0766266479b75654e65f + b 0x5037ea654196cff0cd82b2c14a2fcf2e3ff8775285b545722f03eacdb74b + r 0x1555555555555555555555555555553c6f2885259c31e3fcdf154624522d + h 6 + gx 0x28f9d04e900069c8dc47a08534fe76d2b900b7d7ef31f5709f200c4ca205 + gy 0x5667334c45aff3b5a03bad9dd75e2c71a99362567d5453f7fa6e227ec833 +curve ansi-c2tnb239v3 binpoly + p 0x800000000000000000000000000000000000000000000000001000000001 + a 0x01238774666a67766d6676f778e676b66999176666e687666d8766c66a9f + b 0x6a941977ba9f6a435199acfc51067ed587f519c5ecb541b8e44111de1d40 + r 0x0cccccccccccccccccccccccccccccac4912d2d9df903ef9888b8a0e4cff + h 10 + gx 0x70f6e9d04d289c4e89913ce3530bfde903977d42b146d539bf1bde4e9c92 + gy 0x2e5a0eaf6e5e1305b9004dce5c0ed7fe59a35608f33837c816d80b79f461 +curve ansi-c2onb239v1 binnorm + p 0x800000000000000000000000000000000000000000000000001000000001 + beta 0x3b5ce9846911b248f9347018a7ac8cce3662cee952ba45becd02d4b903ec + a 0x182dd45f5d470239b8983fea47b8b292641c57f9bf84baecde8bb3adce30 + b 0x147a9c1d4c2ce9be5d34ec02797f76667ebad5a3f93fa2a524bfde91ef28 + r 0x200000000000000000000000000000474f7e69f42fe430931d0b455aae8b + h 4 + gx 0x4912ad657f1d1c6b32edb9942c95e226b06fb012cd40fdea0d72197c8104 + gy 0x01f1fbc3d21168fd3f66c441c2b5c6cfdcd9ed3e13646b7a4db9a3b0c286 +curve ansi-c2onb239v2 binnorm + p 0x800000000000000000000000000000000000000000000000001000000001 + beta 0x3b5ce9846911b248f9347018a7ac8cce3662cee952ba45becd02d4b903ec + a 0x1ecf1b9d28d8017505e17475d3df2982e243ca5cb5e9f94a3f36124a486e + b 0x3ee257250d1a2e66cef23aa0f25b12388de8a10ff9554f90afbaa9a08b6d + r 0x1555555555555555555555555555558cf77a5d0589d2a9340d963b7ad703 + h 6 + gx 0x5f949ccb694f26b96d191e8925205a719929e93c37174cb6c7f659a37b85 + gy 0x2d788d605ac81069e9964fd6edbae8bbf582a5c409a1078cf487a147ceb2 + ## The spec seems bogus: the suggested base point G isn't in the + ## subgroup! The point above is h G. + ##gx 0x193279fc543e9f5f7119189785b9c60b249be4820baf6c24bdfa2813f8b8 + ##gy 0x5da021e5af77604051fc5c38da8293c1eeeaa00f046eeb93b6c8b774bb9b + +curve ansi-c2tnb359v1 binpoly + p 0x800000000000000000000000000000000000000000000000000000000000000000000000100000000000000001 + a 0x5667676a654b20754f356ea92017d946567c46675556f19556a04616b567d223a5e05656fb549016a96656a557 + b 0x2472e2d0197c49363f1fe7f5b6db075d52b6947d135d8ca445805d39bc345626089687742b6329e70680231988 + r 0x01af286bca1af286bca1af286bca1af286bca1af286bc9fb8f6b85c556892c20a7eb964fe7719e74f490758d3b + h 76 + gx 0x3c258ef3047767e7ede0f1fdaa79daee3841366a132e163aced4ed2401df9c6bdcde98e8e707c07a2239b1b097 + gy 0x53d7e08529547048121e9c95f3791dd804963948f34fae7bf44ea82365dc7868fe57e4ae2de211305a407104bd + +curve ansi-c2tnb431v1 binpoly + p 0x800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001 + a 0x1a827ef00dd6fc0e234caf046c6a5d8a85395b236cc4ad2cf32a0cadbdc9ddf620b0eb9906d0957f6c6feacd615468df104de296cd8f + b 0x10d9b4a3d9047d8b154359abfb1b7f5485b04ceb868237ddc9deda982a679a5a919b626d4e50a8dd731b107a9962381fb5d807bf2618 + r 0x000340340340340340340340340340340340340340340340340340340323c313fab50589703b5ec68d3587fec60d161cc149c1ad4a91 + h 10080 + gx 0x120fc05d3c67a99de161d2f4092622feca701be4f50f4758714e8a87bbf2a658ef8c21e7c5efe965361f6c2999c0c247b0dbd70ce6b7 + gy 0x20d0af8903a96f8d5fa2c255745d3c451b302c9346d9b7e485e7bce41f6b591f3e8f6addcbb0bc4c2f947a7de1a89b625d6a598b3760 + +# These curves aren't included because their degree isn't prime (so they +# may be vulnerable to Weil descent) +# ansi-c2pnb176w1 is bad: 176 isn't prime +# ansi-c2pnb208v1 is bad: 208 isn't prime +# ansi-c2pnb272w1 is bad: 272 isn't prime +# ansi-c2pnb304w1 is bad: 304 isn't prime +# ansi-c2pnb368w1 is bad: 368 isn't prime + +alias ansi-prime192v1 secp192r1 +curve ansi-prime192v2 niceprime + p 0xfffffffffffffffffffffffffffffffeffffffffffffffff + a 0xfffffffffffffffffffffffffffffffefffffffffffffffc + b 0xcc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953 + r 0xfffffffffffffffffffffffe5fb1a724dc80418648d8dd31 + h 1 + gx 0xeea2bae7e1497842f2de7769cfe9c989c072ad696f48034a + gy 0x6574d11d69b6ec7a672bb82a083df2f2b0847de970b2de15 +curve ansi-prime192v3 niceprime + p 0xfffffffffffffffffffffffffffffffeffffffffffffffff + a 0xfffffffffffffffffffffffffffffffefffffffffffffffc + b 0x22123dc2395a05caa7423daeccc94760a7d462256bd56916 + r 0xffffffffffffffffffffffff7a62d031c83f4294f640ec13 + h 1 + gx 0x7d29778100c65a1da1783716588dce2b8b4aee8e228f1896 + gy 0x38a90f22637337334b49dcb66a6dc8f9978aca7648a943b0 + +curve ansi-prime239v1 niceprime + p 0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff + a 0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc + b 0x6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a + r 0x7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b + h 1 + gx 0x0ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf + gy 0x7debe8e4e90a5dae6e4054ca530ba04654b36818ce226b39fccb7b02f1ae +curve ansi-prime239v2 niceprime + p 0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff + a 0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc + b 0x617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c + r 0x7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063 + h 1 + gx 0x38af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7 + gy 0x5b0125e4dbea0ec7206da0fc01d9b081329fb555de6ef460237dff8be4ba +curve ansi-prime239v3 niceprime + p 0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff + a 0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc + b 0x255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e + r 0x7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551 + h 1 + gx 0x6768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a + gy 0x1607e6898f390c06bc1d552bad226f3b6fcfe48b6e818499af18e3ed6cf3 + +alias ansi-prime256v1 secp256r1 + +#----- Curves from ANSI X9.63 ----------------------------------------------- +# +# These are just duplicates of the SEC curves. + +alias ansit163k1 sect163k1 +alias ansit163r1 sect163r1 +alias ansit163r2 sect163r2 +alias ansit193r1 sect193r1 +alias ansit193r2 sect193r2 +alias ansit233k1 sect233k1 +alias ansit233r1 sect233r1 +alias ansit239k1 sect239k1 +alias ansit283k1 sect283k1 +alias ansit283r1 sect283r1 +alias ansit409k1 sect409k1 +alias ansit409r1 sect409r1 +alias ansit571k1 sect571k1 +alias ansit571r1 sect571r1 + +alias ansip160k1 secp160k1 +alias ansip160r1 secp160r1 +alias ansip160r2 secp160r2 +alias ansip192k1 secp192k1 +alias ansip192r1 secp192r1 +alias ansip224k1 secp224k1 +alias ansip224r1 secp224r1 +alias ansip256k1 secp256k1 +alias ansip256r1 secp256r1 +alias ansip384r1 secp384r1 +alias ansip521r1 secp521r1 + +#----- Curves from RFC2414 (Oakley) ----------------------------------------- +# +# The Oakley curves are not good: +# oakley155 has too large a cofactor +# oakley185's field has composite degree +# Hence, we include neither here. + +#----- NIST curves from FIPS186-2 ------------------------------------------- +# +# These are duplicates of SEC2 curves. However, the normal basis +# representations aren't in SEC, so we give them here. (Conversion factors +# from FIPS186-2. + +alias nist-p192 secp192r1 +alias nist-p224 secp224r1 +alias nist-p256 secp256r1 +alias nist-p384 secp384r1 +alias nist-p521 secp521r1 + +alias nist-k163 sect163k1 +alias nist-k233 sect233k1 +alias nist-k283 sect283k1 +alias nist-k409 sect409k1 +alias nist-k571 sect571k1 + +alias nist-b163 sect163r2 +alias nist-b233 sect233r1 +alias nist-b283 sect283r1 +alias nist-b409 sect409r1 +alias nist-b571 sect571r1 + +curve nist-k163n binnorm + p 0x800000000000000000000000000000000000000c9 + beta 0x715169c109c612e390d347c748342bcd3b02a0bef + a 0x7ffffffffffffffffffffffffffffffffffffffff + b 0x7ffffffffffffffffffffffffffffffffffffffff + r 0x04000000000000000000020108a2e0cc0d99f8a5ef + h 2 + gx 0x05679b353caa46825fea2d3713ba450da0c2a4541 + gy 0x235b7c6710050689906bac3d9dec76a835591edb2 +curve nist-b163n binnorm + p 0x800000000000000000000000000000000000000c9 + beta 0x715169c109c612e390d347c748342bcd3b02a0bef + a 0x7ffffffffffffffffffffffffffffffffffffffff + b 0x6645f3cacf1638e139c6cd13ef61734fbc9e3d9fb + r 0x040000000000000000000292fe77e70c12a4234c33 + h 2 + gx 0x0311103c17167564ace77ccb09c681f886ba54ee8 + gy 0x333ac13c6447f2e67613bf7009daf98c87bb50c7f + +curve nist-k233n binnorm + p 0x20000000000000000000000000000000000000004000000000000000001 + beta 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9 + a 0 + b 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + r 0x8000000000000000000000000000069d5bb915bcd46efb1ad5f173abdf + h 4 + gx 0x0fde76d9dcd26e643ac26f1aa901aa129784b71fc0722b2d05614d650b3 + gy 0x0643e317633155c9e0447ba8020a3c43177450ee036d633501434cac978 +curve nist-b233n binnorm + p 0x20000000000000000000000000000000000000004000000000000000001 + beta 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9 + a 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + b 0x1a003e0962d4f9a8e407c904a9538163adb825212600c7752ad52233279 + r 0x01000000000000000000000000000013e974e72f8a6922031d2603cfe0d7 + h 2 + gx 0x18b863524b3cdfefb94f2784e0b116faac54404bc9162a363bab84a14c5 + gy 0x04925df77bd8b8ff1a5ff519417822bfedf2bbd752644292c98c7af6e02 + +curve nist-k283n binnorm + p 0x800000000000000000000000000000000000000000000000000000000000000000010a1 + beta 0x31e0ed791c3282dc5624a720818049d053e8c7ab8663792bc1d792eba9867fc7b317a99 + a 0 + b 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + r 0x01ffffffffffffffffffffffffffffffffffe9ae2ed07577265dff7f94451e061e163c61 + h 4 + gx 0x3ab9593f8db09fc188f1d7c4ac9fcc3e57fcd3bdb15024b212c70229de5fcd92eb0ea60 + gy 0x2118c4755e7345cd8f603ef93b98b106fe8854ffeb9a3b304634cc83a0e759f0c2686b1 +curve nist-b283n binnorm + p 0x800000000000000000000000000000000000000000000000000000000000000000010a1 + beta 0x31e0ed791c3282dc5624a720818049d053e8c7ab8663792bc1d792eba9867fc7b317a99 + a 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + b 0x157261b894739fb5a13503f55f0b3f10c5601166633102201138cc180c0206bdafbc951 + r 0x03ffffffffffffffffffffffffffffffffffef90399660fc938a90165b042a7cefadb307 + h 2 + gx 0x749468e464ee468634b21f7f61cb700701817e6bc36a2364cb8906e940948eaa463c35d + gy 0x62968bd3b489ac5c9b859da68475c315bafcdc4ccd0dc905b70f62446f49c052f49c08c + +curve nist-k409n binnorm + p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001 + beta 0x0dfa06be206aa97b7a41fffb9b0c55f8f048062fbe8381b4248adf92912ccc8e3f91a24e1cfb3950532b988971c23042e85708d + a 0 + b 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + r 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffe5f83b2d4ea20400ec4557d5ed3e3e7ca5b4b5c83b8e01e5fcf + h 4 + gx 0x1b559c7cba2422e3affe13343e808b55e012d726ca0b7e6a63aeafbc1e3a98e10ca0fcf98350c3b7f89a9754a8e1dc0713cec4a + gy 0x16d8c42052f07e7713e7490eff318ba1abd6fef8a5433c894b24f5c817aeb79852496fbee803a47bc8a203878ebf1c499afd7d6 +curve nist-b409n binnorm + p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001 + beta 0x0dfa06be206aa97b7a41fffb9b0c55f8f048062fbe8381b4248adf92912ccc8e3f91a24e1cfb3950532b988971c23042e85708d + a 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + b 0x124d0651c3d3772f7f5a1fe6e715559e2129bdfa04d52f7b6ac7c532cf0ed06f610072d88ad2fdcc50c6fde72843670f8b3742a + r 0x010000000000000000000000000000000000000000000000000001e2aad6a612f33307be5fa47c3c9e052f838164cd37d9a21173 + h 2 + gx 0x0ceacbc9f475767d8e69f3b5dfab39813685262bcacf22b84c7b6dd981899e7318c96f0761f77c602c016ced7c548de830d708f + gy 0x199d64ba8f089c6db0e0b61e80bb95934afd0caf2e8be76d1c5e9affc7476df49142691ad30390288aa09bcc59c1573aa3c009a + +curve nist-k571n binnorm + p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425 + beta 0x452186bbf5840a0bcf8c9f02a54efa04e813b43c3d4149606c4d27b487bf107393c8907f79d9778beb35ee87467d3288274caebda6ce05aeb4ca5cf3c3044bd4372232f2c1a27c4 + a 0 + b 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + r 0x020000000000000000000000000000000000000000000000000000000000000000000000131850e1f19a63e4b391a8db917f4138b630d84be5d639381e91deb45cfe778f637c1001 + h 4 + gx 0x04bb2dba418d0db107adae003427e5d7cc139acb465e5934f0bea2ab2f3622bc29b3d5b9aa7a1fdfd5d8be66057c1008e71e484bcd98f22bf8476423767367429ef2ec5bc3ebcf7 + gy 0x44cbb57de20788d2c952d7b56cf39bd3e89b18984bd124e751ceff4369dd8dac6a59e6e745df44d8220ce22aa2c852cfcbbef49ebaa98bd2483e33180e04286feaa253050caff60 +curve nist-b571n binnorm + p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425 + beta 0x452186bbf5840a0bcf8c9f02a54efa04e813b43c3d4149606c4d27b487bf107393c8907f79d9778beb35ee87467d3288274caebda6ce05aeb4ca5cf3c3044bd4372232f2c1a27c4 + a 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + b 0x3762d0d47116006179da35688eeaccf591a5cdea75000118d9608c59132d43426101a1dfb3774115f586623f75f00001ce611983c1275fa31f5bc9f4be1a0f467f01ca885c74777 + r 0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47 + h 2 + gx 0x0735e035def5925cc33173eb2a8ce7767522b466d278b650a2916127dfea9d2d361089f0a7a0247a184e1c70d417866e0fe0feb0ff8f2f3f9176418f97d117e624e2015df1662a8 + gy 0x04a36420572616cdf7e606fccadaecfc3b76dab0eb1248dd03fbdfc9cd3242c4726be579855e812de7ec5c500b4576a24628048b6a72d880062eed0dd34b1096d3acbb6b01a4a97 + +#----- That's all, folks----------------------------------------------------- diff --git a/math/exp.c b/math/exp.c new file mode 100644 index 0000000..4ddfa6d --- /dev/null +++ b/math/exp.c @@ -0,0 +1,69 @@ +/* -*-c-*- + * + * Generalized exponentiation + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define EXP_TYPE /* Hack */ +#include "exp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @exp_simulnext@ --- * + * + * Arguments: @exp_simul *e@ = pointer to state structure + * @size_t x@ = a current accumulator + * + * Returns: The next column of bits. + * + * Use: Scans the next column of bits for a simultaneous + * exponentiation. + */ + +size_t exp_simulnext(exp_simul *e, size_t x) +{ + size_t i; + + /* --- Move to the next word along --- */ + + if (!e->b) { + e->o--; + for (i = 0; i < e->n; i++) + e->s[i].w = e->o < e->s[i].len ? e->s[i].v[e->o] : 0; + e->b = MPW_BITS; + } + + /* --- Scan out a column of bits --- */ + + for (i = 0; i < e->n; i++) { + x = (x << 1) | ((e->s[i].w >> (MPW_BITS - 1)) & 1u); + e->s[i].w <<= 1; + } + e->b--; + return (x); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/exp.h b/math/exp.h new file mode 100644 index 0000000..41581c5 --- /dev/null +++ b/math/exp.h @@ -0,0 +1,420 @@ +/* -*-c-*- + * + * Generalized exponentiation + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifdef CATACOMB_EXP_H +# error "Multiple inclusion of " +#endif + +#define CATACOMB_EXP_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct exp_simulscan { + mpw w; + size_t len; + const mpw *v; +} exp_simulscan; + +typedef struct exp_simul { + unsigned b; + size_t o, n; + exp_simulscan *s; +} exp_simul; + +/*----- Macros provided ---------------------------------------------------*/ + +/* --- Parameters --- */ + +#ifndef EXP_WINSZ /* Sliding window size */ +# define EXP_WINSZ 4 /* Predefine if you need to */ +#endif + +/* --- These are determined from the window size --- * + * + * Given a %$k$%-bit exponent, I expect to do %$k/2$% multiplies if I use the + * simple way. If I use an n-bit sliding window, then I do %$2^n$% + * multiplies up front, but I only do %$(2^n - 1)/2^n k/n$% multiplies for + * the exponentiation. This is a win when + * + * %$k \ge \frac{n 2^{n+1}}{n - 2}$% + */ + +#define EXP_TABSZ (1 << EXP_WINSZ) +#define EXP_THRESH \ + ((EXP_WINSZ * (2 << EXP_WINSZ))/((EXP_WINSZ - 2) * MPW_BITS)) + +/* --- Required operations --- * + * + * The macros here are independent of the underlying group elements. You + * must provide the necessary group operations and other definitions. The + * group operation is assumed to be written multiplicatively. + * + * @EXP_TYPE@ The type of a group element, e.g., @mp *@. + * + * @EXP_COPY(d, x)@ Makes @d@ be a copy of @x@. + * + * @EXP_DROP(x)@ Discards the element @x@, reclaiming any + * memory it used. + * + * @EXP_MUL(a, x)@ Multiplies @a@ by @x@ (writing the result + * back to @a@). + * + * @EXP_FIX(x)@ Makes @x@ be a canonical representation of + * its value. All multiplications have the + * right argument canonical. + * + * @EXP_SQR(a)@ Multiplies @a@ by itself. + * + * @EXP_SETMUL(d, x, y)@ Sets @d@ to be the product of @x@ and @y@. + * The value @d@ has not been initialized. + * + * @EXP_SETSQR(d, x)@ Sets @d@ to be the square of @x@. + * + * Only @EXP_TYPE@, @EXP_MUL@ and @EXP_SQR@ are required for simple + * exponentation. Sliding window and simultaneous exponentation require all + * of the operations. + */ + +#ifndef EXP_TYPE +# error "EXP_TYPE not defined for " +#endif + +/* --- @EXP_SIMPLE@ --- * + * + * Arguments: @a@ = the result object, initially a multiplicative identity + * @g@ = the object to exponentiate + * @x@ = the exponent, as a multiprecision integer + * + * Use: Performs a simple left-to-right exponentiation. At the end + * of the code, the answer is left in @a@; @g@ and @x@ are + * unchanged. + */ + +#define EXP_SIMPLE(a, g, x) do { \ + mpscan sc; \ + unsigned sq = 0; \ + \ + /* --- Begin scanning --- */ \ + \ + mp_rscan(&sc, x); \ + if (!MP_RSTEP(&sc)) \ + goto exp_simple_exit; \ + while (!MP_RBIT(&sc)) \ + MP_RSTEP(&sc); \ + \ + /* --- Do the main body of the work --- */ \ + \ + EXP_FIX(g); \ + for (;;) { \ + EXP_MUL(a, g); \ + sq = 0; \ + for (;;) { \ + if (!MP_RSTEP(&sc)) \ + goto exp_simple_done; \ + sq++; \ + if (MP_RBIT(&sc)) \ + break; \ + } \ + while (sq--) EXP_SQR(a); \ + } \ + \ + /* --- Do a final round of squaring --- */ \ + \ +exp_simple_done: \ + while (sq--) EXP_SQR(a); \ +exp_simple_exit:; \ +} while (0) + +/* --- @EXP_WINDOW@ --- * + * + * Arguments: @a@ = the result object, initially a multiplicative identity + * @g@ = the object to exponentiate + * @x@ = the exponent, as a multiprecision integer + * + * Use: Performs a sliding-window exponentiation. At the end of the + * code, the answer is left in @a@; @g@ and @x@ are unchanged. + */ + +#define EXP_WINDOW(a, g, x) do { \ + EXP_TYPE *v; \ + EXP_TYPE g2; \ + unsigned i, sq = 0; \ + mpscan sc; \ + \ + /* --- Get going --- */ \ + \ + mp_rscan(&sc, x); \ + if (!MP_RSTEP(&sc)) \ + goto exp_window_exit; \ + \ + /* --- Do the precomputation --- */ \ + \ + EXP_FIX(g); \ + EXP_SETSQR(g2, g); \ + EXP_FIX(g2); \ + v = xmalloc(EXP_TABSZ * sizeof(EXP_TYPE)); \ + EXP_COPY(v[0], g); \ + for (i = 1; i < EXP_TABSZ; i++) { \ + EXP_SETMUL(v[i], v[i - 1], g2); \ + EXP_FIX(v[i]); \ + } \ + EXP_DROP(g2); \ + \ + /* --- Skip top-end zero bits --- * \ + * \ + * If the initial step worked, there must be a set bit somewhere, so \ + * keep stepping until I find it. \ + */ \ + \ + while (!MP_RBIT(&sc)) \ + MP_RSTEP(&sc); \ + \ + /* --- Now for the main work --- */ \ + \ + for (;;) { \ + unsigned l = 1; \ + unsigned z = 0; \ + \ + /* --- The next bit is set, so read a window index --- * \ + * \ + * Reset @i@ to zero and increment @sq@. Then, until either I read \ + * @WINSZ@ bits or I run out of bits, scan in a bit: if it's clear, \ + * bump the @z@ counter; if it's set, push a set bit into @i@, \ + * shift it over by @z@ bits, bump @sq@ by @z + 1@ and clear @z@. \ + * By the end of this palaver, @i@ is an index to the precomputed \ + * value in @v@. \ + */ \ + \ + i = 0; \ + sq++; \ + while (l < EXP_WINSZ && MP_RSTEP(&sc)) { \ + l++; \ + if (!MP_RBIT(&sc)) \ + z++; \ + else { \ + i = ((i << 1) | 1) << z; \ + sq += z + 1; \ + z = 0; \ + } \ + } \ + \ + /* --- Do the squaring --- * \ + * \ + * Remember that @sq@ carries over from the zero-skipping stuff \ + * below. \ + */ \ + \ + while (sq--) EXP_SQR(a); \ + \ + /* --- Do the multiply --- */ \ + \ + EXP_MUL(a, v[i]); \ + \ + /* --- Now grind along through the rest of the bits --- */ \ + \ + sq = z; \ + for (;;) { \ + if (!MP_RSTEP(&sc)) \ + goto exp_window_done; \ + if (MP_RBIT(&sc)) \ + break; \ + sq++; \ + } \ + } \ + \ + /* --- Do a final round of squaring --- */ \ + \ +exp_window_done: \ + while (sq--) EXP_SQR(a); \ + for (i = 0; i < EXP_TABSZ; i++) \ + EXP_DROP(v[i]); \ + xfree(v); \ +exp_window_exit:; \ +} while (0) + +/* --- @EXP_SIMUL@ --- * + * + * Arguments: @a@ = the result object, initially a multiplicative identity + * @f@ = pointer to a vector of base/exp pairs + * @n@ = the number of base/exp pairs + * + * Use: Performs a simultaneous sliding-window exponentiation. The + * @f@ table is an array of structures containing members @base@ + * of type @EXP_TYPE@, and @exp@ of type @mp *@. + */ + +#define EXP_SIMUL(a, f, n) do { \ + size_t i, j, jj, k; \ + size_t vn = 1 << (EXP_WINSZ * n), m = (1 << n) - 1; \ + EXP_TYPE *v = xmalloc(vn * sizeof(EXP_TYPE)); \ + exp_simul e; \ + unsigned sq = 0; \ + \ + /* --- Fill in the precomputed table --- */ \ + \ + j = 1; \ + for (i = 0; i < n; i++) { \ + EXP_COPY(v[j], f[n - 1 - i].base); \ + EXP_FIX(v[j]); \ + j <<= 1; \ + } \ + k = n * EXP_WINSZ; \ + jj = 1; \ + for (; i < k; i++) { \ + EXP_SETSQR(v[j], v[jj]); \ + EXP_FIX(v[j]); \ + j <<= 1; jj <<= 1; \ + } \ + for (i = 1; i < vn; i <<= 1) { \ + for (j = 1; j < i; j++) { \ + EXP_SETMUL(v[j + i], v[j], v[i]); \ + EXP_FIX(v[j + i]); \ + } \ + } \ + \ + /* --- Set up the bitscanners --- * \ + * \ + * Got to use custom scanners, to keep them all in sync. \ + */ \ + \ + e.n = n; \ + e.b = 0; \ + e.s = xmalloc(n * sizeof(*e.s)); \ + e.o = 0; \ + for (i = 0; i < n; i++) { \ + MP_SHRINK(f[i].exp); \ + e.s[i].len = MP_LEN(f[i].exp); \ + e.s[i].v = f[i].exp->v; \ + if (e.s[i].len > e.o) \ + e.o = e.s[i].len; \ + } \ + \ + /* --- Skip as far as a nonzero column in the exponent matrix --- */ \ + \ + do { \ + if (!e.o && !e.b) \ + goto exp_simul_done; \ + i = exp_simulnext(&e, 0); \ + } while (!(i & m)); \ + \ + /* --- Now for the main work --- */ \ + \ + for (;;) { \ + unsigned l = 1; \ + unsigned z = 0; \ + \ + /* --- Just read a nonzero column, so read a window index --- * \ + * \ + * Clear high bits of @i@ and increment @sq@. Then, until either I \ + * read @WINSZ@ columns or I run out, scan in a column and append \ + * it to @i@. If it's zero, bump the @z@ counter; if it's nonzero, \ + * bump @sq@ by @z + 1@ and clear @z@. By the end of this palaver, \ + * @i@ is an index to the precomputed value in @v@, followed by \ + * @n * z@ zero bits. \ + */ \ + \ + sq++; \ + while (l < EXP_WINSZ && (e.o || e.b)) { \ + l++; \ + i = exp_simulnext(&e, i); \ + if (!(i & m)) \ + z++; \ + else { \ + sq += z + 1; \ + z = 0; \ + } \ + } \ + \ + /* --- Do the squaring --- * \ + * \ + * Remember that @sq@ carries over from the zero-skipping stuff \ + * below. \ + */ \ + \ + while (sq--) EXP_SQR(a); \ + \ + /* --- Do the multiply --- */ \ + \ + i >>= (z * n); \ + EXP_MUL(a, v[i]); \ + \ + /* --- Now grind along through the rest of the bits --- */ \ + \ + sq = z; \ + for (;;) { \ + if (!e.o && !e.b) \ + goto exp_simul_done; \ + if ((i = exp_simulnext(&e, 0)) != 0) \ + break; \ + sq++; \ + } \ + } \ + \ + /* --- Do a final round of squaring --- */ \ + \ +exp_simul_done: \ + while (sq--) EXP_SQR(a); \ + for (i = 1; i < vn; i++) \ + EXP_DROP(v[i]); \ + xfree(v); \ + xfree(e.s); \ +} while (0) + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @exp_simulnext@ --- * + * + * Arguments: @exp_simul *e@ = pointer to state structure + * @size_t x@ = a current accumulator + * + * Returns: The next column of bits. + * + * Use: Scans the next column of bits for a simultaneous + * exponentiation. + */ + +extern size_t exp_simulnext(exp_simul */*e*/, size_t /*x*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif diff --git a/math/f-binpoly.c b/math/f-binpoly.c new file mode 100644 index 0000000..2ed270e --- /dev/null +++ b/math/f-binpoly.c @@ -0,0 +1,182 @@ +/* -*-c-*- + * + * Binary fields with polynomial basis representation + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "field.h" +#include "field-guts.h" +#include "mprand.h" + +/*----- Polynomial basis --------------------------------------------------*/ + +/* --- Field operations --- */ + +static void fdestroy(field *ff) { + fctx_binpoly *f = (fctx_binpoly *)ff; + gfreduce_destroy(&f->r); MP_DROP(f->f.q); + DESTROY(f); +} + +static mp *frand(field *f, mp *d, grand *r) { + return (mprand(d, f->nbits, r, 0)); +} + +static int fzerop(field *ff, mp *x) { return (MP_ZEROP(x)); } + +static mp *fadd(field *ff, mp *d, mp *x, mp *y) { return (gf_add(d, x, y)); } + +static mp *fmul(field *ff, mp *d, mp *x, mp *y) { + fctx_binpoly *f = (fctx_binpoly *)ff; d = gf_mul(d, x, y); + return (gfreduce_do(&f->r, d, d)); +} + +static mp *fsqr(field *ff, mp *d, mp *x) { + fctx_binpoly *f = (fctx_binpoly *)ff; d = gf_sqr(d, x); + return (gfreduce_do(&f->r, d, d)); +} + +static mp *finv(field *ff, mp *d, mp *x) { + fctx_binpoly *f = (fctx_binpoly *)ff; + d = gf_modinv(d, x, f->r.p); + return (d); +} + +static mp *freduce(field *ff, mp *d, mp *x) { + fctx_binpoly *f = (fctx_binpoly *)ff; + return (gfreduce_do(&f->r, d, x)); +} + +static mp *fsqrt(field *ff, mp *d, mp *x) { + fctx_binpoly *f = (fctx_binpoly *)ff; + return (gfreduce_sqrt(&f->r, d, x)); +} + +static mp *fquadsolve(field *ff, mp *d, mp *x) { + fctx_binpoly *f = (fctx_binpoly *)ff; + return (gfreduce_quadsolve(&f->r, d, x)); +} + +/* --- Field operations table --- */ + +static const field_ops fops = { + FTY_BINARY, "binpoly", + fdestroy, frand, field_stdsamep, + freduce, field_id, + fzerop, field_id, fadd, fadd, fmul, fsqr, finv, freduce, fsqrt, + fquadsolve, + 0, 0, 0, 0 +}; + +/* --- @field_binpoly@ --- * + * + * Arguments: @mp *p@ = the reduction polynomial + * + * Returns: A pointer to the field. + * + * Use: Creates a field structure for a binary field mod @p@. + */ + +field *field_binpoly(mp *p) +{ + fctx_binpoly *f = CREATE(fctx_binpoly); + f->f.ops = &fops; + f->f.zero = MP_ZERO; + f->f.one = MP_ONE; + f->f.nbits = mp_bits(p) - 1; + f->f.noctets = (f->f.nbits + 7) >> 3; + gfreduce_create(&f->r, p); + f->f.m = f->r.p; + f->f.q = mp_lsl(MP_NEW, MP_ONE, f->f.nbits); + return (&f->f); +} + +/*----- Normal basis ------------------------------------------------------*/ + +/* --- Field operations --- */ + +static void fndestroy(field *ff) { + fctx_binnorm *f = (fctx_binnorm *)ff; gfreduce_destroy(&f->f.r); + gfn_destroy(&f->ntop); gfn_destroy(&f->pton); MP_DROP(f->f.f.q); + DESTROY(f); +} + +static int fnsamep(field *ff, field *gg) { + fctx_binnorm *f = (fctx_binnorm *)ff, *g = (fctx_binnorm *)gg; + return (MP_EQ(f->ntop.r[0], g->ntop.r[0]) && field_stdsamep(ff, gg)); +} + +static mp *fnin(field *ff, mp *d, mp *x) { + fctx_binnorm *f = (fctx_binnorm *)ff; + return (gfn_transform(&f->ntop, d, x)); +} + +static mp *fnout(field *ff, mp *d, mp *x) { + fctx_binnorm *f = (fctx_binnorm *)ff; + return (gfn_transform(&f->pton, d, x)); +} + +/* --- Field operations table --- */ + +static const field_ops fnops = { + FTY_BINARY, "binnorm", + fndestroy, frand, fnsamep, + fnin, fnout, + fzerop, field_id, fadd, fadd, fmul, fsqr, finv, freduce, fsqrt, + fquadsolve, + 0, 0, 0, 0 +}; + +/* --- @field_binnorm@ --- * + * + * Arguments: @mp *p@ = the reduction polynomial + * @mp *beta@ = representation of normal point + * + * Returns: A pointer to the field. + * + * Use: Creates a field structure for a binary field mod @p@ which + * uses a normal basis representation externally. Computations + * are still done on a polynomial-basis representation. + */ + +field *field_binnorm(mp *p, mp *beta) +{ + fctx_binnorm *f = CREATE(fctx_binnorm); + f->f.f.ops = &fnops; + f->f.f.zero = MP_ZERO; + f->f.f.one = MP_ONE; + f->f.f.nbits = mp_bits(p) - 1; + f->f.f.noctets = (f->f.f.nbits + 7) >> 3; + gfreduce_create(&f->f.r, p); + f->f.f.m = f->f.r.p; + f->f.f.q = mp_lsl(MP_NEW, MP_ONE, f->f.f.nbits); + gfn_create(p, beta, &f->ntop, &f->pton); + return (&f->f.f); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/f-niceprime.c b/math/f-niceprime.c new file mode 100644 index 0000000..342cb86 --- /dev/null +++ b/math/f-niceprime.c @@ -0,0 +1,162 @@ +/* -*-c-*- + * + * Prime fields with efficient reduction for special-form primes + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "field.h" +#include "field-guts.h" +#include "mprand.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- Field operations --- */ + +static void fdestroy(field *ff) { + fctx_niceprime *f = (fctx_niceprime *)ff; + mpreduce_destroy(&f->r); + DESTROY(f); +} + +static mp *frand(field *ff, mp *d, grand *r) { + fctx_niceprime *f = (fctx_niceprime *)ff; + return (mprand_range(d, f->r.p, r, 0)); +} + +static int fzerop(field *ff, mp *x) { return (MP_ZEROP(x)); } + +static mp *fneg(field *ff, mp *d, mp *x) { + fctx_niceprime *f = (fctx_niceprime *)ff; + return (mp_sub(d, f->r.p, x)); +} + +static mp *fadd(field *ff, mp *d, mp *x, mp *y) { + fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_add(d, x, y); + if (MP_NEGP(d)) d = mp_add(d, d, f->r.p); + else if (MP_CMP(d, >, f->r.p)) d = mp_sub(d, d, f->r.p); + return (d); +} + +static mp *fsub(field *ff, mp *d, mp *x, mp *y) { + fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_sub(d, x, y); + if (MP_NEGP(d)) d = mp_add(d, d, f->r.p); + else if (MP_CMP(d, >, f->r.p)) d = mp_sub(d, d, f->r.p); + return (d); +} + +static mp *fmul(field *ff, mp *d, mp *x, mp *y) { + fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_mul(d, x, y); + return (mpreduce_do(&f->r, d, d)); +} + +static mp *fsqr(field *ff, mp *d, mp *x) { + fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_sqr(d, x); + return (mpreduce_do(&f->r, d, d)); +} + +static mp *finv(field *ff, mp *d, mp *x) { + fctx_niceprime *f = (fctx_niceprime *)ff; + d = mp_modinv(d, x, f->r.p); + return (d); +} + +static mp *freduce(field *ff, mp *d, mp *x) { + fctx_niceprime *f = (fctx_niceprime *)ff; + return (mpreduce_do(&f->r, d, x)); +} + +static mp *fsqrt(field *ff, mp *d, mp *x) { + fctx_niceprime *f = (fctx_niceprime *)ff; + return (mp_modsqrt(d, x, f->r.p)); +} + +static mp *fdbl(field *ff, mp *d, mp *x) { + fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_lsl(d, x, 1); + if (MP_CMP(d, >=, f->r.p)) d = mp_sub(d, d, f->r.p); + return (d); +} + +static mp *ftpl(field *ff, mp *d, mp *x) { + fctx_niceprime *f = (fctx_niceprime *)ff; MP_DEST(d, MP_LEN(x) + 1, x->f); + MPX_UMULN(d->v, d->vl, x->v, x->vl, 3); d->f &= ~MP_UNDEF; + while (MP_CMP(d, >=, f->r.p)) d = mp_sub(d, d, f->r.p); + return (d); +} + +static mp *fqdl(field *ff, mp *d, mp *x) { + fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_lsl(d, x, 2); + while (MP_CMP(d, >=, f->r.p)) d = mp_sub(d, d, f->r.p); + return (d); +} + +static mp *fhlv(field *ff, mp *d, mp *x) { + fctx_niceprime *f = (fctx_niceprime *)ff; + if (MP_ZEROP(x)) { MP_COPY(x); MP_DROP(d); return (x); } + if (x->v[0] & 1) { d = mp_add(d, x, f->r.p); x = d; } + return (mp_lsr(d, x, 1)); +} + +/* --- Field operations table --- */ + +static const field_ops fops = { + FTY_PRIME, "niceprime", + fdestroy, frand, field_stdsamep, + freduce, field_id, + fzerop, fneg, fadd, fsub, fmul, fsqr, finv, freduce, fsqrt, + 0, + fdbl, ftpl, fqdl, fhlv +}; + +/* --- @field_niceprime@ --- * + * + * Arguments: @mp *p@ = the characteristic of the field + * + * Returns: A pointer to the field, or null. + * + * Use: Creates a field structure for a prime field of size %$p$%, + * using efficient reduction for nice primes. + */ + +field *field_niceprime(mp *p) +{ + fctx_niceprime *f = CREATE(fctx_niceprime); + f->f.ops = &fops; + f->f.zero = MP_ZERO; + f->f.one = MP_ONE; + f->f.nbits = mp_bits(p); + f->f.noctets = (f->f.nbits + 7) >> 3; + if (mpreduce_create(&f->r, p)) { + DESTROY(f); + return (0); + } + f->f.m = f->r.p; + f->f.q = f->r.p; + return (&f->f); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/f-prime.c b/math/f-prime.c new file mode 100644 index 0000000..d9c5c17 --- /dev/null +++ b/math/f-prime.c @@ -0,0 +1,176 @@ +/* -*-c-*- + * + * Prime fields with Montgomery arithmetic + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "field.h" +#include "mprand.h" +#include "field-guts.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- Field operations --- */ + +static void fdestroy(field *ff) { + fctx_prime *f = (fctx_prime *)ff; + mpmont_destroy(&f->mm); + DESTROY(f); +} + +static mp *frand(field *ff, mp *d, grand *r) { + fctx_prime *f = (fctx_prime *)ff; + return (mprand_range(d, f->mm.m, r, 0)); +} + +static mp *fin(field *ff, mp *d, mp *x) { + fctx_prime *f = (fctx_prime *)ff; + mp_div(0, &d, x, f->mm.m); + return (mpmont_mul(&f->mm, d, d, f->mm.r2)); +} + +static mp *fout(field *ff, mp *d, mp *x) { + fctx_prime *f = (fctx_prime *)ff; + return (mpmont_reduce(&f->mm, d, x)); +} + +static int fzerop(field *ff, mp *x) { return (MP_ZEROP(x)); } + +static mp *fneg(field *ff, mp *d, mp *x) { + fctx_prime *f = (fctx_prime *)ff; + return (mp_sub(d, f->mm.m, x)); +} + +static mp *fadd(field *ff, mp *d, mp *x, mp *y) { + fctx_prime *f = (fctx_prime *)ff; d = mp_add(d, x, y); + if (MP_NEGP(d)) d = mp_add(d, d, f->mm.m); + else if (MP_CMP(d, >, f->mm.m)) d = mp_sub(d, d, f->mm.m); + return (d); +} + +static mp *fsub(field *ff, mp *d, mp *x, mp *y) { + fctx_prime *f = (fctx_prime *)ff; d = mp_sub(d, x, y); + if (MP_NEGP(d)) d = mp_add(d, d, f->mm.m); + else if (MP_CMP(d, >, f->mm.m)) d = mp_sub(d, d, f->mm.m); + return (d); +} + +static mp *fmul(field *ff, mp *d, mp *x, mp *y) { + fctx_prime *f = (fctx_prime *)ff; + return (mpmont_mul(&f->mm, d, x, y)); +} + +static mp *fsqr(field *ff, mp *d, mp *x) { + fctx_prime *f = (fctx_prime *)ff; d = mp_sqr(d, x); + return (mpmont_reduce(&f->mm, d, d)); +} + +static mp *finv(field *ff, mp *d, mp *x) { + fctx_prime *f = (fctx_prime *)ff; d = mpmont_reduce(&f->mm, d, x); + d = mp_modinv(d, d, f->mm.m); return (mpmont_mul(&f->mm, d, d, f->mm.r2)); +} + +static mp *freduce(field *ff, mp *d, mp *x) { + fctx_prime *f = (fctx_prime *)ff; + mp_div(0, &d, x, f->mm.m); + return (d); +} + +static mp *fsqrt(field *ff, mp *d, mp *x) { + fctx_prime *f = (fctx_prime *)ff; d = mpmont_reduce(&f->mm, d, x); + d = mp_modsqrt(d, d, f->mm.m); if (!d) return (d); + return (mpmont_mul(&f->mm, d, d, f->mm.r2)); +} + +static mp *fdbl(field *ff, mp *d, mp *x) { + fctx_prime *f = (fctx_prime *)ff; d = mp_lsl(d, x, 1); + if (MP_CMP(d, >=, f->mm.m)) d = mp_sub(d, d, f->mm.m); + return (d); +} + +static mp *ftpl(field *ff, mp *d, mp *x) { + fctx_prime *f = (fctx_prime *)ff; MP_DEST(d, MP_LEN(x) + 1, x->f); + MPX_UMULN(d->v, d->vl, x->v, x->vl, 3); d->f &= ~MP_UNDEF; + while (MP_CMP(d, >=, f->mm.m)) d = mp_sub(d, d, f->mm.m); + return (d); +} + +static mp *fqdl(field *ff, mp *d, mp *x) { + fctx_prime *f = (fctx_prime *)ff; d = mp_lsl(d, x, 2); + while (MP_CMP(d, >=, f->mm.m)) d = mp_sub(d, d, f->mm.m); + return (d); +} + +static mp *fhlv(field *ff, mp *d, mp *x) { + fctx_prime *f = (fctx_prime *)ff; + if (MP_ZEROP(x)) { MP_COPY(x); MP_DROP(d); return (x); } + if (x->v[0] & 1) { d = mp_add(d, x, f->mm.m); x = d; } + return (mp_lsr(d, x, 1)); +} + +/* --- Field operations table --- */ + +static const field_ops fops = { + FTY_PRIME, "prime", + fdestroy, frand, field_stdsamep, + fin, fout, + fzerop, fneg, fadd, fsub, fmul, fsqr, finv, freduce, fsqrt, + 0, + fdbl, ftpl, fqdl, fhlv +}; + +/* --- @field_prime@ --- * + * + * Arguments: @mp *p@ = the characteristic of the field + * + * Returns: A pointer to the field or null. + * + * Use: Creates a field structure for a prime field of size %$p$%, + * using Montgomery reduction for arithmetic. + */ + +field *field_prime(mp *p) +{ + fctx_prime *f; + + f = CREATE(fctx_prime); + f->f.ops = &fops; + if (mpmont_create(&f->mm, p)) { + DESTROY(f); + return (0); + } + f->f.zero = MP_ZERO; + f->f.one = f->mm.r; + f->f.m = f->mm.m; + f->f.nbits = mp_bits(p); + f->f.noctets = (f->f.nbits + 7) >> 3; + f->f.q = f->mm.m; + return (&f->f); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/field-exp.c b/math/field-exp.c new file mode 100644 index 0000000..bbadb86 --- /dev/null +++ b/math/field-exp.c @@ -0,0 +1,71 @@ +/* -*-c-*- + * + * Exponentiation in finite fields + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "field.h" +#include "field-exp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @field_exp@ --- * + * + * Arguments: @field *f@ = pointer to field + * @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e$%. + * + * Use: Exponentiation in a finite field. Note that all quantities + * are in internal format. + */ + +mp *field_exp(field *f, mp *d, mp *a, mp *e) +{ + mp *x = MP_COPY(f->one); + mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; + + MP_COPY(a); + MP_SHRINK(e); + if (MP_ZEROP(e)) + ; + else { + if (MP_NEGP(e)) + a = F_INV(f, a, a); + if (MP_LEN(e) < EXP_THRESH) + EXP_SIMPLE(x, a, e); + else + EXP_WINDOW(x, a, e); + } + mp_drop(d); + mp_drop(spare); + mp_drop(a); + return (x); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/field-exp.h b/math/field-exp.h new file mode 100644 index 0000000..70dda63 --- /dev/null +++ b/math/field-exp.h @@ -0,0 +1,57 @@ +/* -*-c-*- + * + * Exponentiation in finite fields + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_FIELD_EXP_H +#define CATACOMB_FIELD_EXP_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Exponentiation definitions ----------------------------------------*/ + +#define EXP_TYPE mp * + +#define EXP_COPY(d, x) d = MP_COPY(x) +#define EXP_DROP(x) MP_DROP(x) + +#define EXP_MUL(a, x) a = F_MUL(f, a, a, x) +#define EXP_SQR(a) a = F_SQR(f, a, a) +#define EXP_FIX(x) + +#define EXP_SETMUL(d, x, y) d = F_MUL(f, MP_NEW, x, y) +#define EXP_SETSQR(d, x) d = F_SQR(f, MP_NEW, x) + +#include "exp.h" + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/field-guts.h b/math/field-guts.h new file mode 100644 index 0000000..1122b6c --- /dev/null +++ b/math/field-guts.h @@ -0,0 +1,97 @@ +/* -*-c-*- + * + * Internal structures for built-in fields + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_FIELD_GUTS_H +#define CATACOMB_FIELD_GUTS_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_EC_H +# include "ec.h" +#endif + +#ifndef CATACOMB_MPMONT_H +# include "mpmont.h" +#endif + +#ifndef CATACOMB_MPREDUCE_H +# include "mpreduce.h" +#endif + +#ifndef CATACOMB_GF_H +# include "gf.h" +#endif + +#ifndef CATACOMB_GFN_H +# include "gfn.h" +#endif + +#ifndef CATACOMB_GFREDUCE_H +# include "gfreduce.h" +#endif + +#ifndef CATACOMB_FIELD_H +# include "field.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct fctx_prime { + field f; + mpmont mm; +} fctx_prime; + +typedef struct fctx_niceprime { + field f; + mpreduce r; +} fctx_niceprime; + +typedef struct fctx_binpoly { + field f; + gfreduce r; +} fctx_binpoly; + +typedef struct fctx_binnorm { + fctx_binpoly f; + gfn ntop, pton; +} fctx_binnorm; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/field-parse.c b/math/field-parse.c new file mode 100644 index 0000000..eed08fa --- /dev/null +++ b/math/field-parse.c @@ -0,0 +1,85 @@ +/* -*-c-*- + * + * Parse field descriptions + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "field.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @field_parse@ --- * + * + * Arguments: @qd_parse *qd@ = parser context + * + * Returns: Field pointer if OK, or null. + * + * Use: Parses a field description, which has the form + * + * * `prime', `niceprime' or `binpoly' + * * an optional `:' + * * the field modulus + */ + +field *field_parse(qd_parse *qd) +{ + field *f = 0; + mp *m = MP_NEW, *b = MP_NEW; + + switch (qd_enum(qd, "prime,niceprime,binpoly,binnorm")) { + case 0: + qd_delim(qd, ':'); + if ((m = qd_getmp(qd)) == 0) goto done; + f = field_prime(m); + break; + case 1: + qd_delim(qd, ':'); + if ((m = qd_getmp(qd)) == 0) goto done; + f = field_niceprime(m); + break; + case 2: + qd_delim(qd, ':'); + if ((m = qd_getmp(qd)) == 0) goto done; + f = field_binpoly(m); + break; + case 3: + qd_delim(qd, ':'); + if ((m = qd_getmp(qd)) == 0) goto done; + qd_delim(qd, ','); + if ((b = qd_getmp(qd)) == 0) goto done; + f = field_binnorm(m, b); + break; + default: + goto done; + } + if (!f) qd->e = "bad field parameters"; +done: + mp_drop(m); + mp_drop(b); + return (f); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/field.c b/math/field.c new file mode 100644 index 0000000..0198fca --- /dev/null +++ b/math/field.c @@ -0,0 +1,76 @@ +/* -*-c-*- + * + * Abstract field operations + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "field.h" +#include "mp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @field_id@ --- * + * + * Arguments: @field *f@ = pointer to a field + * @mp *d@ = a destination element + * @mp *x@ = a source element + * + * Returns: The result element. + * + * Use: An identity operation which can be used if your field has no + * internal representation. + */ + +mp *field_id(field *f, mp *d, mp *x) + { x = MP_COPY(x); if (d) MP_DROP(d); return (x); } + +/* --- @field_samep@ --- * + * + * Arguments: @field *f, *g@ = two fields + * + * Returns: Nonzero if the fields are identical (not just isomorphic). + * + * Use: Checks for sameness of fields. This function does the full + * check, not just the field-type-specific check done by the + * @sampep@ field operation. + */ + +int field_samep(field *f, field *g) + { return (f == g || (f->ops == g->ops && F_SAMEP(f, g))); } + +/* --- @field_stdsamep@ --- * + * + * Arguments: @field *f, *g@ = two fields + * + * Returns: Nonzero if the fields are identical (not just isomorphic). + * + * Use: Standard sameness check, based on equality of the @m@ + * member. + */ + +int field_stdsamep(field *f, field *g) { return (MP_EQ(f->m, g->m)); } + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/field.h b/math/field.h new file mode 100644 index 0000000..c1ec030 --- /dev/null +++ b/math/field.h @@ -0,0 +1,265 @@ +/* -*-c-*- + * + * Definitions for field arithmetic + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_FIELD_H +#define CATACOMB_FIELD_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_QDPARSE_H +# include "qdparse.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct field { + const struct field_ops *ops; /* Field operations */ + mp *zero, *one; /* Identities in the field */ + mp *m; /* Modulus (prime and binary) */ + unsigned long nbits; /* Length of field element in bits */ + size_t noctets; /* Length of element in octets */ + mp *q; /* Number of elements in field */ +} field; + +enum { + FTY_PRIME, + FTY_BINARY +}; + +typedef struct field_ops { + + /* --- General information --- */ + + unsigned ty; /* What kind of field this is */ + const char *name; /* Human-readable name string */ + + /* --- Universal operations --- */ + + void (*destroy)(field */*f*/); + mp *(*rand)(field */*f*/, mp */*d*/, grand */*r*/); + int (*samep)(field */*f*/, field */*g*/); + + mp *(*in)(field */*f*/, mp */*d*/, mp */*x*/); + mp *(*out)(field */*f*/, mp */*d*/, mp */*x*/); + + int (*zerop)(field */*f*/, mp */*x*/); + mp *(*neg)(field */*f*/, mp */*d*/, mp */*x*/); + mp *(*add)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/); + mp *(*sub)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/); + mp *(*mul)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/); + mp *(*sqr)(field */*f*/, mp */*d*/, mp */*x*/); + mp *(*inv)(field */*f*/, mp */*d*/, mp */*x*/); + mp *(*reduce)(field */*f*/, mp */*d*/, mp */*x*/); + mp *(*sqrt)(field */*f*/, mp */*d*/, mp */*x*/); + + /* --- Operations for binary fields only --- */ + + mp *(*quadsolve)(field */*f*/, mp */*d*/, mp */*x*/); + + /* --- Operations for prime fields only --- */ + + mp *(*dbl)(field */*f*/, mp */*d*/, mp */*x*/); + mp *(*tpl)(field */*f*/, mp */*d*/, mp */*x*/); + mp *(*qdl)(field */*f*/, mp */*d*/, mp */*x*/); + mp *(*hlv)(field */*f*/, mp */*d*/, mp */*x*/); + +} field_ops; + +#define F_TYPE(f) (f)->ops->ty +#define F_NAME(f) (f)->ops->name + +#define F_DESTROY(f) (f)->ops->destroy((f)) +#define F_RAND(f, d, r) (f)->ops->rand((f), (d), (r)) +#define F_SAMEP(f, g) (f)->ops->samep((f), (g)) + +#define F_IN(f, d, x) (f)->ops->in((f), (d), (x)) +#define F_OUT(f, d, x) (f)->ops->out((f), (d), (x)) + +#define F_ZEROP(f, x) (f)->ops->zerop((f), (x)) +#define F_NEG(f, d, x) (f)->ops->neg((f), (d), (x)) +#define F_ADD(f, d, x, y) (f)->ops->add((f), (d), (x), (y)) +#define F_SUB(f, d, x, y) (f)->ops->sub((f), (d), (x), (y)) +#define F_MUL(f, d, x, y) (f)->ops->mul((f), (d), (x), (y)) +#define F_SQR(f, d, x) (f)->ops->sqr((f), (d), (x)) +#define F_INV(f, d, x) (f)->ops->inv((f), (d), (x)) +#define F_REDUCE(f, d, x) (f)->ops->reduce((f), (d), (x)) +#define F_SQRT(f, d, x) (f)->ops->sqrt((f), (d), (x)) + +#define F_QUADSOLVE(f, d, x) (f)->ops->quadsolve((f), (d), (x)) + +#define F_DBL(f, d, x) (f)->ops->dbl((f), (d), (x)) +#define F_TPL(f, d, x) (f)->ops->tpl((f), (d), (x)) +#define F_QDL(f, d, x) (f)->ops->qdl((f), (d), (x)) +#define F_HLV(f, d, x) (f)->ops->hlv((f), (d), (x)) + +/*----- Helpful field operations ------------------------------------------*/ + +/* --- @field_id@ --- * + * + * Arguments: @field *f@ = pointer to a field + * @mp *d@ = a destination element + * @mp *x@ = a source element + * + * Returns: The result element. + * + * Use: An identity operation which can be used if your field has no + * internal representation. + */ + +extern mp *field_id(field */*f*/, mp */*d*/, mp */*x*/); + +/* --- @field_samep@ --- * + * + * Arguments: @field *f, *g@ = two fields + * + * Returns: Nonzero if the fields are identical (not just isomorphic). + * + * Use: Checks for sameness of fields. This function does the full + * check, not just the field-type-specific check done by the + * @sampep@ field operation. + */ + +extern int field_samep(field */*f*/, field */*g*/); + +/* --- @field_stdsamep@ --- * + * + * Arguments: @field *f, *g@ = two fields + * + * Returns: Nonzero if the fields are identical (not just isomorphic). + * + * Use: Standard sameness check, based on equality of the @m@ + * member. + */ + +extern int field_stdsamep(field */*f*/, field */*g*/); + +/*----- Arithmetic --------------------------------------------------------*/ + +/* --- @field_exp@ --- * + * + * Arguments: @field *f@ = pointer to field + * @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e$%. + * + * Use: Exponentiation in a finite field. Note that all quantities + * are in internal format. This is a generic implementation + * suitable for use with all fields and is not intended to be + * optimal. + */ + +extern mp *field_exp(field */*f*/, mp */*d*/, mp */*a*/, mp */*e*/); + +/*----- Creating fields ---------------------------------------------------*/ + +/* --- @field_prime@ --- * + * + * Arguments: @mp *p@ = the characteristic of the field + * + * Returns: A pointer to the field. + * + * Use: Creates a field structure for a prime field of size %$p$%, + * using Montgomery reduction for arithmetic. + */ + +extern field *field_prime(mp */*p*/); + +/* --- @field_niceprime@ --- * + * + * Arguments: @mp *p@ = the characteristic of the field + * + * Returns: A pointer to the field, or null. + * + * Use: Creates a field structure for a prime field of size %$p$%, + * using efficient reduction for nice primes. + */ + +extern field *field_niceprime(mp */*p*/); + +/* --- @field_binpoly@ --- * + * + * Arguments: @mp *p@ = an irreducible polynomial over %$\gf{2}$% + * + * Returns: A pointer to the field. + * + * Use: Creates a field structure for a binary field using naive + * arithmetic. + */ + +extern field *field_binpoly(mp */*p*/); + +/* --- @field_binnorm@ --- * + * + * Arguments: @mp *p@ = the reduction polynomial + * @mp *beta@ = representation of normal point + * + * Returns: A pointer to the field. + * + * Use: Creates a field structure for a binary field mod @p@ which + * uses a normal basis representation externally. Computations + * are still done on a polynomial-basis representation. + */ + +extern field *field_binnorm(mp */*p*/, mp */*beta*/); + +/* --- @field_parse@ --- * + * + * Arguments: @qd_parse *qd@ = parser context + * + * Returns: Field pointer if OK, or null. + * + * Use: Parses a field description, which has the form + * + * * `prime', `niceprime', `binpoly', or `binnorm' + * * an optional `:' + * * the field modulus + * * for `binnorm', an optional `,' and the beta value + */ + +extern field *field_parse(qd_parse */*qd*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/g-bin.c b/math/g-bin.c new file mode 100644 index 0000000..79a989f --- /dev/null +++ b/math/g-bin.c @@ -0,0 +1,177 @@ +/* -*-c-*- + * + * Abstraction for prime groups + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "mpmont.h" +#include "pgen.h" + +#define ge mp * +#include "group.h" +#include "group-guts.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- Group operations --- */ + +static void gdestroygroup(group *gg) { + gctx_bin *g = (gctx_bin *)gg; + mp_drop(g->gen); mp_drop(g->g.r); mp_drop(g->g.h); + gfreduce_destroy(&g->r); + DESTROY(g); +} + +static mp **gcreate(group *gg) + { mp **x = CREATE(mp *); *x = MP_COPY(*gg->i); return (x); } + +static void gcopy(group *gg, mp **d, mp **x) + { mp *t = MP_COPY(*x); MP_DROP(*d); *d = t; } + +static void gburn(group *gg, mp **x) { (*x)->f |= MP_BURN; } + +static void gdestroy(group *gg, mp **x) { MP_DROP(*x); DESTROY(x); } + +static int gsamep(group *gg, group *hh) { + gctx_bin *g = (gctx_bin *)gg, *h = (gctx_bin *)hh; + return (MP_EQ(g->r.p, h->r.p)); +} + +static int geq(group *gg, mp **x, mp **y) { return (MP_EQ(*x, *y)); } + +static const char *gcheck(group *gg, grand *gr) { + gctx_bin *g = (gctx_bin *)gg; int rc; mp *t, *tt; + if (!gf_irreduciblep(g->r.p)) return ("p is not irreducible"); + t = mp_mul(MP_NEW, g->g.r, g->g.h); t = mp_add(t, t, MP_ONE); + tt = mp_lsl(MP_NEW, MP_ONE, g->g.nbits); + rc = MP_EQ(t, tt); MP_DROP(t); MP_DROP(tt); + if (!rc) return ("not a subgroup"); + return (group_stdcheck(gg, gr)); +} + +static void gmul(group *gg, mp **d, mp **x, mp **y) { + gctx_bin *g = (gctx_bin *)gg; mp *r = gf_mul(*d, *x, *y); + *d = gfreduce_do(&g->r, r, r); +} + +static void gsqr(group *gg, mp **d, mp **x) { + gctx_bin *g = (gctx_bin *)gg; mp *r = gf_sqr(*d, *x); + *d = gfreduce_do(&g->r, r, r); +} + +static void ginv(group *gg, mp **d, mp **x) + { gctx_bin *g = (gctx_bin *)gg; *d = gf_modinv(*d, *x, g->r.p); } + +static void gexp(group *gg, mp **d, mp **x, mp *n) + { gctx_bin *g = (gctx_bin *)gg; *d = gfreduce_exp(&g->r, *d, *x, n); } + +static int gread(group *gg, mp **d, const mptext_ops *ops, void *p) { + mp *t; if ((t = mp_read(MP_NEW, 0, ops, p)) == 0) return (-1); + mp_drop(*d); *d = t; return (0); +} + +static int gwrite(group *gg, mp **x, const mptext_ops *ops, void *p) { + int rc = -1; + if (!ops->put("0x", 2, p) && !mp_write(*x, 16, ops, p)) rc = 0; + return (rc); +} + +static mp *gtoint(group *gg, mp *d, mp **x) { return MP_COPY(*x); } + +static int gfromint(group *gg, mp **d, mp *x) { *d = MP_COPY(x); return 0; } + +static int gtobuf(group *gg, buf *b, mp **x) + { int rc = buf_putmp(b, *x); return (rc); } + +static int gfrombuf(group *gg, buf *b, mp **d) { + gctx_bin *g = (gctx_bin *)gg; mp *x; + if ((x = buf_getmp(b)) == 0) return (-1); + MP_DROP(*d); *d = gfreduce_do(&g->r, x, x); + return (0); +} + +static int gtoraw(group *gg, buf *b, mp **x) { + gctx_bin * g = (gctx_bin *)gg; octet *q; + if ((q = buf_get(b, g->g.noctets)) == 0) return (-1); + mp_storeb(*x, q, g->g.noctets); return (0); +} + +static int gfromraw(group *gg, buf *b, mp **d) { + gctx_bin * g = (gctx_bin *)gg; mp *x; octet *q; + if ((q = buf_get(b, g->g.noctets)) == 0) return (-1); + x = mp_loadb(MP_NEW, q, g->g.noctets); + MP_DROP(*d); *d = gfreduce_do(&g->r, x, x); + return (0); +} + +/* --- @group_binary@ --- * + * + * Arguments: @const gbin_param *gb@ = group parameters + * + * Returns: A pointer to the group, or null. + * + * Use: Constructs an abstract group interface for a subgroup of a + * prime field. Group elements are @mp *@ pointers. + */ + +static const group_ops gops = { + GTY_BINARY, "bin", + gdestroygroup, gcreate, gcopy, gburn, gdestroy, + gsamep, geq, group_stdidentp, + gcheck, + gmul, gsqr, ginv, group_stddiv, gexp, group_stdmexp, + gread, gwrite, + gtoint, gfromint, group_stdtoec, group_stdfromec, gtobuf, gfrombuf, + gtoraw, gfromraw +}; + +group *group_binary(const gbin_param *gb) +{ + gctx_bin *g; + mp *t; + + if (!MP_POSP(gb->p)) + return (0); + g = CREATE(gctx_bin); + g->g.ops = &gops; + g->g.nbits = mp_bits(gb->p) - 1; + g->g.noctets = (g->g.nbits + 7) >> 3; + gfreduce_create(&g->r, gb->p); + g->one = MP_ONE; + g->g.i = &g->one; + g->gen = MP_COPY(gb->g); + g->g.g = &g->gen; + g->g.r = MP_COPY(gb->q); + t = mp_lsl(MP_NEW, MP_ONE, g->g.nbits); + t = mp_sub(t, t, MP_ONE); + g->g.h = MP_NEW; mp_div(&g->g.h, 0, t, gb->q); + MP_DROP(t); + return (&g->g); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/g-ec.c b/math/g-ec.c new file mode 100644 index 0000000..f885c40 --- /dev/null +++ b/math/g-ec.c @@ -0,0 +1,216 @@ +/* -*-c-*- + * + * Abstraction for elliptic curve groups + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#define ge ec +#include "group.h" +#include "ec-raw.h" +#include "group-guts.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- Group operations --- */ + +static void gdestroygroup(group *gg) { + gctx_ec *g = (gctx_ec *)gg; + EC_DESTROY(&g->gen); + ec_freeinfo(&g->ei); + DESTROY(g); +} + +static ec *gcreate(group *gg) + { ec *x = CREATE(ec); EC_CREATE(x); return (x); } + +static void gcopy(group *gg, ec *d, ec *x) { EC_COPY(d, x); } + +static void gburn(group *gg, ec *x) { if (x->x) (x->x)->f |= MP_BURN; } + +static void gdestroy(group *gg, ec *x) { EC_DESTROY(x); DESTROY(x); } + +static int gsamep(group *gg, group *hh) { + gctx_ec *g = (gctx_ec *)gg, *h = (gctx_ec *)hh; + return (ec_sameinfop(&g->ei, &h->ei)); +} + +static int geq(group *gg, ec *x, ec *y) { + gctx_ec *g = (gctx_ec *)gg; EC_FIX(g->ei.c, x, x); EC_FIX(g->ei.c, y, y); + return (EC_EQ(x, y)); +} + +static int gidentp(group *gg, ec *x) { return (EC_ATINF(x)); } + +static const char *gcheck(group *gg, grand *gr) + { gctx_ec *g = (gctx_ec *)gg; return (ec_checkinfo(&g->ei, gr)); } + +static void gmul(group *gg, ec *d, ec *x, ec *y) + { gctx_ec *g = (gctx_ec *)gg; EC_ADD(g->ei.c, d, x, y); } + +static void gsqr(group *gg, ec *d, ec *x) + { gctx_ec *g = (gctx_ec *)gg; EC_DBL(g->ei.c, d, x); } + +static void ginv(group *gg, ec *d, ec *x) + { gctx_ec *g = (gctx_ec *)gg; EC_NEG(g->ei.c, d, x); } + +static void gdiv(group *gg, ec *d, ec *x, ec *y) + { gctx_ec *g = (gctx_ec *)gg; EC_SUB(g->ei.c, d, x, y); } + +static void gexp(group *gg, ec *d, ec *x, mp *n) + { gctx_ec *g = (gctx_ec *)gg; ec_imul(g->ei.c, d, x, n); } + +static void gmexp(group *gg, ec *d, const group_expfactor *f, size_t n) { + gctx_ec *g = (gctx_ec *)gg; size_t i; + ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor)); + for (i = 0; i < n; i++) { ff[i].base = *f[i].base; ff[i].exp = f[i].exp; } + ec_immul(g->ei.c, d, ff, n); xfree(ff); +} + +static int gread(group *gg, ec *d, const mptext_ops *ops, void *p) { + gctx_ec *g = (gctx_ec *)gg; + ec t = EC_INIT; + int rc = -1; + int ch; + + ch = ops->get(p); + if (tolower(ch) == 'i') { + if (tolower(ops->get(p)) != 'n' || tolower(ops->get(p)) != 'f') + return (-1); + EC_SETINF(d); + return (0); + } + ops->unget(ch, p); + if ((t.x = mp_read(MP_NEW, 0, ops, p)) == 0) goto done; + do ch = ops->get(p); while (ch == ',' || isspace(ch)); ops->unget(ch, p); + if ((t.y = mp_read(MP_NEW, 0, ops, p)) == 0) goto done; + EC_IN(g->ei.c, &t, &t); + if (EC_CHECK(g->ei.c, &t)) goto done; + EC_COPY(d, &t); rc = 0; + EC_DESTROY(&t); +done: + return (rc); +} + +static int gwrite(group *gg, ec *x, const mptext_ops *ops, void *p) { + gctx_ec *g = (gctx_ec *)gg; int rc = -1; ec t = EC_INIT; + EC_OUT(g->ei.c, &t, x); if (EC_ATINF(&t)) rc = ops->put("inf", 3, p); + else if (!ops->put("0x", 2, p) && !mp_write(t.x, 16, ops, p) && + !ops->put(", 0x", 4, p) && !mp_write(t.y, 16, ops, p)) rc = 0; + EC_DESTROY(&t); return (rc); +} + +static mp *gtoint(group *gg, mp *d, ec *x) { + gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; mp *i; if (EC_ATINF(x)) i = 0; + else { EC_OUT(g->ei.c, &t, x); i = MP_COPY(t.x); EC_DESTROY(&t); } + mp_drop(d); return (i); +} + +static int gfromint(group *gg, ec *d, mp *x) { + gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; + if (!ec_find(g->ei.c, &t, x)) return (-1); + EC_IN(g->ei.c, d, &t); EC_DESTROY(&t); return (0); +} + +static int gtoec(group *gg, ec *d, ec *x) + { gctx_ec *g = (gctx_ec *)gg; EC_OUT(g->ei.c, d, x); return (0); } + +static int gfromec(group *gg, ec *d, const ec *x) { + gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; EC_IN(g->ei.c, &t, x); + rc = EC_CHECK(g->ei.c, &t); if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); + return (rc); +} + +static int gtobuf(group *gg, buf *b, ec *x) { + gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; + EC_OUT(g->ei.c, &t, x); rc = buf_putec(b, &t); EC_DESTROY(&t); return (rc); +} + +static int gfrombuf(group *gg, buf *b, ec *d) { + gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; + if (buf_getec(b, &t)) return (-1); + EC_IN(g->ei.c, &t, &t); rc = EC_CHECK(g->ei.c, &t); + if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); return (rc); +} + +static int gtoraw(group *gg, buf *b, ec *x) { + gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; + EC_OUT(g->ei.c, &t, x); rc = ec_putraw(g->ei.c, b, &t); + EC_DESTROY(&t); return (rc); +} + +static int gfromraw(group *gg, buf *b, ec *d) { + gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; + if (ec_getraw(g->ei.c, b, &t)) return (-1); + EC_IN(g->ei.c, &t, &t); rc = EC_CHECK(g->ei.c, &t); + if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); return (rc); +} + +/* --- @group_ec@ --- * + * + * Arguments: @const ec_info *ei@ = elliptic curve parameters + * + * Returns: A pointer to the group. + * + * Use: Constructs an abstract group interface for an elliptic curve + * group. Group elements are @ec@ structures. The contents of + * the @ec_info@ structure becomes the property of the @group@ + * object; you can (and should) free the structure itself, but + * calling @ec_freeinfo@ on it is not allowed. + */ + +static const group_ops gops = { + GTY_EC, "ec", + gdestroygroup, gcreate, gcopy, gburn, gdestroy, + gsamep, geq, gidentp, + gcheck, + gmul, gsqr, ginv, gdiv, gexp, gmexp, + gread, gwrite, + gtoint, gfromint, gtoec, gfromec, gtobuf, gfrombuf, gtoraw, gfromraw +}; + +group *group_ec(const ec_info *ei) +{ + gctx_ec *g = CREATE(gctx_ec); + + g->g.ops = &gops; + g->g.nbits = ei->c->f->nbits * 2; + g->g.noctets = ei->c->f->noctets * 2 + 1; + g->ei = *ei; + EC_CREATE(&g->id); + g->g.i = &g->id; + EC_CREATE(&g->gen); + g->g.g = &g->gen; + EC_IN(g->ei.c, &g->gen, &ei->g); + g->g.r = ei->r; + g->g.h = ei->h; + return (&g->g); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/g-prime.c b/math/g-prime.c new file mode 100644 index 0000000..892e743 --- /dev/null +++ b/math/g-prime.c @@ -0,0 +1,188 @@ +/* -*-c-*- + * + * Abstraction for prime groups + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "mpmont.h" +#include "pgen.h" + +#define ge mp * +#include "group.h" +#include "group-guts.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- Group operations --- */ + +static void gdestroygroup(group *gg) { + gctx_prime *g = (gctx_prime *)gg; + mp_drop(g->gen); mp_drop(g->g.r); mp_drop(g->g.h); + mpmont_destroy(&g->mm); + DESTROY(g); +} + +static mp **gcreate(group *gg) + { mp **x = CREATE(mp *); *x = MP_COPY(*gg->i); return (x); } + +static void gcopy(group *gg, mp **d, mp **x) + { mp *t = MP_COPY(*x); MP_DROP(*d); *d = t; } + +static void gburn(group *gg, mp **x) { (*x)->f |= MP_BURN; } + +static void gdestroy(group *gg, mp **x) { MP_DROP(*x); DESTROY(x); } + +static int gsamep(group *gg, group *hh) { + gctx_prime *g = (gctx_prime *)gg, *h = (gctx_prime *)hh; + return (MP_EQ(g->mm.m, h->mm.m)); +} + +static int geq(group *gg, mp **x, mp **y) { return (MP_EQ(*x, *y)); } + +static const char *gcheck(group *gg, grand *gr) { + gctx_prime *g = (gctx_prime *)gg; int rc; mp *t; + if (!pgen_primep(g->mm.m, gr)) return ("p is not prime"); + t = mp_mul(MP_NEW, g->g.r, g->g.h); t = mp_add(t, t, MP_ONE); + rc = MP_EQ(t, g->mm.m); MP_DROP(t); if (!rc) return ("not a subgroup"); + return (group_stdcheck(gg, gr)); +} + +static void gmul(group *gg, mp **d, mp **x, mp **y) + { gctx_prime *g = (gctx_prime *)gg; *d = mpmont_mul(&g->mm, *d, *x, *y); } + +static void gsqr(group *gg, mp **d, mp **x) { + gctx_prime *g = (gctx_prime *)gg; mp *r = mp_sqr(*d, *x); + *d = mpmont_reduce(&g->mm, r, r); +} + +static void ginv(group *gg, mp **d, mp **x) { + gctx_prime *g = (gctx_prime *)gg; mp *r = mpmont_reduce(&g->mm, *d, *x); + r = mp_modinv(r, r, g->mm.m); *d = mpmont_mul(&g->mm, r, r, g->mm.r2); +} + +static void gexp(group *gg, mp **d, mp **x, mp *n) + { gctx_prime *g = (gctx_prime *)gg; *d = mpmont_expr(&g->mm, *d, *x, n); } + +static void gmexp(group *gg, mp **d, const group_expfactor *f, size_t n) { + gctx_prime *g = (gctx_prime *)gg; size_t i; + mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor)); + for (i = 0; i < n; i++) { ff[i].base = *f[i].base; ff[i].exp = f[i].exp; } + *d = mpmont_mexpr(&g->mm, *d, ff, n); xfree(ff); +} + +static int gread(group *gg, mp **d, const mptext_ops *ops, void *p) { + gctx_prime *g = (gctx_prime *)gg; mp *t; + if ((t = mp_read(MP_NEW, 0, ops, p)) == 0) return (-1); + mp_drop(*d); *d = mpmont_mul(&g->mm, t, t, g->mm.r2); return (0); +} + +static int gwrite(group *gg, mp **x, const mptext_ops *ops, void *p) { + gctx_prime *g = (gctx_prime *)gg; + mp *t = mpmont_reduce(&g->mm, MP_NEW, *x); + int rc = mp_write(t, 10, ops, p); MP_DROP(t); return (rc); +} + +static mp *gtoint(group *gg, mp *d, mp **x) { + gctx_prime *g = (gctx_prime *)gg; + return (mpmont_reduce(&g->mm, d, *x)); +} + +static int gfromint(group *gg, mp **d, mp *x) { + gctx_prime *g = (gctx_prime *)gg; mp_div(0, d, x, g->mm.m); + *d = mpmont_mul(&g->mm, *d, *d, g->mm.r2); return (0); +} + +static int gtobuf(group *gg, buf *b, mp **x) { + gctx_prime *g = (gctx_prime *)gg; + mp *t = mpmont_reduce(&g->mm, MP_NEW, *x); + int rc = buf_putmp(b, t); MP_DROP(t); return (rc); +} + +static int gfrombuf(group *gg, buf *b, mp **d) { + gctx_prime * g = (gctx_prime *)gg; mp *x; + if ((x = buf_getmp(b)) == 0) return (-1); + mp_div(0, &x, x, g->mm.m); mp_drop(*d); + *d = mpmont_mul(&g->mm, x, x, g->mm.r2); return(0); +} + +static int gtoraw(group *gg, buf *b, mp **x) { + gctx_prime *g = (gctx_prime *)gg; octet *q; + mp *t = mpmont_reduce(&g->mm, MP_NEW, *x); + if ((q = buf_get(b, g->g.noctets)) == 0) { MP_DROP(t); return (-1); } + mp_storeb(t, q, g->g.noctets); MP_DROP(t); return (0); +} + +static int gfromraw(group *gg, buf *b, mp **d) { + gctx_prime * g = (gctx_prime *)gg; mp *x; octet *q; + if ((q = buf_get(b, g->g.noctets)) == 0) return (-1); + x = mp_loadb(MP_NEW, q, g->g.noctets); + mp_div(0, &x, x, g->mm.m); mp_drop(*d); + *d = mpmont_mul(&g->mm, x, x, g->mm.r2); return(0); +} + +/* --- @group_prime@ --- * + * + * Arguments: @const gprime_param *gp@ = group parameters + * + * Returns: A pointer to the group, or null. + * + * Use: Constructs an abstract group interface for a subgroup of a + * prime field. Group elements are @mp *@ pointers. + */ + +static const group_ops gops = { + GTY_PRIME, "prime", + gdestroygroup, gcreate, gcopy, gburn, gdestroy, + gsamep, geq, group_stdidentp, + gcheck, + gmul, gsqr, ginv, group_stddiv, gexp, gmexp, + gread, gwrite, + gtoint, gfromint, group_stdtoec, group_stdfromec, gtobuf, gfrombuf, + gtoraw, gfromraw +}; + +group *group_prime(const gprime_param *gp) +{ + gctx_prime *g; + + if (!MP_POSP(gp->p) || !MP_ODDP(gp->p)) + return (0); + g = CREATE(gctx_prime); + g->g.ops = &gops; + g->g.nbits = mp_bits(gp->p); + g->g.noctets = (g->g.nbits + 7) >> 3; + mpmont_create(&g->mm, gp->p); + g->g.i = &g->mm.r; + g->gen = mpmont_mul(&g->mm, MP_NEW, gp->g, g->mm.r2); + g->g.g = &g->gen; + g->g.r = MP_COPY(gp->q); + g->g.h = MP_NEW; mp_div(&g->g.h, 0, gp->p, gp->q); + return (&g->g); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/genlimits.c b/math/genlimits.c new file mode 100644 index 0000000..22c9f5f --- /dev/null +++ b/math/genlimits.c @@ -0,0 +1,280 @@ +/* -*-c-*- + * + * Generate limit MPs for C types + * + * (c) 2006 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _GNU_SOURCE +#include +#include +#include +#include + +#if __STDC_VERSION__ >= 199900l +# include +# include +#endif + +#include "mp.h" +#include "mpint.h" + +/*----- Data types --------------------------------------------------------*/ + +/* --- Hack for GCC --- * + * + * WG14 in their infinite wisdom decided not to use the GCC constant name. + */ + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91) +# define EXT __extension__ +#else +# define EXT +#endif + +#if defined(LONG_LONG_MIN) && !defined(LLONG_MIN) +# define LLONG_MIN EXT LONG_LONG_MIN +#endif + +#if defined(LONG_LONG_MAX) && !defined(LLONG_MAX) +# define LLONG_MAX EXT LONG_LONG_MAX +#endif + +#if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX) +# define ULLONG_MAX EXT ULONG_LONG_MAX +#endif + +/* --- Choose the largest integer type --- */ + +#if defined(INTMAX_MAX) + typedef intmax_t imax; +#elif defined(LLONG_MAX) + EXT typedef long long imax; +#else + typedef long imax; +#endif + +#if defined(UINTMAX_MAX) + typedef uintmax_t umax; +#elif defined(ULLONG_MAX) + EXT typedef unsigned long long umax; +#else + typedef unsigned long umax; +#endif + +/*----- Main code ---------------------------------------------------------*/ + +#define TABSZ 64 + +enum { NEG, POS, NSIGN }; + +umax cmap[TABSZ]; +int gmap[TABSZ][NSIGN]; +struct { int g, s; } qmap[TABSZ]; +int dumpp = 0; + +static int n, q; + +static void dump(mp *x) +{ + int i, w, n; + + fputs(" ", stdout); + w = (MPW_BITS + 3)/4; + n = 1; + while (2 + 2 * n * (4 + w) < 72) n <<= 1; + i = 0; + for (;;) { + printf("0x%0*x", w, x->v[i]); + i++; + if (i >= MP_LEN(x)) break; + fputs(",", stdout); + if (i % n) fputs(" ", stdout); else fputs("\n ", stdout); + } + fputs("\n", stdout); +} + +static void doemit(umax c, int s, int *gg, int *qq) +{ + int i; + mp *x = MP_NEW; + + for (i = 0; i < n; i++) { + if (cmap[i] == c) + goto found; + } + + assert(i < TABSZ); + n = i + 1; + cmap[i] = c; + gmap[i][POS] = gmap[i][NEG] = -1; + if (dumpp) { + MP_FROMINT(x, umax, c); + printf("static mpw guts_%d[] = {\n", q); + dump(x); + fputs("};\n\n", stdout); + MP_DROP(x); + } + +found: + *gg = i; + if (gmap[i][s] < 0) { + assert(q < TABSZ); + gmap[i][s] = q; + qmap[q].g = i; + qmap[q].s = s; + q++; + } + *qq = gmap[i][s]; +} + +static void emit(imax c, int *gg, int *qq) +{ + umax uc; + int s; + + if (c >= 0) { uc = c; s = POS; } + else { uc = -c; s = NEG; } + doemit(uc, s, gg, qq); +} + +static void uemit(umax c, int *gg, int *qq) { doemit(c, POS, gg, qq); } + +struct { + const char *name; + imax min; + umax max; + int gmin, gmax; + int qmin, qmax; +} tab[] = { + { "SCHAR", SCHAR_MIN, SCHAR_MAX }, + { "CHAR", CHAR_MIN, CHAR_MAX }, + { "UCHAR", 0, UCHAR_MAX }, + { "UINT8", 0, 0xff }, + { "SHRT", SHRT_MIN, SHRT_MAX }, + { "USHRT", 0, USHRT_MAX }, + { "UINT16", 0, 0xffff }, + { "INT", INT_MIN, INT_MAX }, + { "UINT", 0, UINT_MAX }, + { "LONG", LONG_MIN, LONG_MAX }, + { "ULONG", 0, ULONG_MAX }, + { "UINT32", 0, 0xffffffff }, +#ifdef LLONG_MAX + { "LLONG", LLONG_MIN, LLONG_MAX }, + { "ULLONG", 0, ULLONG_MAX }, +#endif + { "SIZET", 0, ~(size_t)0 }, + { 0 } +}; + +static void dogen(void) +{ + int i; + + for (i = 0; tab[i].name; i++) { + if (tab[i].min) + emit(tab[i].min, &tab[i].gmin, &tab[i].qmin); + uemit(tab[i].max, &tab[i].gmax, &tab[i].qmax); + } +} + +static void cgen(void) +{ + int i; + + fputs("\ +/* -*-c-*-\n\ + *\n\ + * C integer limits [generated]\n\ + */\n\ +\n\ +#include \"mplimits.h\"\n\ +\n\ +#define N(x) (sizeof(x)/sizeof(*x))\n\ +#define MPpos(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }\n\ +#define MPneg(x) { x, x + N(x), N(x), 0, MP_CONST|MP_NEG, 0 }\n\ +\n", + stdout); + dumpp = 1; + dogen(); + + fputs("mp mp_limits[] = {\n", stdout); + for (i = 0; i < q; i++) + printf(" MP%s(guts_%d),\n", qmap[i].s ? "pos" : "neg", qmap[i].g); + fputs("};\n", stdout); +} + +static void hgen(void) +{ + int i; + + fputs("\ +/* -*-c-*-\n\ + *\n\ + * C integer limits [generated]\n\ + */\n\ +\n\ +#ifndef CATACOMB_MPLIMITS_H\n\ +#define CATACOMB_MPLIMITS_H\n\ +\n\ +#ifndef CATACOMB_MP_H\n\ +# include \"mp.h\"\n\ +#endif\n\ +\n\ +extern mp mp_limits[];\n\ +\n", + stdout); + dogen(); + + for (i = 0; tab[i].name; i++) { + if (tab[i].min) { + printf("#define MP_%s_MIN (&mp_limits[%d])\n", + tab[i].name, gmap[tab[i].qmin][NEG]); + } + printf("#define MP_%s_MAX (&mp_limits[%d])\n", + tab[i].name, gmap[tab[i].qmax][POS]); + } + fputs("\n#endif\n", stdout); +} + +int main(int argc, char *argv[]) +{ + const char *what = argc == 2 ? argv[1] : ""; + + switch (what[0]) { + case 'c': cgen(); break; + case 'h': hgen(); break; + default: + fprintf(stderr, "unknown action `%s'\n", what); + exit(1); + } + if (fflush(stdout) || fclose(stdout)) { + fprintf(stderr, "error writing output: %s\n", strerror(errno)); + exit(1); + } + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/genprimes.c b/math/genprimes.c new file mode 100644 index 0000000..a4bf64a --- /dev/null +++ b/math/genprimes.c @@ -0,0 +1,191 @@ +/* -*-c-*- + * + * Generate prime number table + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/*----- Data structures ---------------------------------------------------*/ + +DA_DECL(intv, int); + +/*----- Main code ---------------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + int p_max = 0, p_n = 0; + char *type = "unsigned int"; + char *header = "primetab.h"; + char *source = "primetab.c"; + char *name = "primetab"; + char *sym = 0; + intv p = DA_INIT; + int i; + + ego(argv[0]); + + for (;;) { + int i = getopt(argc, argv, "h:c:i:n:m:t:s:"); + if (i < 0) + break; + switch (i) { + case 'h': + header = optarg; + break; + case 'c': + source = optarg; + break; + case 'i': + name = optarg; + break; + case 'n': + p_max = 0; + p_n = atoi(optarg); + break; + case 'm': + p_n = 0; + p_max = atoi(optarg); + break; + case 't': + type = optarg; + break; + case 's': + sym = optarg; + break; + default: + pquis(stderr, "Usage: $ [-n nprimes] [-m maxprime] [-t type]\n"); + exit(EXIT_FAILURE); + } + } + + if (!p_max && !p_n) + die(EXIT_FAILURE, "bad arguments to `-n' or `-m'"); + + if (p_n || p_max >= 2) + DA_PUSH(&p, 2); + for (i = 3; (!p_max && !p_n) || + (p_n && DA_LEN(&p) < p_n) || + (p_max && i <= p_max); + i += 2) { + int j; + for (j = 0; j < DA_LEN(&p); j++) { + if (i % DA(&p)[j] == 0) + goto composite; + } + DA_PUSH(&p, i); + composite:; + } + + { + FILE *fp = fopen(header, "w"); + dstr d = DSTR_INIT; + char *q; + if (!fp) + die(EXIT_FAILURE, "couldn't write `%s': %s", header, strerror(errno)); + if (!sym) { + for (q = header; *q; q++) { + int ch = (unsigned char)*q; + if (isalnum(ch)) + ch = toupper(ch); + else + ch = '_'; + DPUTC(&d, ch); + } + DPUTZ(&d); + sym = d.buf; + } + fprintf(fp, "\ +/* -*-c-*-\n\ + *\n\ + * Table of small prime numbers [generated]\n\ + */\n\ +\n\ +#ifndef %s\n\ +#define %s\n\ +\n\ +#define NPRIME %luu\n\ +#define MAXPRIME %uu\n\ +\n\ +typedef %s smallprime;\n\ +extern const smallprime %s[];\n\ +\n\ +#endif\n\ +", + sym, sym, + (unsigned long)DA_LEN(&p), + DA_LAST(&p), + type, name); + dstr_destroy(&d); + if (fclose(fp) == EOF) { + remove(header); + die(EXIT_FAILURE, "error writing `%s': %s", header, strerror(errno)); + } + } + + { + FILE *fp = fopen(source, "w"); + int i; + if (!fp) + die(EXIT_FAILURE, "couldn't write `%s': %s", source, strerror(errno)); + fprintf(fp, "\ +/* -*-c-*-\n\ + *\n\ + * Table of small prime numbers [generated]\n\ + */\n\ +\n\ +#include \"%s\"\n\ +\n\ +const %s %s[] = {", + header, type, name); + for (i = 0; i < DA_LEN(&p); i++) { + if (i % 8 == 0) + fputs("\n ", fp); + fprintf(fp, "%5i, ", DA(&p)[i]); + } + fputs("\n\ +};\n\ +", fp); + if (fclose(fp) == EOF) { + remove(source); + die(EXIT_FAILURE, "error writing `%s': %s", source, strerror(errno)); + } + } + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/genwheel.c b/math/genwheel.c similarity index 100% rename from genwheel.c rename to math/genwheel.c diff --git a/math/gf-arith.c b/math/gf-arith.c new file mode 100644 index 0000000..1c67c74 --- /dev/null +++ b/math/gf-arith.c @@ -0,0 +1,307 @@ +/* -*-c-*- + * + * Basic arithmetic on binary polynomials + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "gf.h" + +/*----- Macros ------------------------------------------------------------*/ + +#define MAX(x, y) ((x) >= (y) ? (x) : (y)) + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gf_add@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: Result, @a@ added to @b@. + */ + +mp *gf_add(mp *d, mp *a, mp *b) +{ + MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)), (a->f | b->f) & MP_BURN); + gfx_add(d->v, d->vl, a->v, a->vl, b->v, b->vl); + d->f = (a->f | b->f) & MP_BURN; + MP_SHRINK(d); + return (d); +} + +/* --- @gf_mul@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: Result, @a@ multiplied by @b@. + */ + +mp *gf_mul(mp *d, mp *a, mp *b) +{ + a = MP_COPY(a); + b = MP_COPY(b); + + if (MP_LEN(a) <= MPK_THRESH || MP_LEN(b) <= GFK_THRESH) { + MP_DEST(d, MP_LEN(a) + MP_LEN(b), a->f | b->f | MP_UNDEF); + gfx_mul(d->v, d->vl, a->v, a->vl, b->v, b->vl); + } else { + size_t m = MAX(MP_LEN(a), MP_LEN(b)); + mpw *s; + MP_DEST(d, 2 * m, a->f | b->f | MP_UNDEF); + s = mpalloc(d->a, 3 * m); + gfx_kmul(d->v, d->vl, a->v, a->vl, b->v, b->vl, s, s + 3 * m); + mpfree(d->a, s); + } + + d->f = (a->f | b->f) & MP_BURN; + MP_SHRINK(d); + MP_DROP(a); + MP_DROP(b); + return (d); +} + +/* --- @gf_sqr@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = source + * + * Returns: Result, @a@ squared. + */ + +mp *gf_sqr(mp *d, mp *a) +{ + MP_COPY(a); + MP_DEST(d, 2 * MP_LEN(a), a->f & MP_BURN); + gfx_sqr(d->v, d->vl, a->v, a->vl); + d->f = a->f & MP_BURN; + MP_SHRINK(d); + MP_DROP(a); + return (d); +} + +/* --- @gf_div@ --- * + * + * Arguments: @mp **qq, **rr@ = destination, quotient and remainder + * @mp *a, *b@ = sources + * + * Use: Calculates the quotient and remainder when @a@ is divided by + * @b@. The destinations @*qq@ and @*rr@ must be distinct. + * Either of @qq@ or @rr@ may be null to indicate that the + * result is irrelevant. (Discarding both results is silly.) + * There is a performance advantage if @a == *rr@. + */ + +void gf_div(mp **qq, mp **rr, mp *a, mp *b) + { + mp *r = rr ? *rr : MP_NEW; + mp *q = qq ? *qq : MP_NEW; + + /* --- Set the remainder up right --- */ + + b = MP_COPY(b); + a = MP_COPY(a); + if (r) + MP_DROP(r); + r = a; + MP_DEST(r, MP_LEN(b) + 2, a->f | b->f); + + /* --- Fix up the quotient too --- */ + + r = MP_COPY(r); + MP_DEST(q, MP_LEN(r), r->f | MP_UNDEF); + MP_DROP(r); + + /* --- Perform the calculation --- */ + + gfx_div(q->v, q->vl, r->v, r->vl, b->v, b->vl); + + /* --- Sort out the sign of the results --- * + * + * If the signs of the arguments differ, and the remainder is nonzero, I + * must add one to the absolute value of the quotient and subtract the + * remainder from @b@. + */ + + q->f = (r->f | b->f) & MP_BURN; + r->f = (r->f | b->f) & MP_BURN; + + /* --- Store the return values --- */ + + MP_DROP(b); + + if (!qq) + MP_DROP(q); + else { + MP_SHRINK(q); + *qq = q; + } + + if (!rr) + MP_DROP(r); + else { + MP_SHRINK(r); + *rr = r; + } +} + +/* --- @gf_irreduciblep@ --- * + * + * Arguments: @mp *f@ = a polynomial + * + * Returns: Nonzero if the polynomial is irreducible; otherwise zero. + */ + +int gf_irreduciblep(mp *f) +{ + unsigned long m; + mp *u = MP_TWO; + mp *v = MP_NEW; + + if (MP_ZEROP(f)) + return (0); + else if (MP_LEN(f) == 1) { + if (f->v[0] < 2) return (0); + if (f->v[0] < 4) return (1); + } + m = (mp_bits(f) - 1)/2; + while (m) { + u = gf_sqr(u, u); + gf_div(0, &u, u, f); + v = gf_add(v, u, MP_TWO); + gf_gcd(&v, 0, 0, v, f); + if (!MP_EQ(v, MP_ONE)) break; + m--; + } + MP_DROP(u); + MP_DROP(v); + return (!m); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int verify(const char *op, mp *expect, mp *result, mp *a, mp *b) +{ + if (!MP_EQ(expect, result)) { + fprintf(stderr, "\n*** %s failed", op); + fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 16); + fputs("\n*** b = ", stderr); mp_writefile(b, stderr, 16); + fputs("\n*** result = ", stderr); mp_writefile(result, stderr, 16); + fputs("\n*** expect = ", stderr); mp_writefile(expect, stderr, 16); + fputc('\n', stderr); + return (0); + } + return (1); +} + +#define RIG(name, op) \ + static int t##name(dstr *v) \ + { \ + mp *a = *(mp **)v[0].buf; \ + mp *b = *(mp **)v[1].buf; \ + mp *r = *(mp **)v[2].buf; \ + mp *c = op(MP_NEW, a, b); \ + int ok = verify(#name, r, c, a, b); \ + mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(r); \ + assert(mparena_count(MPARENA_GLOBAL) == 0); \ + return (ok); \ + } + +RIG(add, gf_add) +RIG(mul, gf_mul) +RIG(exp, gf_exp) + +#undef RIG + +static int tsqr(dstr *v) +{ + mp *a = *(mp **)v[0].buf; + mp *r = *(mp **)v[1].buf; + mp *c = MP_NEW; + int ok = 1; + c = gf_sqr(MP_NEW, a); + ok &= verify("sqr", r, c, a, MP_ZERO); + mp_drop(a); mp_drop(r); mp_drop(c); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tdiv(dstr *v) +{ + mp *a = *(mp **)v[0].buf; + mp *b = *(mp **)v[1].buf; + mp *q = *(mp **)v[2].buf; + mp *r = *(mp **)v[3].buf; + mp *c = MP_NEW, *d = MP_NEW; + int ok = 1; + gf_div(&c, &d, a, b); + ok &= verify("div(quotient)", q, c, a, b); + ok &= verify("div(remainder)", r, d, a, b); + mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(d); mp_drop(r); mp_drop(q); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tirred(dstr *v) +{ + mp *a = *(mp **)v[0].buf; + int r = *(int *)v[1].buf; + int c = gf_irreduciblep(a); + int ok = 1; + if (r != c) { + ok = 0; + fprintf(stderr, "\n*** irred failed"); + fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 16); + fprintf(stderr, "\n*** r = %d\n", r); + fprintf(stderr, "*** c = %d\n", c); + } + mp_drop(a); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "add", tadd, { &type_mp, &type_mp, &type_mp, 0 } }, + { "mul", tmul, { &type_mp, &type_mp, &type_mp, 0 } }, + { "sqr", tsqr, { &type_mp, &type_mp, 0 } }, + { "div", tdiv, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, + { "exp", texp, { &type_mp, &type_mp, &type_mp, 0 } }, + { "irred", tirred, { &type_mp, &type_int, 0 } }, + { 0, 0, { 0 } }, +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/gf"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/gf-exp.c b/math/gf-exp.c new file mode 100644 index 0000000..14c40d3 --- /dev/null +++ b/math/gf-exp.c @@ -0,0 +1,65 @@ +/* -*-c-*- + * + * Exponentiation for binary polynomials + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "gf.h" +#include "gf-exp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gf_exp@ --- * + * + * Arguments: @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e$%. + */ + +mp *gf_exp(mp *d, mp *a, mp *e) +{ + mp *x = MP_ONE; + mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; + assert(!MP_NEGP(e)); + + MP_COPY(a); + if (MP_ZEROP(e)) + ; + else if (MP_LEN(e) < EXP_THRESH) + EXP_SIMPLE(x, a, e); + else + EXP_WINDOW(x, a, e); + mp_drop(d); + mp_drop(spare); + mp_drop(a); + return (x); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/gf-exp.h b/math/gf-exp.h new file mode 100644 index 0000000..189fc76 --- /dev/null +++ b/math/gf-exp.h @@ -0,0 +1,67 @@ +/* -*-c-*- + * + * Exponentiation for binary polynomials + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GF_EXP_H +#define CATACOMB_GF_EXP_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Exponentiation ----------------------------------------------------*/ + +#define EXP_TYPE mp * + +#define EXP_COPY(d, x) d = MP_COPY(x) +#define EXP_DROP(x) MP_DROP(x) + +#define EXP_MUL(a, x) do { \ + mp *t = gf_mul(spare, a, x); \ + spare = a; \ + a = t; \ +} while (0) + +#define EXP_SQR(a) do { \ + mp *t = gf_sqr(spare, a); \ + spare = a; \ + a = t; \ +} while (0) + +#define EXP_FIX(x) + +#define EXP_SETMUL(d, x, y) d = gf_mul(MP_NEW, x, y) +#define EXP_SETSQR(d, x) d = gf_sqr(MP_NEW, x) + +#include "exp.h" + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/gf-gcd.c b/math/gf-gcd.c new file mode 100644 index 0000000..f81aac7 --- /dev/null +++ b/math/gf-gcd.c @@ -0,0 +1,261 @@ +/* -*-c-*- + * + * Euclidian algorithm on binary polynomials + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "gf.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gf_gcd@ --- * + * + * Arguments: @mp **gcd, **xx, **yy@ = where to write the results + * @mp *a, *b@ = sources (must be nonzero) + * + * + * Returns: --- + * + * Use: Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that + * @ax + by = gcd(a, b)@. This is useful for computing modular + * inverses. + */ + +void gf_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b) +{ + mp *x = MP_ONE, *X = MP_ZERO; + mp *y = MP_ZERO, *Y = MP_ONE; + mp *u, *v; + mp *q = MP_NEW, *t, *spare = MP_NEW; + unsigned f = 0; + +#define f_swap 1u +#define f_ext 2u + + /* --- Sort out some initial flags --- */ + + if (xx || yy) + f |= f_ext; + + /* --- Ensure that @a@ is larger than @b@ --- * + * + * If they're the same length we don't care which order they're in, so this + * unsigned comparison is fine. + */ + + if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) { + t = a; a = b; b = t; + f |= f_swap; + } + + /* --- Check for zeroness --- */ + + if (MP_EQ(b, MP_ZERO)) { + + /* --- Store %$|a|$% as the GCD --- */ + + if (gcd) { + if (*gcd) MP_DROP(*gcd); + a = MP_COPY(a); + *gcd = a; + } + + /* --- Store %$1$% and %$0$% in the appropriate bins --- */ + + if (f & f_ext) { + if (f & f_swap) { + mp **t = xx; xx = yy; yy = t; + } + if (xx) { + if (*xx) MP_DROP(*xx); + if (MP_EQ(a, MP_ZERO)) + *xx = MP_ZERO; + else + *xx = MP_ONE; + } + if (yy) { + if (*yy) MP_DROP(*yy); + *yy = MP_ZERO; + } + } + return; + } + + /* --- Main extended Euclidean algorithm --- */ + + u = MP_COPY(a); + v = MP_COPY(b); + + while (!MP_ZEROP(v)) { + gf_div(&q, &u, u, v); + if (f & f_ext) { + t = gf_mul(spare, X, q); + t = gf_add(t, t, x); + spare = x; x = X; X = t; + t = gf_mul(spare, Y, q); + t = gf_add(t, t, y); + spare = y; y = Y; Y = t; + } + t = u; u = v; v = t; + } + + MP_DROP(q); if (spare) MP_DROP(spare); + if (!gcd) + MP_DROP(u); + else { + if (*gcd) MP_DROP(*gcd); + u->f &= ~MP_NEG; + *gcd = u; + } + + /* --- Perform a little normalization --- */ + + if (f & f_ext) { + + /* --- If @a@ and @b@ got swapped, swap the coefficients back --- */ + + if (f & f_swap) { + t = x; x = y; y = t; + t = a; a = b; b = t; + } + + /* --- Store the results --- */ + + if (!xx) + MP_DROP(x); + else { + if (*xx) MP_DROP(*xx); + *xx = x; + } + + if (!yy) + MP_DROP(y); + else { + if (*yy) MP_DROP(*yy); + *yy = y; + } + } + + MP_DROP(v); + MP_DROP(X); MP_DROP(Y); +} + +/* -- @gf_modinv@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *x@ = argument + * @mp *p@ = modulus + * + * Returns: The inverse %$x^{-1} \bmod p$%. + * + * Use: Computes a modular inverse, the catch being that the + * arguments and results are binary polynomials. An assertion + * fails if %$p$% has no inverse. + */ + +mp *gf_modinv(mp *d, mp *x, mp *p) +{ + mp *g = MP_NEW; + gf_gcd(&g, 0, &d, p, x); + assert(MP_EQ(g, MP_ONE)); + mp_drop(g); + return (d); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int gcd(dstr *v) +{ + int ok = 1; + mp *a = *(mp **)v[0].buf; + mp *b = *(mp **)v[1].buf; + mp *g = *(mp **)v[2].buf; + mp *x = *(mp **)v[3].buf; + mp *y = *(mp **)v[4].buf; + + mp *gg = MP_NEW, *xx = MP_NEW, *yy = MP_NEW; + gf_gcd(&gg, &xx, &yy, a, b); + if (!MP_EQ(x, xx)) { + fputs("\n*** gf_gcd(x) failed", stderr); + fputs("\na = ", stderr); mp_writefile(a, stderr, 16); + fputs("\nb = ", stderr); mp_writefile(b, stderr, 16); + fputs("\nexpect = ", stderr); mp_writefile(x, stderr, 16); + fputs("\nresult = ", stderr); mp_writefile(xx, stderr, 16); + fputc('\n', stderr); + ok = 0; + } + if (!MP_EQ(y, yy)) { + fputs("\n*** gf_gcd(y) failed", stderr); + fputs("\na = ", stderr); mp_writefile(a, stderr, 16); + fputs("\nb = ", stderr); mp_writefile(b, stderr, 16); + fputs("\nexpect = ", stderr); mp_writefile(y, stderr, 16); + fputs("\nresult = ", stderr); mp_writefile(yy, stderr, 16); + fputc('\n', stderr); + ok = 0; + } + + if (!ok) { + mp *ax = gf_mul(MP_NEW, a, xx); + mp *by = gf_mul(MP_NEW, b, yy); + ax = gf_add(ax, ax, by); + if (MP_EQ(ax, gg)) + fputs("\n*** (Alternative result found.)\n", stderr); + MP_DROP(ax); + MP_DROP(by); + } + + if (!MP_EQ(g, gg)) { + fputs("\n*** gf_gcd(gcd) failed", stderr); + fputs("\na = ", stderr); mp_writefile(a, stderr, 16); + fputs("\nb = ", stderr); mp_writefile(b, stderr, 16); + fputs("\nexpect = ", stderr); mp_writefile(g, stderr, 16); + fputs("\nresult = ", stderr); mp_writefile(gg, stderr, 16); + fputc('\n', stderr); + ok = 0; + } + MP_DROP(a); MP_DROP(b); MP_DROP(g); MP_DROP(x); MP_DROP(y); + MP_DROP(gg); MP_DROP(xx); MP_DROP(yy); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "gcd", gcd, { &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/gf"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/gf.h b/math/gf.h new file mode 100644 index 0000000..edc91fa --- /dev/null +++ b/math/gf.h @@ -0,0 +1,149 @@ +/* -*-c-*- + * + * Arithmetic on binary polynomials + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GF_H +#define CATACOMB_GF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_GFX_H +# include "gfx.h" +#endif + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @gf_add@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: Result, @a@ added to @b@. + */ + +extern mp *gf_add(mp */*d*/, mp */*a*/, mp */*b*/); +#define gf_sub gf_add + +/* --- @gf_mul@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: Result, @a@ multiplied by @b@. + */ + +extern mp *gf_mul(mp */*d*/, mp */*a*/, mp */*b*/); + +/* --- @gf_sqr@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = source + * + * Returns: Result, @a@ squared. + */ + +extern mp *gf_sqr(mp */*d*/, mp */*a*/); + +/* --- @gf_div@ --- * + * + * Arguments: @mp **qq, **rr@ = destination, quotient and remainder + * @mp *a, *b@ = sources + * + * Use: Calculates the quotient and remainder when @a@ is divided by + * @b@. The destinations @*qq@ and @*rr@ must be distinct. + * Either of @qq@ or @rr@ may be null to indicate that the + * result is irrelevant. (Discarding both results is silly.) + * There is a performance advantage if @a == *rr@. + */ + +extern void gf_div(mp **/*qq*/, mp **/*rr*/, mp */*a*/, mp */*b*/); + +/* --- @gf_exp@ --- * + * + * Arguments: @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e$%. + */ + +extern mp *gf_exp(mp */*d*/, mp */*a*/, mp */*e*/); + +/* --- @gf_irreduciblep@ --- * + * + * Arguments: @mp *f@ = a polynomial + * + * Returns: Nonzero if the polynomial is irreducible; otherwise zero. + */ + +extern int gf_irreduciblep(mp */*f*/); + +/* --- @gf_gcd@ --- * + * + * Arguments: @mp **gcd, **xx, **yy@ = where to write the results + * @mp *a, *b@ = sources (must be nonzero) + * + * + * Returns: --- + * + * Use: Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that + * @ax + by = gcd(a, b)@. This is useful for computing modular + * inverses. + */ + +extern void gf_gcd(mp **/*gcd*/, mp **/*xx*/, mp **/*yy*/, + mp */*a*/, mp */*b*/); + +/* -- @gf_modinv@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *x@ = argument + * @mp *p@ = modulus + * + * Returns: The inverse %$x^{-1} \bmod p$%. + * + * Use: Computes a modular inverse, the catch being that the + * arguments and results are binary polynomials. An assertion + * fails if %$p$% has no inverse. + */ + +extern mp *gf_modinv(mp */*d*/, mp */*x*/, mp */*p*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/gfn.c b/math/gfn.c new file mode 100644 index 0000000..c9b90c0 --- /dev/null +++ b/math/gfn.c @@ -0,0 +1,272 @@ +/* -*-c-*- + * + * Normal-basis translation for binary fields + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "gfreduce.h" +#include "gfn.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gfn_copy@ --- * + * + * Arguments: @gfn *d@ = where to put the copy + * @const gfn *s@ = where the source is + * + * Returns: --- + * + * Use: Makes a copy of a translation matrix. + */ + +void gfn_copy(gfn *d, const gfn *s) +{ + size_t i; + + d->n = s->n; + d->r = xmalloc(s->n * sizeof(mp *)); + for (i = 0; i < s->n; i++) + d->r[i] = MP_COPY(s->r[i]); +} + +/* --- @gfn_destroy@ --- * + * + * Arguments: @gfn *m@ = a transformation matrix to free + * + * Returns: --- + * + * Use: Frees up a transformation matrix when it's no longer wanted. + */ + +void gfn_destroy(gfn *m) + { size_t i; for (i = 0; i < m->n; i++) MP_DROP(m->r[i]); xfree(m->r); } + +/* --- @gfn_identity@ --- * + * + * Arguments: @gfn *m@ = where to put the matrix + * @size_t n@ = size of the matrix + * + * Returns: --- + * + * Use: Fills @m@ with an identity matrix. + */ + +void gfn_identity(gfn *m, size_t n) +{ + size_t i; + + m->n = n; + m->r = xmalloc(n * sizeof(mp *)); + m->r[0] = MP_ONE; + for (i = 1; i < n; i++) + m->r[i] = mp_lsl(MP_NEW, m->r[i - 1], 1); +} + +/* --- @gfn_invert@ --- * + * + * Arguments: @gfn *m@ = a transformation matrix + * + * Returns: Zero if successful, nonzero if the matrix was singular. + * + * Use: Inverts a transformation matrix. + */ + +int gfn_invert(gfn *m) +{ + size_t i, j; + gfn mm; + mp *t; + int rc = -1; + + mm = *m; + gfn_identity(m, mm.n); + for (i = 0; i < mm.n; i++) { + if (!mp_testbit(mm.r[i], i)) { + for (j = i + 1; j < mm.n; j++) { + if (mp_testbit(mm.r[j], i)) + goto found_set; + } + goto fail; + found_set: + t = mm.r[i]; mm.r[i] = mm.r[j]; mm.r[j] = t; + t = m->r[i]; m->r[i] = m->r[j]; m->r[j] = t; + } + for (j = 0; j < mm.n; j++) { + if (j == i) continue; + if (mp_testbit(mm.r[j], i)) { + mm.r[j] = mp_xor(mm.r[j], mm.r[j], mm.r[i]); + m->r[j] = mp_xor(m->r[j], m->r[j], m->r[i]); + } + } + } + rc = 0; +fail: + gfn_destroy(&mm); + return (rc); +} + +/* --- @gfn_transform@ --- * + * + * Arguments: @gfn *m@ = conversion matrix to apply + * @mp *d@ = destination pointer + * @mp *x@ = input value + * + * Returns: The transformed element. + * + * Use: Transforms a field element according to the given matrix. + */ + +mp *gfn_transform(gfn *m, mp *d, mp *x) +{ + mp *y = MP_ZERO; + size_t i; + mpscan sc; + + for (i = 0, mp_scan(&sc, x); i < m->n && mp_step(&sc); i++) + if (mp_bit(&sc)) y = mp_xor(y, y, m->r[i]); + mp_drop(d); + return (y); +} + +/* --- @gfn_create@ --- * + * + * Arguments: @mp *p@ = modulus for polynomial basis + * @mp *beta@ = the generator of the normal basis, expressed + * relative to the polynomial basis + * @gfn *ntop@ = output normal-to-polynomail conversion matrix + * @gfn *pton@ = output polynomial-to-normal conversion matrix + * + * Returns: Zero if it worked, nonzero otherwise (e.g., if %$\beta$% + * doesn't generate a proper basis). + * + * Use: Constructs conversion matrices between polynomial and normal + * basis representations of binary field elements. + */ + +int gfn_create(mp *p, mp *beta, gfn *ntop, gfn *pton) +{ + size_t m = mp_bits(p) - 1; + size_t i; + gfreduce gr; + gfn *np, tmp; + + /* --- We start by building the the @ntop@ matrix --- * + * + * For mad reasons, the string representation of normal-basis elements is + * backwards. + */ + + gfreduce_create(&gr, p); + np = ntop ? ntop : &tmp; + np->n = m; + np->r = xmalloc(m * sizeof(mp *)); + np->r[m - 1] = MP_COPY(beta); + for (i = m - 1; i--; ) { + mp *x = gf_sqr(MP_NEW, np->r[i + 1]); + np->r[i] = gfreduce_do(&gr, x, x); + } + gfreduce_destroy(&gr); + + /* --- That was easy -- now invert it --- */ + + if (pton) { + if (ntop) gfn_copy(pton, np); else *pton = *np; + if (gfn_invert(pton)) { + gfn_destroy(pton); + if (ntop) gfn_destroy(ntop); + return (-1); + } + } + + /* --- And we're done --- */ + + return (0); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int check(dstr *v) +{ + mp *p = *(mp **)v[0].buf; + mp *beta = *(mp **)v[1].buf; + mp *xp = *(mp **)v[2].buf; + mp *xn = *(mp **)v[3].buf; + mp *y = MP_NEW; + gfn pton, ntop, ii; + size_t i; + int ok = 1; + + gfn_create(p, beta, &ntop, &pton); + gfn_identity(&ii, pton.n); + for (i = 0; i < pton.n; i++) { + y = gfn_transform(&ntop, y, pton.r[i]); + if (!MP_EQ(y, ii.r[i])) { + ok = 0; + fprintf(stderr, "*** inverse pton->ntop check failed (row %lu)\n", + (unsigned long)i); + MP_EPRINTX("*** p", p); MP_EPRINTX("*** beta", beta); + MP_EPRINTX("*** computed", y); + } + } + gfn_destroy(&ii); + y = gfn_transform(&pton, y, xp); + if (!MP_EQ(y, xn)) { + ok = 0; + fprintf(stderr, "*** pton failed\n"); + MP_EPRINTX("*** p", p); MP_EPRINTX("*** beta", beta); + MP_EPRINTX("*** xp", xp); MP_EPRINTX("*** xn", xn); + MP_EPRINTX("*** computed", y); + } + y = gfn_transform(&ntop, y, xn); + if (!MP_EQ(y, xp)) { + ok = 0; + fprintf(stderr, "*** ntop failed\n"); + MP_EPRINTX("*** p", p); MP_EPRINTX("*** beta", beta); + MP_EPRINTX("*** xp", xp); MP_EPRINTX("*** xn", xn); + MP_EPRINTX("*** computed", y); + } + gfn_destroy(&pton); gfn_destroy(&ntop); + mp_drop(p); mp_drop(beta); mp_drop(xp); mp_drop(xn); mp_drop(y); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "gfn", check, { &type_mp, &type_mp, &type_mp, &type_mp } }, + { 0 } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, tests, SRCDIR "/t/gfn"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/gfn.h b/math/gfn.h new file mode 100644 index 0000000..11ecb44 --- /dev/null +++ b/math/gfn.h @@ -0,0 +1,130 @@ +/* -*-c-*- + * + * Normal-basis translation for binary fields + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GFN_H +#define CATACOMB_GFN_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include "gf.h" + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct gfn { + size_t n; /* Number of rows */ + mp **r; /* Array of the rows */ +} gfn; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @gfn_copy@ --- * + * + * Arguments: @gfn *d@ = where to put the copy + * @const gfn *s@ = where the source is + * + * Returns: --- + * + * Use: Makes a copy of a translation matrix. + */ + +extern void gfn_copy(gfn */*d*/, const gfn */*s*/); + +/* --- @gfn_destroy@ --- * + * + * Arguments: @gfn *m@ = a transformation matrix to free + * + * Returns: --- + * + * Use: Frees up a transformation matrix when it's no longer wanted. + */ + +extern void gfn_destroy(gfn */*m*/); + +/* --- @gfn_identity@ --- * + * + * Arguments: @gfn *m@ = where to put the matrix + * @size_t n@ = size of the matrix + * + * Returns: --- + * + * Use: Fills @m@ with an identity matrix. + */ + +extern void gfn_identity(gfn */*m*/, size_t /*n*/); + +/* --- @gfn_invert@ --- * + * + * Arguments: @gfn *m@ = a transformation matrix + * + * Returns: Zero if successful, nonzero if the matrix was singular. + * + * Use: Inverts a transformation matrix. + */ + +extern int gfn_invert(gfn */*m*/); + +/* --- @gfn_transform@ --- * + * + * Arguments: @gfn *m@ = conversion matrix to apply + * @mp *d@ = destination pointer + * @mp *x@ = input value + * + * Returns: The transformed element. + * + * Use: Transforms a field element according to the given matrix. + */ + +extern mp *gfn_transform(gfn */*m*/, mp */*d*/, mp */*x*/); + +/* --- @gfn_create@ --- * + * + * Arguments: @mp *p@ = modulus for polynomial basis + * @mp *beta@ = the generator of the normal basis, expressed + * relative to the polynomial basis + * @gfn *ntop@ = output normal-to-polynomail conversion matrix + * @gfn *pton@ = output polynomial-to-normal conversion matrix + * + * Returns: Zero if it worked, nonzero otherwise (e.g., if %$\beta$% + * doesn't generate a proper basis). + * + * Use: Constructs conversion matrices between polynomial and normal + * basis representations of binary field elements. + */ + +extern int gfn_create(mp */*p*/, mp */*beta*/, gfn */*ntop*/, gfn */*pton*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/gfreduce-exp.h b/math/gfreduce-exp.h new file mode 100644 index 0000000..93af649 --- /dev/null +++ b/math/gfreduce-exp.h @@ -0,0 +1,74 @@ +/* -*-c-*- + * + * Exponentiation operations for binary field reduction + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GFREDUCE_EXP_H +#define CATACOMB_GFREDUCE_EXP_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Exponentiation definitions ----------------------------------------*/ + +#define EXP_TYPE mp * + +#define EXP_COPY(d, x) d = MP_COPY(x) +#define EXP_DROP(x) MP_DROP(x) + +#define EXP_MUL(a, x) do { \ + mp *t = gf_mul(spare, a, x); \ + spare = a; \ + a = gfreduce_do(gr, t, t); \ +} while (0) + +#define EXP_SQR(a) do { \ + mp *t = gf_sqr(spare, a); \ + spare = a; \ + a = gfreduce_do(gr, t, t); \ +} while (0) + +#define EXP_FIX(x) + +#define EXP_SETMUL(d, x, y) do { \ + d = gf_mul(MP_NEW, x, y); \ + d = gfreduce_do(gr, d, d); \ +} while (0) + +#define EXP_SETSQR(d, x) do { \ + d = gf_sqr(MP_NEW, x); \ + d = gfreduce_do(gr, d, d); \ +} while (0) + +#include "exp.h" + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/gfreduce.c b/math/gfreduce.c new file mode 100644 index 0000000..164122d --- /dev/null +++ b/math/gfreduce.c @@ -0,0 +1,650 @@ +/* -*-c-*- + * + * Efficient reduction modulo sparse binary polynomials + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include "gf.h" +#include "gfreduce.h" +#include "gfreduce-exp.h" +#include "fibrand.h" +#include "mprand.h" + +/*----- Data structures ---------------------------------------------------*/ + +DA_DECL(instr_v, gfreduce_instr); + +/*----- Main code ---------------------------------------------------------*/ + +/* --- What's going on here? --- * + * + * Let's face it, @gfx_div@ sucks. It works (I hope), but it's not in any + * sense fast. Here, we do efficient reduction modulo sparse polynomials. + * + * Suppose we have a polynomial @X@ we're trying to reduce mod @P@. If we + * take the topmost nonzero word of @X@, call it @w@, then we can eliminate + * it by subtracting off @w P x^{k}@ for an appropriate value of @k@. The + * trick is in observing that if @P@ is sparse we can do this multiplication + * and subtraction efficiently, just by XORing appropriate shifts of @w@ into + * @X@. + * + * The first tricky bit is in working out when to stop. I'll use eight-bit + * words to demonstrate what I'm talking about. + * + * xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx + * 001ppppp pppppppp pppppppp pppppppp + * || + * |<------------ bp ------------->| + * |<------------ nw --------------->| + * + * The trick of taking whole words off of @X@ stops working when there are + * only @nw@ words left. Then we have to mask off the bottom bits of @w@ + * before continuing. + */ + +/* --- @gfreduce_create@ --- * + * + * Arguments: @gfreduce *r@ = structure to fill in + * @mp *x@ = a (hopefully sparse) polynomial + * + * Returns: --- + * + * Use: Initializes a context structure for reduction. + */ + +void gfreduce_create(gfreduce *r, mp *p) +{ + instr_v iv = DA_INIT; + unsigned long d; + unsigned dw; + mpscan sc; + unsigned long i; + gfreduce_instr *ip; + unsigned f = 0; + size_t w, ww, wi, wl, ll, bb; + + /* --- Sort out the easy stuff --- */ + + d = mp_bits(p); assert(d); d--; + r->lim = d/MPW_BITS; + dw = d%MPW_BITS; + if (!dw) + r->mask = 0; + else { + r->mask = MPW(((mpw)-1) << dw); + r->lim++; + } + r->p = mp_copy(p); + + /* --- Stash a new instruction --- */ + +#define INSTR(op_, arg_) do { \ + DA_ENSURE(&iv, 1); \ + DA(&iv)[DA_LEN(&iv)].op = (op_); \ + DA(&iv)[DA_LEN(&iv)].arg = (arg_); \ + DA_EXTEND(&iv, 1); \ +} while (0) + +#define f_lsr 1u + + w = (d + MPW_BITS - 1)/MPW_BITS; + INSTR(GFRI_LOAD, w); + wi = DA_LEN(&iv); + f = 0; + ll = 0; + bb = MPW_BITS - dw; + for (i = 0, mp_scan(&sc, p); mp_step(&sc) && i < d; i++) { + if (!mp_bit(&sc)) + continue; + ww = (d - i + MPW_BITS - 1)/MPW_BITS; + if (ww != w) { + wl = DA_LEN(&iv); + INSTR(GFRI_STORE, w); + if (!ll) + ll = DA_LEN(&iv); + if (!(f & f_lsr)) + INSTR(GFRI_LOAD, ww); + else { + INSTR(GFRI_LOAD, w - 1); + for (; wi < wl; wi++) { + ip = &DA(&iv)[wi]; + assert(ip->op == GFRI_LSL); + if (ip->arg) + INSTR(GFRI_LSR, MPW_BITS - ip->arg); + } + if (w - 1 != ww) { + INSTR(GFRI_STORE, w - 1); + INSTR(GFRI_LOAD, ww); + } + f &= ~f_lsr; + } + w = ww; + wi = DA_LEN(&iv); + } + INSTR(GFRI_LSL, (bb + i)%MPW_BITS); + if ((bb + i)%MPW_BITS) + f |= f_lsr; + } + wl = DA_LEN(&iv); + INSTR(GFRI_STORE, w); + if (!ll) + ll = DA_LEN(&iv); + if (f & f_lsr) { + INSTR(GFRI_LOAD, w - 1); + for (; wi < wl; wi++) { + ip = &DA(&iv)[wi]; + assert(ip->op == GFRI_LSL); + if (ip->arg) + INSTR(GFRI_LSR, MPW_BITS - ip->arg); + } + INSTR(GFRI_STORE, w - 1); + } + +#undef INSTR + + r->in = DA_LEN(&iv); + r->iv = xmalloc(r->in * sizeof(gfreduce_instr)); + r->liv = r->iv + ll; + memcpy(r->iv, DA(&iv), r->in * sizeof(gfreduce_instr)); + DA_DESTROY(&iv); +} + +/* --- @gfreduce_destroy@ --- * + * + * Arguments: @gfreduce *r@ = structure to free + * + * Returns: --- + * + * Use: Reclaims the resources from a reduction context. + */ + +void gfreduce_destroy(gfreduce *r) +{ + mp_drop(r->p); + xfree(r->iv); +} + +/* --- @gfreduce_dump@ --- * + * + * Arguments: @gfreduce *r@ = structure to dump + * @FILE *fp@ = file to dump on + * + * Returns: --- + * + * Use: Dumps a reduction context. + */ + +void gfreduce_dump(gfreduce *r, FILE *fp) +{ + size_t i; + + fprintf(fp, "poly = "); mp_writefile(r->p, fp, 16); + fprintf(fp, "\n lim = %lu; mask = %lx\n", + (unsigned long)r->lim, (unsigned long)r->mask); + for (i = 0; i < r->in; i++) { + static const char *opname[] = { "load", "lsl", "lsr", "store" }; + assert(r->iv[i].op < N(opname)); + fprintf(fp, " %s %lu\n", + opname[r->iv[i].op], + (unsigned long)r->iv[i].arg); + } +} + +/* --- @gfreduce_do@ --- * + * + * Arguments: @gfreduce *r@ = reduction context + * @mp *d@ = destination + * @mp *x@ = source + * + * Returns: Destination, @x@ reduced modulo the reduction poly. + */ + +static void run(const gfreduce_instr *i, const gfreduce_instr *il, + mpw *v, mpw z) +{ + mpw w = 0; + + for (; i < il; i++) { + switch (i->op) { + case GFRI_LOAD: w = *(v - i->arg); break; + case GFRI_LSL: w ^= z << i->arg; break; + case GFRI_LSR: w ^= z >> i->arg; break; + case GFRI_STORE: *(v - i->arg) = MPW(w); break; + default: abort(); + } + } +} + +mp *gfreduce_do(gfreduce *r, mp *d, mp *x) +{ + mpw *v, *vl; + const gfreduce_instr *il; + mpw z; + + /* --- Try to reuse the source's space --- */ + + MP_COPY(x); + if (d) MP_DROP(d); + MP_DEST(x, MP_LEN(x), x->f); + + /* --- Do the reduction --- */ + + il = r->iv + r->in; + if (MP_LEN(x) >= r->lim) { + v = x->v + r->lim; + vl = x->vl; + while (vl-- > v) { + while (*vl) { + z = *vl; + *vl = 0; + run(r->iv, il, vl, z); + } + } + if (r->mask) { + while (*vl & r->mask) { + z = *vl & r->mask; + *vl &= ~r->mask; + run(r->iv, il, vl, z); + } + } + } + + /* --- Done --- */ + + MP_SHRINK(x); + return (x); +} + +/* --- @gfreduce_sqrt@ --- * + * + * Arguments: @gfreduce *r@ = pointer to reduction context + * @mp *d@ = destination + * @mp *x@ = some polynomial + * + * Returns: The square root of @x@ modulo @r->p@, or null. + */ + +mp *gfreduce_sqrt(gfreduce *r, mp *d, mp *x) +{ + mp *y = MP_COPY(x); + mp *z, *spare = MP_NEW; + unsigned long m = mp_bits(r->p) - 1; + unsigned long i; + + for (i = 0; i < m - 1; i++) { + mp *t = gf_sqr(spare, y); + spare = y; + y = gfreduce_do(r, t, t); + } + z = gf_sqr(spare, y); + z = gfreduce_do(r, z, z); + if (!MP_EQ(x, z)) { + mp_drop(y); + y = 0; + } + mp_drop(z); + mp_drop(d); + return (y); +} + +/* --- @gfreduce_trace@ --- * + * + * Arguments: @gfreduce *r@ = pointer to reduction context + * @mp *x@ = some polynomial + * + * Returns: The trace of @x@. (%$\Tr(x)=x + x^2 + \cdots + x^{2^{m-1}}$% + * if %$x \in \gf{2^m}$%). + */ + +int gfreduce_trace(gfreduce *r, mp *x) +{ + mp *y = MP_COPY(x); + mp *spare = MP_NEW; + unsigned long m = mp_bits(r->p) - 1; + unsigned long i; + int rc; + + for (i = 0; i < m - 1; i++) { + mp *t = gf_sqr(spare, y); + spare = y; + y = gfreduce_do(r, t, t); + y = gf_add(y, y, x); + } + rc = !MP_ZEROP(y); + mp_drop(spare); + mp_drop(y); + return (rc); +} + +/* --- @gfreduce_halftrace@ --- * + * + * Arguments: @gfreduce *r@ = pointer to reduction context + * @mp *d@ = destination + * @mp *x@ = some polynomial + * + * Returns: The half-trace of @x@. + * (%$\HfTr(x)= x + x^{2^2} + \cdots + x^{2^{m-1}}$% + * if %$x \in \gf{2^m}$% with %$m$% odd). + */ + +mp *gfreduce_halftrace(gfreduce *r, mp *d, mp *x) +{ + mp *y = MP_COPY(x); + mp *spare = MP_NEW; + unsigned long m = mp_bits(r->p) - 1; + unsigned long i; + + mp_drop(d); + for (i = 0; i < m - 1; i += 2) { + mp *t = gf_sqr(spare, y); + spare = y; + y = gfreduce_do(r, t, t); + t = gf_sqr(spare, y); + spare = y; + y = gfreduce_do(r, t, t); + y = gf_add(y, y, x); + } + mp_drop(spare); + return (y); +} + +/* --- @gfreduce_quadsolve@ --- * + * + * Arguments: @gfreduce *r@ = pointer to reduction context + * @mp *d@ = destination + * @mp *x@ = some polynomial + * + * Returns: A polynomial @y@ such that %$y^2 + y = x$%, or null. + */ + +mp *gfreduce_quadsolve(gfreduce *r, mp *d, mp *x) +{ + unsigned long m = mp_bits(r->p) - 1; + mp *t; + + MP_COPY(x); + if (m & 1) + d = gfreduce_halftrace(r, d, x); + else { + mp *z, *w, *rho = MP_NEW; + mp *spare = MP_NEW; + grand *fr = fibrand_create(0); + unsigned long i; + + for (;;) { + rho = mprand(rho, m, fr, 0); + z = MP_ZERO; + w = MP_COPY(rho); + for (i = 0; i < m - 1; i++) { + t = gf_sqr(spare, z); spare = z; z = gfreduce_do(r, t, t); + t = gf_sqr(spare, w); spare = w; w = gfreduce_do(r, t, t); + t = gf_mul(spare, w, x); t = gfreduce_do(r, t, t); spare = t; + z = gf_add(z, z, t); + w = gf_add(w, w, rho); + } + if (!MP_ZEROP(w)) + break; + MP_DROP(z); + MP_DROP(w); + } + if (d) MP_DROP(d); + MP_DROP(w); + MP_DROP(spare); + MP_DROP(rho); + fr->ops->destroy(fr); + d = z; + } + + t = gf_sqr(MP_NEW, d); t = gfreduce_do(r, t, t); t = gf_add(t, t, d); + if (!MP_EQ(t, x)) { + MP_DROP(d); + d = 0; + } + MP_DROP(t); + MP_DROP(x); + if (d) d->v[0] &= ~(mpw)1; + return (d); +} + +/* --- @gfreduce_exp@ --- * + * + * Arguments: @gfreduce *gr@ = pointer to reduction context + * @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e \bmod m$%. + */ + +mp *gfreduce_exp(gfreduce *gr, mp *d, mp *a, mp *e) +{ + mp *x = MP_ONE; + mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; + + MP_SHRINK(e); + MP_COPY(a); + if (MP_ZEROP(e)) + ; + else { + if (MP_NEGP(e)) + a = gf_modinv(a, a, gr->p); + if (MP_LEN(e) < EXP_THRESH) + EXP_SIMPLE(x, a, e); + else + EXP_WINDOW(x, a, e); + } + mp_drop(d); + mp_drop(a); + mp_drop(spare); + return (x); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#define MP(x) mp_readstring(MP_NEW, #x, 0, 0) + +static int vreduce(dstr *v) +{ + mp *d = *(mp **)v[0].buf; + mp *n = *(mp **)v[1].buf; + mp *r = *(mp **)v[2].buf; + mp *c; + int ok = 1; + gfreduce rr; + + gfreduce_create(&rr, d); + c = gfreduce_do(&rr, MP_NEW, n); + if (!MP_EQ(c, r)) { + fprintf(stderr, "\n*** reduction failed\n*** "); + gfreduce_dump(&rr, stderr); + fprintf(stderr, "\n*** n = "); mp_writefile(n, stderr, 16); + fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16); + fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16); + fprintf(stderr, "\n"); + ok = 0; + } + gfreduce_destroy(&rr); + mp_drop(n); mp_drop(d); mp_drop(r); mp_drop(c); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vmodexp(dstr *v) +{ + mp *p = *(mp **)v[0].buf; + mp *g = *(mp **)v[1].buf; + mp *x = *(mp **)v[2].buf; + mp *r = *(mp **)v[3].buf; + mp *c; + int ok = 1; + gfreduce rr; + + gfreduce_create(&rr, p); + c = gfreduce_exp(&rr, MP_NEW, g, x); + if (!MP_EQ(c, r)) { + fprintf(stderr, "\n*** modexp failed\n*** "); + fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16); + fprintf(stderr, "\n*** g = "); mp_writefile(g, stderr, 16); + fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16); + fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16); + fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16); + fprintf(stderr, "\n"); + ok = 0; + } + gfreduce_destroy(&rr); + mp_drop(p); mp_drop(g); mp_drop(r); mp_drop(x); mp_drop(c); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vsqrt(dstr *v) +{ + mp *p = *(mp **)v[0].buf; + mp *x = *(mp **)v[1].buf; + mp *r = *(mp **)v[2].buf; + mp *c; + int ok = 1; + gfreduce rr; + + gfreduce_create(&rr, p); + c = gfreduce_sqrt(&rr, MP_NEW, x); + if (!MP_EQ(c, r)) { + fprintf(stderr, "\n*** sqrt failed\n*** "); + fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16); + fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16); + fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16); + fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16); + fprintf(stderr, "\n"); + ok = 0; + } + gfreduce_destroy(&rr); + mp_drop(p); mp_drop(r); mp_drop(x); mp_drop(c); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vtr(dstr *v) +{ + mp *p = *(mp **)v[0].buf; + mp *x = *(mp **)v[1].buf; + int r = *(int *)v[2].buf, c; + int ok = 1; + gfreduce rr; + + gfreduce_create(&rr, p); + c = gfreduce_trace(&rr, x); + if (c != r) { + fprintf(stderr, "\n*** trace failed\n*** "); + fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16); + fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16); + fprintf(stderr, "\n*** c = %d", c); + fprintf(stderr, "\n*** r = %d", r); + fprintf(stderr, "\n"); + ok = 0; + } + gfreduce_destroy(&rr); + mp_drop(p); mp_drop(x); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vhftr(dstr *v) +{ + mp *p = *(mp **)v[0].buf; + mp *x = *(mp **)v[1].buf; + mp *r = *(mp **)v[2].buf; + mp *c; + int ok = 1; + gfreduce rr; + + gfreduce_create(&rr, p); + c = gfreduce_halftrace(&rr, MP_NEW, x); + if (!MP_EQ(c, r)) { + fprintf(stderr, "\n*** halftrace failed\n*** "); + fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16); + fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16); + fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16); + fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16); + fprintf(stderr, "\n"); + ok = 0; + } + gfreduce_destroy(&rr); + mp_drop(p); mp_drop(r); mp_drop(x); mp_drop(c); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vquad(dstr *v) +{ + mp *p = *(mp **)v[0].buf; + mp *x = *(mp **)v[1].buf; + mp *r = *(mp **)v[2].buf; + mp *c; + int ok = 1; + gfreduce rr; + + gfreduce_create(&rr, p); + c = gfreduce_quadsolve(&rr, MP_NEW, x); + if (!MP_EQ(c, r)) { + fprintf(stderr, "\n*** quadsolve failed\n*** "); + fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16); + fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16); + fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16); + fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16); + fprintf(stderr, "\n"); + ok = 0; + } + gfreduce_destroy(&rr); + mp_drop(p); mp_drop(r); mp_drop(x); mp_drop(c); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk defs[] = { + { "reduce", vreduce, { &type_mp, &type_mp, &type_mp, 0 } }, + { "modexp", vmodexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, + { "sqrt", vsqrt, { &type_mp, &type_mp, &type_mp, 0 } }, + { "trace", vtr, { &type_mp, &type_mp, &type_int, 0 } }, + { "halftrace", vhftr, { &type_mp, &type_mp, &type_mp, 0 } }, + { "quadsolve", vquad, { &type_mp, &type_mp, &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/t/gfreduce"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/gfreduce.h b/math/gfreduce.h new file mode 100644 index 0000000..2c8a884 --- /dev/null +++ b/math/gfreduce.h @@ -0,0 +1,176 @@ +/* -*-c-*- + * + * Reduction modulo sparse binary polynomials + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GFREDUCE_H +#define CATACOMB_GFREDUCE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GF_H +# include "gf.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct gfreduce_instr { + unsigned op; /* Instruction opcode */ + size_t arg; /* Immediate argument */ +} gfreduce_instr; + +enum { + GFRI_LOAD, /* Load @p[arg]@ */ + GFRI_LSL, /* XOR with @w << arg@ */ + GFRI_LSR, /* XOR with @w >> arg@ */ + GFRI_STORE, /* Store @p[arg]@ */ + GFRI_MAX +}; + +typedef struct gfreduce { + size_t lim; /* Word of degree bit */ + mpw mask; /* Mask for degree word */ + mp *p; /* Copy of the polynomial */ + size_t in; /* Number of instruction words */ + gfreduce_instr *iv, *liv; /* Vector of instructions */ +} gfreduce; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @gfreduce_create@ --- * + * + * Arguments: @gfreduce *r@ = structure to fill in + * @mp *x@ = a (hopefully sparse) polynomial + * + * Returns: --- + * + * Use: Initializes a context structure for reduction. + */ + +extern void gfreduce_create(gfreduce */*r*/, mp */*p*/); + +/* --- @gfreduce_destroy@ --- * + * + * Arguments: @gfreduce *r@ = structure to free + * + * Returns: --- + * + * Use: Reclaims the resources from a reduction context. + */ + +extern void gfreduce_destroy(gfreduce */*r*/); + +/* --- @gfreduce_dump@ --- * + * + * Arguments: @gfreduce *r@ = structure to dump + * @FILE *fp@ = file to dump on + * + * Returns: --- + * + * Use: Dumps a reduction context. + */ + +extern void gfreduce_dump(gfreduce */*r*/, FILE */*fp*/); + +/* --- @gfreduce_do@ --- * + * + * Arguments: @gfreduce *r@ = reduction context + * @mp *d@ = destination + * @mp *x@ = source + * + * Returns: Destination, @x@ reduced modulo the reduction poly. + */ + +extern mp *gfreduce_do(gfreduce */*r*/, mp */*d*/, mp */*x*/); + +/* --- @gfreduce_sqrt@ --- * + * + * Arguments: @gfreduce *r@ = pointer to reduction context + * @mp *d@ = destination + * @mp *x@ = some polynomial + * + * Returns: The square root of @x@ modulo @r->p@, or null. + */ + +extern mp *gfreduce_sqrt(gfreduce */*r*/, mp */*d*/, mp */*x*/); + +/* --- @gfreduce_trace@ --- * + * + * Arguments: @gfreduce *r@ = pointer to reduction context + * @mp *x@ = some polynomial + * + * Returns: The trace of @x@. (%$\Tr(x)=x + x^2 + \cdots + x^{2^{m-1}}$% + * if %$x \in \gf{2^m}$%). + */ + +extern int gfreduce_trace(gfreduce */*r*/, mp */*x*/); + +/* --- @gfreduce_halftrace@ --- * + * + * Arguments: @gfreduce *r@ = pointer to reduction context + * @mp *d@ = destination + * @mp *x@ = some polynomial + * + * Returns: The half-trace of @x@. + * (%$\HfTr(x)= x + x^{2^2} + \cdots + x^{2^{m-1}}$% + * if %$x \in \gf{2^m}$% with %$m$% odd). + */ + +extern mp *gfreduce_halftrace(gfreduce */*r*/, mp */*d*/, mp */*x*/); + +/* --- @gfreduce_quadsolve@ --- * + * + * Arguments: @gfreduce *r@ = pointer to reduction context + * @mp *d@ = destination + * @mp *x@ = some polynomial + * + * Returns: A polynomial @y@ such that %$y^2 + y = x$%, or null. + */ + +extern mp *gfreduce_quadsolve(gfreduce */*r*/, mp */*d*/, mp */*x*/); + +/* --- @gfreduce_exp@ --- * + * + * Arguments: @gfreduce *gr@ = pointer to reduction context + * @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e \bmod m$%. + */ + +extern mp *gfreduce_exp(gfreduce */*gr*/, mp */*d*/, mp */*a*/, mp */*e*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/gfx-kmul.c b/math/gfx-kmul.c new file mode 100644 index 0000000..5a5838a --- /dev/null +++ b/math/gfx-kmul.c @@ -0,0 +1,247 @@ +/* -*-c-*- + * + * Karatsuba's multiplication algorithm on binary polynomials + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include "gfx.h" +#include "karatsuba.h" + +/*----- Tweakables --------------------------------------------------------*/ + +#ifdef TEST_RIG +# undef GFK_THRESH +# define GFK_THRESH 1 +#endif + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gfx_kmul@ --- * + * + * Arguments: @mpw *dv, *dvl@ = pointer to destination buffer + * @const mpw *av, *avl@ = pointer to first argument + * @const mpw *bv, *bvl@ = pointer to second argument + * @mpw *sv, *svl@ = pointer to scratch workspace + * + * Returns: --- + * + * Use: Multiplies two binary polynomials using Karatsuba's + * algorithm. This is rather faster than traditional long + * multiplication (e.g., @gfx_umul@) on polynomials with large + * degree, although more expensive on small ones. + * + * The destination must be twice as large as the larger + * argument. The scratch space must be twice as large as the + * larger argument. + */ + +void gfx_kmul(mpw *dv, mpw *dvl, + const mpw *av, const mpw *avl, + const mpw *bv, const mpw *bvl, + mpw *sv, mpw *svl) +{ + const mpw *avm, *bvm; + size_t m; + + /* --- Dispose of easy cases to @mpx_umul@ --- * + * + * Karatsuba is only a win on large numbers, because of all the + * recursiveness and bookkeeping. The recursive calls make a quick check + * to see whether to bottom out to @gfx_umul@ which should help quite a + * lot, but sometimes the only way to know is to make sure... + */ + + MPX_SHRINK(av, avl); + MPX_SHRINK(bv, bvl); + + if (avl - av <= GFK_THRESH || bvl - bv <= GFK_THRESH) { + gfx_mul(dv, dvl, av, avl, bv, bvl); + return; + } + + /* --- How the algorithm works --- * + * + * Let %$A = xb + y$% and %$B = ub + v$%. Then, simply by expanding, + * %$AB = x u b^2 + b(x v + y u) + y v$%. That's not helped any, because + * I've got four multiplications, each four times easier than the one I + * started with. However, note that I can rewrite the coefficient of %$b$% + * as %$xv + yu = (x + y)(u + v) - xu - yv$%. The terms %$xu$% and %$yv$% + * I've already calculated, and that leaves only one more multiplication to + * do. So now I have three multiplications, each four times easier, and + * that's a win. + */ + + /* --- First things --- * + * + * Sort out where to break the factors in half. I'll choose the midpoint + * of the larger one, since this minimizes the amount of work I have to do + * most effectively. + */ + + if (avl - av > bvl - bv) { + m = (avl - av + 1) >> 1; + avm = av + m; + if (bvl - bv > m) + bvm = bv + m; + else + bvm = bvl; + } else { + m = (bvl - bv + 1) >> 1; + bvm = bv + m; + if (avl - av > m) + avm = av + m; + else + avm = avl; + } + + /* --- Sort out the middle term --- */ + + { + mpw *bsv = sv + m, *ssv = bsv + m; + mpw *rdv = dv + m, *rdvl = rdv + 2 * m; + + assert(rdvl <= dvl); + assert(ssv <= svl); + UXOR2(sv, bsv, av, avm, avm, avl); + UXOR2(bsv, ssv, bv, bvm, bvm, bvl); + if (m > GFK_THRESH) + gfx_kmul(rdv, rdvl, sv, bsv, bsv, ssv, ssv, svl); + else + gfx_mul(rdv, rdvl, sv, bsv, bsv, ssv); + } + + /* --- Sort out the other two terms --- */ + + { + mpw *svm = sv + m, *ssv = svm + m; + mpw *tdv = dv + m; + mpw *rdv = tdv + m; + + if (avl == avm || bvl == bvm) + MPX_ZERO(rdv + m, dvl); + else { + if (m > GFK_THRESH) + gfx_kmul(sv, ssv, avm, avl, bvm, bvl, ssv, svl); + else + gfx_mul(sv, ssv, avm, avl, bvm, bvl); + MPX_COPY(rdv + m, dvl, svm, ssv); + UXOR(rdv, sv, svm); + UXOR(tdv, sv, ssv); + } + + if (m > GFK_THRESH) + gfx_kmul(sv, ssv, av, avm, bv, bvm, ssv, svl); + else + gfx_mul(sv, ssv, av, avm, bv, bvm); + MPX_COPY(dv, tdv, sv, svm); + UXOR(tdv, sv, ssv); + UXOR(tdv, svm, ssv); + } +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include +#include + +#define ALLOC(v, vl, sz) do { \ + size_t _sz = (sz); \ + mpw *_vv = xmalloc(MPWS(_sz)); \ + mpw *_vvl = _vv + _sz; \ + (v) = _vv; \ + (vl) = _vvl; \ +} while (0) + +#define LOAD(v, vl, d) do { \ + const dstr *_d = (d); \ + mpw *_v, *_vl; \ + ALLOC(_v, _vl, MPW_RQ(_d->len)); \ + mpx_loadb(_v, _vl, _d->buf, _d->len); \ + (v) = _v; \ + (vl) = _vl; \ +} while (0) + +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +static void dumpmp(const char *msg, const mpw *v, const mpw *vl) +{ + fputs(msg, stderr); + MPX_SHRINK(v, vl); + while (v < vl) + fprintf(stderr, " %08lx", (unsigned long)*--vl); + fputc('\n', stderr); +} + +static int mul(dstr *v) +{ + mpw *a, *al; + mpw *b, *bl; + mpw *c, *cl; + mpw *d, *dl; + mpw *s, *sl; + size_t m; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(b, bl, &v[1]); + LOAD(c, cl, &v[2]); + m = MAX(al - a, bl - b) + 1; + ALLOC(d, dl, 2 * m); + ALLOC(s, sl, 2 * m); + + gfx_kmul(d, dl, a, al, b, bl, s, sl); + if (!mpx_ueq(d, dl, c, cl)) { + fprintf(stderr, "\n*** mul failed\n"); + dumpmp(" a", a, al); + dumpmp(" b", b, bl); + dumpmp("expected", c, cl); + dumpmp(" result", d, dl); + ok = 0; + } + + xfree(a); xfree(b); xfree(c); xfree(d); xfree(s); + return (ok); +} + +static test_chunk defs[] = { + { "mul", mul, { &type_hex, &type_hex, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/t/gfx"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/gfx-sqr-mktab.c b/math/gfx-sqr-mktab.c new file mode 100644 index 0000000..1ecd995 --- /dev/null +++ b/math/gfx-sqr-mktab.c @@ -0,0 +1,89 @@ +/* -*-c-*- + * + * Build table for squaring of binary polynomials + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +/*----- Main code ---------------------------------------------------------*/ + +static void mktab(uint16 *t) +{ + unsigned i, j, x; + + for (i = 0; i < 256; i++) { + x = 0; + for (j = 0; j < 8; j++) { + if (i & (1 << j)) + x |= 1 << (2 * j); + } + t[i] = x; + } +} + +int main(void) +{ + uint16 t[256]; + unsigned i; + + mktab(t); +fputs("\ +/* -*-c-*-\n\ + *\n\ + * Bit spacing table for binary polynomial squaring\n\ + */\n\ +\n\ +#ifndef GFX_SQR_TAB_H\n\ +#define GFX_SQR_TAB_H\n\ +\n\ +#define GFX_SQRTAB { \\\n\ + ", stdout); + + for (i = 0; i < 256; i++) { + printf("0x%04x", t[i]); + if (i == 255) + puts(" \\\n}\n"); + else if (i % 8 == 7) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + fputs("#endif\n", stdout); + + if (fclose(stdout)) { + fprintf(stderr, "error writing data\n"); + exit(EXIT_FAILURE); + } + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/gfx-sqr.c b/math/gfx-sqr.c new file mode 100644 index 0000000..8e26f36 --- /dev/null +++ b/math/gfx-sqr.c @@ -0,0 +1,212 @@ +/* -*-c-*- + * + * Sqaring binary polynomials + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mpx.h" +#include "gfx.h" +#include "gfx-sqr-tab.h" + +/*----- Static variables --------------------------------------------------*/ + +static const uint16 tab[256] = GFX_SQRTAB; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gfx_sqr@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = argument vector base and limit + * + * Returns: --- + * + * Use: Performs squaring of binary polynomials. + */ + +void gfx_sqr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl) +{ + mpd a = 0, aa = 0; + unsigned b = 0, bb = 0; + + /* --- Simple stuff --- */ + + if (dv >= dvl) + return; + MPX_SHRINK(av, avl); + + /* --- The main algorithm --- * + * + * Our method depends on the fact that, in a field of characteristic 2, we + * have that %$(a + b)^2 = a^2 + b^2$%. Thus, to square a polynomial, it's + * sufficient just to put a zero bit between each of the bits of the + * original argument. We use a precomputed table for this, and work on + * entire octets at a time. Life is more complicated because we've got to + * be careful of bizarre architectures which don't have words with a + * multiple of 8 bits in them. + */ + + for (;;) { + + /* --- Input buffering --- */ + + if (b < 8) { + if (av >= avl) + break; + a |= *av++ << b; + b += MPW_BITS; + } + + /* --- Do the work in the middle --- */ + + aa |= (mpd)(tab[U8(a)]) << bb; + bb += 16; + a >>= 8; + b -= 8; + + /* --- Output buffering --- */ + + if (bb >= MPW_BITS) { + *dv++ = MPW(aa); + if (dv >= dvl) + return; + aa >>= MPW_BITS; + bb -= MPW_BITS; + } + } + + /* --- Flush the input buffer --- */ + + if (b) for (;;) { + aa |= (mpd)(tab[U8(a)]) << bb; + bb += 16; + if (bb > MPW_BITS) { + *dv++ = MPW(aa); + if (dv >= dvl) + return; + aa >>= MPW_BITS; + bb -= MPW_BITS; + } + a >>= 8; + if (b <= 8) + break; + else + b -= 8; + } + + /* --- Flush the output buffer --- */ + + if (bb) for (;;) { + *dv++ = MPW(aa); + if (dv >= dvl) + return; + aa >>= MPW_BITS; + if (bb <= MPW_BITS) + break; + else + bb -= MPW_BITS; + } + + /* --- Zero the rest of everything --- */ + + MPX_ZERO(dv, dvl); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include +#include +#include +#include + +#define ALLOC(v, vl, sz) do { \ + size_t _sz = (sz); \ + mpw *_vv = xmalloc(MPWS(_sz)); \ + mpw *_vvl = _vv + _sz; \ + (v) = _vv; \ + (vl) = _vvl; \ +} while (0) + +#define LOAD(v, vl, d) do { \ + const dstr *_d = (d); \ + mpw *_v, *_vl; \ + ALLOC(_v, _vl, MPW_RQ(_d->len)); \ + mpx_loadb(_v, _vl, _d->buf, _d->len); \ + (v) = _v; \ + (vl) = _vl; \ +} while (0) + +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +static void dumpmp(const char *msg, const mpw *v, const mpw *vl) +{ + fputs(msg, stderr); + MPX_SHRINK(v, vl); + while (v < vl) + fprintf(stderr, " %08lx", (unsigned long)*--vl); + fputc('\n', stderr); +} + +static int vsqr(dstr *v) +{ + mpw *a, *al; + mpw *b, *bl; + mpw *d, *dl; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(b, bl, &v[1]); + ALLOC(d, dl, 2 * (al - a)); + + gfx_sqr(d, dl, a, al); + if (!mpx_ueq(d, dl, b, bl)) { + fprintf(stderr, "\n*** vsqr failed\n"); + dumpmp(" a", a, al); + dumpmp("expected", b, bl); + dumpmp(" result", d, dl); + ok = 0; + } + + xfree(a); xfree(b); xfree(d); + return (ok); +} + +static test_chunk defs[] = { + { "sqr", vsqr, { &type_hex, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/t/gfx"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/gfx.c b/math/gfx.c new file mode 100644 index 0000000..56bea48 --- /dev/null +++ b/math/gfx.c @@ -0,0 +1,387 @@ +/* -*-c-*- + * + * Low-level arithmetic on binary polynomials + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "mpx.h" +#include "mpscan.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gfx_add@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = first addend vector base and limit + * @const mpw *bv, *bvl@ = second addend vector base and limit + * + * Returns: --- + * + * Use: Adds two %$\gf{2}$% polynomials. This is the same as + * subtraction. + */ + +void gfx_add(mpw *dv, mpw *dvl, + const mpw *av, const mpw *avl, + const mpw *bv, const mpw *bvl) +{ + MPX_SHRINK(av, avl); + MPX_SHRINK(bv, bvl); + + while (av < avl || bv < bvl) { + mpw a, b; + if (dv >= dvl) + return; + a = (av < avl) ? *av++ : 0; + b = (bv < bvl) ? *bv++ : 0; + *dv++ = a ^ b; + } + if (dv < dvl) + MPX_ZERO(dv, dvl); +} + +/* --- @gfx_acc@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = addend vector base and limit + * + * Returns: --- + * + * Use: Adds the addend into the destination. This is considerably + * faster than the three-address add call. + */ + +void gfx_acc(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl) +{ + size_t dlen, alen; + + MPX_SHRINK(av, avl); + dlen = dvl - dv; + alen = avl - av; + if (dlen < alen) + avl = av + dlen; + while (av < avl) + *dv++ ^= *av++; +} + +/* --- @gfx_accshift@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = addend vector base and limit + * @size_t n@ = number of bits to shift + * + * Returns: --- + * + * Use: Shifts the argument left by %$n$% places and adds it to the + * destination. This is a primitive used by multiplication and + * division. + */ + +void gfx_accshift(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n) +{ + size_t c = n / MPW_BITS; + mpw x = 0, y; + size_t dlen, alen; + + /* --- Sort out the shift amounts --- */ + + if (dvl - dv < c) + return; + dv += c; + n %= MPW_BITS; + if (!n) { + gfx_acc(dv, dvl, av, avl); + return; + } + c = MPW_BITS - n; + + /* --- Sort out vector lengths --- */ + + MPX_SHRINK(av, avl); + dlen = dvl - dv; + alen = avl - av; + if (dlen < alen) + avl = av + dlen; + + /* --- Now do the hard work --- */ + + while (av < avl) { + y = *av++; + *dv++ ^= MPW((y << n) | (x >> c)); + x = y; + } + if (dv < dvl) + *dv++ ^= x >> c; +} + +/* --- @gfx_mul@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = first argument vector base and limit + * @const mpw *bv, *bvl@ = second argument vector base and limit + * + * Returns: --- + * + * Use: Does multiplication of polynomials over %$\gf{2}$%. + */ + +void gfx_mul(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, + const mpw *bv, const mpw *bvl) +{ + mpscan sc; + const mpw *v; + mpw *vv; + mpw z; + mpd x, y; + + MPX_SHRINK(av, avl); + MPX_SHRINK(bv, bvl); + MPSCAN_INITX(&sc, av, avl); + MPX_ZERO(dv, dvl); + + while (bv < bvl && dv < dvl) { + x = 0; + for (v = av, vv = dv++; v < avl && vv < dvl; v++) { + z = *bv; y = *v; + while (z) { + if (z & 1u) x ^= y; + z >>= 1; y <<= 1; + } + *vv++ ^= MPW(x); + x >>= MPW_BITS; + } + if (vv < dvl) + *vv++ = MPW(x); + bv++; + } +} + +/* --- @gfx_div@ --- * + * + * Arguments: @mpw *qv, *qvl@ = quotient vector base and limit + * @mpw *rv, *rvl@ = dividend/remainder vector base and limit + * @const mpw *dv, *dvl@ = divisor vector base and limit + * + * Returns: --- + * + * Use: Performs division on polynomials over %$\gf{2}$%. + */ + +void gfx_div(mpw *qv, mpw *qvl, mpw *rv, mpw *rvl, + const mpw *dv, const mpw *dvl) +{ + size_t dlen, rlen, qlen; + size_t dbits; + mpw *rvv, *rvd; + unsigned rvm, n, qi; + mpw q; + + MPX_SHRINK(rv, rvl); + MPX_SHRINK(dv, dvl); + assert(((void)"division by zero in gfx_div", dv < dvl)); + MPX_BITS(dbits, dv, dvl); + dlen = dvl - dv; + rlen = rvl - rv; + qlen = qvl - qv; + + MPX_ZERO(qv, qvl); + if (dlen > rlen) + return; + rvd = rvl - dlen; + rvv = rvl - 1; + rvm = 1 << (MPW_BITS - 1); + n = MPW_BITS - (dbits % MPW_BITS); + if (n == MPW_BITS) + n = 0; + q = 0; + qi = rvd - rv; + + for (;;) { + q <<= 1; + if (*rvv & rvm) { + q |= 1; + gfx_accshift(rvd, rvl, dv, dvl, n); + } + rvm >>= 1; + if (!rvm) { + rvm = 1 << (MPW_BITS - 1); + rvv--; + } + if (n) + n--; + else { + if (qi < qlen) + qv[qi] = q; + q = 0; + qi--; + if (rvd == rv) + break; + n = MPW_BITS - 1; + rvd--; + } + } +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include +#include +#include +#include + +#define ALLOC(v, vl, sz) do { \ + size_t _sz = (sz); \ + mpw *_vv = xmalloc(MPWS(_sz)); \ + mpw *_vvl = _vv + _sz; \ + (v) = _vv; \ + (vl) = _vvl; \ +} while (0) + +#define LOAD(v, vl, d) do { \ + const dstr *_d = (d); \ + mpw *_v, *_vl; \ + ALLOC(_v, _vl, MPW_RQ(_d->len)); \ + mpx_loadb(_v, _vl, _d->buf, _d->len); \ + (v) = _v; \ + (vl) = _vl; \ +} while (0) + +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +static void dumpmp(const char *msg, const mpw *v, const mpw *vl) +{ + fputs(msg, stderr); + MPX_SHRINK(v, vl); + while (v < vl) + fprintf(stderr, " %08lx", (unsigned long)*--vl); + fputc('\n', stderr); +} + +static int vadd(dstr *v) +{ + mpw *a, *al; + mpw *b, *bl; + mpw *c, *cl; + mpw *d, *dl; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(b, bl, &v[1]); + LOAD(c, cl, &v[2]); + ALLOC(d, dl, MAX(al - a, bl - b) + 1); + + gfx_add(d, dl, a, al, b, bl); + if (!mpx_ueq(d, dl, c, cl)) { + fprintf(stderr, "\n*** vadd failed\n"); + dumpmp(" a", a, al); + dumpmp(" b", b, bl); + dumpmp("expected", c, cl); + dumpmp(" result", d, dl); + ok = 0; + } + + xfree(a); xfree(b); xfree(c); xfree(d); + return (ok); +} + +static int vmul(dstr *v) +{ + mpw *a, *al; + mpw *b, *bl; + mpw *c, *cl; + mpw *d, *dl; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(b, bl, &v[1]); + LOAD(c, cl, &v[2]); + ALLOC(d, dl, (al - a) + (bl - b)); + + gfx_mul(d, dl, a, al, b, bl); + if (!mpx_ueq(d, dl, c, cl)) { + fprintf(stderr, "\n*** vmul failed\n"); + dumpmp(" a", a, al); + dumpmp(" b", b, bl); + dumpmp("expected", c, cl); + dumpmp(" result", d, dl); + ok = 0; + } + + xfree(a); xfree(b); xfree(c); xfree(d); + return (ok); +} + +static int vdiv(dstr *v) +{ + mpw *a, *al; + mpw *b, *bl; + mpw *q, *ql; + mpw *r, *rl; + mpw *qq, *qql; + int ok = 1; + + ALLOC(a, al, MPW_RQ(v[0].len) + 2); mpx_loadb(a, al, v[0].buf, v[0].len); + LOAD(b, bl, &v[1]); + LOAD(q, ql, &v[2]); + LOAD(r, rl, &v[3]); + ALLOC(qq, qql, al - a); + + gfx_div(qq, qql, a, al, b, bl); + if (!mpx_ueq(qq, qql, q, ql) || + !mpx_ueq(a, al, r, rl)) { + fprintf(stderr, "\n*** vdiv failed\n"); + dumpmp(" divisor", b, bl); + dumpmp("expect r", r, rl); + dumpmp("result r", a, al); + dumpmp("expect q", q, ql); + dumpmp("result q", qq, qql); + ok = 0; + } + + xfree(a); xfree(b); xfree(r); xfree(q); xfree(qq); + return (ok); +} + +static test_chunk defs[] = { + { "add", vadd, { &type_hex, &type_hex, &type_hex, 0 } }, + { "mul", vmul, { &type_hex, &type_hex, &type_hex, 0 } }, + { "div", vdiv, { &type_hex, &type_hex, &type_hex, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/t/gfx"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/gfx.h b/math/gfx.h new file mode 100644 index 0000000..214ec2b --- /dev/null +++ b/math/gfx.h @@ -0,0 +1,173 @@ +/* -*-c-*- + * + * Low-level arithmetic on binary polynomials + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GFX_H +#define CATACOMB_GFX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MPX_H +# include "mpx.h" +#endif + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @gfx_add@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = first addend vector base and limit + * @const mpw *bv, *bvl@ = second addend vector base and limit + * + * Returns: --- + * + * Use: Adds two %$\gf{2}$% polynomials. This is the same as + * subtraction. + */ + +extern void gfx_add(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, + const mpw */*bv*/, const mpw */*bvl*/); + +/* --- @gfx_acc@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = addend vector base and limit + * + * Returns: --- + * + * Use: Adds the addend into the destination. This is considerably + * faster than the three-address add call. + */ + +extern void gfx_acc(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/); + +/* --- @gfx_accshift@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = addend vector base and limit + * @size_t n@ = number of bits to shift + * + * Returns: --- + * + * Use: Shifts the argument left by %$n$% places and adds it to the + * destination. This is a primitive used by multiplication and + * division. + */ + +extern void gfx_accshift(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, + size_t /*n*/); + +/* --- @gfx_mul@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = first argument vector base and limit + * @const mpw *bv, *bvl@ = second argument vector base and limit + * + * Returns: --- + * + * Use: Does multiplication of polynomials over %$\gf{2}$%. + */ + +extern void gfx_mul(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, + const mpw */*bv*/, const mpw */*bvl*/); + +/* --- @gfx_sqr@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = argument vector base and limit + * + * Returns: --- + * + * Use: Performs squaring of binary polynomials. + */ + +extern void gfx_sqr(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/); + +/* --- @gfx_div@ --- * + * + * Arguments: @mpw *qv, *qvl@ = quotient vector base and limit + * @mpw *rv, *rvl@ = dividend/remainder vector base and limit + * @const mpw *dv, *dvl@ = divisor vector base and limit + * + * Returns: --- + * + * Use: Performs division on polynomials over %$\gf{2}$%. + */ + +extern void gfx_div(mpw */*qv*/, mpw */*qvl*/, mpw */*rv*/, mpw */*rvl*/, + const mpw */*dv*/, const mpw */*dvl*/); + +/*----- Karatsuba multiplication algorithms -------------------------------*/ + +/* --- @GFK_THRESH@ --- * + * + * This is the limiting length for using Karatsuba algorithms. It's best to + * use the simpler classical multiplication method on numbers smaller than + * this. + */ + +#define GFK_THRESH 2 + +/* --- @gfx_kmul@ --- * + * + * Arguments: @mpw *dv, *dvl@ = pointer to destination buffer + * @const mpw *av, *avl@ = pointer to first argument + * @const mpw *bv, *bvl@ = pointer to second argument + * @mpw *sv, *svl@ = pointer to scratch workspace + * + * Returns: --- + * + * Use: Multiplies two binary polynomials using Karatsuba's + * algorithm. This is rather faster than traditional long + * multiplication (e.g., @gfx_umul@) on polynomials with large + * degree, although more expensive on small ones. + * + * The destination must be twice as large as the larger + * argument. The scratch space must be twice as large as the + * larger argument. + */ + +extern void gfx_kmul(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, + const mpw */*bv*/, const mpw */*bvl*/, + mpw */*sv*/, mpw */*svl*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/group-dstr.c b/math/group-dstr.c new file mode 100644 index 0000000..4714183 --- /dev/null +++ b/math/group-dstr.c @@ -0,0 +1,83 @@ +/* -*-c-*- + * + * Dynamic string I/O for group elements + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "group.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @group_readdstr@ --- * + * + * Arguments: @group *g@ = an abstract group + * @ge *d@ = destination group element + * @dstr *dd@ = string to read from + * @size_t *off@ = offset to start at (updated) + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Parses a group element from a dynamic string. + */ + +int group_readdstr(group *g, ge *d, dstr *dd, size_t *off) +{ + mptext_dstrctx md; + + md.d = dd; + md.i = off ? *off : 0; + if (G_READ(g, d, &mptext_dstrops, &md)) + return (-1); + if (off) *off = md.i; + return (0); +} + +/* --- @group_writedstr@ --- * + * + * Arguments: @group *g@ = an abstract group + * @ge *x@ = a group element + * @dstr *d@ = string to write to + * @size_t sz@ = how long the buffer is + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Writes a group element to a dstr buffer. + */ + +int group_writedstr(group *g, ge *x, dstr *d) +{ + mptext_dstrctx md; + + md.d = d; + if (G_WRITE(g, x, &mptext_dstrops, &md)) + return (-1); + DPUTZ(d); + return (0); +} + + + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/group-exp.c b/math/group-exp.c new file mode 100644 index 0000000..083da9e --- /dev/null +++ b/math/group-exp.c @@ -0,0 +1,107 @@ +/* -*-c-*- + * + * Exponentiation for abstract groups + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "group.h" +#include "group-exp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @group_stdexp@ --- * + * + * Arguments: @group *g@ = abstract group + * @ge *d@ = destination pointer + * @ge *x@ = base element + * @mp *n@ = exponent + * + * Returns: --- + * + * Use: Computes %$d = x^n$% efficiently. + */ + +void group_stdexp(group *gg, ge *d, ge *x, mp *n) +{ + ge *t = G_CREATE(gg); + + G_COPY(gg, t, x); + MP_SHRINK(n); + G_COPY(gg, d, gg->i); + if (n->f & MP_BURN) + G_BURN(gg, t); + if (MP_ZEROP(n)) + ; + else { + if (MP_NEGP(n)) + G_INV(gg, t, t); + if (MP_LEN(n) < EXP_THRESH) + EXP_SIMPLE(d, t, n); + else + EXP_WINDOW(d, t, n); + } + G_DESTROY(gg, t); +} + +/* --- @group_stdmexp@ --- * + * + * Arguments: @group *g@ = abstract group + * @ge *d@ = destination pointer + * @const group_expfactor *f@ = vector of factors + * @size_t n@ = number of factors + * + * Returns: --- + * + * Use: Computes %$d = g_0^{x_0} g_1^{x_1} \ldots$% efficiently. + */ + +#undef EXP_WINSZ +#define EXP_WINSZ 3 + +void group_stdmexp(group *gg, ge *d, const group_expfactor *f, size_t n) +{ + group_expfactor *ff = xmalloc(n * sizeof(group_expfactor)); + size_t i; + + for (i = 0; i < n; i++) { + ff[i].base = G_CREATE(gg); + MP_SHRINK(f[i].exp); + if (MP_NEGP(f[i].exp)) + G_INV(gg, ff[i].base, f[i].base); + else + G_COPY(gg, ff[i].base, f[i].base); + if (f[i].exp->f & MP_BURN) + G_BURN(gg, ff[i].base); + ff[i].exp = f[i].exp; + } + G_COPY(gg, d, gg->i); + EXP_SIMUL(d, ff, n); + for (i = 0; i < n; i++) + G_DESTROY(gg, ff[i].base); + xfree(ff); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/group-exp.h b/math/group-exp.h new file mode 100644 index 0000000..0bc029c --- /dev/null +++ b/math/group-exp.h @@ -0,0 +1,66 @@ +/* -*-c-*- + * + * Exponentiation operations for abstract groups + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GROUP_EXP_H +#define CATACOMB_GROUP_EXP_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Exponentation definitions -----------------------------------------*/ + +#define EXP_TYPE ge * + +#define EXP_COPY(d, p) do { \ + (d) = G_CREATE(gg); \ + G_COPY(gg, (d), (p)); \ +} while (0) +#define EXP_DROP(x) G_DESTROY(gg, (x)) + +#define EXP_MUL(a, x) G_MUL(gg, (a), (a), (x)) +#define EXP_SQR(a) G_SQR(gg, (a), (a)); +#define EXP_FIX(x) + +#define EXP_SETMUL(d, x, y) do { \ + (d) = G_CREATE(gg); \ + G_MUL(gg, (d), (x), (y)); \ +} while (0) +#define EXP_SETSQR(d, x) do { \ + (d) = G_CREATE(gg); \ + G_SQR(gg, (d), (x)); \ +} while (0) + +#include "exp.h" + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/group-file.c b/math/group-file.c new file mode 100644 index 0000000..bb95df1 --- /dev/null +++ b/math/group-file.c @@ -0,0 +1,62 @@ +/* -*-c-*- + * + * File I/O for group elements + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "group.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @group_readfile@ --- * + * + * Arguments: @group *g@ = an abstract group + * @ge *d@ = destination group element + * @FILE *fp@ = the file to read from + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Parses a group element from a file. + */ + +int group_readfile(group *g, ge *d, FILE *fp) + { return (G_READ(g, d, &mptext_fileops, fp)); } + +/* --- @group_writefile@ --- * + * + * Arguments: @group *g@ = an abstract group + * @ge *x@ = a group element + * @FILE *fp@ = the file to write on + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Writes a group element to a file. + */ + +int group_writefile(group *g, ge *x, FILE *fp) + { return (G_WRITE(g, x, &mptext_fileops, fp)); } + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/group-guts.h b/math/group-guts.h new file mode 100644 index 0000000..c34d89c --- /dev/null +++ b/math/group-guts.h @@ -0,0 +1,84 @@ +/* -*-c-*- + * + * Internal structures for built-in groups + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GROUP_GUTS_H +#define CATACOMB_GROUP_GUTS_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_EC_H +# include "ec.h" +#endif + +#ifndef CATACOMB_MPMONT_H +# include "mpmont.h" +#endif + +#ifndef CATACOMB_GFREDUCE_H +# include "gfreduce.h" +#endif + +#ifndef CATACOMB_GROUP_H +# include "group.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct gctx_prime { + group g; + mp *gen; + mpmont mm; +} gctx_prime; + +typedef struct gctx_ec { + group g; + ec id, gen; + ec_info ei; +} gctx_ec; + +typedef struct gctx_bin { + group g; + mp *gen; + mp *one; + gfreduce r; +} gctx_bin; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/group-parse.c b/math/group-parse.c new file mode 100644 index 0000000..b46898d --- /dev/null +++ b/math/group-parse.c @@ -0,0 +1,95 @@ +/* -*-c-*- + * + * Parse group description strings + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Trivial IP Encryption (TrIPE). + * + * TrIPE 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 2 of the License, or + * (at your option) any later version. + * + * TrIPE 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 TrIPE; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "group.h" +#include "dh.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @group_parse@ --- * + * + * Arguments: @qd_parse *qd@ = quick-and-dirty parser + * + * Returns: Group pointer, or null for failure. + * + * Use: Parses a group description and returns the group. This has + * the form `TYPE { SPEC }' where TYPE is `prime' or `ec', and + * SPEC is the appropriate kind of group specification of the + * given type. + */ + +group *group_parse(qd_parse *qd) +{ + group *g = 0; + + switch (qd_enum(qd, "prime,ec")) { + case 0: { + dh_param dp; + qd_delim(qd, '{'); + if (dh_parse(qd, &dp)) goto ouch; + qd_delim(qd, '}'); + g = group_prime(&dp); + dh_paramfree(&dp); + } break; + case 1: { + ec_info ei; + qd_delim(qd, '{'); + if (ec_infoparse(qd, &ei)) goto ouch; + qd_delim(qd, '}'); + g = group_ec(&ei); + } break; + } + if (!g) qd->e = "bad group parameters"; +ouch: + return (g); +} + +/* --- @group_fromstring@ --- * + * + * Arguments: @const char *p@ = pointer to string to read + * @group **gg@ = where to put the group pointer + * + * Returns: Null if OK, or an error string. + * + * Use: Parses a group spec from a string, and returns the group. + */ + +const char *group_fromstring(const char *p, group **gg) +{ + group *g; + qd_parse qd; + + qd.p = p; + qd.e = 0; + if ((g = group_parse(&qd)) == 0) return (qd.e); + if (!qd_eofp(&qd)) { G_DESTROYGROUP(g); return ("junk at end of string"); } + *gg = g; + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/group-stdops.c b/math/group-stdops.c new file mode 100644 index 0000000..b0f8753 --- /dev/null +++ b/math/group-stdops.c @@ -0,0 +1,166 @@ +/* -*-c-*- + * + * Standard group operations + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "group.h" +#include "pgen.h" + +/*----- Handy functions ---------------------------------------------------*/ + +/* --- @group_check@ --- * + * + * Arguments: @group *g@ = an abstract group + * @ge *x@ = a group element + * + * Returns: Zero on success, nonzero for failure. + * + * Use: Checks that @x@ is a valid group element. This may take a + * while, since it checks that %$x \ne 1$% and %$x^r = 1$%. + */ + +int group_check(group *g, ge *x) +{ + ge *d = G_CREATE(g); + int rc; + + G_EXP(g, d, x, g->r); + rc = (G_IDENTP(g, d) && !G_IDENTP(g, x)); + G_DESTROY(g, d); + if (!rc) return (-1); + return (0); +} + +/* --- @group_samep@ --- * + * + * Arguments: @group *g, *h@ = two abstract groups + * + * Returns: Nonzero if the groups are in fact identical (not just + * isomorphic). + * + * Use: Checks to see whether two groups are actually the same. This + * function does the full check: the group operatrion @samep@ + * just does the group-specific details. + */ + +int group_samep(group *g, group *h) +{ + return (g == h || (g->ops == h->ops && + MP_EQ(g->r, h->r) && MP_EQ(g->h, h->h) && + G_EQ(g, g->i, h->i) && G_EQ(g, g->g, h->g) && + G_SAMEP(g, h))); +} + +/*----- Standard implementations ------------------------------------------*/ + +/* --- @group_stdidentp@ --- * + * + * Arguments: @group *g@ = abstract group + * @ge *x@ = group element + * + * Returns: Nonzero if %$x$% is the group identity. + */ + +int group_stdidentp(group *g, ge *x) { return (G_EQ(g, x, g->i)); } + +/* --- @group_stdsqr@ --- * + * + * Arguments: @group *g@ = abstract group + * @ge *d@ = destination pointer + * @ge *x@ = group element + * + * Returns: --- + * + * Use: Computes %$d = x^2$% as %$d = x x$%. + */ + +void group_stdsqr(group *g, ge *d, ge *x) { G_MUL(g, d, x, x); } + +/* --- @group_stddiv@ --- * + * + * Arguments: @group *g@ = abstract group + * @ge *d@ = destination pointer + * @ge *x@ = dividend + * @ge *y@ = divisor + * + * Returns: --- + * + * Use: Computes %$d = x/y$% as %$d = x y^{-1}$%. + */ + +void group_stddiv(group *g, ge *d, ge *x, ge *y) + { G_INV(g, d, y); G_MUL(g, d, x, d); } + +/* --- @group_stdtoec@ --- * + * + * Arguments: @group *g@ = abstract group + * @ec *d@ = destination point + * @ge *x@ = group element + * + * Returns: @-1@, indicating failure. + * + * Use: Fails to convert a group element to an elliptic curve point. + */ + +int group_stdtoec(group *g, ec *d, ge *x) { return (-1); } + +/* --- @group_stdfromec@ --- * + * + * Arguments: @group *g@ = abstract group + * @ge *d@ = destination pointer + * @const ec *p@ = elliptic curve point + * + * Returns: Zero for success, @-1@ on failure. + * + * Use: Converts %$p$% to a group element by converting its %$x$%- + * coordinate. + */ + +int group_stdfromec(group *g, ge *d, const ec *p) + { if (EC_ATINF(p)) return (-1); return (G_FROMINT(g, d, p->x)); } + +/* --- @group_stdcheck@ --- * + * + * Arguments: @group *g@ = abstract group + * @grand *gr@ = random number source. + * + * Returns: Null on success, or a pointer to an error message. + */ + +const char *group_stdcheck(group *g, grand *gr) +{ + ge *t; + int rc; + + if (!pgen_primep(g->r, gr)) return ("group order not prime"); + t = G_CREATE(g); G_EXP(g, t, g->g, g->r); + rc = G_IDENTP(g, t); G_DESTROY(g, t); + if (!rc) return ("generator not in the group"); + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/group-string.c b/math/group-string.c new file mode 100644 index 0000000..09db3ea --- /dev/null +++ b/math/group-string.c @@ -0,0 +1,82 @@ +/* -*-c-*- + * + * String I/O for group elements + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "group.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @group_readstring@ --- * + * + * Arguments: @group *g@ = an abstract group + * @ge *d@ = destination group element + * @const char *p@ = where the string is + * @char **end@ = where to put the end pointer + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Parses a group element from a string. + */ + +int group_readstring(group *g, ge *d, const char *p, char **end) +{ + mptext_stringctx ms; + + ms.buf = (/*unconst*/ char *)p; + ms.lim = (/*unconst*/ char *)p + strlen(p); + if (G_READ(g, d, &mptext_stringops, &ms)) + return (-1); + if (end) *end = ms.buf; + return (0); +} + +/* --- @group_writestring@ --- * + * + * Arguments: @group *g@ = an abstract group + * @ge *x@ = a group element + * @char *p@ = where the string should go + * @size_t sz@ = how long the buffer is + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Writes a group element to a string buffer. + */ + +int group_writestring(group *g, ge *x, char *p, size_t sz) +{ + mptext_stringctx ms; + + ms.buf = p; + ms.lim = p + sz - 1; + if (G_WRITE(g, x, &mptext_stringops, &ms)) + return (-1); + *ms.buf = 0; + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/group-test.c b/math/group-test.c new file mode 100644 index 0000000..7cd0cd2 --- /dev/null +++ b/math/group-test.c @@ -0,0 +1,561 @@ +/* -*-c-*- + * + * Testing group operations + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#include "group.h" +#include "fibrand.h" +#include "ec.h" +#include "ec-test.h" + +/*----- Main code ---------------------------------------------------------*/ + +static group *getgroup(const char *p) { + group *g; qd_parse qd; + qd.p = p; qd.e = 0; g = group_parse(&qd); + if (g && !qd_eofp(&qd)) { G_DESTROYGROUP(g); g = 0; qd.e = "junk at eof"; } + if (!g) { fprintf(stderr, "bad group string `%.*s|%s': %s\n", qd.p - p, + p, qd.p, qd.e); exit(1); } + return (g); +} + +static ge *getge(group *g, const char *p) { + ge *x = G_CREATE(g); + if (group_readstring(g, x, p, 0)) { + fprintf(stderr, "bad group element `%s'\n", p); + exit(1); + } + return (x); +} + +static void show(group *g, const char *p, ge *x) { + fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr); + putc('\n', stderr); +} + +static void showec(const char *p, ec *q) { + fprintf(stderr, "*** %s = ", p); + if (EC_ATINF(q)) fprintf(stderr, "inf\n"); + else { + mp_writefile(q->x, stderr, 16); fputs(", ", stderr); + mp_writefile(q->x, stderr, 16); putchar('\n'); + } +} + +static void showmp(const char *p, mp *x, int r) { + fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r); + putc('\n', stderr); +} + +static int check(const char *op, const char *gd, group *g, + ge *r, ge *c, ...) { + va_list ap; + + if (G_EQ(g, r, c)) return (1); + fprintf(stderr, "\n*** %s failed\n", op); + fprintf(stderr, "*** group: %s\n", gd); + va_start(ap, c); + for (;;) { + const char *p; ge *x; + p = va_arg(ap, const char *); if (!p) break; + x = va_arg(ap, ge *); show(g, p, x); + } + show(g, "expected", r); + show(g, "computed", c); + return (0); +} + +/*----- Actual tests ------------------------------------------------------*/ + +static int vcheck(dstr *v) +{ + group *g = getgroup(v[0].buf); + grand *gr = fibrand_create(0); + const char *e = G_CHECK(g, gr); + int ok = 1; + gr->ops->destroy(gr); + if (!e) e = "ok"; + G_DESTROYGROUP(g); + if (strcmp(e, v[1].buf)) { + ok = 0; + fprintf(stderr, "*** check failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + fprintf(stderr, "*** expected: %s\n", v[1].buf); + fprintf(stderr, "*** returned: %s\n", e); + } + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vcheckelt(dstr *v) +{ + group *g = getgroup(v[0].buf); + ge *x = getge(g, v[1].buf); + int ir = *(int *)v[2].buf; + int ic = group_check(g, x); + int ok = 1; + if (ir != ic) { + ok = 0; + fprintf(stderr, "*** check failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + show(g, "x", x); + fprintf(stderr, "*** expected %s\n", ir ? "failure" : "success"); + } + G_DESTROY(g, x); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vmul(dstr *v) +{ + group *g = getgroup(v[0].buf); + ge *x = getge(g, v[1].buf); + ge *y = getge(g, v[2].buf); + ge *r = getge(g, v[3].buf); + ge *c = G_CREATE(g); + int ok = 1; + G_MUL(g, c, x, y); + ok &= check("mul", v[0].buf, g, r, c, "x", x, "y", y, (char *)0); + G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vsqr(dstr *v) +{ + group *g = getgroup(v[0].buf); + ge *x = getge(g, v[1].buf); + ge *r = getge(g, v[2].buf); + ge *c = G_CREATE(g); + int ok = 1; + G_SQR(g, c, x); + ok &= check("sqr", v[0].buf, g, r, c, "x", x, (char *)0); + G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vinv(dstr *v) +{ + group *g = getgroup(v[0].buf); + ge *x = getge(g, v[1].buf); + ge *r = getge(g, v[2].buf); + ge *c = G_CREATE(g); + int ok = 1; + G_INV(g, c, x); + ok &= check("inv", v[0].buf, g, r, c, "x", x, (char *)0); + G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vdiv(dstr *v) +{ + group *g = getgroup(v[0].buf); + ge *x = getge(g, v[1].buf); + ge *y = getge(g, v[2].buf); + ge *r = getge(g, v[3].buf); + ge *c = G_CREATE(g); + int ok = 1; + G_DIV(g, c, x, y); + ok &= check("div", v[0].buf, g, r, c, "x", x, "y", y, (char *)0); + group_stddiv(g, c, x, y); + ok &= check("stddiv", v[0].buf, g, r, c, "x", x, "y", y, (char *)0); + G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vexp(dstr *v) +{ + group *g = getgroup(v[0].buf); + ge *x = getge(g, v[1].buf); + mp *n = *(mp **)v[2].buf; + ge *r = getge(g, v[3].buf); + ge *c = G_CREATE(g); + int ok = 1; + G_EXP(g, c, x, n); + if (!G_EQ(g, r, c)) { + ok = 0; + fprintf(stderr, "\n*** exp failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + show(g, "x", x); showmp("n", n, 10); + show(g, "expected", r); show(g, "computed", c); + } + group_stdexp(g, c, x, n); + if (!G_EQ(g, r, c)) { + ok = 0; + fprintf(stderr, "\n*** stdexp failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + show(g, "x", x); showmp("n", n, 10); + show(g, "expected", r); show(g, "computed", c); + } + G_DESTROY(g, x); MP_DROP(n); G_DESTROY(g, r); G_DESTROY(g, c); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vmexp(size_t n, dstr *v) +{ + group *g = getgroup(v[0].buf); + ge *c, *r; + group_expfactor *f = xmalloc(n * sizeof(group_expfactor)); + int ok = 1; + size_t i; + for (i = 0; i < n; i++) { + f[i].base = getge(g, v[1 + 2 * i].buf); + f[i].exp = *(mp **)v[2 + 2 * i].buf; + } + r = getge(g, v[1 + 2 * n].buf); + c = G_CREATE(g); + G_MEXP(g, c, f, n); + if (!G_EQ(g, r, c)) { + ok = 0; + fprintf(stderr, "\n*** mexp failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + for (i = 0; i < n; i++) { + show(g, "base", f[i].base); + showmp("exp", f[i].exp, 10); + } + show(g, "expected", r); show(g, "computed", c); + } + group_stdmexp(g, c, f, n); + if (!G_EQ(g, r, c)) { + ok = 0; + fprintf(stderr, "\n*** stdmexp failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + for (i = 0; i < n; i++) { + show(g, "base", f[i].base); + showmp("exp", f[i].exp, 10); + } + show(g, "expected", r); show(g, "computed", c); + } + for (i = 0; i < n; i++) { G_DESTROY(g, f[i].base); MP_DROP(f[i].exp); } + G_DESTROY(g, r); G_DESTROY(g, c); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vmexp1(dstr *v) { return vmexp(1, v); } +static int vmexp2(dstr *v) { return vmexp(2, v); } +static int vmexp3(dstr *v) { return vmexp(3, v); } +static int vmexp4(dstr *v) { return vmexp(4, v); } + +static int vtoint(dstr *v) +{ + group *g = getgroup(v[0].buf); + ge *x = getge(g, v[1].buf); + int ir = *(int *)v[2].buf; + mp *r = *(mp **)v[3].buf; + mp *c; + int ic; + int ok = 1; + c = G_TOINT(g, MP_NEW, x); + ic = c ? 0 : -1; + if (ir != ic || (!ic && !MP_EQ(r, c))) { + ok = 0; + fprintf(stderr, "\n*** toint failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + if (ir) fprintf(stderr, "*** expected failure\n"); + else { show(g, "x", x); showmp("expected", r, 16); + showmp("computed", c, 16); } + } + G_DESTROY(g, x); mp_drop(r); mp_drop(c); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vfromint(dstr *v) +{ + group *g = getgroup(v[0].buf); + mp *x = *(mp **)v[1].buf; + int ir = *(int *)v[2].buf; + ge *r = getge(g, v[3].buf); + int ic; + ge *c = G_CREATE(g); + int ok = 1; + ic = G_FROMINT(g, c, x); + if (ir != ic || (!ic && !G_EQ(g, r, c))) { + ok = 0; + fprintf(stderr, "\n*** fromint failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + showmp("x", x, 16); if (ir) fprintf(stderr, "*** should have failed\n"); + else { show(g, "expected", r); show(g, "computed", c); } + } + MP_DROP(x); G_DESTROY(g, r); G_DESTROY(g, c); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vtoec(dstr *v) +{ + group *g = getgroup(v[0].buf); + ge *x = getge(g, v[1].buf); + int ir = *(int *)v[2].buf; + ec *r = (ec *)v[3].buf; + int ic; + ec c = EC_INIT; + int ok = 1; + ic = G_TOEC(g, &c, x); + if (ir != ic || (!ic && !EC_EQ(r, &c))) { + ok = 0; + fprintf(stderr, "\n*** toec failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + show(g, "x", x); + if (ir) fprintf(stderr, "*** should have failed\n"); + else { showec("expected", r); showec("computed", &c); } + } + G_DESTROY(g, x); EC_DESTROY(&c); EC_DESTROY(r); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vfromec(dstr *v) +{ + group *g = getgroup(v[0].buf); + ec *p = (ec *)v[1].buf; + int ir = *(int *)v[2].buf; + ge *r = getge(g, v[3].buf); + int ic; + ge *c = G_CREATE(g); + int ok = 1; + ic = G_FROMEC(g, c, p); + if (ir != ic || (!ic && !G_EQ(g, r, c))) { + ok = 0; + fprintf(stderr, "\n*** fromec failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + showec("p", p); if (ir) fprintf(stderr, "*** should have failed\n"); + else { show(g, "expected", r); show(g, "computed", c); } + } + EC_DESTROY(p); G_DESTROY(g, r); G_DESTROY(g, c); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vtobuf(dstr *v) +{ + group *g = getgroup(v[0].buf); + ge *x = getge(g, v[1].buf); + int ir = *(int *)v[2].buf; + dstr c = DSTR_INIT; + int ic; + buf b; + int ok = 1; + + dstr_ensure(&c, v[3].len); + buf_init(&b, c.buf, v[3].len); + ic = G_TOBUF(g, &b, x); + c.len = BLEN(&b); + if (ic != ir || (!ic && (c.len != v[3].len || + memcmp(c.buf, v[3].buf, c.len)))) { + ok = 0; + fprintf(stderr, "*** tobuf failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + show(g, "x", x); + if (ir) fprintf(stderr, "*** expected failure\n"); + else { + fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr); + fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr); + fputc('\n', stderr); + } + } + G_DESTROY(g, x); dstr_destroy(&c); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vfrombuf(dstr *v) +{ + group *g = getgroup(v[0].buf); + int ir = *(int *)v[2].buf; + ge *r = getge(g, v[3].buf); + int ic; + ge *c = G_CREATE(g); + buf b; + int ok = 1; + + buf_init(&b, v[1].buf, v[1].len); + ic = G_FROMBUF(g, &b, c); + if ((ic < 0) != (ir < 0) || (ir >= 0 && + (ir != BLEN(&b) || !G_EQ(g, r, c)))) { + ok = 0; + fprintf(stderr, "*** frombuf failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr); + fputc('\n', stderr); + if (ir < 0) fprintf(stderr, "*** expected failure\n"); + else { + show(g, "expected", r); show(g, "computed", c); + fprintf(stderr, "*** expected used = %d\n", ir); + fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b)); + } + } + G_DESTROY(g, r); G_DESTROY(g, c); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vtoraw(dstr *v) +{ + group *g = getgroup(v[0].buf); + ge *x = getge(g, v[1].buf); + int ir = *(int *)v[2].buf; + dstr c = DSTR_INIT; + int ic; + buf b; + int ok = 1; + + dstr_ensure(&c, v[3].len); + buf_init(&b, c.buf, v[3].len); + ic = G_TORAW(g, &b, x); + c.len = BLEN(&b); + if (ic != ir || (!ic && (c.len != v[3].len || + memcmp(c.buf, v[3].buf, c.len)))) { + ok = 0; + fprintf(stderr, "*** toraw failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + show(g, "x", x); + if (ir) fprintf(stderr, "*** expected failure\n"); + else { + fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr); + fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr); + fputc('\n', stderr); + } + } + G_DESTROY(g, x); dstr_destroy(&c); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vfromraw(dstr *v) +{ + group *g = getgroup(v[0].buf); + int ir = *(int *)v[2].buf; + ge *r = getge(g, v[3].buf); + int ic; + ge *c = G_CREATE(g); + buf b; + int ok = 1; + + buf_init(&b, v[1].buf, v[1].len); + ic = G_FROMRAW(g, &b, c); + if ((ic < 0) != (ir < 0) || (ir >= 0 && + (ir != BLEN(&b) || !G_EQ(g, r, c)))) { + ok = 0; + fprintf(stderr, "*** fromraw failed\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr); + fputc('\n', stderr); + if (ir < 0) fprintf(stderr, "*** expected failure\n"); + else { + show(g, "expected", r); show(g, "computed", c); + fprintf(stderr, "*** expected used = %d\n", ir); + fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b)); + } + } + G_DESTROY(g, r); G_DESTROY(g, c); + G_DESTROYGROUP(g); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static const test_chunk tests[] = { + { "check", vcheck, { &type_string, &type_string } }, + { "checkelt", vcheckelt, { &type_string, &type_string, &type_int } }, + { "mul", vmul, { &type_string, &type_string, + &type_string, &type_string } }, + { "sqr", vsqr, { &type_string, &type_string, + &type_string } }, + { "inv", vinv, { &type_string, &type_string, + &type_string } }, + { "div", vdiv, { &type_string, &type_string, + &type_string, &type_string } }, + { "exp", vexp, { &type_string, &type_string, + &type_mp, &type_string } }, + { "mexp-1", vmexp1, { &type_string, + &type_string, &type_mp, + &type_string } }, + { "mexp-2", vmexp2, { &type_string, + &type_string, &type_mp, + &type_string, &type_mp, + &type_string } }, + { "mexp-3", vmexp3, { &type_string, + &type_string, &type_mp, + &type_string, &type_mp, + &type_string, &type_mp, + &type_string } }, + { "mexp-4", vmexp4, { &type_string, + &type_string, &type_mp, + &type_string, &type_mp, + &type_string, &type_mp, + &type_string, &type_mp, + &type_string } }, + { "toint", vtoint, { &type_string, &type_string, + &type_int, &type_mp } }, + { "fromint", vfromint, { &type_string, &type_mp, + &type_int, &type_string } }, + { "toec", vtoec, { &type_string, &type_string, + &type_int, &type_ec } }, + { "fromec", vfromec, { &type_string, &type_ec, + &type_int, &type_string } }, + { "tobuf", vtobuf, { &type_string, &type_string, + &type_int, &type_hex } }, + { "frombuf", vfrombuf, { &type_string, &type_hex, + &type_int, &type_string } }, + { "toraw", vtoraw, { &type_string, &type_string, + &type_int, &type_hex } }, + { "fromraw", vfromraw, { &type_string, &type_hex, + &type_int, &type_string } }, + { 0 } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/group"); + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/group.h b/math/group.h new file mode 100644 index 0000000..cdfbdd4 --- /dev/null +++ b/math/group.h @@ -0,0 +1,409 @@ +/* -*-c-*- + * + * General cyclic group abstraction + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GROUP_H +#define CATACOMB_GROUP_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_BUF_H +# include "buf.h" +#endif + +#ifndef CATACOMB_DH_H +# include "ec.h" +#endif + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_QDPARSE_H +# include "qdparse.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +#ifndef ge + typedef struct ge ge; /* Group element (abstract type) */ +#endif + +typedef struct group_ { + const struct group_ops *ops; /* Operations table */ + size_t nbits; /* Size of an element in bits */ + size_t noctets; /* Size of raw element in octets */ + ge *i; /* Identity element */ + ge *g; /* Generator element */ + mp *r; /* Order of the generator */ + mp *h; /* Cofactor */ +} group; + +typedef struct group_expfactor { + ge *base; /* The base */ + mp *exp; /* The exponent */ +} group_expfactor; + +typedef struct group_ops { + + /* --- General information --- */ + + unsigned ty; /* Type of this group */ + const char *name; /* Textual name string */ + + /* --- Memory management --- */ + + void (*destroygroup)(group */*g*/); + ge *(*create)(group */*g*/); + void (*copy)(group */*g*/, ge */*d*/, ge */*x*/); + void (*burn)(group */*g*/, ge */*x*/); + void (*destroy)(group */*g*/, ge */*e*/); + + /* --- Comparisons --- */ + + int (*samep)(group */*g*/, group */*h*/); + int (*eq)(group */*g*/, ge */*x*/, ge */*y*/); + int (*identp)(group */*g*/, ge */*x*/); + + /* --- Other stuff --- */ + + const char *(*check)(group */*g*/, grand */*gr*/); + + /* --- Arithmetic --- */ + + void (*mul)(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/); + void (*sqr)(group */*g*/, ge */*d*/, ge */*x*/); + void (*inv)(group */*g*/, ge */*d*/, ge */*x*/); + void (*div)(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/); + void (*exp)(group */*g*/, ge */*d*/, ge */*x*/, mp */*n*/); + void (*mexp)(group */*g*/, ge */*d*/, + const group_expfactor */*f*/, size_t /*n*/); + + /* --- Debugging --- */ + + int (*read)(group */*g*/, ge */*d*/, + const mptext_ops */*ops*/, void */*p*/); + int (*write)(group */*g*/, ge */*x*/, + const mptext_ops */*ops*/, void */*p*/); + + /* --- Conversions --- */ + + mp *(*toint)(group */*g*/, mp */*d*/, ge */*x*/); + int (*fromint)(group */*g*/, ge */*d*/, mp */*x*/); + int (*toec)(group */*g*/, ec */*d*/, ge */*x*/); + int (*fromec)(group */*g*/, ge */*d*/, const ec */*p*/); + int (*tobuf)(group */*h*/, buf */*b*/, ge */*x*/); + int (*frombuf)(group */*h*/, buf */*b*/, ge */*d*/); + int (*toraw)(group */*h*/, buf */*b*/, ge */*x*/); + int (*fromraw)(group */*h*/, buf */*b*/, ge */*d*/); + +} group_ops; + +enum { + GTY_PRIME, /* Prime field subgroup */ + GTY_BINARY, /* Binary feld subgroup */ + GTY_EC /* Elliptic curve group */ +}; + +#define G_NAME(g) (g)->ops->name +#define G_TYPE(g) (g)->ops->ty + +#define G_DESTROYGROUP(g) (g)->ops->destroygroup((g)) +#define G_CREATE(g) (g)->ops->create((g)) +#define G_COPY(g, d, x) (g)->ops->copy((g), (d), (x)) +#define G_BURN(g, x) (g)->ops->burn((g), (x)) +#define G_DESTROY(g, x) (g)->ops->destroy((g), (x)) + +#define G_SAMEP(g, h) (g)->ops->samep((g), (h)) +#define G_EQ(g, x, y) (g)->ops->eq((g), (x), (y)) +#define G_IDENTP(g, x) (g)->ops->identp((g), (x)) + +#define G_CHECK(g, gr) (g)->ops->check((g), (gr)) + +#define G_MUL(g, d, x, y) (g)->ops->mul((g), (d), (x), (y)) +#define G_SQR(g, d, x) (g)->ops->sqr((g), (d), (x)) +#define G_INV(g, d, x) (g)->ops->inv((g), (d), (x)) +#define G_DIV(g, d, x, y) (g)->ops->div((g), (d), (x), (y)) +#define G_EXP(g, d, x, n) (g)->ops->exp((g), (d), (x), (n)) +#define G_MEXP(g, d, f, n) (g)->ops->mexp((g), (d), (f), (n)) + +#define G_READ(g, d, o, p) (g)->ops->read((g), (d), (o), (p)) +#define G_WRITE(g, x, o, p) (g)->ops->write((g), (x), (o), (p)) + +#define G_TOINT(g, d, x) (g)->ops->toint((g), (d), (x)) +#define G_FROMINT(g, d, x) (g)->ops->fromint((g), (d), (x)) +#define G_TOEC(g, d, x) (g)->ops->toec((g), (d), (x)) +#define G_FROMEC(g, d, p) (g)->ops->fromec((g), (d), (p)) +#define G_TOBUF(g, b, x) (g)->ops->tobuf((g), (b), (x)) +#define G_FROMBUF(g, b, d) (g)->ops->frombuf((g), (b), (d)) +#define G_TORAW(g, b, x) (g)->ops->toraw((g), (b), (x)) +#define G_FROMRAW(g, b, d) (g)->ops->fromraw((g), (b), (d)) + +/*----- Handy functions ---------------------------------------------------*/ + +/* --- @group_check@ --- * + * + * Arguments: @group *g@ = an abstract group + * @ge *x@ = a group element + * + * Returns: Zero on success, nonzero for failure. + * + * Use: Checks that @x@ is a valid group element. This may take a + * while, since it checks that %$x^h \ne 1$%. + */ + +extern int group_check(group */*g*/, ge */*x*/); + +/* --- @group_samep@ --- * + * + * Arguments: @group *g, *h@ = two abstract groups + * + * Returns: Nonzero if the groups are in fact identical (not just + * isomorphic). + * + * Use: Checks to see whether two groups are actually the same. This + * function does the full check: the group operatrion @samep@ + * just does the group-specific details. + */ + +extern int group_samep(group */*g*/, group */*h*/); + +/*----- Textual I/O on group elements -------------------------------------*/ + +extern int group_readstring(group */*g*/, ge */*d*/, + const char */*p*/, char **/*end*/); +extern int group_writestring(group */*g*/, ge */*d*/, + char */*p*/, size_t /*sz*/); + +extern int group_readfile(group */*g*/, ge */*d*/, FILE */*fp*/); +extern int group_writefile(group */*g*/, ge */*x*/, FILE */*fp*/); + +extern int group_readdstr(group */*g*/, ge */*d*/, + dstr */*dd*/, size_t */*off*/); +extern int group_writedstr(group */*g*/, ge */*x*/, dstr */*d*/); + +/*----- Standard implementations ------------------------------------------*/ + +/* --- @group_stdidentp@ --- * + * + * Arguments: @group *g@ = abstract group + * @ge *x@ = group element + * + * Returns: Nonzero if %$x$% is the group identity. + */ + +extern int group_stdidentp(group */*g*/, ge */*x*/); + +/* --- @group_stdcheck@ --- * + * + * Arguments: @group *g@ = abstract group + * @grand *gr@ = random number source. + * + * Returns: Null on success, or a pointer to an error message. + */ + +extern const char *group_stdcheck(group */*g*/, grand */*gr*/); + +/* --- @group_stdsqr@ --- * + * + * Arguments: @group *g@ = abstract group + * @ge *d@ = destination pointer + * @ge *x@ = group element + * + * Returns: --- + * + * Use: Computes %$d = x^2$% as %$d = x x$%. + */ + +extern void group_stdsqr(group */*g*/, ge */*d*/, ge */*x*/); + +/* --- @group_stddiv@ --- * + * + * Arguments: @group *g@ = abstract group + * @ge *d@ = destination pointer + * @ge *x@ = dividend + * @ge *y@ = divisor + * + * Returns: --- + * + * Use: Computes %$d = x/y$% as %$d = x y^{-1}$%. + */ + +extern void group_stddiv(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/); + +/* --- @group_stdexp@ --- * + * + * Arguments: @group *g@ = abstract group + * @ge *d@ = destination pointer + * @ge *x@ = base element + * @mp *n@ = exponent + * + * Returns: --- + * + * Use: Computes %$d = x^n$% efficiently. + */ + +extern void group_stdexp(group */*g*/, ge */*d*/, ge */*x*/, mp */*n*/); + +/* --- @group_stdmexp@ --- * + * + * Arguments: @group *g@ = abstract group + * @ge *d@ = destination pointer + * @const group_expfactor *f@ = vector of factors + * @size_t n@ = number of factors + * + * Returns: --- + * + * Use: Computes %$d = g_0^{x_0} g_1^{x_1} \ldots$% efficiently. + */ + +extern void group_stdmexp(group */*g*/, ge */*d*/, + const group_expfactor */*f*/, size_t /*n*/); + +/* --- @group_stdtoec@ --- * + * + * Arguments: @group *g@ = abstract group + * @ec *d@ = destination point + * @ge *x@ = group element + * + * Returns: @-1@, indicating failure. + * + * Use: Fails to convert a group element to an elliptic curve point. + */ + +extern int group_stdtoec(group */*g*/, ec */*d*/, ge */*x*/); + +/* --- @group_stdfromec@ --- * + * + * Arguments: @group *g@ = abstract group + * @ge *d@ = destination pointer + * @const ec *p@ = elliptic curve point + * + * Returns: Zero for success, @-1@ on failure. + * + * Use: Converts %$p$% to a group element by converting its %$x$%- + * coordinate. + */ + +extern int group_stdfromec(group */*g*/, ge */*d*/, const ec */*p*/); + +/*----- Prime field subgroups ---------------------------------------------*/ + +typedef struct gprime_param { + mp *p, *q; /* Prime numbers %$p$% and %$q$% */ + mp *g; /* Generates order-%$q$% subgroup */ +} gprime_param; + +/* --- @group_prime@ --- * + * + * Arguments: @const gprime_param *gp@ = group parameters + * + * Returns: A pointer to the group, or null. + * + * Use: Constructs an abstract group interface for a subgroup of a + * prime field. Group elements are @mp *@ pointers. + */ + +group *group_prime(const gprime_param */*gp*/); + +/*----- Binary field subgroups --------------------------------------------*/ + +typedef gprime_param gbin_param; + +/* --- @group_binary@ --- * + * + * Arguments: @const gbin_param *gb@ = group parameters + * + * Returns: A pointer to the group, or null. + * + * Use: Constructs an abstract group interface for a subgroup of a + * prime field. Group elements are @mp *@ pointers. + */ + +group *group_binary(const gbin_param */*gp*/); + +/*----- Elliptic curve groups ---------------------------------------------*/ + +/* --- @group_ec@ --- * + * + * Arguments: @const ec_info *ei@ = elliptic curve parameters + * + * Returns: A pointer to the group, or null. + * + * Use: Constructs an abstract group interface for an elliptic curve + * group. Group elements are @ec@ structures. The contents of + * the @ec_info@ structure becomes the property of the @group@ + * object; you can (and should) free the structure itself, but + * calling @ec_freeinfo@ on it is not allowed. + */ + +group *group_ec(const ec_info */*ei*/); + +/*----- General group initialization --------------------------------------*/ + +/* --- @group_parse@ --- * + * + * Arguments: @qd_parse *qd@ = quick-and-dirty parser + * + * Returns: Group pointer, or null for failure. + * + * Use: Parses a group description and returns the group. This has + * the form `TYPE { SPEC }' where TYPE is `prime' or `ec', and + * SPEC is the appropriate kind of group specification of the + * given type. + */ + +extern group *group_parse(qd_parse */*qd*/); + +/* --- @group_fromstring@ --- * + * + * Arguments: @const char *p@ = pointer to string to read + * @group **gg@ = where to put the group pointer + * + * Returns: Null if OK, or an error string. + * + * Use: Parses a group spec from a string, and returns the group. + */ + +extern const char *group_fromstring(const char */*p*/, group **/*gg*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/karatsuba.h b/math/karatsuba.h new file mode 100644 index 0000000..015f7b0 --- /dev/null +++ b/math/karatsuba.h @@ -0,0 +1,142 @@ +/* -*-c-*- + * + * Macros for Karatsuba functions + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_KARATSUBA_H +#define CATACOMB_KARATSUBA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MPW_H +# include "mpw.h" +#endif + +/*----- Normal arithmetic macros ------------------------------------------*/ + +#define UADD(dv, av, avl) do { \ + mpw *_dv = (dv); \ + const mpw *_av = (av), *_avl = (avl); \ + mpw _c = 0; \ + \ + while (_av < _avl) { \ + mpw _a, _b; \ + mpd _x; \ + _a = *_av++; \ + _b = *_dv; \ + _x = (mpd)_a + (mpd)_b + _c; \ + *_dv++ = MPW(_x); \ + _c = _x >> MPW_BITS; \ + } \ + while (_c) { \ + mpd _x = (mpd)*_dv + (mpd)_c; \ + *_dv++ = MPW(_x); \ + _c = _x >> MPW_BITS; \ + } \ +} while (0) + +#define UADD2(dv, dvl, av, avl, bv, bvl) do { \ + mpw *_dv = (dv), *_dvl = (dvl); \ + const mpw *_av = (av), *_avl = (avl); \ + const mpw *_bv = (bv), *_bvl = (bvl); \ + mpw _c = 0; \ + \ + while (_av < _avl || _bv < _bvl) { \ + mpw _a, _b; \ + mpd _x; \ + _a = (_av < _avl) ? *_av++ : 0; \ + _b = (_bv < _bvl) ? *_bv++ : 0; \ + _x = (mpd)_a + (mpd)_b + _c; \ + *_dv++ = MPW(_x); \ + _c = _x >> MPW_BITS; \ + } \ + *_dv++ = _c; \ + while (_dv < _dvl) \ + *_dv++ = 0; \ +} while (0) + +#define USUB(dv, av, avl) do { \ + mpw *_dv = (dv); \ + const mpw *_av = (av), *_avl = (avl); \ + mpw _c = 0; \ + \ + while (_av < _avl) { \ + mpw _a, _b; \ + mpd _x; \ + _a = *_av++; \ + _b = *_dv; \ + _x = (mpd)_b - (mpd)_a - _c; \ + *_dv++ = MPW(_x); \ + if (_x >> MPW_BITS) \ + _c = 1; \ + else \ + _c = 0; \ + } \ + while (_c) { \ + mpd _x = (mpd)*_dv - (mpd)_c; \ + *_dv++ = MPW(_x); \ + if (_x >> MPW_BITS) \ + _c = 1; \ + else \ + _c = 0; \ + } \ +} while (0) + +/*----- Binary polynomial arithmetic macros -------------------------------*/ + +#define UXOR(dv, av, avl) do { \ + mpw *_dv = (dv); \ + const mpw *_av = (av), *_avl = (avl); \ + \ + while (_av < _avl) \ + *_dv++ ^= *_av++; \ +} while (0) + +#define UXOR2(dv, dvl, av, avl, bv, bvl) do { \ + mpw *_dv = (dv), *_dvl = (dvl); \ + const mpw *_av = (av), *_avl = (avl); \ + const mpw *_bv = (bv), *_bvl = (bvl); \ + \ + while (_av < _avl || _bv < _bvl) { \ + mpw _a, _b; \ + _a = (_av < _avl) ? *_av++ : 0; \ + _b = (_bv < _bvl) ? *_bv++ : 0; \ + *_dv++ = _a ^ _b; \ + } \ + while (_dv < _dvl) \ + *_dv++ = 0; \ +} while (0) + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/limlee.c b/math/limlee.c new file mode 100644 index 0000000..b20965a --- /dev/null +++ b/math/limlee.c @@ -0,0 +1,396 @@ +/* -*-c-*- + * + * Generate Lim-Lee primes + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include "limlee.h" +#include "mpmul.h" +#include "mprand.h" +#include "pgen.h" +#include "rabin.h" + +/*----- Stepping through combinations -------------------------------------*/ + +/* --- @comb_init@ --- * + * + * Arguments: @octet *c@ = pointer to byte-flag array + * @unsigned n@ = number of items in the array + * @unsigned r@ = number of desired items + * + * Returns: --- + * + * Use: Initializes a byte-flag array which, under the control of + * @comb_next@, will step through all combinations of @r@ chosen + * elements. + */ + +static void comb_init(octet *c, unsigned n, unsigned r) +{ + memset(c, 0, n - r); + memset(c + (n - r), 1, r); +} + +/* --- @comb_next@ --- * + * + * Arguments: @octet *c@ = pointer to byte-flag array + * @unsigned n@ = number of items in the array + * @unsigned r@ = number of desired items + * + * Returns: Nonzero if another combination was returned, zero if we've + * reached the end. + * + * Use: Steps on to the next combination in sequence. + */ + +static int comb_next(octet *c, unsigned n, unsigned r) +{ + unsigned g = 0; + + /* --- How the algorithm works --- * + * + * Set bits start at the end and work their way towards the start. + * Excepting bits already at the start, we scan for the lowest set bit, and + * move it one place nearer the start. A group of bits at the start are + * counted and reset just below the `moved' bit. If there is no moved bit + * then we're done. + */ + + /* --- Count the group at the start --- */ + + for (; *c; c++) { + g++; + *c = 0; + } + if (g == r) + return (0); + + /* --- Move the next bit down one --- * + * + * There must be one, because otherwise we'd have counted %$r$% bits + * earlier. + */ + + for (; !*c; c++) + ; + *c = 0; + g++; + for (; g; g--) + *--c = 1; + return (1); +} + +/*----- Default prime generator -------------------------------------------*/ + +static void llgen(limlee_factor *f, unsigned pl, limlee_stepctx *l) +{ + pgen_filterctx pf; + rabin r; + mp *p; + +again: + p = mprand(l->newp, pl, l->r, 1); + pf.step = 2; + p = pgen(l->d.buf, p, p, l->iev, l->iec, 0, pgen_filter, &pf, + rabin_iters(pl), pgen_test, &r); + if (!p) + goto again; + f->p = p; +} + +static void llfree(limlee_factor *f, limlee_stepctx *l) +{ + mp_drop(f->p); +} + +static const limlee_primeops primeops_simple = { llgen, llfree }; + +/*----- Lim-Lee stepper ---------------------------------------------------*/ + +/* --- @init@ --- * + * + * Arguments: @pgen_event *ev@ = pointer to event block + * @limlee_stepctx *l@ = pointer to Lim-Lee context + * + * Returns: A @PGEN@ result code. + * + * Use: Initializes the stepper. + */ + +static int init(pgen_event *ev, limlee_stepctx *l) +{ + size_t i; + unsigned qql; + + /* --- First of all, decide on a number of factors to make --- */ + + l->nf = l->pl / l->ql; + qql = l->pl % l->ql; + if (!l->nf) + return (PGEN_ABORT); + else if (qql && l->nf > 1) { + l->nf--; + qql += l->ql; + } + + /* --- Now decide on how many primes I'll actually generate --- * + * + * The formula %$m = \max(3 n + 5, 25)$% comes from GPG's prime generation + * library. + */ + + l->poolsz = l->nf * 3 + 5; + if (l->poolsz < 25) + l->poolsz = 25; + + /* --- Allocate and initialize the various tables --- */ + + l->c = xmalloc(l->poolsz); + l->v = xmalloc(l->poolsz * sizeof(limlee_factor)); + comb_init(l->c, l->poolsz, l->nf); + for (i = 0; i < l->poolsz; i++) + l->v[i].p = 0; + + /* --- Other bits of initialization --- */ + + l->seq = 0; + dstr_create(&l->d); + if (!l->pops) { + l->pops = &primeops_simple; + l->pc = 0; + } + + /* --- Find a big prime --- */ + + if (!qql) + l->qq.p = 0; + else { + dstr_putf(&l->d, "%s*", ev->name); + l->pops->pgen(&l->qq, qql, l); + } + + return (PGEN_TRY); +} + +/* --- @next@ --- * + * + * Arguments: @int rq@ = request which triggered this call + * @pgen_event *ev@ = pointer to event block + * @limlee_stepctx *l@ = pointer to Lim-Lee context + * + * Returns: A @PGEN@ result code. + * + * Use: Initializes the stepper. + */ + +static int next(int rq, pgen_event *ev, limlee_stepctx *l) +{ + mp *p; + int rc; + + mp_drop(ev->m); + + for (;;) { + size_t i; + mpmul mm = MPMUL_INIT; + + /* --- Step on to next combination --- */ + + if (rq == PGEN_TRY && !comb_next(l->c, l->poolsz, l->nf)) { + for (i = 0; i < l->poolsz; i++) { + l->pops->pfree(&l->v[i], l); + l->v[i].p = 0; + } + } + rq = PGEN_TRY; /* For next time through */ + + /* --- Gather up some factors --- */ + + if (l->qq.p) + mpmul_add(&mm, l->qq.p); + for (i = 0; i < l->poolsz; i++) { + if (!l->c[i]) + continue; + if (!l->v[i].p) { + DRESET(&l->d); + dstr_putf(&l->d, "%s_%lu", ev->name, l->seq++); + l->pops->pgen(&l->v[i], l->ql, l); + } + mpmul_add(&mm, l->v[i].p); + } + + /* --- Check it for small factors --- */ + + p = mpmul_done(&mm); + p = mp_lsl(p, p, 1); + p->v[0] |= 1; + if ((rc = pfilt_smallfactor(p)) != PGEN_FAIL) + break; + mp_drop(p); + } + + ev->m = p; + return (rc); +} + +/* --- @done@ --- * + * + * Arguments: @pgen_event *ev@ = pointer to event block + * @limlee_stepctx *l@ = pointer to Lim-Lee context + * + * Returns: A @PGEN@ result code. + * + * Use: Finalizes the stepper. The output values in the context + * take on their final results; other resources are discarded. + */ + +static int done(pgen_event *ev, limlee_stepctx *l) +{ + size_t i, j; + limlee_factor *v; + + /* --- If an output vector of factors is wanted, produce one --- */ + + if (!(l->f & LIMLEE_KEEPFACTORS)) + v = 0; + else { + if (l->qq.p) + l->nf++; + v = xmalloc(l->nf * sizeof(limlee_factor)); + } + + for (i = 0, j = 0; i < l->poolsz; i++) { + if (v && l->c[i]) + v[j++] = l->v[i]; + else if (l->v[i].p) + l->pops->pfree(&l->v[i], l); + } + + if (l->qq.p) { + if (v) + v[j++] = l->qq; + else + l->pops->pfree(&l->qq, l); + } + + xfree(l->v); + l->v = v; + + /* --- Free other resources --- */ + + xfree(l->c); + dstr_destroy(&l->d); + + /* --- Done --- */ + + return (PGEN_DONE); +} + +/* --- @limlee_step@ --- */ + +int limlee_step(int rq, pgen_event *ev, void *p) +{ + limlee_stepctx *l = p; + int rc; + + switch (rq) { + case PGEN_BEGIN: + if ((rc = init(ev, l)) != PGEN_TRY) + return (rc); + case PGEN_TRY: + return (next(rq, ev, l)); + case PGEN_DONE: + return (done(ev, l)); + } + return (PGEN_ABORT); +} + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @limlee@ --- * + * + * Arguments: @const char *name@ = pointer to name root + * @mp *d@ = pointer to destination integer + * @mp *newp@ = how to generate factor primes + * @unsigned ql@ = size of individual factors + * @unsigned pl@ = size of large prime + * @grand *r@ = a random number source + * @unsigned on@ = number of outer attempts to make + * @pgen_proc *oev@ = outer event handler function + * @void *oec@ = argument for the outer event handler + * @pgen_proc *iev@ = inner event handler function + * @void *iec@ = argument for the inner event handler + * @size_t *nf@, @mp ***f@ = output array for factors + * + * Returns: A Lim-Lee prime, or null if generation failed. + * + * Use: Generates Lim-Lee primes. A Lim-Lee prime %$p$% is one which + * satisfies %$p = 2 \prod_i q_i + 1$%, where all of the %$q_i$% + * are large enough to resist square-root discrete log + * algorithms. + * + * If we succeed, and @f@ is non-null, we write the array of + * factors chosen to @f@ for the benefit of the caller. + */ + +mp *limlee(const char *name, mp *d, mp *newp, + unsigned ql, unsigned pl, grand *r, + unsigned on, pgen_proc *oev, void *oec, + pgen_proc *iev, void *iec, + size_t *nf, mp ***f) +{ + limlee_stepctx l; + rabin rr; + + l.f = 0; if (f) l.f |= LIMLEE_KEEPFACTORS; + l.newp = newp; + l.pl = pl; l.ql = ql; + l.pops = 0; + l.iev = iev; + l.iec = iec; + l.r = r; + + d = pgen(name, d, 0, oev, oec, on, limlee_step, &l, + rabin_iters(pl), pgen_test, &rr); + + if (d && f) { + mp **v; + size_t i; + v = xmalloc(l.nf * sizeof(mp *)); + for (i = 0; i < l.nf; i++) + v[i] = l.v[i].p; + xfree(l.v); + *f = v; + *nf = l.nf; + } + + return (d); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/limlee.h b/math/limlee.h new file mode 100644 index 0000000..d22b5a7 --- /dev/null +++ b/math/limlee.h @@ -0,0 +1,138 @@ +/* -*-c-*- + * + * Generate Lim-Lee primes + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_LIMLEE_H +#define CATACOMB_LIMLEE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_PGEN_H +# include "pgen.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct limlee_factor { + mp *p; /* The actual prime */ + unsigned tag; /* A tag, usable by the generator */ + void *more; /* Pointer to more data */ +} limlee_factor; + +typedef struct limlee_stepctx { + + /* --- To be initialized by the caller --- */ + + unsigned f; /* Various useful flags */ + mp *newp; /* Initial valid for new primes */ + unsigned ql, pl; /* Size of factors and result */ + const struct limlee_primeops *pops; /* Pointer to generator ops */ + void *pc; /* Context ptr for generator ops */ + pgen_proc *iev; /* Event handler for inner @pgen@ */ + void *iec; /* Context for inner @pgen@ */ + grand *r; /* Random number generator */ + + /* --- Output values --- */ + + size_t nf; /* Number of factors wanted */ + limlee_factor *v; /* Vector of factors */ + + /* --- Maintained internally --- */ + + octet *c; /* Combination byte-flag vector */ + unsigned long seq; /* Sequence number for primes */ + size_t poolsz; /* Size of the small-prime pool */ + dstr d; /* String for subprime name */ + limlee_factor qq; /* Big prime to pick up slack */ + +} limlee_stepctx; + +typedef struct limlee_primeops { + void (*pgen)(limlee_factor */*f*/, unsigned /*pl*/, limlee_stepctx */*l*/); + void (*pfree)(limlee_factor */*f*/, limlee_stepctx */*l*/); +} limlee_primeops; + +/* --- Flags --- */ + +#define LIMLEE_KEEPFACTORS 1u + +/*----- The Lim-Lee stepper function --------------------------------------*/ + +extern pgen_proc limlee_step; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @limlee@ --- * + * + * Arguments: @const char *name@ = pointer to name root + * @mp *d@ = pointer to destination integer + * @mp *newp@ = how to generate factor primes + * @unsigned ql@ = size of individual factors + * @unsigned pl@ = size of large prime + * @grand *r@ = a random number source + * @unsigned on@ = number of outer attempts to make + * @pgen_proc *oev@ = outer event handler function + * @void *oec@ = argument for the outer event handler + * @pgen_proc *iev@ = inner event handler function + * @void *iec@ = argument for the inner event handler + * @size_t *nf@, @mp ***f@ = output array for factors + * + * Returns: A Lim-Lee prime, or null if generation failed. + * + * Use: Generates Lim-Lee primes. A Lim-Lee prime %$p$% is one which + * satisfies %$p = 2 \prod_i q_i + 1$%, where all of the %$q_i$% + * are large enough to resist square-root discrete log + * algorithms. + * + * If we succeed, and @f@ is non-null, we write the array of + * factors chosen to @f@ for the benefit of the caller. + */ + +extern mp *limlee(const char */*name*/, mp */*d*/, mp */*newp*/, + unsigned /*ql*/, unsigned /*pl*/, grand */*r*/, + unsigned /*on*/, pgen_proc */*oev*/, void */*oec*/, + pgen_proc */*iev*/, void */*iec*/, + size_t */*nf*/, mp ***/*f*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mp-arith.c b/math/mp-arith.c new file mode 100644 index 0000000..2d7d635 --- /dev/null +++ b/math/mp-arith.c @@ -0,0 +1,929 @@ +/* -*-c-*- + * + * Basic arithmetic on multiprecision integers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" + +/*----- Macros ------------------------------------------------------------*/ + +#define MAX(x, y) ((x) >= (y) ? (x) : (y)) + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mp_lsl@, @mp_lslc@, @mp_lsr@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = source + * @size_t n@ = number of bits to move + * + * Returns: Result, @a@ shifted left or right by @n@. + * + * Use: Bitwise shift operators. @mp_lslc@ fills the bits introduced + * on the right with ones instead of zeroes: it's used + * internally by @mp_lsl2c@, though it may be useful on its + * own. + */ + +mp *mp_lsl(mp *d, mp *a, size_t n) +{ + MP_DEST(d, MP_LEN(a) + (n + MPW_BITS - 1) / MPW_BITS, a->f); + mpx_lsl(d->v, d->vl, a->v, a->vl, n); + d->f = a->f & (MP_NEG | MP_BURN); + MP_SHRINK(d); + return (d); +} + +mp *mp_lslc(mp *d, mp *a, size_t n) +{ + MP_DEST(d, MP_LEN(a) + (n + MPW_BITS - 1) / MPW_BITS, a->f); + mpx_lslc(d->v, d->vl, a->v, a->vl, n); + d->f = a->f & (MP_NEG | MP_BURN); + MP_SHRINK(d); + return (d); +} + +mp *mp_lsr(mp *d, mp *a, size_t n) +{ + MP_DEST(d, MP_LEN(a), a->f); + mpx_lsr(d->v, d->vl, a->v, a->vl, n); + d->f = a->f & (MP_NEG | MP_BURN); + MP_SHRINK(d); + return (d); +} + +/* --- @mp_lsl2c@, @mp_lsr2c@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = source + * @size_t n@ = number of bits to move + * + * Returns: Result, @a@ shifted left or right by @n@. Handles the + * pretence of sign-extension for negative numbers. + */ + +mp *mp_lsl2c(mp *d, mp *a, size_t n) +{ + if (!MP_NEGP(a)) + return (mp_lsl(d, a, n)); + d = mp_not2c(d, a); + d = mp_lslc(d, d, n); + d = mp_not2c(d, d); + return (d); +} + +mp *mp_lsr2c(mp *d, mp *a, size_t n) +{ + if (!MP_NEGP(a)) + return (mp_lsr(d, a, n)); + d = mp_not2c(d, a); + d = mp_lsr(d, d, n); + d = mp_not2c(d, d); + return (d); +} + +/* --- @mp_testbit@ --- * + * + * Arguments: @mp *x@ = a large integer + * @unsigned long n@ = which bit to test + * + * Returns: Nonzero if the bit is set, zero if not. + */ + +int mp_testbit(mp *x, unsigned long n) +{ + if (n > MPW_BITS * MP_LEN(x)) + return (0); + return ((x->v[n/MPW_BITS] >> n%MPW_BITS) & 1u); +} + +/* --- @mp_testbit2c@ --- * + * + * Arguments: @mp *x@ = a large integer + * @unsigned long n@ = which bit to test + * + * Returns: Nonzero if the bit is set, zero if not. Fakes up two's + * complement representation. + */ + +int mp_testbit2c(mp *x, unsigned long n) +{ + int r; + if (!MP_NEGP(x)) + return (mp_testbit(x, n)); + x = mp_not2c(MP_NEW, x); + r = !mp_testbit(x, n); + MP_DROP(x); + return (r); +} + +/* --- @mp_setbit@, @mp_clearbit@ --- * + * + * Arguments: @mp *d@ = a destination + * @mp *x@ = a large integer + * @unsigned long n@ = which bit to modify + * + * Returns: The argument @x@, with the appropriate bit set or cleared. + */ + +mp *mp_setbit(mp *d, mp *x, unsigned long n) +{ + size_t rq; + + rq = n + MPW_BITS; rq -= rq % MPW_BITS; + if (d != x) { + if (d) MP_DROP(d); + d = MP_COPY(x); + } + MP_DEST(d, rq, x->f & (MP_NEG | MP_BURN)); + d->v[n/MPW_BITS] |= 1 << n%MPW_BITS; + return (d); +} + +mp *mp_clearbit(mp *d, mp *x, unsigned long n) +{ + size_t rq; + + rq = n + MPW_BITS; rq -= rq % MPW_BITS; + if (d != x) { + if (d) MP_DROP(d); + d = MP_COPY(x); + } + MP_DEST(d, rq, x->f & (MP_NEG | MP_BURN)); + d->v[n/MPW_BITS] &= ~(1 << n%MPW_BITS); + return (d); +} + +/* --- @mp_setbit2c@, @mp_clearbit2c@ --- * + * + * Arguments: @mp *d@ = a destination + * @mp *x@ = a large integer + * @unsigned long n@ = which bit to modify + * + * Returns: The argument @x@, with the appropriate bit set or cleared. + * Fakes up two's complement representation. + */ + +mp *mp_setbit2c(mp *d, mp *x, unsigned long n) +{ + if (!MP_NEGP(x)) + return mp_setbit(d, x, n); + d = mp_not2c(d, x); + d = mp_clearbit(d, d, n); + d = mp_not2c(d, d); + return (d); +} + +mp *mp_clearbit2c(mp *d, mp *x, unsigned long n) +{ + if (!MP_NEGP(x)) + return mp_clearbit(d, x, n); + d = mp_not2c(d, x); + d = mp_setbit(d, d, n); + d = mp_not2c(d, d); + return (d); +} + +/* --- @mp_eq@ --- * + * + * Arguments: @const mp *a, *b@ = two numbers + * + * Returns: Nonzero if the numbers are equal. + */ + +int mp_eq(const mp *a, const mp *b) { return (MP_EQ(a, b)); } + +/* --- @mp_cmp@ --- * + * + * Arguments: @const mp *a, *b@ = two numbers + * + * Returns: Less than, equal to or greater than zero, according to + * whether @a@ is less than, equal to or greater than @b@. + */ + +int mp_cmp(const mp *a, const mp *b) +{ + if (!((a->f ^ b->f) & MP_NEG)) { + if (a->f & MP_NEG) + return (-mpx_ucmp(a->v, a->vl, b->v, b->vl)); + else + return (mpx_ucmp(a->v, a->vl, b->v, b->vl)); + } else if (a->f & MP_NEG) + return (-1); + else + return (+1); +} + +/* --- @mp_neg@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = argument + * + * Returns: The negation of the argument. + * + * Use: Negates its argument. + */ + +mp *mp_neg(mp *d, mp *a) +{ + /* --- Surprising amounts of messing about required --- */ + + MP_SHRINK(a); + MP_COPY(a); + if (d) + MP_DROP(d); + if (a->v == a->vl) + return (a); + MP_DEST(a, MP_LEN(a), a->f); + a->f ^= MP_NEG; + return (a); +} + +/* --- @mp_bitop@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: The result of the given bitwise operation. These functions + * don't handle negative numbers at all sensibly. For that, use + * the @...2c@ variants. The functions are named after the + * truth tables they generate: + * + * a: 0011 + * b: 0101 + * @mpx_bitXXXX@ + */ + +#define MP_BITBINOP(string) \ + \ +mp *mp_bit##string(mp *d, mp *a, mp *b) \ +{ \ + MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)), (a->f | b->f) & ~MP_NEG); \ + mpx_bit##string(d->v, d->vl, a->v, a->vl, b->v, b->vl); \ + d->f = (a->f | b->f) & MP_BURN; \ + MP_SHRINK(d); \ + return (d); \ +} + +MPX_DOBIN(MP_BITBINOP) + +/* --- @mp_not@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = source + * + * Returns: The bitwise complement of the source. + */ + +mp *mp_not(mp *d, mp *a) +{ + MP_DEST(d, MP_LEN(a), a->f); + mpx_not(d->v, d->vl, a->v, a->vl); + d->f = a->f & MP_BURN; + MP_SHRINK(d); + return (d); +} + +/* --- @mp_bitop2c@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: The result of the given bitwise operation. Negative numbers + * are treated as two's complement, sign-extended infinitely to + * the left. The functions are named after the truth tables + * they generate: + * + * a: 0011 + * b: 0101 + * @mpx_bitXXXX@ + */ + +/* --- How this actually works --- * + * + * The two arguments are inverted (with a sign-swap) if they're currently + * negative. This means that we end up using a different function (one which + * reinverts as we go) for the main operation. Also, if the sign would be + * negative at the end, we preinvert the output and then invert again with a + * sign-swap. + * + * Start with: wxyz WXYZ + * If @a@ negative: yzwx or YZWX + * If @b@ negative: xwzy XWZY + * If both negative: zyxw ZYXW + */ + +#define MP_BIT2CBINOP(n, base, an, bn, abn, p_base, p_an, p_bn, p_abn) \ + \ +mp *mp_bit##n##2c(mp *d, mp *a, mp *b) \ +{ \ + if (!((a->f | b->f) & MP_NEG)) { /* Both positive */ \ + d = mp_bit##base(d, a, b); \ + p_base \ + } else if (!(b->f & MP_NEG)) { /* Only @b@ positive */ \ + MP_COPY(b); \ + d = mp_not2c(d, a); \ + d = mp_bit##an(d, d, b); \ + MP_DROP(b); \ + p_an \ + } else if (!(a->f & MP_NEG)) { /* Only @a@ positive */ \ + MP_COPY(a); \ + d = mp_not2c(d, b); \ + d = mp_bit##bn(d, a, d); \ + MP_DROP(a); \ + p_bn \ + } else { /* Both negative */ \ + mp *t = mp_not2c(MP_NEW, a); \ + d = mp_not2c(d, b); \ + d = mp_bit##abn(d, t, d); \ + MP_DROP(t); \ + p_abn \ + } \ + return (d); \ +} \ + +#define NEG d = mp_not2c(d, d); +#define POS +MP_BIT2CBINOP(0000, 0000, 0000, 0000, 0000, POS, POS, POS, POS) +MP_BIT2CBINOP(0001, 0001, 0100, 0010, 0111, POS, POS, POS, NEG) +MP_BIT2CBINOP(0010, 0010, 0111, 0001, 0100, POS, NEG, POS, POS) +MP_BIT2CBINOP(0011, 0011, 0011, 0011, 0011, POS, NEG, POS, NEG) +MP_BIT2CBINOP(0100, 0100, 0001, 0111, 0010, POS, POS, NEG, POS) +MP_BIT2CBINOP(0101, 0101, 0101, 0101, 0101, POS, POS, NEG, NEG) +MP_BIT2CBINOP(0110, 0110, 0110, 0110, 0110, POS, NEG, NEG, POS) +MP_BIT2CBINOP(0111, 0111, 0010, 0100, 0001, POS, NEG, NEG, NEG) +MP_BIT2CBINOP(1000, 0111, 0010, 0100, 0001, NEG, POS, POS, POS) +MP_BIT2CBINOP(1001, 0110, 0110, 0110, 0110, NEG, POS, POS, NEG) +MP_BIT2CBINOP(1010, 0101, 0101, 0101, 0101, NEG, NEG, POS, POS) +MP_BIT2CBINOP(1011, 0100, 0001, 0111, 0010, NEG, NEG, POS, NEG) +MP_BIT2CBINOP(1100, 0011, 0011, 0011, 0011, NEG, POS, NEG, POS) +MP_BIT2CBINOP(1101, 0010, 0111, 0001, 0100, NEG, POS, NEG, NEG) +MP_BIT2CBINOP(1110, 0001, 0100, 0010, 0111, NEG, NEG, NEG, POS) +MP_BIT2CBINOP(1111, 0000, 0000, 0000, 0000, NEG, NEG, NEG, NEG) +#undef NEG +#undef POS + +/* --- @mp_not2c@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = source + * + * Returns: The sign-extended complement of the argument. + */ + +mp *mp_not2c(mp *d, mp *a) +{ + mpw one = 1; + + MP_DEST(d, MP_LEN(a) + 1, a->f); + if (d == a) { + if (MP_NEGP(a)) + MPX_USUBN(d->v, d->vl, 1); + else + MPX_UADDN(d->v, d->vl, 1); + } else { + if (MP_NEGP(a)) + mpx_usub(d->v, d->vl, a->v, a->vl, &one, &one + 1); + else + mpx_uadd(d->v, d->vl, a->v, a->vl, &one, &one + 1); + } + d->f = (a->f & (MP_NEG | MP_BURN)) ^ MP_NEG; + MP_SHRINK(d); + return (d); +} + +/* --- @mp_add@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: Result, @a@ added to @b@. + */ + +mp *mp_add(mp *d, mp *a, mp *b) +{ + MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)) + 1, a->f | b->f); + if (!((a->f ^ b->f) & MP_NEG)) + mpx_uadd(d->v, d->vl, a->v, a->vl, b->v, b->vl); + else { + if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) { + mp *t = a; a = b; b = t; + } + mpx_usub(d->v, d->vl, a->v, a->vl, b->v, b->vl); + } + d->f = ((a->f | b->f) & MP_BURN) | (a->f & MP_NEG); + MP_SHRINK(d); + return (d); +} + +/* --- @mp_sub@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: Result, @b@ subtracted from @a@. + */ + +mp *mp_sub(mp *d, mp *a, mp *b) +{ + unsigned sgn = 0; + MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)) + 1, a->f | b->f); + if ((a->f ^ b->f) & MP_NEG) + mpx_uadd(d->v, d->vl, a->v, a->vl, b->v, b->vl); + else { + if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) { + mp *t = a; a = b; b = t; + sgn = MP_NEG; + } + mpx_usub(d->v, d->vl, a->v, a->vl, b->v, b->vl); + } + d->f = ((a->f | b->f) & MP_BURN) | ((a->f ^ sgn) & MP_NEG); + MP_SHRINK(d); + return (d); +} + +/* --- @mp_mul@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: Result, @a@ multiplied by @b@. + */ + +mp *mp_mul(mp *d, mp *a, mp *b) +{ + a = MP_COPY(a); + b = MP_COPY(b); + + if (MP_LEN(a) <= MPK_THRESH || MP_LEN(b) <= MPK_THRESH) { + MP_DEST(d, MP_LEN(a) + MP_LEN(b), a->f | b->f | MP_UNDEF); + mpx_umul(d->v, d->vl, a->v, a->vl, b->v, b->vl); + } else { + size_t m = MAX(MP_LEN(a), MP_LEN(b)); + mpw *s; + MP_DEST(d, 3 * m, a->f | b->f | MP_UNDEF); + s = mpalloc(d->a, 5 * m); + mpx_kmul(d->v, d->vl, a->v, a->vl, b->v, b->vl, s, s + 5 * m); + mpfree(d->a, s); + } + + d->f = ((a->f | b->f) & MP_BURN) | ((a->f ^ b->f) & MP_NEG); + MP_SHRINK(d); + MP_DROP(a); + MP_DROP(b); + return (d); +} + +/* --- @mp_sqr@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = source + * + * Returns: Result, @a@ squared. + */ + +mp *mp_sqr(mp *d, mp *a) +{ + size_t m = MP_LEN(a); + + a = MP_COPY(a); + if (m > MPK_THRESH) { + mpw *s; + MP_DEST(d, 3 * m, a->f | MP_UNDEF); + s = mpalloc(d->a, 5 * m); + mpx_ksqr(d->v, d->vl, a->v, a->vl, s, s + 5 * m); + mpfree(d->a, s); + } else { + MP_DEST(d, 2 * m + 2, a->f | MP_UNDEF); + mpx_usqr(d->v, d->vl, a->v, a->vl); + } + d->f = a->f & MP_BURN; + MP_SHRINK(d); + MP_DROP(a); + return (d); +} + +/* --- @mp_div@ --- * + * + * Arguments: @mp **qq, **rr@ = destination, quotient and remainder + * @mp *a, *b@ = sources + * + * Use: Calculates the quotient and remainder when @a@ is divided by + * @b@. The destinations @*qq@ and @*rr@ must be distinct. + * Either of @qq@ or @rr@ may be null to indicate that the + * result is irrelevant. (Discarding both results is silly.) + * There is a performance advantage if @a == *rr@. + * + * The behaviour when @a@ and @b@ have the same sign is + * straightforward. When the signs differ, this implementation + * chooses @r@ to have the same sign as @b@, rather than the + * more normal choice that the remainder has the same sign as + * the dividend. This makes modular arithmetic a little more + * straightforward. + */ + +void mp_div(mp **qq, mp **rr, mp *a, mp *b) + { + mp *r = rr ? *rr : MP_NEW; + mp *q = qq ? *qq : MP_NEW; + mpw *sv, *svl; + + /* --- Set the remainder up right --- * + * + * Just in case the divisor is larger, be able to cope with this. It's not + * important in @mpx_udiv@, but it is here because of the sign correction. + */ + + b = MP_COPY(b); + a = MP_COPY(a); + if (r) + MP_DROP(r); + r = a; + MP_DEST(r, MAX(MP_LEN(a), MP_LEN(b)) + 2, a->f | b->f); + + /* --- Fix up the quotient too --- */ + + r = MP_COPY(r); + MP_DEST(q, MP_LEN(r), r->f | MP_UNDEF); + MP_DROP(r); + + /* --- Set up some temporary workspace --- */ + + { + size_t rq = MP_LEN(b) + 1; + sv = mpalloc(r->a, rq); + svl = sv + rq; + } + + /* --- Perform the calculation --- */ + + mpx_udiv(q->v, q->vl, r->v, r->vl, b->v, b->vl, sv, svl); + + /* --- Sort out the sign of the results --- * + * + * If the signs of the arguments differ, and the remainder is nonzero, I + * must add one to the absolute value of the quotient and subtract the + * remainder from @b@. + */ + + q->f = ((r->f | b->f) & MP_BURN) | ((r->f ^ b->f) & MP_NEG); + if (MP_NEGP(q)) { + mpw *v; + for (v = r->v; v < r->vl; v++) { + if (*v) { + MPX_UADDN(q->v, q->vl, 1); + mpx_usub(r->v, r->vl, b->v, b->vl, r->v, r->vl); + break; + } + } + } + + r->f = ((r->f | b->f) & MP_BURN) | (b->f & MP_NEG); + + /* --- Store the return values --- */ + + mpfree(r->a, sv); + MP_DROP(b); + + if (!qq) + MP_DROP(q); + else { + MP_SHRINK(q); + *qq = q; + } + + if (!rr) + MP_DROP(r); + else { + MP_SHRINK(r); + *rr = r; + } +} + +/* --- @mp_odd@ --- * + * + * Arguments: @mp *d@ = pointer to destination integer + * @mp *m@ = pointer to source integer + * @size_t *s@ = where to store the power of 2 + * + * Returns: An odd integer integer %$t$% such that %$m = 2^s t$%. + * + * Use: Computes a power of two and an odd integer which, when + * multiplied, give a specified result. This sort of thing is + * useful in number theory quite often. + */ + +mp *mp_odd(mp *d, mp *m, size_t *s) +{ + size_t ss = 0; + const mpw *v, *vl; + + v = m->v; + vl = m->vl; + for (; !*v && v < vl; v++) + ss += MPW_BITS; + if (v >= vl) + ss = 0; + else { + mpw x = *v; + unsigned z = MPW_P2; + mpw mask = ((mpw)1 << z) - 1; + + while (z) { + if (!(x & mask)) { + x >>= z; + ss += z; + } + z >>= 1; + mask >>= z; + } + } + + *s = ss; + return (mp_lsr(d, m, ss)); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int verify(const char *op, mp *expect, mp *result, mp *a, mp *b) +{ + if (!MP_EQ(expect, result)) { + fprintf(stderr, "\n*** %s failed", op); + fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 10); + fputs("\n*** b = ", stderr); mp_writefile(b, stderr, 10); + fputs("\n*** result = ", stderr); mp_writefile(result, stderr, 10); + fputs("\n*** expect = ", stderr); mp_writefile(expect, stderr, 10); + fputc('\n', stderr); + return (0); + } + return (1); +} + +#define RIG(name, op) \ + static int t##name(dstr *v) \ + { \ + mp *a = *(mp **)v[0].buf; \ + mpw n = *(int *)v[1].buf; \ + mp b; \ + mp *r = *(mp **)v[2].buf; \ + mp *c = op(MP_NEW, a, n); \ + int ok; \ + mp_build(&b, &n, &n + 1); \ + ok = verify(#name, r, c, a, &b); \ + mp_drop(a); mp_drop(c); mp_drop(r); \ + assert(mparena_count(MPARENA_GLOBAL) == 0); \ + return (ok); \ + } + +RIG(lsl, mp_lsl) +RIG(lsr, mp_lsr) +RIG(lsl2c, mp_lsl2c) +RIG(lsr2c, mp_lsr2c) + +#undef RIG + +#define RIG(name, op) \ + static int t##name(dstr *v) \ + { \ + mp *a = *(mp **)v[0].buf; \ + mp *b = *(mp **)v[1].buf; \ + mp *r = *(mp **)v[2].buf; \ + mp *c = op(MP_NEW, a, b); \ + int ok = verify(#name, r, c, a, b); \ + mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(r); \ + assert(mparena_count(MPARENA_GLOBAL) == 0); \ + return (ok); \ + } + +RIG(add, mp_add) +RIG(sub, mp_sub) +RIG(mul, mp_mul) +RIG(exp, mp_exp) + +#undef RIG + +static int tdiv(dstr *v) +{ + mp *a = *(mp **)v[0].buf; + mp *b = *(mp **)v[1].buf; + mp *q = *(mp **)v[2].buf; + mp *r = *(mp **)v[3].buf; + mp *c = MP_NEW, *d = MP_NEW; + int ok = 1; + mp_div(&c, &d, a, b); + ok &= verify("div(quotient)", q, c, a, b); + ok &= verify("div(remainder)", r, d, a, b); + mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(d); mp_drop(r); mp_drop(q); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tbin(dstr *v) +{ + static mp *(*fn[])(mp *, mp *, mp *) = { +#define DO(string) mp_bit##string##2c, +MPX_DOBIN(DO) +#undef DO + }; + int ok = 1; + unsigned op = 0; + mp *a = *(mp **)v[1].buf; + mp *b = *(mp **)v[2].buf; + mp *r = *(mp **)v[3].buf; + mp *c; + + if (strcmp(v[0].buf, "and") == 0) op = 1; + else if (strcmp(v[0].buf, "or") == 0) op = 7; + else if (strcmp(v[0].buf, "nand") == 0) op = 14; + else if (strcmp(v[0].buf, "nor") == 0) op = 8; + else if (strcmp(v[0].buf, "xor") == 0) op = 6; + else { + char *p = v[0].buf; + while (*p) { + op <<= 1; + if (*p++ == '1') + op |= 1; + } + } + + c = fn[op](MP_NEW, a, b); + ok = verify(v[0].buf, r, c, a, b); + mp_drop(a); mp_drop(b); mp_drop(r); mp_drop(c); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tset(dstr *v) +{ + mp *a = *(mp **)v[0].buf; + unsigned long n = *(unsigned long *)v[1].buf; + mp *r = *(mp **)v[2].buf; + mp *c; + int ok = 1; + + c = mp_setbit2c(MP_NEW, a, n); + if (!MP_EQ(c, r)) { + ok = 0; + fprintf(stderr, "\n***setbit (set) failed"); + fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 16); + fprintf(stderr, "\n*** n = %lu", n); + fputs("\n*** r = ", stderr); mp_writefile(r, stderr, 16); + fputs("\n*** c = ", stderr); mp_writefile(c, stderr, 16); + fputc('\n', stderr); + } + if (!mp_testbit2c(r, n)) { + ok = 0; + fprintf(stderr, "\n***setbit (test) failed"); + fprintf(stderr, "\n*** n = %lu", n); + fputs("\n*** r = ", stderr); mp_writefile(r, stderr, 16); + fputc('\n', stderr); + } + mp_drop(a); + mp_drop(r); + mp_drop(c); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tclr(dstr *v) +{ + mp *a = *(mp **)v[0].buf; + unsigned long n = *(unsigned long *)v[1].buf; + mp *r = *(mp **)v[2].buf; + mp *c; + int ok = 1; + + c = mp_clearbit2c(MP_NEW, a, n); + if (!MP_EQ(c, r)) { + ok = 0; + fprintf(stderr, "\n***clrbit (set) failed"); + fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 16); + fprintf(stderr, "\n*** n = %lu", n); + fputs("\n*** r = ", stderr); mp_writefile(r, stderr, 16); + fputs("\n*** c = ", stderr); mp_writefile(c, stderr, 16); + fputc('\n', stderr); + } + if (mp_testbit2c(r, n)) { + ok = 0; + fprintf(stderr, "\n***clrbit (test) failed"); + fprintf(stderr, "\n*** n = %lu", n); + fputs("\n*** r = ", stderr); mp_writefile(r, stderr, 16); + fputc('\n', stderr); + } + mp_drop(a); + mp_drop(c); + mp_drop(r); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tneg(dstr *v) +{ + mp *a = *(mp **)v[0].buf; + mp *r = *(mp **)v[1].buf; + int ok = 1; + mp *n = mp_neg(MP_NEW, a); + if (!MP_EQ(r, n)) { + ok = 0; + fprintf(stderr, "\n*** neg failed\n"); + fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 10); + fputs("\n*** r = ", stderr); mp_writefile(r, stderr, 10); + fputs("\n*** n = ", stderr); mp_writefile(n, stderr, 10); + fputc('\n', stderr); + } + mp_drop(n); + n = mp_neg(a, a); + if (!MP_EQ(r, n)) { + ok = 0; + fprintf(stderr, "\n*** neg failed\n"); + fputs("\n*** a* = ", stderr); mp_writefile(a, stderr, 10); + fputs("\n*** r = ", stderr); mp_writefile(r, stderr, 10); + fputs("\n*** n = ", stderr); mp_writefile(n, stderr, 10); + fputc('\n', stderr); + } + mp_drop(a); + mp_drop(r); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int todd(dstr *v) +{ + mp *a = *(mp **)v[0].buf; + size_t rs = *(uint32 *)v[1].buf; + mp *rt = *(mp **)v[2].buf; + int ok = 1; + mp *t; + size_t s; + t = mp_odd(MP_NEW, a, &s); + if (s != rs || !MP_EQ(t, rt)) { + ok = 0; + fprintf(stderr, "\n*** odd failed"); + fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 10); + fprintf(stderr, "\n*** s = %lu", (unsigned long)s); + fputs("\n*** t = ", stderr); mp_writefile(t, stderr, 10); + fprintf(stderr, "\n*** rs = %lu", (unsigned long)rs); + fputs("\n*** rt = ", stderr); mp_writefile(rt, stderr, 10); + fputc('\n', stderr); + } + mp_drop(a); + mp_drop(rt); + mp_drop(t); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "lsl", tlsl, { &type_mp, &type_int, &type_mp, 0 } }, + { "lsr", tlsr, { &type_mp, &type_int, &type_mp, 0 } }, + { "lsl2c", tlsl2c, { &type_mp, &type_int, &type_mp, 0 } }, + { "lsr2c", tlsr2c, { &type_mp, &type_int, &type_mp, 0 } }, + { "setbit", tset, { &type_mp, &type_ulong, &type_mp, 0 } }, + { "clrbit", tclr, { &type_mp, &type_ulong, &type_mp, 0 } }, + { "add", tadd, { &type_mp, &type_mp, &type_mp, 0 } }, + { "sub", tsub, { &type_mp, &type_mp, &type_mp, 0 } }, + { "mul", tmul, { &type_mp, &type_mp, &type_mp, 0 } }, + { "div", tdiv, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, + { "exp", texp, { &type_mp, &type_mp, &type_mp, 0 } }, + { "bin2c", tbin, { &type_string, &type_mp, &type_mp, &type_mp, 0 } }, + { "odd", todd, { &type_mp, &type_uint32, &type_mp, 0 } }, + { "neg", tneg, { &type_mp, &type_mp, 0 } }, + { 0, 0, { 0 } }, +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mp"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mp-const.c b/math/mp-const.c new file mode 100644 index 0000000..b35a0e6 --- /dev/null +++ b/math/mp-const.c @@ -0,0 +1,49 @@ +/* -*-c-*- + * + * Useful multiprecision constants + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" + +/*----- Global variables --------------------------------------------------*/ + +static mpw mpw_const[] = { 1, 2, 3, 4, 5, 10, 256 }; + +mp mp_const[] = { + { &mpw_const[0], &mpw_const[0], 0, 0, MP_CONST, 0 }, + { &mpw_const[0], &mpw_const[0] + 1, 1, 0, MP_CONST, 0 }, + { &mpw_const[1], &mpw_const[1] + 1, 1, 0, MP_CONST, 0 }, + { &mpw_const[2], &mpw_const[2] + 1, 1, 0, MP_CONST, 0 }, + { &mpw_const[3], &mpw_const[3] + 1, 1, 0, MP_CONST, 0 }, + { &mpw_const[4], &mpw_const[4] + 1, 1, 0, MP_CONST, 0 }, + { &mpw_const[5], &mpw_const[5] + 1, 1, 0, MP_CONST, 0 }, + { &mpw_const[6], &mpw_const[6] + 1, 1, 0, MP_CONST, 0 }, + { &mpw_const[0], &mpw_const[0] + 1, 1, 0, MP_CONST | MP_NEG, 0 }, + { 0, mpw_const, 1, 0, MP_CONST | MP_BURN, 0 }, +}; + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mp-exp.c b/math/mp-exp.c new file mode 100644 index 0000000..9ef2fa0 --- /dev/null +++ b/math/mp-exp.c @@ -0,0 +1,65 @@ +/* -*-c-*- + * + * Exponentiation for large integers + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "mp.h" +#include "mp-exp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mp_exp@ --- * + * + * Arguments: @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e$%. + */ + +mp *mp_exp(mp *d, mp *a, mp *e) +{ + mp *x = MP_ONE; + mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; + assert(!MP_NEGP(e)); + + MP_COPY(a); + if (MP_ZEROP(e)) + ; + else if (MP_LEN(e) < EXP_THRESH) + EXP_SIMPLE(x, a, e); + else + EXP_WINDOW(x, a, e); + mp_drop(d); + mp_drop(spare); + mp_drop(a); + return (x); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mp-exp.h b/math/mp-exp.h new file mode 100644 index 0000000..d0fce30 --- /dev/null +++ b/math/mp-exp.h @@ -0,0 +1,67 @@ +/* -*-c-*- + * + * Exponentiation for large integers + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MP_EXP_H +#define CATACOMB_MP_EXP_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Exponentiation ----------------------------------------------------*/ + +#define EXP_TYPE mp * + +#define EXP_COPY(d, x) d = MP_COPY(x) +#define EXP_DROP(x) MP_DROP(x) + +#define EXP_MUL(a, x) do { \ + mp *t = mp_mul(spare, a, x); \ + spare = a; \ + a = t; \ +} while (0) + +#define EXP_SQR(a) do { \ + mp *t = mp_sqr(spare, a); \ + spare = a; \ + a = t; \ +} while (0) + +#define EXP_FIX(x) + +#define EXP_SETMUL(d, x, y) d = mp_mul(MP_NEW, x, y) +#define EXP_SETSQR(d, x) d = mp_sqr(MP_NEW, x) + +#include "exp.h" + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mp-fibonacci.c b/math/mp-fibonacci.c new file mode 100644 index 0000000..9b37ebf --- /dev/null +++ b/math/mp-fibonacci.c @@ -0,0 +1,271 @@ +/* -*-c-*- + * + * Compute the %$n$%th Fibonacci number + * + * (c) 2013 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpint.h" + +/*----- About the algorithm -----------------------------------------------* + * + * Define %$F_0 = 0$% and %$F_1 = 1$%, and %$F_{k+1} = F_k + F_{k-1}$% for + * all %$k$%. (This defines %$F_k$% for negative %$k$% too, by + * %$F_{k-1} = F_{k+1} - F_k$%; in particular, %$F_{-1} = 1$% and + * %$F_{-2} = -1$%.) We say that %$F_k$% is the %$k$%th Fibonacci number. + * + * We work in the ring %$\ZZ[t]/(t^2 - t -1)$%. Every residue class in this + * ring contains a unique representative with degree at most 1. I claim that + * %$t^k = F_k t + F_{k-1}$% for all %$k$%. Certainly %$t = F_1 t + F_0$%. + * Note that %$t (F_{-1} t + F_{-2}) = t (t - 1) = t^2 - t = 1$%, so the + * claim holds for %$k = -1$%. Suppose, inductively, that it holds for + * %$k$%; then %$t^{k+1} = t \cdot t^k = F_k t^2 + F_{k-1} t = {}$% + * %$(F_k + F_{k-1}) t + F_k = F_{k+1} t + F_k$%; and %$t^{k-1} = {}$% + * %$t^{-1} t^k = (t - 1) t^k = t^{k+1} - t^k = {}$% + * %$(F_{k+1} - F_k) t + (F_k - F_{k-1}) = F_{k-1} t + F_{k-2}$%, proving the + * claim. + * + * So we can compute Fibonacci numbers by exponentiating in this ring. + * Squaring and multiplication work like this. + * + * * Square: %$(a t + b)^2 = a^2 t^2 + 2 a b t + b^2 = {}$% + * %$(a^2 + 2 a b) t + (a^2 + b^2)$% + * + * * Multiply: %$(a t + b)(c t + d) = a c t^2 + (a d + b c) t + b d = {}$% + * %$(a c + a d + b c) t + (a c + b d)$%. + */ + +/*----- Exponentiation machinery ------------------------------------------*/ + +/* --- @struct fib@ --- * + * + * A simple structure tracking polynomial coefficients. + */ + +struct fib { + int n; /* Exponent for this entry */ + mp *a, *b; /* Coefficients: %$a t + b$% */ +}; + +#define MAX 100 /* Saturation bounds for exponent */ +#define MIN -100 + +/* --- @CLAMP@ --- * + * + * Clamp @n@ within the upper and lower bounds. + */ + +#define CLAMP(n) do { \ + if (n > MAX) n = MAX; else if (n < MIN) n = MIN; \ +} while (0) + +/* --- Basic structure maintenance functions --- */ + +static void fib_init(struct fib *f) + { f->a = f->b = MP_NEW; } + +static void fib_drop(struct fib *f) + { if (f->a) MP_DROP(f->a); if (f->b) MP_DROP(f->b); } + +static void fib_copy(struct fib *d, struct fib *x) + { d->n = x->n; d->a = MP_COPY(x->a); d->b = MP_COPY(x->b); } + +/* --- @fib_sqr@ --- * + * + * Arguments: @struct fib *d@ = destination structure + * @struct fib *x@ = operand + * + * Returns: --- + * + * Use: Set @d@ to the square of @x@. + */ + +static void fib_sqr(struct fib *d, struct fib *x) +{ + mp *aa, *t; + + /* --- Special case: if @x@ is the identity then just copy --- */ + + if (!x->n) { + if (d != x) { fib_drop(d); fib_copy(d, x); } + return; + } + + /* --- Compute the result --- */ + + aa = mp_sqr(MP_NEW, x->a); /* %$a^2$% */ + + t = mp_mul(d->a, x->a, x->b); /* %$t = a b$% */ + t = mp_lsl(t, t, 1); /* %$t = 2 a b$% */ + d->a = mp_add(t, t, aa); /* %$a' = a^2 + 2 a b$% */ + + t = mp_sqr(d->b, x->b); /* %$t = b^2$% */ + d->b = mp_add(t, t, aa); /* %$b' = a^2 + b^2$% */ + + /* --- Sort out the exponent on the result --- */ + + d->n = 2*x->n; CLAMP(d->n); + + /* --- Done --- */ + + MP_DROP(aa); +} + +/* --- @fib_mul@ --- * + * + * Arguments: @struct fib *d@ = destination structure + * @struct fib *x, *y@ = operands + * + * Returns: --- + * + * Use: Set @d@ to the product of @x@ and @y@. + */ + +static void fib_mul(struct fib *d, struct fib *x, struct fib *y) +{ + mp *t, *u, *bd; + + /* --- Lots of special cases for low exponents --- */ + + if (y->n == 0) { + copy_x: + if (d != x) { fib_drop(d); fib_copy(d, x); } + return; + } else if (x->n == 0) { x = y; goto copy_x; } + else if (y->n == -1) { + dec_x: + t = mp_sub(d->a, x->a, x->b); + d->a = MP_COPY(x->b); if (d->b) MP_DROP(d->b); d->b = t; + d->n = x->n - 1; CLAMP(d->n); + return; + } else if (y->n == +1) { + inc_x: + t = mp_add(d->b, x->a, x->b); + d->b = MP_COPY(x->a); if (d->a) MP_DROP(d->a); d->a = t; + d->n = x->n + 1; CLAMP(d->n); + return; + } else if (x->n == -1) { x = y; goto dec_x; } + else if (x->n == +1) { x = y; goto inc_x; } + + /* --- Compute the result --- */ + + bd = mp_mul(MP_NEW, x->b, y->b); /* %$b d$% */ + t = mp_add(MP_NEW, x->a, x->b); /* %$t = a + b$% */ + u = mp_add(MP_NEW, y->a, y->b); /* %$u = c + d$% */ + t = mp_mul(t, t, u); /* %$t = (a + b)(c + d)$% */ + u = mp_mul(u, x->a, y->a); /* %$u = a c$% */ + + d->a = mp_sub(d->a, t, bd); /* %$a' = a c + a d + b c$% */ + d->b = mp_add(d->b, u, bd); /* %$b' = a c + b d$% */ + + /* --- Sort out the exponent on the result --- */ + + if (x->n == MIN || x->n == MAX) d->n = x->n; + else if (y->n == MIN || y->n == MAX) d->n = y->n; + else { d->n = x->n + y->n; CLAMP(d->n); } + + /* --- Done --- */ + + MP_DROP(bd); MP_DROP(t); MP_DROP(u); +} + +/* --- Exponentiation --- */ + +#define EXP_TYPE struct fib +#define EXP_COPY(d, x) fib_copy(&d, &x) +#define EXP_DROP(x) fib_drop(&x) +#define EXP_FIX(d) + +#define EXP_SQR(x) fib_sqr(&x, &x) +#define EXP_MUL(x, y) fib_mul(&x, &x, &y) +#define EXP_SETSQR(d, x) fib_init(&d); fib_sqr(&d, &x) +#define EXP_SETMUL(d, x, y) fib_init(&d); fib_mul(&d, &x, &y) + +#include "exp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mp_fibonacci@ --- * + * + * Arguments: @long n@ = index desired (may be negative) + * + * Returns: The %$n$%th Fibonacci number. + */ + +mp *mp_fibonacci(long n) +{ + struct fib d, g; + mp *nn; + + d.n = 0; d.a = MP_ZERO; d.b = MP_ONE; + if (n >= 0) { g.n = 1; g.a = MP_ONE; g.b = MP_ZERO; } + else { g.n = -1; g.a = MP_ONE; g.b = MP_MONE; n = -n; } + nn = mp_fromlong(MP_NEW, n); + + EXP_WINDOW(d, g, nn); + + MP_DROP(nn); fib_drop(&g); MP_DROP(d.b); + return (d.a); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +static int vfib(dstr *v) +{ + long x = *(long *)v[0].buf; + mp *fx = *(mp **)v[1].buf; + mp *y = mp_fibonacci(x); + int ok = 1; + if (!MP_EQ(fx, y)) { + fprintf(stderr, "fibonacci failed\n"); + MP_FPRINTF(stderr, (stderr, "fib(%ld) = ", x), fx); + MP_EPRINT("result", y); + ok = 0; + } + mp_drop(fx); + mp_drop(y); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "fibonacci", vfib, { &type_long, &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, tests, SRCDIR "/t/mp"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp-fibonacci.h b/math/mp-fibonacci.h similarity index 100% rename from mp-fibonacci.h rename to math/mp-fibonacci.h diff --git a/math/mp-gcd.c b/math/mp-gcd.c new file mode 100644 index 0000000..6e059e3 --- /dev/null +++ b/math/mp-gcd.c @@ -0,0 +1,345 @@ +/* -*-c-*- + * + * Extended GCD calculation + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mp_gcd@ --- * + * + * Arguments: @mp **gcd, **xx, **yy@ = where to write the results + * @mp *a, *b@ = sources (must be nonzero) + * + * Returns: --- + * + * Use: Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that + * @ax + by = gcd(a, b)@. This is useful for computing modular + * inverses. + */ + +void mp_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b) +{ + mp *x = MP_ONE, *X = MP_ZERO; + mp *y = MP_ZERO, *Y = MP_ONE; + mp *u, *v; + mp *q = MP_NEW, *t, *spare = MP_NEW; + unsigned f = 0; + +#define f_swap 1u +#define f_aneg 2u +#define f_bneg 4u +#define f_ext 8u + + /* --- Sort out some initial flags --- */ + + if (xx || yy) + f |= f_ext; + + if (MP_NEGP(a)) + f |= f_aneg; + if (MP_NEGP(b)) + f |= f_bneg; + + /* --- Ensure that @a@ is larger than @b@ --- * + * + * Use absolute values here! + */ + + if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) { + t = a; a = b; b = t; + f |= f_swap; + } + + /* --- Check for zeroness --- */ + + if (MP_ZEROP(b)) { + + /* --- Store %$|a|$% as the GCD --- */ + + if (gcd) { + if (*gcd) MP_DROP(*gcd); + a = MP_COPY(a); + if (MP_NEGP(a)) { + MP_SPLIT(a); + a->f &= ~MP_NEG; + f |= f_aneg; + } + *gcd = a; + } + + /* --- Store %$1$% and %$0$% in the appropriate bins --- */ + + if (f & f_ext) { + if (f & f_swap) { + mp **tt = xx; xx = yy; yy = tt; + } + if (xx) { + if (*xx) MP_DROP(*xx); + if (MP_EQ(a, MP_ZERO)) + *xx = MP_ZERO; + else if (f & f_aneg) + *xx = MP_MONE; + else + *xx = MP_ONE; + } + if (yy) { + if (*yy) MP_DROP(*yy); + *yy = MP_ZERO; + } + } + return; + } + + /* --- Force the signs on the arguments and take copies --- */ + + a = MP_COPY(a); + b = MP_COPY(b); + + MP_SPLIT(a); a->f &= ~MP_NEG; + MP_SPLIT(b); b->f &= ~MP_NEG; + + u = MP_COPY(a); + v = MP_COPY(b); + + /* --- Main extended Euclidean algorithm --- */ + + while (!MP_ZEROP(v)) { + mp_div(&q, &u, u, v); + if (f & f_ext) { + t = mp_mul(spare, X, q); + t = mp_sub(t, x, t); + spare = x; x = X; X = t; + t = mp_mul(spare, Y, q); + t = mp_sub(t, y, t); + spare = y; y = Y; Y = t; + } + t = u; u = v; v = t; + } + + MP_DROP(q); if (spare) MP_DROP(spare); + if (!gcd) + MP_DROP(u); + else { + if (*gcd) MP_DROP(*gcd); + u->f &= ~MP_NEG; + *gcd = u; + } + + /* --- Perform a little normalization --- * + * + * Ensure that the coefficient returned is positive, if there is only one. + * If there are two, favour @y@. Of course, if the original arguments were + * negative then I'll need to twiddle their signs as well. + */ + + if (f & f_ext) { + + /* --- If @a@ and @b@ got swapped, swap the coefficients back --- */ + + if (f & f_swap) { + t = x; x = y; y = t; + t = a; a = b; b = t; + } + + /* --- Sort out the signs --- * + * + * Note that %$ax + by = a(x - b) + b(y + a)$%. + * + * This is currently bodgy. It needs sorting out at some time. + */ + + if (yy) { + if (MP_NEGP(y)) { + do { + y = mp_add(y, y, a); + x = mp_sub(x, x, b); + } while (MP_NEGP(y)); + } else { + while (MP_CMP(y, >=, a)) { + y = mp_sub(y, y, a); + x = mp_add(x, x, b); + } + } + } else { + if (MP_NEGP(x)) { + do + x = mp_add(x, x, b); + while (MP_NEGP(x)); + } else { + while (MP_CMP(x, >=, b)) + x = mp_sub(x, x, b); + } + } + + /* --- Twiddle the signs --- */ + + if (f & f_aneg) + x->f ^= MP_NEG; + if (f & f_bneg) + y->f ^= MP_NEG; + + /* --- Store the results --- */ + + if (!xx) + MP_DROP(x); + else { + if (*xx) MP_DROP(*xx); + *xx = x; + } + + if (!yy) + MP_DROP(y); + else { + if (*yy) MP_DROP(*yy); + *yy = y; + } + } + + MP_DROP(v); + MP_DROP(X); MP_DROP(Y); + MP_DROP(a); MP_DROP(b); +} + +/* -- @mp_modinv@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *x@ = argument + * @mp *p@ = modulus + * + * Returns: The inverse %$x^{-1} \bmod p$%. + * + * Use: Computes a modular inverse. An assertion fails if %$p$% + * has no inverse. + */ + +mp *mp_modinv(mp *d, mp *x, mp *p) +{ + mp *g = MP_NEW; + mp_gcd(&g, 0, &d, p, x); + assert(MP_EQ(g, MP_ONE)); + mp_drop(g); + return (d); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int modinv(dstr *v) +{ + int ok = 1; + mp *x = *(mp **)v[0].buf; + mp *m = *(mp **)v[1].buf; + mp *r = *(mp **)v[2].buf; + + mp *y = mp_modinv(MP_NEW, x, m); + if (!MP_EQ(y, r)) { + fputs("\n*** mp_modinv failed", stderr); + fputs("\nx = ", stderr); mp_writefile(x, stderr, 10); + fputs("\nm = ", stderr); mp_writefile(m, stderr, 10); + fputs("\nexpect = ", stderr); mp_writefile(r, stderr, 10); + fputs("\nresult = ", stderr); mp_writefile(y, stderr, 10); + ok = 0; + } + MP_DROP(x); MP_DROP(m); MP_DROP(r); MP_DROP(y); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int gcd(dstr *v) +{ + int ok = 1; + mp *a = *(mp **)v[0].buf; + mp *b = *(mp **)v[1].buf; + mp *g = *(mp **)v[2].buf; + mp *x = *(mp **)v[3].buf; + mp *y = *(mp **)v[4].buf; + + mp *gg = MP_NEW, *xx = MP_NEW, *yy = MP_NEW; + mp_gcd(&gg, &xx, &yy, a, b); + if (!MP_EQ(x, xx)) { + fputs("\n*** mp_gcd(x) failed", stderr); + fputs("\na = ", stderr); mp_writefile(a, stderr, 10); + fputs("\nb = ", stderr); mp_writefile(b, stderr, 10); + fputs("\nexpect = ", stderr); mp_writefile(x, stderr, 10); + fputs("\nresult = ", stderr); mp_writefile(xx, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + if (!MP_EQ(y, yy)) { + fputs("\n*** mp_gcd(y) failed", stderr); + fputs("\na = ", stderr); mp_writefile(a, stderr, 10); + fputs("\nb = ", stderr); mp_writefile(b, stderr, 10); + fputs("\nexpect = ", stderr); mp_writefile(y, stderr, 10); + fputs("\nresult = ", stderr); mp_writefile(yy, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + if (!ok) { + mp *ax = mp_mul(MP_NEW, a, xx); + mp *by = mp_mul(MP_NEW, b, yy); + ax = mp_add(ax, ax, by); + if (MP_EQ(ax, gg)) + fputs("\n*** (Alternative result found.)\n", stderr); + MP_DROP(ax); + MP_DROP(by); + } + + if (!MP_EQ(g, gg)) { + fputs("\n*** mp_gcd(gcd) failed", stderr); + fputs("\na = ", stderr); mp_writefile(a, stderr, 10); + fputs("\nb = ", stderr); mp_writefile(b, stderr, 10); + fputs("\nexpect = ", stderr); mp_writefile(g, stderr, 10); + fputs("\nresult = ", stderr); mp_writefile(gg, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + MP_DROP(a); MP_DROP(b); MP_DROP(g); MP_DROP(x); MP_DROP(y); + MP_DROP(gg); MP_DROP(xx); MP_DROP(yy); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "gcd", gcd, { &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, + { "modinv", modinv, { &type_mp, &type_mp, &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mp"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mp-io.c b/math/mp-io.c new file mode 100644 index 0000000..d7046f3 --- /dev/null +++ b/math/mp-io.c @@ -0,0 +1,279 @@ +/* -*-c-*- + * + * Loading and storing of multiprecision integers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mp_octets@ --- * + * + * Arguments: @const mp *m@ = a multiprecision integer + * + * Returns: The number of octets required to represent @m@. + * + * Use: Calculates the external storage required for a multiprecision + * integer. + */ + +size_t mp_octets(const mp *m) +{ + size_t sz; + MPX_OCTETS(sz, m->v, m->vl); + return (sz); +} + +/* --- @mp_octets2c@ --- * + * + * Arguments: @const mp *m@ = a multiprecision integer + * + * Returns: The number of octets required to represent @m@. + * + * Use: Calculates the external storage required for a multiprecision + * integer represented as two's complement. + */ + +size_t mp_octets2c(const mp *m) +{ + size_t sz; + MPX_OCTETS2C(sz, m->v, m->vl); + return (sz); +} + +/* --- @mp_bits@ --- * + * + * Arguments: @const mp *m@ = a multiprecision integer + * + * Returns: The number of bits required to represent @m@. + * + * Use: Calculates the external storage required for a multiprecision + * integer. + */ + +unsigned long mp_bits(const mp *m) +{ + unsigned long bits; + MPX_BITS(bits, m->v, m->vl); + return (bits); +} + +/* --- @mp_loadl@ --- * + * + * Arguments: @mp *d@ = destination + * @const void *pv@ = pointer to source data + * @size_t sz@ = size of the source data + * + * Returns: Resulting multiprecision number. + * + * Use: Loads a multiprecision number from an array of octets. The + * first byte in the array is the least significant. More + * formally, if the bytes are %$b_0, b_1, \ldots, b_{n-1}$% + * then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%. + */ + +mp *mp_loadl(mp *d, const void *pv, size_t sz) +{ + MP_DEST(d, MPW_RQ(sz), MP_UNDEF); + mpx_loadl(d->v, d->vl, pv, sz); + d->f &= ~(MP_UNDEF | MP_NEG); + mp_shrink(d); + return (d); +} + +/* --- @mp_storel@ --- * + * + * Arguments: @const mp *m@ = source + * @void *pv@ = pointer to output array + * @size_t sz@ = size of the output array + * + * Returns: --- + * + * Use: Stores a multiprecision number in an array of octets. The + * first byte in the array is the least significant. If the + * array is too small to represent the number, high-order bits + * are truncated; if the array is too large, high order bytes + * are filled with zeros. More formally, if the number is + * %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%, + * then the array is %$b_0, b_1, \ldots, b_{n-1}$%. + */ + +void mp_storel(const mp *m, void *pv, size_t sz) +{ + mpx_storel(m->v, m->vl, pv, sz); +} + +/* --- @mp_loadb@ --- * + * + * Arguments: @mp *d@ = destination + * @const void *pv@ = pointer to source data + * @size_t sz@ = size of the source data + * + * Returns: Resulting multiprecision number. + * + * Use: Loads a multiprecision number from an array of octets. The + * last byte in the array is the least significant. More + * formally, if the bytes are %$b_{n-1}, b_{n-2}, \ldots, b_0$% + * then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%. + */ + +mp *mp_loadb(mp *d, const void *pv, size_t sz) +{ + MP_DEST(d, MPW_RQ(sz), MP_UNDEF); + mpx_loadb(d->v, d->vl, pv, sz); + d->f &= ~(MP_UNDEF | MP_NEG); + mp_shrink(d); + return (d); +} + +/* --- @mp_storeb@ --- * + * + * Arguments: @const mp *m@ = source + * @void *pv@ = pointer to output array + * @size_t sz@ = size of the output array + * + * Returns: --- + * + * Use: Stores a multiprecision number in an array of octets. The + * last byte in the array is the least significant. If the + * array is too small to represent the number, high-order bits + * are truncated; if the array is too large, high order bytes + * are filled with zeros. More formally, if the number is + * %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%, + * then the array is %$b_{n-1}, b_{n-2}, \ldots, b_0$%. + */ + +void mp_storeb(const mp *m, void *pv, size_t sz) +{ + mpx_storeb(m->v, m->vl, pv, sz); +} + +/* --- @mp_loadl2c@ --- * + * + * Arguments: @mp *d@ = destination + * @const void *pv@ = pointer to source data + * @size_t sz@ = size of the source data + * + * Returns: Resulting multiprecision number. + * + * Use: Loads a multiprecision number from an array of octets as + * two's complement. The first byte in the array is the least + * significant. + */ + +mp *mp_loadl2c(mp *d, const void *pv, size_t sz) +{ + const octet *ov = pv; + MP_DEST(d, MPW_RQ(sz), MP_UNDEF); + if (!sz || !(ov[sz - 1] & 0x80)) { + mpx_loadl(d->v, d->vl, pv, sz); + d->f &= ~MP_NEG; + } else { + mpx_loadl2cn(d->v, d->vl, pv, sz); + d->f |= MP_NEG; + } + d->f &= ~MP_UNDEF; + mp_shrink(d); + return (d); +} + +/* --- @mp_storel2c@ --- * + * + * Arguments: @const mp *m@ = source + * @void *pv@ = pointer to output array + * @size_t sz@ = size of the output array + * + * Returns: --- + * + * Use: Stores a multiprecision number in an array of octets as two's + * complement. The first byte in the array is the least + * significant. If the array is too small to represent the + * number, high-order bits are truncated; if the array is too + * large, high order bytes are sign-extended. + */ + +void mp_storel2c(const mp *m, void *pv, size_t sz) +{ + if (MP_NEGP(m)) + mpx_storel2cn(m->v, m->vl, pv, sz); + else + mpx_storel(m->v, m->vl, pv, sz); +} + +/* --- @mp_loadb2c@ --- * + * + * Arguments: @mp *d@ = destination + * @const void *pv@ = pointer to source data + * @size_t sz@ = size of the source data + * + * Returns: Resulting multiprecision number. + * + * Use: Loads a multiprecision number from an array of octets as + * two's complement. The last byte in the array is the least + * significant. + */ + +mp *mp_loadb2c(mp *d, const void *pv, size_t sz) +{ + const octet *ov = pv; + MP_DEST(d, MPW_RQ(sz), MP_UNDEF); + if (!sz || !(ov[0] & 0x80)) { + mpx_loadb(d->v, d->vl, pv, sz); + d->f &= ~MP_NEG; + } else { + mpx_loadb2cn(d->v, d->vl, pv, sz); + d->f |= MP_NEG; + } + d->f &= ~MP_UNDEF; + mp_shrink(d); + return (d); +} + +/* --- @mp_storeb2c@ --- * + * + * Arguments: @const mp *m@ = source + * @void *pv@ = pointer to output array + * @size_t sz@ = size of the output array + * + * Returns: --- + * + * Use: Stores a multiprecision number in an array of octets, as + * two's complement. The last byte in the array is the least + * significant. If the array is too small to represent the + * number, high-order bits are truncated; if the array is too + * large, high order bytes are sign-extended. + */ + +void mp_storeb2c(const mp *m, void *pv, size_t sz) +{ + if (MP_NEGP(m)) + mpx_storeb2cn(m->v, m->vl, pv, sz); + else + mpx_storeb(m->v, m->vl, pv, sz); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mp-jacobi.c b/math/mp-jacobi.c new file mode 100644 index 0000000..1a2835b --- /dev/null +++ b/math/mp-jacobi.c @@ -0,0 +1,201 @@ +/* -*-c-*- + * + * Compute Jacobi symbol + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mp_jacobi@ --- * + * + * Arguments: @mp *a@ = an integer + * @mp *n@ = another integer + * + * Returns: @-1@, @0@ or @1@ -- the Jacobi symbol %$J(a, n)$%. + * + * Use: Computes the Kronecker symbol %$\jacobi{a}{n}$%. If @n@ is + * prime, this is the Legendre symbol and is equal to 1 if and + * only if @a@ is a quadratic residue mod @n@. The result is + * zero if and only if @a@ and @n@ have a common factor greater + * than one. + * + * If @n@ is composite, then this computes the Kronecker symbol + * + * %$\jacobi{a}{n}=\jacobi{a}{u}\prod_i\jacobi{a}{p_i}^{e_i}$% + * + * where %$n = u p_0^{e_0} \ldots p_{n-1}^{e_{n-1}}$% is the + * prime factorization of %$n$%. The missing bits are: + * + * * %$\jacobi{a}{1} = 1$%; + * * %$\jacobi{a}{-1} = 1$% if @a@ is negative, or 1 if + * positive; + * * %$\jacobi{a}{0} = 0$%; + * * %$\jacobi{a}{2}$ is 0 if @a@ is even, 1 if @a@ is + * congruent to 1 or 7 (mod 8), or %$-1$% otherwise. + * + * If %$n$% is positive and odd, then this is the Jacobi + * symbol. (The Kronecker symbol is a consistant domain + * extension; the Jacobi symbol was implemented first, and the + * name stuck.) + */ + +int mp_jacobi(mp *a, mp *n) +{ + int s = 1; + size_t p2; + + /* --- Handle zero specially --- * + * + * I can't find any specific statement for what to do when %$n = 0$%; PARI + * opts to set %$\jacobi{\pm1}{0} = \pm 1$% and %$\jacobi{a}{0} = 0$% for + * other %$a$%. + */ + + if (MP_ZEROP(n)) { + if (MP_EQ(a, MP_ONE)) return (+1); + else if (MP_EQ(a, MP_MONE)) return (-1); + else return (0); + } + + /* --- Deal with powers of two --- * + * + * This implicitly takes a copy of %$n$%. Copy %$a$% at the same time to + * make cleanup easier. + */ + + MP_COPY(a); + n = mp_odd(MP_NEW, n, &p2); + if (p2) { + if (MP_EVENP(a)) { + s = 0; + goto done; + } else if ((p2 & 1) && ((a->v[0] & 7) == 3 || (a->v[0] & 7) == 5)) + s = -s; + } + + /* --- Deal with negative %$n$% --- */ + + if (MP_NEGP(n)) { + n = mp_neg(n, n); + if (MP_NEGP(a)) + s = -s; + } + + /* --- Check for unit %$n$% --- */ + + if (MP_EQ(n, MP_ONE)) + goto done; + + /* --- Reduce %$a$% modulo %$n$% --- */ + + if (MP_NEGP(a) || MP_CMP(a, >=, n)) + mp_div(0, &a, a, n); + + /* --- Main recursive mess, flattened out into something nice --- */ + + for (;;) { + mpw nn; + size_t e; + + /* --- Some simple special cases --- */ + + MP_SHRINK(a); + if (MP_ZEROP(a)) { + s = 0; + goto done; + } + + /* --- Main case with powers of two --- */ + + a = mp_odd(a, a, &e); + nn = n->v[0] & 7; + if ((e & 1) && (nn == 3 || nn == 5)) + s = -s; + if (MP_LEN(a) == 1 && a->v[0] == 1) + goto done; + if ((nn & 3) == 3 && (a->v[0] & 3) == 3) + s = -s; + + /* --- Reduce and swap --- */ + + mp_div(0, &n, n, a); + { mp *t = n; n = a; a = t; } + } + + /* --- Wrap everything up --- */ + +done: + MP_DROP(a); + MP_DROP(n); + return (s); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +static int verify(dstr *v) +{ + mp *a = *(mp **)v[0].buf; + mp *n = *(mp **)v[1].buf; + int s = *(int *)v[2].buf; + int j = mp_jacobi(a, n); + int ok = 1; + + if (s != j) { + fputs("\n*** fail", stderr); + fputs("a = ", stderr); mp_writefile(a, stderr, 10); fputc('\n', stderr); + fputs("n = ", stderr); mp_writefile(n, stderr, 10); fputc('\n', stderr); + fprintf(stderr, "s = %i\n", s); + fprintf(stderr, "j = %i\n", j); + ok = 0; + } + + mp_drop(a); + mp_drop(n); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "jacobi", verify, { &type_mp, &type_mp, &type_int, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mp"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mp-mem.c b/math/mp-mem.c new file mode 100644 index 0000000..e1840ee --- /dev/null +++ b/math/mp-mem.c @@ -0,0 +1,334 @@ +/* -*-c-*- + * + * Memory management for multiprecision numbers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + + +#include "mp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mp_new@ --- * + * + * Arguments: @size_t sz@ = size of vector required + * @unsigned f@ = flags to set + * + * Returns: Pointer to a new MP structure. + * + * Use: Allocates a new multiprecision integer. The data space is + * allocated from either the standard global or secret arena, + * depending on the initial flags requested. + */ + +mp *mp_new(size_t sz, unsigned f) +{ + mp *m = CREATE(mp); + m->a = (f & MP_BURN) ? MPARENA_SECURE : MPARENA_GLOBAL; + m->v = mpalloc(m->a, sz); + m->vl = m->v + sz; + m->sz = sz; + m->f = f & ~(MP_CONST | MP_DESTROYED); + m->ref = 1; + return (m); +} + +/* --- @mp_create@ --- * + * + * Arguments: @size_t sz@ = size of vector required + * + * Returns: Pointer to pristine new MP structure with enough memory + * bolted onto it. + * + * Use: Creates a new multiprecision integer, initially zero. The + * integer has a single reference. + */ + +mp *mp_create(size_t sz) +{ + mp *m = CREATE(mp); + m->v = mpalloc(MPARENA_GLOBAL, sz); + m->vl = m->v + sz; + m->sz = sz; + m->a = MPARENA_GLOBAL; + m->f = MP_UNDEF; + m->ref = 1; + return (m); +} + +/* --- @mp_createsecure@ --- * + * + * Arguments: @size_t sz@ = size of vector required + * + * Returns: Pointer to pristine new MP structure with enough memory + * bolted onto it. + * + * Use: Creates a new multiprecision integer with indeterminate + * contents. The integer has a single reference. The integer's + * data space is allocated from the secure arena. Its burn flag + * is set. + */ + +mp *mp_createsecure(size_t sz) +{ + mp *m = CREATE(mp); + m->v = mpalloc(MPARENA_SECURE, sz); + m->vl = m->v + sz; + m->sz = sz; + m->a = MPARENA_SECURE; + m->f = MP_UNDEF | MP_BURN; + m->ref = 1; + return (m); +} + +/* --- @mp_build@ --- * + * + * Arguments: @mp *m@ = pointer to an MP block to fill in + * @mpw *v@ = pointer to a word array + * @mpw *vl@ = pointer just past end of array + * + * Returns: --- + * + * Use: Creates a multiprecision integer representing some smallish + * number. You must provide storage for the number and dispose + * of it when you've finished with it. The number is marked as + * constant while it exists. + */ + +void mp_build(mp *m, mpw *v, mpw *vl) +{ + m->v = v; + m->vl = vl; + m->sz = vl - v; + m->a = MPARENA_GLOBAL; + m->f = MP_CONST; + m->ref = 1; +} + +/* --- @mp_destroy@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * + * Returns: --- + * + * Use: Destroys a multiprecision integer. The reference count isn't + * checked. Don't use this function if you don't know what + * you're doing: use @mp_drop@ instead. + */ + +void mp_destroy(mp *m) +{ + assert(((void)"Destroying a free integer", !(m->f & MP_DESTROYED))); + assert(((void)"Attempted to destroy a constant", !(m->f & MP_CONST))); + if (m->f & MP_BURN) + memset(m->v, 0, MPWS(m->sz)); + mpfree(m->a, m->v); + m->f |= MP_DESTROYED; + DESTROY(m); +} + +/* --- @mp_copy@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * + * Returns: A copy of the given multiprecision integer. + * + * Use: Copies the given integer. In fact you just get another + * reference to the same old one again. + */ + +mp *mp_copy(mp *m) { return MP_COPY(m); } + +/* --- @mp_drop@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * + * Returns: --- + * + * Use: Drops a reference to an integer which isn't wanted any more. + * If there are no more references, the integer is destroyed. + */ + +void mp_drop(mp *m) { if (m) MP_DROP(m); } + +/* --- @mp_split@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * + * Returns: A reference to the same integer, possibly with a different + * address. + * + * Use: Splits off a modifiable version of the integer referred to. + */ + +mp *mp_split(mp *m) { MP_SPLIT(m); return (m); } + +/* --- @mp_resize@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * @size_t sz@ = new size + * + * Returns: --- + * + * Use: Changes an integer's size. The length and value are not + * changed. It is an error to + */ + +void mp_resize(mp *m, size_t sz) { MP_RESIZE(m, sz); } + +/* --- @mp_ensure@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * @size_t sz@ = required length + * + * Returns: --- + * + * Use: Changes an integer's length. If there is not enough space + * allocated for the new length then the size is increased. It + */ + +void mp_ensure(mp *m, size_t sz) { MP_ENSURE(m, sz); } + +/* --- @mp_dest@ --- * + * + * Arguments: @mp *m@ = a suggested destination integer + * @size_t sz@ = size required for result, in digits + * @unsigned f@ = various flags + * + * Returns: A pointer to an appropriate destination. + * + * Use: Converts a suggested destination into a real destination with + * the required properties. If the real destination is @d@, + * then the following properties will hold: + * + * * @d@ will have exactly one reference. + * + * * If @m@ is not @MP_NEW@, then the contents of @m@ will not + * change, unless @f@ has the @MP_UNDEF@ flag set. + * + * * If @m@ is not @MP_NEW@, then he reference count of @m@ on + * entry is equal to the sum of the counts of @d@ and @m@ on + * exit. + * + * * The size of @d@ will be at least @sz@. + * + * * If @f@ has the @MP_BURN@ flag set, then @d@ will be + * allocated from @MPARENA_SECURE@. + * + * Understanding this function is crucial to using Catacomb's + * multiprecision integer library effectively. + */ + +mp *mp_dest(mp *m, size_t sz, unsigned f) +{ + /* --- If no destination, make one --- */ + + if (m == MP_NEWSEC) + m = mp_new(sz, f | MP_UNDEF | MP_BURN); + else if (m == MP_NEW) + m = mp_new(sz, f | MP_UNDEF); + else { + size_t len = MP_LEN(m); + unsigned undef = (m->f | f) & MP_UNDEF; + + /* --- If the value must be preserved, the block can't shrink --- */ + + if (!undef && sz < len) + sz = len; + + /* --- Otherwise check whether the destination is suitable --- */ + + if (m->ref > 1 || (m->f & MP_CONST) || + sz > m->sz || ((f & ~m->f) & MP_BURN)) { + + /* --- No -- allocate a new buffer --- * + * + * The buffer must be secure if (a) the caller requested a secure + * buffer, or (b) the old buffer is secure and I'm not allowed to + * discard the old contents. + */ + + mparena *a; + mpw *v; + + if ((f & MP_BURN) || (!undef && (m->f & MP_BURN))) + a = MPARENA_SECURE; + else + a = MPARENA_GLOBAL; + v = mpalloc(a, sz); + + /* --- Copy the data over --- */ + + if (!undef) { + memcpy(v, m->v, MPWS(len)); + if (sz - len > 0) + memset(v + len, 0, MPWS(sz - len)); + } + + /* --- If @m@ has other references, make a new node --- * + * + * Otherwise dispose of the old buffer. + */ + + if (!(m->f & MP_CONST) && m->ref == 1) { + if (m->f & MP_BURN) + memset(m->v, 0, MPWS(m->sz)); + mpfree(m->a, m->v); + } else { + mp *mm = CREATE(mp); + mm->ref = 1; + mm->f = m->f; + m->ref--; + m = mm; + } + + /* --- Fix up the node --- */ + + m->v = v; + m->vl = v + sz; + m->sz = sz; + m->f = ((m->f & ~(MP_CONST | MP_BURN)) | + (f & (MP_BURN | MP_UNDEF))); + m->a = a; + } + + /* --- If the number is growing in its buffer, fix it up --- */ + + else if (sz > len) { + if (!undef) + memset(m->vl, 0, MPWS(sz - len)); + m->vl = m->v + sz; + } + } + + /* --- Done --- */ + + return (m); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mp-misc.c b/math/mp-misc.c new file mode 100644 index 0000000..35cdc8e --- /dev/null +++ b/math/mp-misc.c @@ -0,0 +1,94 @@ +/* -*-c-*- + * + * Miscellaneous multiprecision support functions + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" + +/*----- Basic manipulation ------------------------------------------------*/ + +/* --- @mp_shrink@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * + * Returns: --- + * + * Use: Reduces the recorded length of an integer. This doesn't + * reduce the amount of memory used, although it can improve + * performance a bit. To reduce memory, use @mp_minimize@ + * instead. This can't change the value of an integer, and is + * therefore safe to use even when there are multiple + * references. + */ + +void mp_shrink(mp *m) { MP_SHRINK(m); } + +/* --- @mp_minimize@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * + * Returns: --- + * + * Use: Reduces the amount of memory an integer uses. It's best to + * do this to numbers which aren't going to change in the + * future. + */ + +void mp_minimize(mp *m) +{ + MP_SHRINK(m); + MP_RESIZE(m, MP_LEN(m)); +} + +/*----- Bit scanning ------------------------------------------------------*/ + +/* --- @mp_scan@ --- * + * + * Arguments: @mpscan *sc@ = pointer to bitscanner block + * @const mp *m@ = pointer to a multiprecision integer + * + * Returns: --- + * + * Use: Initializes a bitscanner on a multiprecision integer. + */ + +void mp_scan(mpscan *sc, const mp *m) { MP_SCAN(sc, m); } + +/* --- @mp_scan@ --- * + * + * Arguments: @mpscan *sc@ = pointer to bitscanner block + * @const mp *m@ = pointer to a multiprecision integer + * + * Returns: --- + * + * Use: Initializes a reverse bitscanner on a multiprecision + * integer. + */ + +void mp_rscan(mpscan *sc, const mp *m) { MP_RSCAN(sc, m); } + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mp-modexp.c b/math/mp-modexp.c new file mode 100644 index 0000000..f52e5b0 --- /dev/null +++ b/math/mp-modexp.c @@ -0,0 +1,111 @@ +/* -*-c-*- + * + * General-purpose modular exponentiation + * + * (c) 2006 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpbarrett.h" +#include "mpmont.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mp_modexp@ --- * + * + * Arguments: @mp *d@ = fake destination + * @mp *x@ = base of exponentiation + * @mp *e@ = exponent + * @mp *n@ = modulus (must be positive) + * + * Returns: The value %$x^e \bmod n$%. + */ + +mp *mp_modexp(mp *d, mp *x, mp *e, mp *n) +{ + if (MP_ODDP(n)) { + mpmont mm; + mpmont_create(&mm, n); + d = mpmont_exp(&mm, d, x, e); + mpmont_destroy(&mm); + } else { + mpbarrett mb; + mpbarrett_create(&mb, n); + d = mpbarrett_exp(&mb, d, x, e); + mpbarrett_destroy(&mb); + } + return (d); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int tmodexp(dstr *v) +{ + mp *a = *(mp **)v[0].buf; + mp *b = *(mp **)v[1].buf; + mp *m = *(mp **)v[2].buf; + mp *r = *(mp **)v[3].buf; + mp *mr; + int ok = 1; + + mr = mp_modexp(MP_NEW, a, b, m); + + if (!MP_EQ(mr, r)) { + fputs("\n*** modexp failed", stderr); + fputs("\n a = ", stderr); mp_writefile(a, stderr, 10); + fputs("\n e = ", stderr); mp_writefile(b, stderr, 10); + fputs("\n m = ", stderr); mp_writefile(m, stderr, 10); + fputs("\n r = ", stderr); mp_writefile(r, stderr, 10); + fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + MP_DROP(m); + MP_DROP(a); + MP_DROP(b); + MP_DROP(r); + MP_DROP(mr); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return ok; +} + +static test_chunk tests[] = { + { "modexp", tmodexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mp"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mp-modsqrt.c b/math/mp-modsqrt.c new file mode 100644 index 0000000..b4a11fa --- /dev/null +++ b/math/mp-modsqrt.c @@ -0,0 +1,207 @@ +/* -*-c-*- + * + * Compute square roots modulo a prime + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "fibrand.h" +#include "grand.h" +#include "mp.h" +#include "mpmont.h" +#include "mprand.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mp_modsqrt@ --- * + * + * Arguments: @mp *d@ = destination integer + * @mp *a@ = source integer + * @mp *p@ = modulus (must be prime) + * + * Returns: If %$a$% is a quadratic residue, a square root of %$a$%; else + * a null pointer. + * + * Use: Returns an integer %$x$% such that %$x^2 \equiv a \pmod{p}$%, + * if one exists; else a null pointer. This function will not + * work if %$p$% is composite: you must factor the modulus, take + * a square root mod each factor, and recombine the results + * using the Chinese Remainder Theorem. + * + * We guarantee that the square root returned is the smallest + * one (i.e., the `positive' square root). + */ + +mp *mp_modsqrt(mp *d, mp *a, mp *p) +{ + mpmont mm; + mp *t; + size_t s; + mp *b; + mp *ainv; + mp *c, *r; + size_t i, j; + mp *dd, *mone; + + /* --- Cope if %$a \not\in Q_p$% --- */ + + if (mp_jacobi(a, p) != 1) { + mp_drop(d); + return (0); + } + + /* --- Choose some quadratic non-residue --- */ + + { + grand *g = fibrand_create(0); + + b = MP_NEW; + do + b = mprand_range(b, p, g, 0); + while (mp_jacobi(b, p) != -1); + g->ops->destroy(g); + } + + /* --- Find the inverse of %$a$% --- */ + + ainv = mp_modinv(MP_NEW, a, p); + + /* --- Split %$p - 1$% into a power of two and an odd number --- */ + + t = mp_sub(MP_NEW, p, MP_ONE); + t = mp_odd(t, t, &s); + + /* --- Now to really get going --- */ + + mpmont_create(&mm, p); + b = mpmont_mul(&mm, b, b, mm.r2); + c = mpmont_expr(&mm, b, b, t); + t = mp_add(t, t, MP_ONE); + t = mp_lsr(t, t, 1); + dd = mpmont_mul(&mm, MP_NEW, a, mm.r2); + r = mpmont_expr(&mm, t, dd, t); + mp_drop(dd); + ainv = mpmont_mul(&mm, ainv, ainv, mm.r2); + + mone = mp_sub(MP_NEW, p, mm.r); + + dd = MP_NEW; + + for (i = 1; i < s; i++) { + + /* --- Compute %$d_0 = r^2a^{-1}$% --- */ + + dd = mp_sqr(dd, r); + dd = mpmont_reduce(&mm, dd, dd); + dd = mpmont_mul(&mm, dd, dd, ainv); + + /* --- Now %$d = d_0^{2^{s - i - 1}}$% --- */ + + for (j = i; j < s - 1; j++) { + dd = mp_sqr(dd, dd); + dd = mpmont_reduce(&mm, dd, dd); + } + + /* --- Fiddle at the end --- */ + + if (MP_EQ(dd, mone)) + r = mpmont_mul(&mm, r, r, c); + c = mp_sqr(c, c); + c = mpmont_reduce(&mm, c, c); + } + + /* --- Done, so tidy up --- * + * + * Canonify the answer. + */ + + d = mpmont_reduce(&mm, d, r); + r = mp_sub(r, p, d); + if (MP_CMP(r, <, d)) { mp *tt = r; r = d; d = tt; } + mp_drop(ainv); + mp_drop(r); mp_drop(c); + mp_drop(dd); + mp_drop(mone); + mpmont_destroy(&mm); + + return (d); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +static int verify(dstr *v) +{ + mp *a = *(mp **)v[0].buf; + mp *p = *(mp **)v[1].buf; + mp *rr = *(mp **)v[2].buf; + mp *r = mp_modsqrt(MP_NEW, a, p); + int ok = 0; + + if (!r) + ok = 0; + else if (MP_EQ(r, rr)) + ok = 1; + + if (!ok) { + fputs("\n*** fail\n", stderr); + fputs("a = ", stderr); mp_writefile(a, stderr, 10); fputc('\n', stderr); + fputs("p = ", stderr); mp_writefile(p, stderr, 10); fputc('\n', stderr); + if (r) { + fputs("r = ", stderr); + mp_writefile(r, stderr, 10); + fputc('\n', stderr); + } else + fputs("r = \n", stderr); + fputs("rr = ", stderr); mp_writefile(rr, stderr, 10); fputc('\n', stderr); + ok = 0; + } + + mp_drop(a); + mp_drop(p); + mp_drop(r); + mp_drop(rr); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "modsqrt", verify, { &type_mp, &type_mp, &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mp"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mp-sqrt.c b/math/mp-sqrt.c new file mode 100644 index 0000000..2dbe418 --- /dev/null +++ b/math/mp-sqrt.c @@ -0,0 +1,153 @@ +/* -*-c-*- + * + * Compute integer square roots + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mp_sqrt@ --- * + * + * Arguments: @mp *d@ = pointer to destination integer + * @mp *a@ = (nonnegative) integer to take square root of + * + * Returns: The largest integer %$x$% such that %$x^2 \le a$%. + * + * Use: Computes integer square roots. + * + * The current implementation isn't very good: it uses the + * Newton-Raphson method to find an approximation to %$a$%. If + * there's any demand for a better version, I'll write one. + */ + +mp *mp_sqrt(mp *d, mp *a) +{ + unsigned long z; + mp *q = MP_NEW, *r = MP_NEW; + + /* --- Sanity preservation --- */ + + assert(!MP_NEGP(a)); + + /* --- Deal with trivial cases --- */ + + MP_SHRINK(a); + if (MP_ZEROP(a)) { + mp_drop(d); + return (MP_ZERO); + } + + /* --- Find an initial guess of about the right size --- */ + + z = mp_bits(a); + z >>= 1; + mp_copy(a); + d = mp_lsr(d, a, z); + + /* --- Main approximation --- * + * + * We use the Newton-Raphson recurrence relation + * + * %$x_{i+1} = x_i - \frac{x_i^2 - a}{2 x_i}$% + * + * We inspect the term %$q = x^2 - a$% to see when to stop. Increasing + * %$x$% is pointless when %$-q < 2 x + 1$%. + */ + + for (;;) { + q = mp_sqr(q, d); + q = mp_sub(q, q, a); + if (MP_ZEROP(q)) + break; + if (MP_NEGP(q)) { + r = mp_lsl(r, d, 1); + r->f |= MP_NEG; + if (MP_CMP(q, >=, r)) + break; + } + mp_div(&r, &q, q, d); + r = mp_lsr(r, r, 1); + if (r->v == r->vl) + d = mp_sub(d, d, MP_ONE); + else + d = mp_sub(d, d, r); + } + + /* --- Finished, at last --- */ + + mp_drop(a); + mp_drop(q); + mp_drop(r); + return (d); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +static int verify(dstr *v) +{ + mp *a = *(mp **)v[0].buf; + mp *qq = *(mp **)v[1].buf; + mp *q = mp_sqrt(MP_NEW, a); + int ok = 1; + + if (!MP_EQ(q, qq)) { + ok = 0; + fputs("\n*** sqrt failed", stderr); + fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 10); + fputs("\n*** result = ", stderr); mp_writefile(q, stderr, 10); + fputs("\n*** expect = ", stderr); mp_writefile(qq, stderr, 10); + fputc('\n', stderr); + } + + mp_drop(a); + mp_drop(q); + mp_drop(qq); + assert(mparena_count(MPARENA_GLOBAL) == 0); + + return (ok); +} + +static test_chunk tests[] = { + { "sqrt", verify, { &type_mp, &type_mp, 0 } }, + { 0, 0, { 0 } }, +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mp"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mp-test.c b/math/mp-test.c new file mode 100644 index 0000000..ebc4833 --- /dev/null +++ b/math/mp-test.c @@ -0,0 +1,62 @@ +/* -*-c-*- + * + * Testing functionality for multiprecision integers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include +#include +#include +#include + +#include "mp.h" +#include "mptext.h" + +/*----- The `MP' testrig data type ----------------------------------------*/ + +static void mp_cvt(const char *buf, dstr *d) +{ + mp *m; + DENSURE(d, sizeof(mp *)); + m = mp_readstring(MP_NEW, (char *)buf, 0, 0); + if (!m) + die(1, "bad integer `%s'", buf); + *(mp **)d->buf = m; +} + +static void mp_dump(dstr *d, FILE *fp) +{ + mp *m = *(mp **)d->buf; + mp_writefile(m, fp, 10); +} + +const test_type type_mp = { mp_cvt, mp_dump }; + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mp.h b/math/mp.h new file mode 100644 index 0000000..cfaeed5 --- /dev/null +++ b/math/mp.h @@ -0,0 +1,1024 @@ +/* -*-c-*- + * + * Simple multiprecision arithmetic + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MP_H +#define CATACOMB_MP_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +#ifndef CATACOMB_MPW_H +# include "mpw.h" +#endif + +#ifndef CATACOMB_ARENA_H +# include "arena.h" +#endif + +#ifndef CATACOMB_MPARENA_H +# include "mparena.h" +#endif + +#ifndef CATACOMB_MPX_H +# include "mpx.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- A multiprecision integer --- */ + +typedef struct mp { + mpw *v, *vl; /* Vector of digits, current limit */ + size_t sz; /* Size of digit buffer in words */ + mparena *a; /* Arena for buffer allocation */ + unsigned f; /* Flags (see below) */ + unsigned ref; /* Reference counter */ +} mp; + +#define MP_NEG 1u /* Negative (signed magnitude) */ +#define MP_BURN 2u /* Secret (viral flag) */ +#define MP_CONST 4u /* Uses strange memory allocation */ +#define MP_UNDEF 8u /* Contains nothing interesting */ +#define MP_DESTROYED 16u /* Has been destroyed */ + +/* --- A factor for simultaneous exponentation --- * + * + * Used by the Montgomery and Barrett exponentiators. + */ + +typedef struct mp_expfactor { + mp *base; + mp *exp; +} mp_expfactor; + +/*----- Useful constants --------------------------------------------------*/ + +extern mp mp_const[]; + +#define MP_ZERO (&mp_const[0]) +#define MP_ONE (&mp_const[1]) +#define MP_TWO (&mp_const[2]) +#define MP_THREE (&mp_const[3]) +#define MP_FOUR (&mp_const[4]) +#define MP_FIVE (&mp_const[5]) +#define MP_TEN (&mp_const[6]) +#define MP_256 (&mp_const[7]) +#define MP_MONE (&mp_const[8]) + +#define MP_NEW ((mp *)0) +#define MP_NEWSEC (&mp_const[9]) + +/*----- Trivial macros ----------------------------------------------------*/ + +/* --- @MP_LEN@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * + * Returns: Length of the integer, in words. + */ + +#define MP_LEN(m) ((m)->vl - ((m)->v)) + +/*----- Memory management and reference counting --------------------------*/ + +/* --- @mp_new@ --- * + * + * Arguments: @size_t sz@ = size of vector required + * @unsigned f@ = flags to set + * + * Returns: Pointer to a new MP structure. + * + * Use: Allocates a new multiprecision integer. The data space is + * allocated from either the standard global or secret arena, + * depending on the initial flags requested. + */ + +extern mp *mp_new(size_t /*sz*/, unsigned /*f*/); + +/* --- @mp_create@ --- * + * + * Arguments: @size_t sz@ = size of vector required + * + * Returns: Pointer to pristine new MP structure with enough memory + * bolted onto it. + * + * Use: Creates a new multiprecision integer with indeterminate + * contents. The integer has a single reference. + */ + +extern mp *mp_create(size_t /*sz*/); + +/* --- @mp_createsecure@ --- * + * + * Arguments: @size_t sz@ = size of vector required + * + * Returns: Pointer to pristine new MP structure with enough memory + * bolted onto it. + * + * Use: Creates a new multiprecision integer with indeterminate + * contents. The integer has a single reference. The integer's + * data space is allocated from the secure arena. Its burn flag + * is set. + */ + +extern mp *mp_createsecure(size_t /*sz*/); + +/* --- @mp_build@ --- * + * + * Arguments: @mp *m@ = pointer to an MP block to fill in + * @mpw *v@ = pointer to a word array + * @mpw *vl@ = pointer just past end of array + * + * Returns: --- + * + * Use: Creates a multiprecision integer representing some smallish + * number. You must provide storage for the number and dispose + * of it when you've finished with it. The number is marked as + * constant while it exists. + */ + +extern void mp_build(mp */*m*/, mpw */*v*/, mpw */*vl*/); + +/* --- @mp_destroy@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * + * Returns: --- + * + * Use: Destroys a multiprecision integer. The reference count isn't + * checked. Don't use this function if you don't know what + * you're doing: use @mp_drop@ instead. + */ + +extern void mp_destroy(mp */*m*/); + +/* --- @mp_copy@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * + * Returns: A copy of the given multiprecision integer. + * + * Use: Copies the given integer. In fact you just get another + * reference to the same old one again. + */ + +extern mp *mp_copy(mp */*m*/); + +#define MP_COPY(m) ((m)->ref++, (m)) + +/* --- @mp_drop@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * + * Returns: --- + * + * Use: Drops a reference to an integer which isn't wanted any more. + * If there are no more references, the integer is destroyed. + */ + +extern void mp_drop(mp */*m*/); + +#define MP_DROP(m) do { \ + mp *_mm = (m); \ + _mm->ref--; \ + if (_mm->ref == 0 && !(_mm->f & MP_CONST)) \ + mp_destroy(_mm); \ +} while (0) + +/* --- @mp_split@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * + * Returns: A reference to the same integer, possibly with a different + * address. + * + * Use: Splits off a modifiable version of the integer referred to. + */ + +extern mp *mp_split(mp */*m*/); + +#define MP_SPLIT(m) do { \ + mp *_m = (m); \ + if ((_m->f & MP_CONST) || _m->ref > 1) { \ + size_t _len = MP_LEN(_m); \ + mp *_mm = mp_new(_len, _m->f); \ + if (!(_m->f & MP_UNDEF)) \ + memcpy(_mm->v, _m->v, MPWS(_len)); \ + _m->ref--; \ + _m = _mm; \ + } \ + (m) = _m; \ +} while (0) + +/* --- @mp_resize@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * @size_t sz@ = new size + * + * Returns: --- + * + * Use: Resizes the vector containing the integer's digits. The new + * size must be at least as large as the current integer's + * length. This isn't really intended for client use. + */ + +extern void mp_resize(mp */*m*/, size_t /*sz*/); + +#define MP_RESIZE(m, ssz) do { \ + mp *_m = (m); \ + size_t _sz = (ssz); \ + mparena *_a = (_m->f & MP_BURN) ? MPARENA_SECURE : MPARENA_GLOBAL; \ + mpw *_v; \ + size_t _len = MP_LEN(_m); \ + assert(((void)"can't make size less than length", _sz >= _len)); \ + _v = mpalloc(_a, _sz); \ + if (!(_m->f & MP_UNDEF)) \ + memcpy(_v, _m->v, MPWS(_len)); \ + if (_m->f & MP_BURN) \ + memset(_m->v, 0, MPWS(_m->sz)); \ + mpfree(_m->a, _m->v); \ + _m->a = _a; \ + _m->v = _v; \ + _m->vl = _v + _len; \ +} while (0) + +/* --- @mp_ensure@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * @size_t sz@ = required size + * + * Returns: --- + * + * Use: Ensures that the integer has enough space for @sz@ digits. + * The value is not changed. + */ + +extern void mp_ensure(mp */*m*/, size_t /*sz*/); + +#define MP_ENSURE(m, ssz) do { \ + mp *_m = (m); \ + size_t _ssz = (ssz); \ + size_t _len = MP_LEN(_m); \ + if (_ssz >= _len) { \ + if (_ssz > _m->sz) \ + mp_resize(_m, _ssz); \ + if (!(_m->f & MP_UNDEF) && _ssz > _len) \ + memset(_m->vl, 0, MPWS(_ssz - _len)); \ + _m->vl = _m->v + _ssz; \ + } \ +} while (0) + +/* --- @mp_dest@ --- * + * + * Arguments: @mp *m@ = a suggested destination integer + * @size_t sz@ = size required for result, in digits + * @unsigned f@ = various flags + * + * Returns: A pointer to an appropriate destination. + * + * Use: Converts a suggested destination into a real destination with + * the required properties. If the real destination is @d@, + * then the following properties will hold: + * + * * @d@ will have exactly one reference. + * + * * If @m@ is not @MP_NEW@, then the contents of @m@ will not + * change, unless @f@ has the @MP_UNDEF@ flag set. + * + * * If @m@ is not @MP_NEW@, then he reference count of @m@ on + * entry is equal to the sum of the counts of @d@ and @m@ on + * exit. + * + * * The size of @d@ will be at least @sz@. + * + * * If @f@ has the @MP_BURN@ flag set, then @d@ will be + * allocated from @MPARENA_SECURE@. + * + * Understanding this function is crucial to using Catacomb's + * multiprecision integer library effectively. + */ + +extern mp *mp_dest(mp */*m*/, size_t /*sz*/, unsigned /*f*/); + +#define MP_DEST(m, ssz, f) do { \ + mp *_m = (m); \ + size_t _ssz = (ssz); \ + unsigned _f = (f); \ + _m = mp_dest(_m, _ssz, _f); \ + (m) = _m; \ +} while (0) + +/*----- Size manipulation -------------------------------------------------*/ + +/* --- @mp_shrink@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * + * Returns: --- + * + * Use: Reduces the recorded length of an integer. This doesn't + * reduce the amount of memory used, although it can improve + * performance a bit. To reduce memory, use @mp_minimize@ + * instead. This can't change the value of an integer, and is + * therefore safe to use even when there are multiple + * references. + */ + +extern void mp_shrink(mp */*m*/); + +#define MP_SHRINK(m) do { \ + mp *_mm = (m); \ + MPX_SHRINK(_mm->v, _mm->vl); \ + if (MP_ZEROP(_mm)) \ + _mm->f &= ~MP_NEG; \ +} while (0) + +/* --- @mp_minimize@ --- * + * + * Arguments: @mp *m@ = pointer to a multiprecision integer + * + * Returns: --- + * + * Use: Reduces the amount of memory an integer uses. It's best to + * do this to numbers which aren't going to change in the + * future. + */ + +extern void mp_minimize(mp */*m*/); + +/*----- Bit scanning ------------------------------------------------------*/ + +#ifndef CATACOMB_MPSCAN_H +# include "mpscan.h" +#endif + +/* --- @mp_scan@ --- * + * + * Arguments: @mpscan *sc@ = pointer to bitscanner block + * @const mp *m@ = pointer to a multiprecision integer + * + * Returns: --- + * + * Use: Initializes a bitscanner on a multiprecision integer. + */ + +extern void mp_scan(mpscan */*sc*/, const mp */*m*/); + +#define MP_SCAN(sc, m) do { \ + const mp *_mm = (m); \ + mpscan *_sc = (sc); \ + MPSCAN_INITX(_sc, _mm->v, _mm->vl); \ +} while (0) + +/* --- @mp_rscan@ --- * + * + * Arguments: @mpscan *sc@ = pointer to bitscanner block + * @const mp *m@ = pointer to a multiprecision integer + * + * Returns: --- + * + * Use: Initializes a reverse bitscanner on a multiprecision + * integer. + */ + +extern void mp_rscan(mpscan */*sc*/, const mp */*m*/); + +#define MP_RSCAN(sc, m) do { \ + const mp *_mm = (m); \ + mpscan *_sc = (sc); \ + MPSCAN_RINITX(_sc, _mm->v, _mm->vl); \ +} while (0) + +/* --- Other bitscanning aliases --- */ + +#define mp_step mpscan_step +#define mp_bit mpscan_bit +#define mp_rstep mpscan_rstep +#define mp_rbit mpscan_rbit + +#define MP_STEP MPSCAN_STEP +#define MP_BIT MPSCAN_BIT +#define MP_RSTEP MPSCAN_RSTEP +#define MP_RBIT MPSCAN_RBIT + +/*----- Loading and storing -----------------------------------------------*/ + +/* --- @mp_octets@ --- * + * + * Arguments: @const mp *m@ = a multiprecision integer + * + * Returns: The number of octets required to represent @m@. + * + * Use: Calculates the external storage required for a multiprecision + * integer. + */ + +extern size_t mp_octets(const mp */*m*/); + +/* --- @mp_octets2c@ --- * + * + * Arguments: @const mp *m@ = a multiprecision integer + * + * Returns: The number of octets required to represent @m@. + * + * Use: Calculates the external storage required for a multiprecision + * integer represented as two's complement. + */ + +extern size_t mp_octets2c(const mp */*m*/); + +/* --- @mp_bits@ --- * + * + * Arguments: @const mp *m@ = a multiprecision integer + * + * Returns: The number of bits required to represent @m@. + * + * Use: Calculates the external storage required for a multiprecision + * integer. + */ + +extern unsigned long mp_bits(const mp */*m*/); + +/* --- @mp_loadl@ --- * + * + * Arguments: @mp *d@ = destination + * @const void *pv@ = pointer to source data + * @size_t sz@ = size of the source data + * + * Returns: Resulting multiprecision number. + * + * Use: Loads a multiprecision number from an array of octets. The + * first byte in the array is the least significant. More + * formally, if the bytes are %$b_0, b_1, \ldots, b_{n-1}$% + * then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%. + */ + +extern mp *mp_loadl(mp */*d*/, const void */*pv*/, size_t /*sz*/); + +/* --- @mp_storel@ --- * + * + * Arguments: @const mp *m@ = source + * @void *pv@ = pointer to output array + * @size_t sz@ = size of the output array + * + * Returns: --- + * + * Use: Stores a multiprecision number in an array of octets. The + * first byte in the array is the least significant. If the + * array is too small to represent the number, high-order bits + * are truncated; if the array is too large, high order bytes + * are filled with zeros. More formally, if the number is + * %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%, + * then the array is %$b_0, b_1, \ldots, b_{n-1}$%. + */ + +extern void mp_storel(const mp */*m*/, void */*pv*/, size_t /*sz*/); + +/* --- @mp_loadb@ --- * + * + * Arguments: @mp *d@ = destination + * @const void *pv@ = pointer to source data + * @size_t sz@ = size of the source data + * + * Returns: Resulting multiprecision number. + * + * Use: Loads a multiprecision number from an array of octets. The + * last byte in the array is the least significant. More + * formally, if the bytes are %$b_{n-1}, b_{n-2}, \ldots, b_0$% + * then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%. + */ + +extern mp *mp_loadb(mp */*d*/, const void */*pv*/, size_t /*sz*/); + +/* --- @mp_storeb@ --- * + * + * Arguments: @const mp *m@ = source + * @void *pv@ = pointer to output array + * @size_t sz@ = size of the output array + * + * Returns: --- + * + * Use: Stores a multiprecision number in an array of octets. The + * last byte in the array is the least significant. If the + * array is too small to represent the number, high-order bits + * are truncated; if the array is too large, high order bytes + * are filled with zeros. More formally, if the number is + * %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%, + * then the array is %$b_{n-1}, b_{n-2}, \ldots, b_0$%. + */ + +extern void mp_storeb(const mp */*m*/, void */*pv*/, size_t /*sz*/); + +/* --- @mp_loadl2c@ --- * + * + * Arguments: @mp *d@ = destination + * @const void *pv@ = pointer to source data + * @size_t sz@ = size of the source data + * + * Returns: Resulting multiprecision number. + * + * Use: Loads a multiprecision number from an array of octets as + * two's complement. The first byte in the array is the least + * significant. + */ + +extern mp *mp_loadl2c(mp */*d*/, const void */*pv*/, size_t /*sz*/); + +/* --- @mp_storel2c@ --- * + * + * Arguments: @const mp *m@ = source + * @void *pv@ = pointer to output array + * @size_t sz@ = size of the output array + * + * Returns: --- + * + * Use: Stores a multiprecision number in an array of octets as two's + * complement. The first byte in the array is the least + * significant. If the array is too small to represent the + * number, high-order bits are truncated; if the array is too + * large, high order bytes are sign-extended. + */ + +extern void mp_storel2c(const mp */*m*/, void */*pv*/, size_t /*sz*/); + +/* --- @mp_loadb2c@ --- * + * + * Arguments: @mp *d@ = destination + * @const void *pv@ = pointer to source data + * @size_t sz@ = size of the source data + * + * Returns: Resulting multiprecision number. + * + * Use: Loads a multiprecision number from an array of octets as + * two's complement. The last byte in the array is the least + * significant. + */ + +extern mp *mp_loadb2c(mp */*d*/, const void */*pv*/, size_t /*sz*/); + +/* --- @mp_storeb2c@ --- * + * + * Arguments: @const mp *m@ = source + * @void *pv@ = pointer to output array + * @size_t sz@ = size of the output array + * + * Returns: --- + * + * Use: Stores a multiprecision number in an array of octets, as + * two's complement. The last byte in the array is the least + * significant. If the array is too small to represent the + * number, high-order bits are truncated; if the array is too + * large, high order bytes are sign-extended. + */ + +extern void mp_storeb2c(const mp */*m*/, void */*pv*/, size_t /*sz*/); + +/*----- Bit operations ----------------------------------------------------*/ + +/* --- @mp_not@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = source + * + * Returns: The bitwise complement of the source. + */ + +extern mp *mp_not(mp */*d*/, mp */*a*/); + +/* --- @mp_bitop@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: The result of the given bitwise operation. These functions + * don't handle negative numbers at all sensibly. For that, use + * the @...2c@ variants. The functions are named after the + * truth tables they generate: + * + * a: 0011 + * b: 0101 + * @mpx_bitXXXX@ + */ + +#define MP_BITDECL(string) \ + extern mp *mp_bit##string(mp */*d*/, mp */*a*/, mp */*b*/); +MPX_DOBIN(MP_BITDECL) + +/* --- @mp_[n]and@, @mp_[n]or@, @mp_[n]xor@, @mp_not@ --- * + * + * Synonyms for the commonly-used functions. + */ + +#define mp_and mp_bit0001 +#define mp_or mp_bit0111 +#define mp_nand mp_bit1110 +#define mp_nor mp_bit1000 +#define mp_xor mp_bit0110 + +/* --- @mp_testbit@ --- * + * + * Arguments: @mp *x@ = a large integer + * @unsigned long n@ = which bit to test + * + * Returns: Nonzero if the bit is set, zero if not. + */ + +extern int mp_testbit(mp */*x*/, unsigned long /*n*/); + +/* --- @mp_setbit@, @mp_clearbit@ --- * + * + * Arguments: @mp *d@ = a destination + * @mp *x@ = a large integer + * @unsigned long n@ = which bit to modify + * + * Returns: The argument @x@, with the appropriate bit set or cleared. + */ + +extern mp *mp_setbit(mp */*d*/, mp */*x*/, unsigned long /*n*/); +extern mp *mp_clearbit(mp */*d*/, mp */*x*/, unsigned long /*n*/); + +/* --- @mp_lsl@, @mp_lslc@, @mp_lsr@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = source + * @size_t n@ = number of bits to move + * + * Returns: Result, @a@ shifted left or right by @n@. + * + * Use: Bitwise shift operators. @mp_lslc@ fills the bits introduced + * on the right with ones instead of zeroes: it's used + * internally by @mp_lsl2c@, though it may be useful on its + * own. + */ + +extern mp *mp_lsl(mp */*d*/, mp */*a*/, size_t /*n*/); +extern mp *mp_lslc(mp */*d*/, mp */*a*/, size_t /*n*/); +extern mp *mp_lsr(mp */*d*/, mp */*a*/, size_t /*n*/); + +/* --- @mp_not2c@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = source + * + * Returns: The sign-extended complement of the argument. + */ + +extern mp *mp_not2c(mp */*d*/, mp */*a*/); + +/* --- @mp_bitop2c@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: The result of the given bitwise operation. Negative numbers + * are treated as two's complement, sign-extended infinitely to + * the left. The functions are named after the truth tables + * they generate: + * + * a: 0011 + * b: 0101 + * @mpx_bitXXXX@ + */ + +#define MP_BIT2CDECL(string) \ + extern mp *mp_bit##string##2c(mp */*d*/, mp */*a*/, mp */*b*/); +MPX_DOBIN(MP_BIT2CDECL) + +/* --- @mp_[n]and@, @mp_[n]or@, @mp_[n]xor@, @mp_not@ --- * + * + * Synonyms for the commonly-used functions. + */ + +#define mp_and2c mp_bit00012c +#define mp_or2c mp_bit01112c +#define mp_nand2c mp_bit11102c +#define mp_nor2c mp_bit10002c +#define mp_xor2c mp_bit01102c + +/* --- @mp_lsl2c@, @mp_lsr2c@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = source + * @size_t n@ = number of bits to move + * + * Returns: Result, @a@ shifted left or right by @n@. Handles the + * pretence of sign-extension for negative numbers. + */ + +extern mp *mp_lsl2c(mp */*d*/, mp */*a*/, size_t /*n*/); +extern mp *mp_lsr2c(mp */*d*/, mp */*a*/, size_t /*n*/); + +/* --- @mp_testbit2c@ --- * + * + * Arguments: @mp *x@ = a large integer + * @unsigned long n@ = which bit to test + * + * Returns: Nonzero if the bit is set, zero if not. Fakes up two's + * complement representation. + */ + +extern int mp_testbit2c(mp */*x*/, unsigned long /*n*/); + +/* --- @mp_setbit2c@, @mp_clearbit2c@ --- * + * + * Arguments: @mp *d@ = a destination + * @mp *x@ = a large integer + * @unsigned long n@ = which bit to modify + * + * Returns: The argument @x@, with the appropriate bit set or cleared. + * Fakes up two's complement representation. + */ + +extern mp *mp_setbit2c(mp */*d*/, mp */*x*/, unsigned long /*n*/); +extern mp *mp_clearbit2c(mp */*d*/, mp */*x*/, unsigned long /*n*/); + +/*----- Comparisons -------------------------------------------------------*/ + +/* --- @mp_eq@ --- * + * + * Arguments: @const mp *a, *b@ = two numbers + * + * Returns: Nonzero if the numbers are equal. + */ + +extern int mp_eq(const mp */*a*/, const mp */*b*/); + +#define MP_EQ(a, b) \ + ((((a)->f ^ (b)->f) & MP_NEG) == 0 && \ + mpx_ueq((a)->v, (a)->vl, (b)->v, (b)->vl)) + +/* --- @mp_cmp@ --- * + * + * Arguments: @const mp *a, *b@ = two numbers + * + * Returns: Less than, equal to or greater than zero, according to + * whether @a@ is less than, equal to or greater than @b@. + */ + +extern int mp_cmp(const mp */*a*/, const mp */*b*/); + +#define MP_CMP(a, op, b) (mp_cmp((a), (b)) op 0) + +/* --- Other handy macros --- */ + +#define MP_NEGP(x) ((x)->f & MP_NEG) +#define MP_ZEROP(x) (!MP_LEN(x)) +#define MP_POSP(x) (!MP_NEGP(x) && !MP_ZEROP(x)) +#define MP_ODDP(x) (!MP_ZEROP(x) && ((x)->v[0] & 1u)) +#define MP_EVENP(x) (!MP_ODDP(x)) + +/*----- Arithmetic operations ---------------------------------------------*/ + +/* --- @mp_neg@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = argument + * + * Returns: The negation of the argument. + * + * Use: Negates its argument. + */ + +extern mp *mp_neg(mp */*d*/, mp */*a*/); + +/* --- @mp_add@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: Result, @a@ added to @b@. + */ + +extern mp *mp_add(mp */*d*/, mp */*a*/, mp */*b*/); + +/* --- @mp_sub@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: Result, @b@ subtracted from @a@. + */ + +extern mp *mp_sub(mp */*d*/, mp */*a*/, mp */*b*/); + +/* --- @mp_mul@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a, *b@ = sources + * + * Returns: Result, @a@ multiplied by @b@. + */ + +extern mp *mp_mul(mp */*d*/, mp */*a*/, mp */*b*/); + +/* --- @mp_sqr@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = source + * + * Returns: Result, @a@ squared. + */ + +extern mp *mp_sqr(mp */*d*/, mp */*a*/); + +/* --- @mp_div@ --- * + * + * Arguments: @mp **qq, **rr@ = destination, quotient and remainder + * @mp *a, *b@ = sources + * + * Use: Calculates the quotient and remainder when @a@ is divided by + * @b@. + */ + +extern void mp_div(mp **/*qq*/, mp **/*rr*/, mp */*a*/, mp */*b*/); + +/* --- @mp_exp@ --- * + * + * Arguments: @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e$%. + */ + +extern mp *mp_exp(mp */*d*/, mp */*a*/, mp */*e*/); + +/* --- @mp_odd@ --- * + * + * Arguments: @mp *d@ = pointer to destination integer + * @mp *m@ = pointer to source integer + * @size_t *s@ = where to store the power of 2 + * + * Returns: An odd integer integer %$t$% such that %$m = 2^s t$%. + * + * Use: Computes a power of two and an odd integer which, when + * multiplied, give a specified result. This sort of thing is + * useful in number theory quite often. + */ + +extern mp *mp_odd(mp */*d*/, mp */*m*/, size_t */*s*/); + +/*----- More advanced algorithms ------------------------------------------*/ + +/* --- @mp_sqrt@ --- * + * + * Arguments: @mp *d@ = pointer to destination integer + * @mp *a@ = (nonnegative) integer to take square root of + * + * Returns: The largest integer %$x$% such that %$x^2 \le a$%. + * + * Use: Computes integer square roots. + * + * The current implementation isn't very good: it uses the + * Newton-Raphson method to find an approximation to %$a$%. If + * there's any demand for a better version, I'll write one. + */ + +extern mp *mp_sqrt(mp */*d*/, mp */*a*/); + +/* --- @mp_gcd@ --- * + * + * Arguments: @mp **gcd, **xx, **yy@ = where to write the results + * @mp *a, *b@ = sources (must be nonzero) + * + * Returns: --- + * + * Use: Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that + * @ax + by = gcd(a, b)@. This is useful for computing modular + * inverses. Neither @a@ nor @b@ may be zero. + */ + +extern void mp_gcd(mp **/*gcd*/, mp **/*xx*/, mp **/*yy*/, + mp */*a*/, mp */*b*/); + +/* -- @mp_modinv@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *x@ = argument + * @mp *p@ = modulus + * + * Returns: The inverse %$x^{-1} \bmod p$%. + * + * Use: Computes a modular inverse. An assertion fails if %$p$% + * has no inverse. + */ + +extern mp *mp_modinv(mp */*d*/, mp */*x*/, mp */*p*/); + +/* --- @mp_jacobi@ --- * + * + * Arguments: @mp *a@ = an integer + * @mp *n@ = another integer + * + * Returns: @-1@, @0@ or @1@ -- the Jacobi symbol %$J(a, n)$%. + * + * Use: Computes the Kronecker symbol %$\jacobi{a}{n}$%. If @n@ is + * prime, this is the Legendre symbol and is equal to 1 if and + * only if @a@ is a quadratic residue mod @n@. The result is + * zero if and only if @a@ and @n@ have a common factor greater + * than one. + * + * If @n@ is composite, then this computes the Kronecker symbol + * + * %$\jacobi{a}{n}=\jacobi{a}{u}\prod_i\jacobi{a}{p_i}^{e_i}$% + * + * where %$n = u p_0^{e_0} \ldots p_{n-1}^{e_{n-1}}$% is the + * prime factorization of %$n$%. The missing bits are: + * + * * %$\jacobi{a}{1} = 1$%; + * * %$\jacobi{a}{-1} = 1$% if @a@ is negative, or 1 if + * positive; + * * %$\jacobi{a}{0} = 0$%; + * * %$\jacobi{a}{2}$ is 0 if @a@ is even, 1 if @a@ is + * congruent to 1 or 7 (mod 8), or %$-1$% otherwise. + * + * If %$n$% is positive and odd, then this is the Jacobi + * symbol. (The Kronecker symbol is a consistant domain + * extension; the Jacobi symbol was implemented first, and the + * name stuck.) + */ + +extern int mp_jacobi(mp */*a*/, mp */*n*/); + +/* --- @mp_modsqrt@ --- * + * + * Arguments: @mp *d@ = destination integer + * @mp *a@ = source integer + * @mp *p@ = modulus (must be prime) + * + * Returns: If %$a$% is a quadratic residue, a square root of %$a$%; else + * a null pointer. + * + * Use: Returns an integer %$x$% such that %$x^2 \equiv a \pmod{p}$%, + * if one exists; else a null pointer. This function will not + * work if %$p$% is composite: you must factor the modulus, take + * a square root mod each factor, and recombine the results + * using the Chinese Remainder Theorem. + * + * We guarantee that the square root returned is the smallest + * one (i.e., the `positive' square root). + */ + +extern mp *mp_modsqrt(mp */*d*/, mp */*a*/, mp */*p*/); + +/* --- @mp_modexp@ --- * + * + * Arguments: @mp *d@ = fake destination + * @mp *x@ = base of exponentiation + * @mp *e@ = exponent + * @mp *n@ = modulus (must be positive) + * + * Returns: The value %$x^e \bmod n$%. + */ + +extern mp *mp_modexp(mp */*d*/, mp */*x*/, mp */*e*/, mp */*n*/); + +/*----- Test harness support ----------------------------------------------*/ + +#include + +#ifndef CATACOMB_MPTEXT_H +# include "mptext.h" +#endif + +extern const test_type type_mp; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mparena.c b/math/mparena.c new file mode 100644 index 0000000..bbe5867 --- /dev/null +++ b/math/mparena.c @@ -0,0 +1,338 @@ +/* -*-c-*- + * + * Allocation and freeing of MP buffers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include +#include +#include + +#include "mparena.h" + +/*----- Tweakables --------------------------------------------------------*/ + +/* --- @MPARENA_TRIVIAL@ --- * + * + * Make the allocator a passthrough. It immediately calls the underlying + * allocation functions rather than attempting to keep track of blocks + * itself. + */ + +#define MPARENA_TRIVIAL + +/* --- @MPARENA_DEBUG@ --- * + * + * The name of an output trace file to which logging information about the + * state of arena trees should be written. If unset, no logging is done. + */ + +/* #define MPARENA_DEBUG "mparena.out" */ + +/*----- Static variables --------------------------------------------------*/ + +#ifdef MPARENA_DEBUG + static FILE *debugfp = 0; + +# define MPARENA_OPENFILE do { \ + if (!debugfp) { \ + if ((debugfp = fopen(MPARENA_DEBUG, "w")) == 0) { \ + fprintf(stderr, "couldn't open debug output file\n"); \ + exit(EXIT_FAILURE); \ + } \ + } \ + } while (0) + +#endif + +/*----- Standard arenas ---------------------------------------------------*/ + +mparena mparena_global = MPARENA_INIT; +mparena mparena_secure = MPARENA_INIT; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @tdump@ --- * + * + * Arguments: @mparena_node *n@ = pointer to tree node to dump + * + * Returns: --- + * + * Use: Recursively dumps out the allocation tree. + */ + +#ifdef MPARENA_DEBUG + +static void tdump(mparena_node *n) +{ + if (!n) + putc('*', debugfp); + else { + putc('(', debugfp); + tdump(n->left); + fprintf(debugfp, ", %u, ", n->v[0]); + tdump(n->right); + putc(')', debugfp); + } +} + +#endif + +/* --- @mparena_create@ --- * + * + * Arguments: @mparena *a@ = pointer to arena block + * + * Returns: --- + * + * Use: Initializes an MP arena so that blocks can be allocated from + * it. + */ + +void mparena_create(mparena *a) +{ + a->root = 0; + a->n = 0; + a->a = &arena_stdlib; +} + +/* --- @mparena_setarena@ --- * + * + * Arguments: @mparena *a@ = pointer to MP arena block + * @arena *aa@ = pointer to arena + * + * Returns: --- + * + * Use: Sets the underlying arena for an MP arena. + */ + +extern void mparena_setarena(mparena *a, arena *aa) { a->a = aa; } + +/* --- @mparena_destroy@ --- * + * + * Arguments: @mparena *a@ = pointer to arena block + * + * Returns: --- + * + * Use: Frees an MP arena, and all the vectors held within it. The + * blocks which are currently allocated can be freed into some + * other arena. + */ + +static void tfree(mparena *a, mparena_node *n) +{ + A_FREE(a->a, n->v); + if (n->left) + tfree(a, n->left); + if (n->right) + tfree(a, n->right); + DESTROY(n); +} + +void mparena_destroy(mparena *a) +{ + tfree(a, a->root); + a->root = 0; +} + +/* --- @mparena_count@ --- * + * + * Arguments: @mparena *a@ = pointer to arena block + * + * Returns: Number of allocated blocks from this arena. + * + * Use: Reports the number of blocks allocated from the arena and not + * yet freed. + */ + +unsigned mparena_count(mparena *a) +{ + return (a->n); +} + +/* --- @mpalloc@ --- * + * + * Arguments: @mparena *a@ = pointer to arena block + * @size_t sz@ = number of digits required + * + * Returns: Pointer to a suitably sized block. + * + * Use: Allocates a lump of data suitable for use as an array of MP + * digits. + */ + +#ifdef MPARENA_TRIVIAL + +mpw *mpalloc(mparena *a, size_t sz) +{ + mpw *v; + if (!sz) return (0); + a->n++; + v = A_ALLOC(a->a, MPWS(sz)); + if (!v) + THROW(EXC_NOMEM); + return (v); +} + +#else + +mpw *mpalloc(mparena *a, size_t sz) +{ + mparena_node **nn, *n; + mpw *v; + + nn = &a->root; + +#ifdef MPARENA_DEBUG + MPARENA_OPENFILE; + fprintf(debugfp, "alloc %u\n before: ", sz); + tdump(a->root); putc('\n', debugfp); +#endif + + /* --- First, find a block which is big enough --- */ + +again: + n = *nn; + if (!n) { +#ifdef MPARENA_DEBUG + fputs(" failed\n", debugfp); +#endif + if ((v = A_ALLOC(a->a, MPWS(sz + 1))) == 0) + THROW(EXC_NOMEM); + v[0] = sz; + a->n++; + return (v + 1); + } + if (n->v[0] < sz) { + nn = &n->right; + goto again; + } + + /* --- Now try to find a smaller block which is suitable --- */ + + while (n->left && n->left->v[0] >= sz) { + nn = &n->left; + n = *nn; + } + + /* --- If the block we've got is still too large, start digging --- */ + + if (n->v[0] > sz * 2) { + nn = &n->left; + goto again; + } + + /* --- I've now found a suitable block --- */ + + v = n->v; + + /* --- Remove this node from the tree --- */ + + if (!n->left) + *nn = n->right; + else if (!n->right) + *nn = n->left; + else { + mparena_node *left = n->left; + mparena_node *p = *nn = n->right; + while (p->left) + p = p->left; + p->left = left; + } + +#ifdef MPARENA_DEBUG + fputs(" after: ", debugfp); + tdump(a->root); putc('\n', debugfp); +#endif + + /* --- Get rid of this node now --- */ + + DESTROY(n); + a->n++; + return (v + 1); +} + +#endif + +/* --- @mpfree@ --- * + * + * Arguments: @mparena *a@ = pointer to arena block + * @mpw *v@ = pointer to allocated vector + * + * Returns: --- + * + * Use: Returns an MP vector to an arena. + */ + +#ifdef MPARENA_TRIVIAL + +void mpfree(mparena *a, mpw *v) +{ + if (!v) return; + a->n--; + A_FREE(a->a, v); +} + +#else + +void mpfree(mparena *a, mpw *v) +{ + mparena_node **nn, *n; + size_t sz = *--v; + +#ifdef MPARENA_DEBUG + MPARENA_OPENFILE; + fprintf(debugfp, "free %u\n before: ", sz); + tdump(a->root); putc('\n', debugfp); +#endif + + nn = &a->root; + while (*nn) { + n = *nn; + if (n->v[0] > sz) + nn = &n->left; + else + nn = &n->right; + } + + n = CREATE(mparena_node); + n->left = n->right = 0; + n->v = v; + *nn = n; + a->n--; + +#ifdef MPARENA_DEBUG + fputs(" after: ", debugfp); + tdump(a->root); putc('\n', debugfp); +#endif +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mparena.h b/math/mparena.h new file mode 100644 index 0000000..21cacf1 --- /dev/null +++ b/math/mparena.h @@ -0,0 +1,160 @@ +/* -*-c-*- + * + * Allocation and freeing of MP buffers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPARENA_H +#define CATACOMB_MPARENA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_MPW_H +# include "mpw.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- @mparena_node@ --- * + * + * For internal use by the MP arena manager. The free blocks are held in a + * binary tree by size, held in the first digit of each vector. + */ + +typedef struct mparena_node { + struct mparena_node *left, *right; + mpw *v; +} mparena_node; + +/* --- @mparena@ --- * + * + * The actual arena. + */ + +typedef struct mparena { + mparena_node *root; + unsigned n; + arena *a; +} mparena; + +/*----- Standard arenas ---------------------------------------------------*/ + +extern mparena mparena_global; +#define MPARENA_GLOBAL (&mparena_global) + +extern mparena mparena_secure; +#define MPARENA_SECURE (&mparena_secure) + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @mparena_create@ --- * + * + * Arguments: @mparena *a@ = pointer to arena block + * + * Returns: --- + * + * Use: Initializes an MP arena so that blocks can be allocated from + * it. + */ + +extern void mparena_create(mparena */*a*/); + +#define MPARENA_INIT { 0, 0, &arena_stdlib } + +/* --- @mparena_setarena@ --- * + * + * Arguments: @mparena *a@ = pointer to MP arena block + * @arena *aa@ = pointer to arena + * + * Returns: --- + * + * Use: Sets the underlying arena for an MP arena. + */ + +extern void mparena_setarena(mparena */*a*/, arena */*aa*/); + +/* --- @mparena_destroy@ --- * + * + * Arguments: @mparena *a@ = pointer to arena block + * + * Returns: --- + * + * Use: Frees an MP arena, and all the vectors held within it. The + * blocks which are currently allocated can be freed into some + * other MP arena, as long as the underlying arenas are the + * same. + */ + +extern void mparena_destroy(mparena */*a*/); + +/* --- @mparena_count@ --- * + * + * Arguments: @mparena *a@ = pointer to arena block + * + * Returns: Number of allocated blocks from this arena. + * + * Use: Reports the number of blocks allocated from the arena and not + * yet freed. + */ + +extern unsigned mparena_count(mparena */*a*/); + +/* --- @mpalloc@ --- * + * + * Arguments: @mparena *a@ = pointer to arena block + * @size_t sz@ = number of digits required + * + * Returns: Pointer to a suitably sized block. + * + * Use: Allocates a lump of data suitable for use as an array of MP + * digits. + */ + +extern mpw *mpalloc(mparena */*a*/, size_t /*sz*/); + +/* --- @mpfree@ --- * + * + * Arguments: @mparena *a@ = pointer to arena block + * @mpw *v@ = pointer to allocated vector + * + * Returns: --- + * + * Use: Returns an MP vector to an arena. + */ + +extern void mpfree(mparena */*a*/, mpw */*v*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mpbarrett-exp.c b/math/mpbarrett-exp.c new file mode 100644 index 0000000..44cad7e --- /dev/null +++ b/math/mpbarrett-exp.c @@ -0,0 +1,122 @@ +/* -*-c-*- + * + * Modular exponentiation using Barrett reduction + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpbarrett.h" +#include "mpbarrett-exp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mpbarrett_exp@ --- * + * + * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context + * @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e \bmod m$%. + */ + +mp *mpbarrett_exp(mpbarrett *mb, mp *d, mp *a, mp *e) +{ + mp *x = MP_ONE; + mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; + + MP_COPY(a); + MP_SHRINK(e); + if (MP_ZEROP(e)) + ; + else { + if (MP_NEGP(e)) + a = mp_modinv(a, a, mb->m); + if (MP_LEN(e) < EXP_THRESH) + EXP_SIMPLE(x, a, e); + else + EXP_WINDOW(x, a, e); + } + mp_drop(d); + mp_drop(spare); + mp_drop(a); + return (x); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int vexp(dstr *v) +{ + mp *m = *(mp **)v[0].buf; + mp *a = *(mp **)v[1].buf; + mp *b = *(mp **)v[2].buf; + mp *r = *(mp **)v[3].buf; + mp *mr; + int ok = 1; + + mpbarrett mb; + mpbarrett_create(&mb, m); + + mr = mpbarrett_exp(&mb, MP_NEW, a, b); + + if (!MP_EQ(mr, r)) { + fputs("\n*** barrett modexp failed", stderr); + fputs("\n m = ", stderr); mp_writefile(m, stderr, 10); + fputs("\n a = ", stderr); mp_writefile(a, stderr, 10); + fputs("\n e = ", stderr); mp_writefile(b, stderr, 10); + fputs("\n r = ", stderr); mp_writefile(r, stderr, 10); + fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + mp_drop(m); + mp_drop(a); + mp_drop(b); + mp_drop(r); + mp_drop(mr); + mpbarrett_destroy(&mb); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return ok; +} + +static test_chunk tests[] = { + { "mpbarrett-exp", vexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mpbarrett"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpbarrett-exp.h b/math/mpbarrett-exp.h new file mode 100644 index 0000000..08741f3 --- /dev/null +++ b/math/mpbarrett-exp.h @@ -0,0 +1,74 @@ +/* -*-c-*- + * + * Exponentiation operations for Barrett reduction + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPBARRETT_EXP_H +#define CATACOMB_MPBARRETT_EXP_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Exponentation definitions -----------------------------------------*/ + +#define EXP_TYPE mp * + +#define EXP_COPY(d, x) d = MP_COPY(x) +#define EXP_DROP(x) MP_DROP(x) + +#define EXP_MUL(a, x) do { \ + mp *t = mp_mul(spare, a, x); \ + spare = a; \ + a = mpbarrett_reduce(mb, t, t); \ +} while (0) + +#define EXP_SQR(a) do { \ + mp *t = mp_sqr(spare, a); \ + spare = a; \ + a = mpbarrett_reduce(mb, t, t); \ +} while (0) + +#define EXP_FIX(x) + +#define EXP_SETMUL(d, x, y) do { \ + d = mp_mul(MP_NEW, x, y); \ + d = mpbarrett_reduce(mb, d, d); \ +} while (0) + +#define EXP_SETSQR(d, x) do { \ + d = mp_sqr(MP_NEW, x); \ + d = mpbarrett_reduce(mb, d, d); \ +} while (0) + +#include "exp.h" + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mpbarrett-mexp.c b/math/mpbarrett-mexp.c new file mode 100644 index 0000000..a221f10 --- /dev/null +++ b/math/mpbarrett-mexp.c @@ -0,0 +1,175 @@ +/* -*-c-*- + * + * Multiple simultaneous exponentiations + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpbarrett.h" + +#define EXP_WINSZ 3 +#include "mpbarrett-exp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mpbarrett_mexp@ --- * + * + * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context + * @mp *d@ = fake destination + * @const mp_expfactor *f@ = pointer to array of factors + * @size_t n@ = number of factors supplied + * + * Returns: If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the + * exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result + * is: + * + * %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$% + */ + +mp *mpbarrett_mexp(mpbarrett *mb, mp *d, const mp_expfactor *f, size_t n) +{ + mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor)); + mp *a = MP_ONE; + mp *spare; + mp *g = MP_NEW; + size_t i; + + spare = MP_NEW; + for (i = 0; i < n; i++) { + if (f[i].exp->f & MP_BURN) + spare = MP_NEWSEC; + if (MP_NEGP(f[i].exp)) + ff[i].base = mp_modinv(MP_NEW, f[i].base, mb->m); + else + ff[i].base = MP_COPY(f[i].base); + ff[i].exp = f[i].exp; + } + mp_drop(g); + EXP_SIMUL(a, ff, n); + mp_drop(d); + mp_drop(spare); + for (i = 0; i < n; i++) + mp_drop(ff[i].base); + xfree(ff); + return (a); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +static int verify(size_t n, dstr *v) +{ + mp *m = *(mp **)v[0].buf; + mp_expfactor *f = xmalloc(n * sizeof(*f)); + mp *r, *rr; + size_t i, j; + mpbarrett mb; + int ok = 1; + + j = 1; + for (i = 0; i < n; i++) { + f[i].base = *(mp **)v[j++].buf; + f[i].exp = *(mp **)v[j++].buf; + } + + rr = *(mp **)v[j].buf; + mpbarrett_create(&mb, m); + r = mpbarrett_mexp(&mb, MP_NEW, f, n); + if (!MP_EQ(r, rr)) { + fputs("\n*** mexp failed\n", stderr); + fputs("m = ", stderr); mp_writefile(m, stderr, 10); + for (i = 0; i < n; i++) { + fprintf(stderr, "\ng_%u = ", i); + mp_writefile(f[i].base, stderr, 10); + fprintf(stderr, "\ne_%u = ", i); + mp_writefile(f[i].exp, stderr, 10); + } + fputs("\nr = ", stderr); mp_writefile(r, stderr, 10); + fputs("\nR = ", stderr); mp_writefile(rr, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + for (i = 0; i < n; i++) { + MP_DROP(f[i].base); + MP_DROP(f[i].exp); + } + MP_DROP(m); + MP_DROP(r); + MP_DROP(rr); + mpbarrett_destroy(&mb); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int t1(dstr *v) { return verify(1, v); } +static int t2(dstr *v) { return verify(2, v); } +static int t3(dstr *v) { return verify(3, v); } +static int t4(dstr *v) { return verify(4, v); } +static int t5(dstr *v) { return verify(5, v); } + +static test_chunk tests[] = { + { "mexp-1", t1, { &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { "mexp-2", t2, { &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { "mexp-3", t3, { &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { "mexp-4", t4, { &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { "mexp-5", t5, { &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mpbarrett"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpbarrett.c b/math/mpbarrett.c new file mode 100644 index 0000000..cadb9b3 --- /dev/null +++ b/math/mpbarrett.c @@ -0,0 +1,211 @@ +/* -*-c-*- + * + * Barrett modular reduction + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpbarrett.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mpbarrett_create@ --- * + * + * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context + * @mp *m@ = modulus to work to + * + * + * Returns: Zero on success, nonzero on error. + * + * Use: Initializes a Barrett reduction context ready for use. + */ + +int mpbarrett_create(mpbarrett *mb, mp *m) +{ + mp *b; + + /* --- Validate the arguments --- */ + + if (!MP_POSP(m)) + return (-1); + + /* --- Compute %$\mu$% --- */ + + mp_shrink(m); + mb->k = MP_LEN(m); + mb->m = MP_COPY(m); + b = mp_new(2 * mb->k + 1, 0); + MPX_ZERO(b->v, b->vl - 1); + b->vl[-1] = 1; + mp_div(&b, 0, b, m); + mb->mu = b; + return (0); +} + +/* --- @mpbarrett_destroy@ --- * + * + * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context + * + * Returns: --- + * + * Use: Destroys a Barrett reduction context releasing any resources + * claimed. + */ + +void mpbarrett_destroy(mpbarrett *mb) +{ + mp_drop(mb->m); + mp_drop(mb->mu); +} + +/* --- @mpbarrett_reduce@ --- * + * + * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context + * @mp *d@ = destination for result + * @mp *m@ = number to reduce + * + * Returns: The residue of @m@ modulo the number in the reduction + * context. + * + * Use: Performs an efficient modular reduction. + */ + +mp *mpbarrett_reduce(mpbarrett *mb, mp *d, mp *m) +{ + mp *q; + size_t k = mb->k; + + /* --- Special case if @m@ is too small --- */ + + if (MP_LEN(m) < k) { + m = MP_COPY(m); + if (d) + MP_DROP(d); + return (m); + } + + /* --- First stage --- */ + + { + mp qq; + mp_build(&qq, m->v + (k - 1), m->vl); + q = mp_mul(MP_NEW, &qq, mb->mu); + if (MP_LEN(q) <= k) { + m = MP_COPY(m); + if (d) + MP_DROP(d); + MP_DROP(q); + return (m); + } + } + + /* --- Second stage --- */ + + { + mp *r; + mpw *mvl; + + MP_COPY(m); + if (MP_LEN(m) <= k + 1) + mvl = m->vl; + else + mvl = m->v + k + 1; + r = mp_new(k + 1, (q->f | mb->m->f) & MP_BURN); + mpx_umul(r->v, r->vl, q->v + k + 1, q->vl, mb->m->v, mb->m->vl); + MP_DEST(d, k + 1, r->f | MP_UNDEF); + mpx_usub(d->v, d->vl, m->v, mvl, r->v, r->vl); + d->f = (m->f | r->f) & (MP_BURN | MP_NEG); + MP_DROP(r); + MP_DROP(q); + MP_DROP(m); + } + + /* --- Final stage --- */ + + MP_SHRINK(d); + while (MPX_UCMP(d->v, d->vl, >=, mb->m->v, mb->m->vl)) + mpx_usub(d->v, d->vl, d->v, d->vl, mb->m->v, mb->m->vl); + + /* --- Fix up the sign --- */ + + if (d->f & MP_NEG) { + mpx_usub(d->v, d->vl, mb->m->v, mb->m->vl, d->v, d->vl); + d->f &= ~MP_NEG; + } + + MP_SHRINK(d); + return (d); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int vmod(dstr *v) +{ + mp *x = *(mp **)v[0].buf; + mp *n = *(mp **)v[1].buf; + mp *r = *(mp **)v[2].buf; + mp *s; + mpbarrett mb; + int ok = 1; + + mpbarrett_create(&mb, n); + s = mpbarrett_reduce(&mb, MP_NEW, x); + + if (!MP_EQ(s, r)) { + fputs("\n*** barrett reduction failure\n", stderr); + fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr); + fputs("n = ", stderr); mp_writefile(n, stderr, 10); fputc('\n', stderr); + fputs("r = ", stderr); mp_writefile(r, stderr, 10); fputc('\n', stderr); + fputs("s = ", stderr); mp_writefile(s, stderr, 10); fputc('\n', stderr); + ok = 0; + } + + mpbarrett_destroy(&mb); + mp_drop(x); + mp_drop(n); + mp_drop(r); + mp_drop(s); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "mpbarrett-reduce", vmod, { &type_mp, &type_mp, &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mpbarrett"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpbarrett.h b/math/mpbarrett.h new file mode 100644 index 0000000..40e0fe4 --- /dev/null +++ b/math/mpbarrett.h @@ -0,0 +1,141 @@ +/* -*-c-*- + * + * Barrett modular reduction + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on Barrett reduction ----------------------------------------* + * + * Barrett reduction is a technique for computing modular residues. Unlike + * Montgomery reduction, it doesn't have restrictions on the modulus (except + * that it be positive) and doesn't confuse matters by putting an extra + * factor all the way through your computation. + * + * It's useful for slightly less heavy-duty work than Montgomery reduction + * because the precomputation phase is rather simpler, involving a single + * division operation. + * + * Sometimes it's useful to exponentiate modulo an even number, so there's a + * modexp routine provided which uses Barrett reduction rather than + * Montgomery reduction. This is handy when you're working on indices in an + * even-order cyclic group or something. + */ + +#ifndef CATACOMB_MPBARRETT_H +#define CATACOMB_MPBARRETT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct mpbarrett { + mp *m; + mp *mu; + size_t k; +} mpbarrett; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @mpbarrett_create@ --- * + * + * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context + * @mp *m@ = modulus to work to + * + * Returns: Zero on success, nonzero on error. + * + * Use: Initializes a Barrett reduction context ready for use. + */ + +extern int mpbarrett_create(mpbarrett */*mb*/, mp */*m*/); + +/* --- @mpbarrett_destroy@ --- * + * + * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context + * + * Returns: --- + * + * Use: Destroys a Barrett reduction context releasing any resources + * claimed. + */ + +extern void mpbarrett_destroy(mpbarrett */*mb*/); + +/* --- @mpbarrett_reduce@ --- * + * + * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context + * @mp *d@ = destination for result + * @mp *m@ = number to reduce + * + * Returns: The residue of @m@ modulo the number in the reduction + * context. + * + * Use: Performs an efficient modular reduction. + */ + +extern mp *mpbarrett_reduce(mpbarrett */*mb*/, mp */*d*/, mp */*m*/); + +/* --- @mpbarrett_exp@ --- * + * + * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context + * @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e \bmod m$%. + */ + +extern mp *mpbarrett_exp(mpbarrett */*mb*/, mp */*d*/, mp */*a*/, mp */*e*/); + +/* --- @mpbarrett_mexp@ --- * + * + * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context + * @mp *d@ = fake destination + * @const mp_expfactor *f@ = pointer to array of factors + * @size_t n@ = number of factors supplied + * + * Returns: If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the + * exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result + * is: + * + * %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$% + */ + +extern mp *mpbarrett_mexp(mpbarrett */*mb*/, mp */*d*/, + const mp_expfactor */*f*/, size_t /*n*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mpcrt.c b/math/mpcrt.c new file mode 100644 index 0000000..a8f805f --- /dev/null +++ b/math/mpcrt.c @@ -0,0 +1,291 @@ +/* -*-c-*- + * + * Chinese Remainder Theorem computations (Gauss's algorithm) + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpcrt.h" +#include "mpmul.h" +#include "mpbarrett.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mpcrt_create@ --- * + * + * Arguments: @mpcrt *c@ = pointer to CRT context + * @mpcrt_mod *v@ = pointer to vector of moduli + * @size_t k@ = number of moduli + * @mp *n@ = product of all moduli (@MP_NEW@ if unknown) + * + * Returns: --- + * + * Use: Initializes a context for solving Chinese Remainder Theorem + * problems. The vector of moduli can be incomplete. Omitted + * items must be left as null pointers. Not all combinations of + * missing things can be coped with, even if there is + * technically enough information to cope. For example, if @n@ + * is unspecified, all the @m@ values must be present, even if + * there is one modulus with both @m@ and @n@ (from which the + * product of all moduli could clearly be calculated). + */ + +void mpcrt_create(mpcrt *c, mpcrt_mod *v, size_t k, mp *n) +{ + size_t i; + + /* --- Simple initialization things --- */ + + c->k = k; + c->v = v; + + /* --- Work out @n@ if I don't have it already --- */ + + if (n != MP_NEW) + n = MP_COPY(n); + else { + mpmul mm; + mpmul_init(&mm); + for (i = 0; i < k; i++) + mpmul_add(&mm, v[i].m); + n = mpmul_done(&mm); + } + + /* --- A quick hack if %$k = 2$% --- */ + + if (k == 2) { + + /* --- The %$n / n_i$% values are trivial in this case --- */ + + if (!v[0].n) + v[0].n = MP_COPY(v[1].m); + if (!v[1].n) + v[1].n = MP_COPY(v[0].m); + + /* --- Now sort out the inverses --- * + * + * @mp_gcd@ will ensure that the first argument is negative. + */ + + if (!v[0].ni && !v[1].ni) { + mp *g = MP_NEW; + mp_gcd(&g, &v[0].ni, &v[1].ni, v[0].n, v[1].n); + assert(MP_EQ(g, MP_ONE)); + mp_drop(g); + v[0].ni = mp_add(v[0].ni, v[0].ni, v[1].n); + } else { + int i, j; + mp *x; + + if (!v[0].ni) + i = 0, j = 1; + else + i = 1, j = 0; + + x = mp_mul(MP_NEW, v[j].n, v[j].ni); + x = mp_sub(x, x, MP_ONE); + mp_div(&x, 0, x, v[i].n); + v[i].ni = x; + } + } + + /* --- Set up the Barrett context --- */ + + mpbarrett_create(&c->mb, n); + + /* --- Walk through filling in @n@, @ni@ and @nnir@ --- */ + + for (i = 0; i < k; i++) { + if (!v[i].n) + mp_div(&v[i].n, 0, n, v[i].m); + if (!v[i].ni) + v[i].ni = mp_modinv(MP_NEW, v[i].n, v[i].m); + if (!v[i].nni) + v[i].nni = mp_mul(MP_NEW, v[i].n, v[i].ni); + } + + /* --- Done --- */ + + mp_drop(n); +} + +/* --- @mpcrt_destroy@ --- * + * + * Arguments: @mpcrt *c@ - pointer to CRT context + * + * Returns: --- + * + * Use: Destroys a CRT context, releasing all the resources it holds. + */ + +void mpcrt_destroy(mpcrt *c) +{ + size_t i; + + for (i = 0; i < c->k; i++) { + if (c->v[i].m) mp_drop(c->v[i].m); + if (c->v[i].n) mp_drop(c->v[i].n); + if (c->v[i].ni) mp_drop(c->v[i].ni); + if (c->v[i].nni) mp_drop(c->v[i].nni); + } + mpbarrett_destroy(&c->mb); +} + +/* --- @mpcrt_solve@ --- * + * + * Arguments: @mpcrt *c@ = pointer to CRT context + * @mp *d@ = fake destination + * @mp **v@ = array of residues + * + * Returns: The unique solution modulo the product of the individual + * moduli, which leaves the given residues. + * + * Use: Constructs a result given its residue modulo an array of + * coprime integers. This can be used to improve performance of + * RSA encryption or Blum-Blum-Shub generation if the factors + * of the modulus are known, since results can be computed mod + * each of the individual factors and then combined at the end. + * This is rather faster than doing the full-scale modular + * exponentiation. + */ + +mp *mpcrt_solve(mpcrt *c, mp *d, mp **v) +{ + mp *a = MP_ZERO; + mp *x = MP_NEW; + size_t i; + + for (i = 0; i < c->k; i++) { + x = mp_mul(x, c->v[i].nni, v[i]); + x = mpbarrett_reduce(&c->mb, x, x); + a = mp_add(a, a, x); + } + if (x) + MP_DROP(x); + a = mpbarrett_reduce(&c->mb, a, a); + if (d != MP_NEW) + MP_DROP(d); + return (a); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int verify(size_t n, dstr *v) +{ + mpcrt_mod *m = xmalloc(n * sizeof(mpcrt_mod)); + mp **r = xmalloc(n * sizeof(mp *)); + mpcrt c; + mp *a, *b; + size_t i; + int ok = 1; + + for (i = 0; i < n; i++) { + r[i] = *(mp **)v[2 * i].buf; + m[i].m = *(mp **)v[2 * i + 1].buf; + m[i].n = 0; + m[i].ni = 0; + m[i].nni = 0; + } + a = *(mp **)v[2 * n].buf; + + mpcrt_create(&c, m, n, 0); + b = mpcrt_solve(&c, MP_NEW, r); + + if (!MP_EQ(a, b)) { + fputs("\n*** failed\n", stderr); + fputs("n = ", stderr); + mp_writefile(c.mb.m, stderr, 10); + for (i = 0; i < n; i++) { + fprintf(stderr, "\nr[%u] = ", i); + mp_writefile(r[i], stderr, 10); + fprintf(stderr, "\nm[%u] = ", i); + mp_writefile(m[i].m, stderr, 10); + fprintf(stderr, "\nN[%u] = ", i); + mp_writefile(m[i].n, stderr, 10); + fprintf(stderr, "\nM[%u] = ", i); + mp_writefile(m[i].ni, stderr, 10); + } + fputs("\nresult = ", stderr); + mp_writefile(b, stderr, 10); + fputs("\nexpect = ", stderr); + mp_writefile(a, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + for (i = 0; i < n; i++) + mp_drop(r[i]); + mp_drop(a); + mp_drop(b); + mpcrt_destroy(&c); + xfree(m); + xfree(r); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int crt1(dstr *v) { return verify(1, v); } +static int crt2(dstr *v) { return verify(2, v); } +static int crt3(dstr *v) { return verify(3, v); } +static int crt4(dstr *v) { return verify(4, v); } +static int crt5(dstr *v) { return verify(5, v); } + +static test_chunk tests[] = { + { "crt-1", crt1, { &type_mp, &type_mp, + &type_mp, 0 } }, + { "crt-2", crt2, { &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { "crt-3", crt3, { &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { "crt-4", crt4, { &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { "crt-5", crt5, { &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mpcrt"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpcrt.h b/math/mpcrt.h new file mode 100644 index 0000000..cebdce5 --- /dev/null +++ b/math/mpcrt.h @@ -0,0 +1,123 @@ +/* -*-c-*- + * + * Chinese Remainder Theorem computations (Gauss's algorithm) + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPCRT_H +#define CATACOMB_MPCRT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_MPBARRETT_H +# include "mpbarrett.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct mpcrt_mod { + mp *m; /* %$n_i$% -- the modulus */ + mp *n; /* %$N_i = n / n_i$% */ + mp *ni; /* %$M_i = N_i^{-1} \bmod n_i$% */ + mp *nni; /* %$N_i M_i \bmod m$% */ +} mpcrt_mod; + +typedef struct mpcrt { + size_t k; /* Number of distinct moduli */ + mpbarrett mb; /* Barrett context for product */ + mpcrt_mod *v; /* Vector of information for each */ +} mpcrt; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @mpcrt_create@ --- * + * + * Arguments: @mpcrt *c@ = pointer to CRT context + * @mpcrt_mod *v@ = pointer to vector of moduli + * @size_t k@ = number of moduli + * @mp *n@ = product of all moduli (@MP_NEW@ if unknown) + * + * Returns: --- + * + * Use: Initializes a context for solving Chinese Remainder Theorem + * problems. The vector of moduli can be incomplete. Omitted + * items must be left as null pointers. Not all combinations of + * missing things can be coped with, even if there is + * technically enough information to cope. For example, if @n@ + * is unspecified, all the @m@ values must be present, even if + * there is one modulus with both @m@ and @n@ (from which the + * product of all moduli could clearly be calculated). + */ + +extern void mpcrt_create(mpcrt */*c*/, mpcrt_mod */*v*/, + size_t /*k*/, mp */*n*/); + +/* --- @mpcrt_destroy@ --- * + * + * Arguments: @mpcrt *c@ - pointer to CRT context + * + * Returns: --- + * + * Use: Destroys a CRT context, releasing all the resources it holds. + */ + +extern void mpcrt_destroy(mpcrt */*c*/); + +/* --- @mpcrt_solve@ --- * + * + * Arguments: @mpcrt *c@ = pointer to CRT context + * @mp *d@ = fake destination + * @mp **v@ = array of residues + * + * Returns: The unique solution modulo the product of the individual + * moduli, which leaves the given residues. + * + * Use: Constructs a result given its residue modulo an array of + * coprime integers. This can be used to improve performance of + * RSA encryption or Blum-Blum-Shub generation if the factors + * of the modulus are known, since results can be computed mod + * each of the individual factors and then combined at the end. + * This is rather faster than doing the full-scale modular + * exponentiation. + */ + +extern mp *mpcrt_solve(mpcrt */*c*/, mp */*d*/, mp **/*v*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mpdump.c b/math/mpdump.c new file mode 100644 index 0000000..3eb2883 --- /dev/null +++ b/math/mpdump.c @@ -0,0 +1,72 @@ +/* -*-c-*- + * + * Dump a multiprecision integer as C data + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include "mp.h" + +/*----- Main code ---------------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + mp *x; + int i; + int w, n; + + if (argc != 2) { + fprintf(stderr, "%s: missing argument\n", argv[0]); + return (1); + } + if ((x = mp_readstring(0, argv[1], 0, 0)) == 0) { + fprintf(stderr, "%s: bad integer `%s'", argv[0], argv[1]); + return (1); + } + fputs(" ", stdout); + w = (MPW_BITS + 3)/4; + n = 1; + while (2 + 2 * n * (4 + w) < 72) n <<= 1; + i = 0; + for (;;) { + printf("0x%0*x", w, x->v[i]); + i++; + if (i >= MP_LEN(x)) break; + fputs(",", stdout); + if (i % n) fputs(" ", stdout); else fputs("\n ", stdout); + } + if (fflush(stdout) || ferror(stdout)) { + fprintf(stderr, "%s: error writing data: %s", argv[0], strerror(errno)); + return (1); + } + fputs("\n", stdout); + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpint.c b/math/mpint.c new file mode 100644 index 0000000..d89fb07 --- /dev/null +++ b/math/mpint.c @@ -0,0 +1,177 @@ +/* -*-c-*- + * + * Conversion between MPs and standard C integers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mpint.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- Conversion from C integers --- */ + +#define FROM(name, type) \ + mp *mp_from##name(mp *d, type i) { \ + MP_FROMINT(d, type, i); \ + return (d); \ + } + +FROM(short, short) +FROM(ushort, unsigned short) +FROM(int, int) +FROM(uint, unsigned) +FROM(uint32, uint32) +FROM(long, long) +FROM(ulong, unsigned long) + +#undef FROM + +/* --- Conversion to C integers --- */ + +#define TO(name, type, max) \ + type mp_to##name(const mp *m) \ + { \ + type i; \ + MP_TOINT(m, type, max, i); \ + return (i); \ + } + +TO(short, short, SHRT_MAX) +TO(ushort, unsigned short, USHRT_MAX) +TO(int, int, INT_MAX) +TO(uint, unsigned, UINT_MAX) +TO(uint32, uint32, 0xffffffff) +TO(long, long, LONG_MAX) +TO(ulong, unsigned long, ULONG_MAX) + +#undef TO + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +static int fromuint(dstr *v) +{ + unsigned long i = *(unsigned long *)v[0].buf; + mp *m = *(mp **)v[1].buf; + mp *d = mp_fromuint(MP_NEW, i); + int ok = 1; + + if (!MP_EQ(d, m)) { + fputs("\n*** fromint failed.\n", stderr); + fprintf(stderr, "i = %lu", i); + fputs("\nexpect = ", stderr); mp_writefile(m, stderr, 10); + fputs("\nresult = ", stderr); mp_writefile(d, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + mp_drop(m); + mp_drop(d); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int fromint(dstr *v) +{ + long i = *(long *)v[0].buf; + mp *m = *(mp **)v[1].buf; + mp *d = mp_fromint(MP_NEW, i); + int ok = 1; + + if (!MP_EQ(d, m)) { + fputs("\n*** fromint failed.\n", stderr); + fprintf(stderr, "i = %li", i); + fputs("\nexpect = ", stderr); mp_writefile(m, stderr, 10); + fputs("\nresult = ", stderr); mp_writefile(d, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + mp_drop(m); + mp_drop(d); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int touint(dstr *v) +{ + mp *m = *(mp **)v[0].buf; + unsigned long i = *(unsigned long *)v[1].buf; + unsigned j = mp_touint(m); + int ok = 1; + + if ((unsigned)i != j) { + fputs("\n*** touint failed.\n", stderr); + fputs("m = ", stderr); mp_writefile(m, stderr, 10); + fprintf(stderr, "\nexpect = %lu; result = %u\n", i, j); + ok = 0; + } + + mp_drop(m); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int toint(dstr *v) +{ + mp *m = *(mp **)v[0].buf; + long i = *(long *)v[1].buf; + int j = mp_toint(m); + int ok = 1; + + if (i != j) { + fputs("\n*** toint failed.\n", stderr); + fputs("m = ", stderr); mp_writefile(m, stderr, 10); + fprintf(stderr, "\nexpect = %li; result = %i\n", i, j); + ok = 0; + } + + mp_drop(m); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "fromuint", fromuint, { &type_ulong, &type_mp, 0 } }, + { "fromint", fromint, { &type_long, &type_mp, 0 } }, + { "touint", touint, { &type_mp, &type_ulong, 0 } }, + { "toint", toint, { &type_mp, &type_long, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mpint"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpint.h b/math/mpint.h new file mode 100644 index 0000000..7867f6a --- /dev/null +++ b/math/mpint.h @@ -0,0 +1,190 @@ +/* -*-c-*- + * + * Conversion between MPs and standard C integers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPINT_H +#define CATACOMB_MPINT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +/*----- Generic translation macros ----------------------------------------*/ + +/* --- @MP_FROMINT@ --- * + * + * Arguments: @d@ = destination multiprecision integer + * @type@ = type of integer which @i@ is + * @i@ = a standard C integer + * + * Use: Stores the value of @i@ in @d@. This macro is actually + * rather subtle in places. Be careful what you change. + */ + +#define MP_FROMINT(d, type, i) do { \ + type _i = (i); \ + size_t _o = 0; \ + mp *_d = (d); \ + size_t _sz = 4; \ + \ + MP_DEST(_d, _sz, 0); \ + _d->f &= ~(MP_NEG | MP_UNDEF); \ + \ + if (_i >= 0) { \ + while (_i) { \ + if (_o == _sz) { \ + _sz <<= 1; \ + MP_ENSURE(_d, _sz); \ + } \ + _d->v[_o++] = MPW(_i); \ + if (_i <= MPW_MAX) \ + break; \ + else \ + _i /= (type)MPW_MAX + 1; \ + } \ + } else { \ + _d->f |= MP_NEG; \ + while (_i) { \ + if (_o == _sz) { \ + _sz <<= 1; \ + MP_ENSURE(_d, _sz); \ + } \ + _d->v[_o++] = MPW(-_i); \ + if (_i >= -MPW_MAX) \ + break; \ + else \ + _i /= (type)MPW_MAX + 1; \ + } \ + } \ + \ + _d->vl = _d->v + _o; \ + (d) = _d; \ +} while (0) + +/* --- @MP_TOINT@ --- * + * + * Arguments: @m@ = a multiprecision integer + * @type@ = the type of @i@ + * @max@ = the largest value @i@ can represent + * @i@ = an integer variable + * + * Use: Stores the value of a multiprecision integer in a standard C + * integer. If the value won't fit, the behaviour is determined + * by the type of @i@: if @i@ is unsigned, the value of the + * multiprecision integer modulo @max + 1@ is stored; if @i@ is + * signed, the behaviour is undefined. + * + * If you don't want to be bitten by these sorts of things, keep + * copies of @INT_MAX@ or whatever is appropriate in + * multiprecision form and compare before conversion. + */ + +#define MP_TOINT(m, type, max, i) do { \ + type _i = 0; \ + type _max = (max); \ + unsigned _s = 0; \ + const mp *_m = (m); \ + const mpw *_v = _m->v, *_vl = _m->vl; \ + \ + /* --- Do all the arithmetic in negative numbers --- */ \ + \ + while (_v < _vl && _max > 0) { \ + _i -= *_v << _s; \ + _s += MPW_BITS; \ + _v++; \ + _max /= (mpd)MPW_MAX + 1; \ + } \ + if (!MP_NEGP(_m)) \ + _i = -_i; \ + (i) = _i; \ +} while (0) + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @mp_fromINT@ --- * + * + * Arguments: @mp *d@ = pointer to destination multiprecision integer + * @INT i@ = standard C integer to convert + * + * Returns: The resulting multiprecision integer. + * + * Use: Converts a standard C integer to a multiprecision integer. + */ + +#define mp_fromINT(name, type) \ + extern mp *mp_from##name(mp */*d*/, type /*i*/) + +mp_fromINT(short, short); +mp_fromINT(ushort, unsigned short); +mp_fromINT(int, int); +mp_fromINT(uint, unsigned); +mp_fromINT(uint32, uint32); +mp_fromINT(long, long); +mp_fromINT(ulong, unsigned long); + +#undef mp_fromINT + +/* --- @mp_toINT@ --- * + * + * Arguments: @const mp *m@ = pointer to a multiprecision integer + * + * Returns: The value of the integer @m@ as a C integer. + * + * Use: Converts a multiprecision integer to a standard C integer. + * If the value of the multiprecision integer cannot be + * represented in the return type, and the return type is + * unsigned, it is reduced modulo @TYPE_MAX + 1@; if the return + * type is signed, the behaviour is undefined. + */ + +#define mp_toINT(name, type) \ + extern type mp_to##name(const mp */*m*/) + +mp_toINT(short, short); +mp_toINT(ushort, unsigned short); +mp_toINT(int, int); +mp_toINT(uint, unsigned); +mp_toINT(uint32, uint32); +mp_toINT(long, long); +mp_toINT(ulong, unsigned long); + +#undef mp_toINT + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mpmont-exp.c b/math/mpmont-exp.c new file mode 100644 index 0000000..0ea554e --- /dev/null +++ b/math/mpmont-exp.c @@ -0,0 +1,145 @@ +/* -*-c-*- + * + * Modular exponentiation with Montgomery reduction + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpmont.h" +#include "mpmont-exp.h" + +/*----- Exponentiation ----------------------------------------------------*/ + +/* --- @mpmont_expr@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$(a R^{-1})^e R \bmod m$%. + */ + +mp *mpmont_expr(mpmont *mm, mp *d, mp *a, mp *e) +{ + mp *x = MP_COPY(mm->r); + mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; + + MP_COPY(a); + MP_SHRINK(e); + if (MP_ZEROP(e)) + ; + else { + if (MP_NEGP(e)) { + a = mpmont_reduce(mm, a, a); + a = mp_modinv(a, a, mm->m); + a = mpmont_mul(mm, a, a, mm->r2); + } + if (MP_LEN(e) < EXP_THRESH) + EXP_SIMPLE(x, a, e); + else + EXP_WINDOW(x, a, e); + } + mp_drop(d); + mp_drop(spare); + mp_drop(a); + return (x); +} + +/* --- @mpmont_exp@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e \bmod m$%. + */ + +mp *mpmont_exp(mpmont *mm, mp *d, mp *a, mp *e) +{ + e = MP_COPY(e); + d = mpmont_mul(mm, d, a, mm->r2); + d = mpmont_expr(mm, d, d, e); + d = mpmont_reduce(mm, d, d); + MP_DROP(e); + return (d); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int texp(dstr *v) +{ + mp *m = *(mp **)v[0].buf; + mp *a = *(mp **)v[1].buf; + mp *b = *(mp **)v[2].buf; + mp *r = *(mp **)v[3].buf; + mp *mr; + int ok = 1; + + mpmont mm; + mpmont_create(&mm, m); + + mr = mpmont_exp(&mm, MP_NEW, a, b); + + if (!MP_EQ(mr, r)) { + fputs("\n*** montgomery modexp failed", stderr); + fputs("\n m = ", stderr); mp_writefile(m, stderr, 10); + fputs("\n a = ", stderr); mp_writefile(a, stderr, 10); + fputs("\n e = ", stderr); mp_writefile(b, stderr, 10); + fputs("\n r = ", stderr); mp_writefile(r, stderr, 10); + fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + MP_DROP(m); + MP_DROP(a); + MP_DROP(b); + MP_DROP(r); + MP_DROP(mr); + mpmont_destroy(&mm); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return ok; +} + +static test_chunk tests[] = { + { "exp", texp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, + { 0, 0, { 0 } }, +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mpmont"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpmont-exp.h b/math/mpmont-exp.h new file mode 100644 index 0000000..7ae714d --- /dev/null +++ b/math/mpmont-exp.h @@ -0,0 +1,71 @@ +/* -*-c-*- + * + * Exponentiation operations for Montgomery reduction + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPMONT_EXP_H +#define CATACOMB_MPMONT_EXP_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Exponentation definitions -----------------------------------------*/ + +#define EXP_TYPE mp * + +#define EXP_COPY(d, x) d = MP_COPY(x) +#define EXP_DROP(x) MP_DROP(x) + +#define EXP_MUL(a, x) do { \ + mp *t = mpmont_mul(mm, spare, a, x); \ + spare = a; \ + a = t; \ +} while (0) + +#define EXP_SQR(a) do { \ + mp *t = mp_sqr(spare, a); \ + spare = a; \ + a = mpmont_reduce(mm, t, t); \ +} while (0) + +#define EXP_FIX(x) + +#define EXP_SETMUL(d, x, y) d = mpmont_mul(mm, MP_NEW, x, y) + +#define EXP_SETSQR(d, x) do { \ + d = mp_sqr(MP_NEW, x); \ + d = mpmont_reduce(mm, d, d); \ +} while (0) + +#include "exp.h" + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mpmont-mexp.c b/math/mpmont-mexp.c new file mode 100644 index 0000000..e0f37b5 --- /dev/null +++ b/math/mpmont-mexp.c @@ -0,0 +1,211 @@ +/* -*-c-*- + * + * Multiple simultaneous exponentiations + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpmont.h" + +#define EXP_WINSZ 3 +#include "mpmont-exp.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mpmont_mexpr@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *d@ = fake destination + * @const mp_expfactor *f@ = pointer to array of factors + * @size_t n@ = number of factors supplied + * + * Returns: If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the + * exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result + * is: + * + * %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$% + * + * except that the %$g_i$% and result are in Montgomery form. + */ + +static mp *mexpr(mpmont *mm, mp *d, mp_expfactor *f, size_t n) +{ + mp *a = MP_COPY(mm->r); + mp *spare = MP_NEW; + size_t i; + + for (i = 0; i < n; i++) { + mp *t; + if (f[i].exp->f & MP_BURN) + spare = MP_NEWSEC; + if (MP_NEGP(f[i].exp)) { + t = mpmont_reduce(mm, f[i].base, f[i].base); + t = mp_modinv(t, t, mm->m); + f[i].base = mpmont_mul(mm, t, t, mm->r2); + } + } + EXP_SIMUL(a, f, n); + mp_drop(d); + mp_drop(spare); + for (i = 0; i < n; i++) + MP_DROP(f[i].base); + xfree(f); + return (a); +} + +mp *mpmont_mexpr(mpmont *mm, mp *d, const mp_expfactor *f, size_t n) +{ + mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor)); + size_t i; + + for (i = 0; i < n; i++) { + ff[i].base = MP_COPY(f[i].base); + ff[i].exp = f[i].exp; + } + return (mexpr(mm, d, ff, n)); +} + +/* --- @mpmont_mexp@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *d@ = fake destination + * @const mp_expfactor *f@ = pointer to array of factors + * @size_t n@ = number of factors supplied + * + * Returns: Product of bases raised to exponents, all mod @m@. + * + * Use: Convenient interface over @mpmont_mexpr@. + */ + +mp *mpmont_mexp(mpmont *mm, mp *d, const mp_expfactor *f, size_t n) +{ + mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor)); + size_t i; + + for (i = 0; i < n; i++) { + ff[i].base = mpmont_mul(mm, MP_NEW, f[i].base, mm->r2); + ff[i].exp = f[i].exp; + } + d = mexpr(mm, d, ff, n); + return (mpmont_reduce(mm, d, d)); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +static int verify(size_t n, dstr *v) +{ + mp *m = *(mp **)v[0].buf; + mp_expfactor *f = xmalloc(n * sizeof(*f)); + mp *r, *rr; + size_t i, j; + mpmont mm; + int ok = 1; + + j = 1; + for (i = 0; i < n; i++) { + f[i].base = *(mp **)v[j++].buf; + f[i].exp = *(mp **)v[j++].buf; + } + + rr = *(mp **)v[j].buf; + mpmont_create(&mm, m); + r = mpmont_mexp(&mm, MP_NEW, f, n); + if (!MP_EQ(r, rr)) { + fputs("\n*** mexp failed\n", stderr); + fputs("m = ", stderr); mp_writefile(m, stderr, 10); + for (i = 0; i < n; i++) { + fprintf(stderr, "\ng_%u = ", i); + mp_writefile(f[i].base, stderr, 10); + fprintf(stderr, "\ne_%u = ", i); + mp_writefile(f[i].exp, stderr, 10); + } + fputs("\nr = ", stderr); mp_writefile(r, stderr, 10); + fputs("\nR = ", stderr); mp_writefile(rr, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + for (i = 0; i < n; i++) { + MP_DROP(f[i].base); + MP_DROP(f[i].exp); + } + MP_DROP(m); + MP_DROP(r); + MP_DROP(rr); + mpmont_destroy(&mm); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int t1(dstr *v) { return verify(1, v); } +static int t2(dstr *v) { return verify(2, v); } +static int t3(dstr *v) { return verify(3, v); } +static int t4(dstr *v) { return verify(4, v); } +static int t5(dstr *v) { return verify(5, v); } + +static test_chunk tests[] = { + { "mexp-1", t1, { &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { "mexp-2", t2, { &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { "mexp-3", t3, { &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { "mexp-4", t4, { &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { "mexp-5", t5, { &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, &type_mp, + &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mpmont"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpmont.c b/math/mpmont.c new file mode 100644 index 0000000..88efaca --- /dev/null +++ b/math/mpmont.c @@ -0,0 +1,427 @@ +/* -*-c-*- + * + * Montgomery reduction + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpmont.h" + +/*----- Tweakables --------------------------------------------------------*/ + +/* --- @MPMONT_DISABLE@ --- * + * + * Replace all the clever Montgomery reduction with good old-fashioned long + * division. + */ + +/* #define MPMONT_DISABLE */ + +/*----- Reduction and multiplication --------------------------------------*/ + +/* --- @mpmont_create@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *m@ = modulus to use + * + * Returns: Zero on success, nonzero on error. + * + * Use: Initializes a Montgomery reduction context ready for use. + * The argument @m@ must be a positive odd integer. + */ + +#ifdef MPMONT_DISABLE + +int mpmont_create(mpmont *mm, mp *m) +{ + mp_shrink(m); + mm->m = MP_COPY(m); + mm->r = MP_ONE; + mm->r2 = MP_ONE; + mm->mi = MP_ONE; + return (0); +} + +#else + +int mpmont_create(mpmont *mm, mp *m) +{ + size_t n = MP_LEN(m); + mp *r2 = mp_new(2 * n + 1, 0); + mp r; + + /* --- Take a copy of the modulus --- */ + + if (!MP_POSP(m) || !MP_ODDP(m)) + return (-1); + mm->m = MP_COPY(m); + + /* --- Determine %$R^2$% --- */ + + mm->n = n; + MPX_ZERO(r2->v, r2->vl - 1); + r2->vl[-1] = 1; + + /* --- Find the magic value @mi@ --- */ + + mp_build(&r, r2->v + n, r2->vl); + mm->mi = mp_modinv(MP_NEW, m, &r); + mm->mi = mp_sub(mm->mi, &r, mm->mi); + + /* --- Discover the values %$R \bmod m$% and %$R^2 \bmod m$% --- */ + + mm->r2 = MP_NEW; + mp_div(0, &mm->r2, r2, m); + mm->r = mpmont_reduce(mm, MP_NEW, mm->r2); + MP_DROP(r2); + return (0); +} + +#endif + +/* --- @mpmont_destroy@ --- * + * + * Arguments: @mpmont *mm@ = pointer to a Montgomery reduction context + * + * Returns: --- + * + * Use: Disposes of a context when it's no longer of any use to + * anyone. + */ + +void mpmont_destroy(mpmont *mm) +{ + MP_DROP(mm->m); + MP_DROP(mm->r); + MP_DROP(mm->r2); + MP_DROP(mm->mi); +} + +/* --- @mpmont_reduce@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *d@ = destination + * @mp *a@ = source, assumed positive + * + * Returns: Result, %$a R^{-1} \bmod m$%. + */ + +#ifdef MPMONT_DISABLE + +mp *mpmont_reduce(mpmont *mm, mp *d, mp *a) +{ + mp_div(0, &d, a, mm->m); + return (d); +} + +#else + +mp *mpmont_reduce(mpmont *mm, mp *d, mp *a) +{ + size_t n = mm->n; + + /* --- Check for serious Karatsuba reduction --- */ + + if (n > MPK_THRESH * 3) { + mp al; + mpw *vl; + mp *u; + + if (MP_LEN(a) >= n) + vl = a->v + n; + else + vl = a->vl; + mp_build(&al, a->v, vl); + u = mp_mul(MP_NEW, &al, mm->mi); + if (MP_LEN(u) > n) + u->vl = u->v + n; + u = mp_mul(u, u, mm->m); + d = mp_add(d, a, u); + mp_drop(u); + } + + /* --- Otherwise do it the hard way --- */ + + else { + mpw *dv, *dvl; + mpw *mv, *mvl; + mpw mi; + size_t k = n; + + /* --- Initial conditioning of the arguments --- */ + + a = MP_COPY(a); + if (d) + MP_DROP(d); + d = a; + MP_DEST(d, 2 * n + 1, a->f); + + dv = d->v; dvl = d->vl; + mv = mm->m->v; mvl = mm->m->vl; + + /* --- Let's go to work --- */ + + mi = mm->mi->v[0]; + while (k--) { + mpw u = MPW(*dv * mi); + MPX_UMLAN(dv, dvl, mv, mvl, u); + dv++; + } + } + + /* --- Wrap everything up --- */ + + memmove(d->v, d->v + n, MPWS(MP_LEN(d) - n)); + d->vl -= n; + if (MPX_UCMP(d->v, d->vl, >=, mm->m->v, mm->m->vl)) + mpx_usub(d->v, d->vl, d->v, d->vl, mm->m->v, mm->m->vl); + if (d->f & MP_NEG) { + mpx_usub(d->v, d->vl, mm->m->v, mm->m->vl, d->v, d->vl); + d->f &= ~MP_NEG; + } + MP_SHRINK(d); + return (d); +} + +#endif + +/* --- @mpmont_mul@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *d@ = destination + * @mp *a, *b@ = sources, assumed positive + * + * Returns: Result, %$a b R^{-1} \bmod m$%. + */ + +#ifdef MPMONT_DISABLE + +mp *mpmont_mul(mpmont *mm, mp *d, mp *a, mp *b) +{ + d = mp_mul(d, a, b); + mp_div(0, &d, d, mm->m); + return (d); +} + +#else + +mp *mpmont_mul(mpmont *mm, mp *d, mp *a, mp *b) +{ + if (mm->n > MPK_THRESH * 3) { + d = mp_mul(d, a, b); + d = mpmont_reduce(mm, d, d); + } else { + mpw *dv, *dvl; + mpw *av, *avl; + mpw *bv, *bvl; + mpw *mv, *mvl; + mpw y; + size_t n, i; + mpw mi; + + /* --- Initial conditioning of the arguments --- */ + + if (MP_LEN(a) > MP_LEN(b)) { + mp *t = a; a = b; b = t; + } + n = MP_LEN(mm->m); + + a = MP_COPY(a); + b = MP_COPY(b); + MP_DEST(d, 2 * n + 1, a->f | b->f | MP_UNDEF); + dv = d->v; dvl = d->vl; + MPX_ZERO(dv, dvl); + av = a->v; avl = a->vl; + bv = b->v; bvl = b->vl; + mv = mm->m->v; mvl = mm->m->vl; + y = *bv; + + /* --- Montgomery multiplication phase --- */ + + i = 0; + mi = mm->mi->v[0]; + while (i < n && av < avl) { + mpw x = *av++; + mpw u = MPW((*dv + x * y) * mi); + MPX_UMLAN(dv, dvl, bv, bvl, x); + MPX_UMLAN(dv, dvl, mv, mvl, u); + dv++; + i++; + } + + /* --- Simpler Montgomery reduction phase --- */ + + while (i < n) { + mpw u = MPW(*dv * mi); + MPX_UMLAN(dv, dvl, mv, mvl, u); + dv++; + i++; + } + + /* --- Done --- */ + + memmove(d->v, dv, MPWS(dvl - dv)); + d->vl -= dv - d->v; + if (MPX_UCMP(d->v, d->vl, >=, mm->m->v, mm->m->vl)) + mpx_usub(d->v, d->vl, d->v, d->vl, mm->m->v, mm->m->vl); + if ((a->f ^ b->f) & MP_NEG) + mpx_usub(d->v, d->vl, mm->m->v, mm->m->vl, d->v, d->vl); + MP_SHRINK(d); + d->f = (a->f | b->f) & MP_BURN; + MP_DROP(a); + MP_DROP(b); + } + + return (d); +} + +#endif + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int tcreate(dstr *v) +{ + mp *m = *(mp **)v[0].buf; + mp *mi = *(mp **)v[1].buf; + mp *r = *(mp **)v[2].buf; + mp *r2 = *(mp **)v[3].buf; + + mpmont mm; + int ok = 1; + + mpmont_create(&mm, m); + + if (mm.mi->v[0] != mi->v[0]) { + fprintf(stderr, "\n*** bad mi: found %lu, expected %lu", + (unsigned long)mm.mi->v[0], (unsigned long)mi->v[0]); + fputs("\nm = ", stderr); mp_writefile(m, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + if (!MP_EQ(mm.r, r)) { + fputs("\n*** bad r", stderr); + fputs("\nm = ", stderr); mp_writefile(m, stderr, 10); + fputs("\nexpected ", stderr); mp_writefile(r, stderr, 10); + fputs("\n found ", stderr); mp_writefile(mm.r, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + if (!MP_EQ(mm.r2, r2)) { + fputs("\n*** bad r2", stderr); + fputs("\nm = ", stderr); mp_writefile(m, stderr, 10); + fputs("\nexpected ", stderr); mp_writefile(r2, stderr, 10); + fputs("\n found ", stderr); mp_writefile(mm.r2, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + MP_DROP(m); + MP_DROP(mi); + MP_DROP(r); + MP_DROP(r2); + mpmont_destroy(&mm); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tmul(dstr *v) +{ + mp *m = *(mp **)v[0].buf; + mp *a = *(mp **)v[1].buf; + mp *b = *(mp **)v[2].buf; + mp *r = *(mp **)v[3].buf; + int ok = 1; + + mpmont mm; + mpmont_create(&mm, m); + + { + mp *qr = mp_mul(MP_NEW, a, b); + mp_div(0, &qr, qr, m); + + if (!MP_EQ(qr, r)) { + fputs("\n*** classical modmul failed", stderr); + fputs("\n m = ", stderr); mp_writefile(m, stderr, 10); + fputs("\n a = ", stderr); mp_writefile(a, stderr, 10); + fputs("\n b = ", stderr); mp_writefile(b, stderr, 10); + fputs("\n r = ", stderr); mp_writefile(r, stderr, 10); + fputs("\nqr = ", stderr); mp_writefile(qr, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + mp_drop(qr); + } + + { + mp *ar = mpmont_mul(&mm, MP_NEW, a, mm.r2); + mp *br = mpmont_mul(&mm, MP_NEW, b, mm.r2); + mp *mr = mpmont_mul(&mm, MP_NEW, ar, br); + mr = mpmont_reduce(&mm, mr, mr); + if (!MP_EQ(mr, r)) { + fputs("\n*** montgomery modmul failed", stderr); + fputs("\n m = ", stderr); mp_writefile(m, stderr, 10); + fputs("\n a = ", stderr); mp_writefile(a, stderr, 10); + fputs("\n b = ", stderr); mp_writefile(b, stderr, 10); + fputs("\n r = ", stderr); mp_writefile(r, stderr, 10); + fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + MP_DROP(ar); MP_DROP(br); + mp_drop(mr); + } + + + MP_DROP(m); + MP_DROP(a); + MP_DROP(b); + MP_DROP(r); + mpmont_destroy(&mm); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return ok; +} + +static test_chunk tests[] = { + { "create", tcreate, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, + { "mul", tmul, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, + { 0, 0, { 0 } }, +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mpmont"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpmont.h b/math/mpmont.h new file mode 100644 index 0000000..9973ec3 --- /dev/null +++ b/math/mpmont.h @@ -0,0 +1,201 @@ +/* -*-c-*- + * + * Montgomery reduction + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPMONT_H +#define CATACOMB_MPMONT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +/*----- Notes on Montgomery reduction -------------------------------------* + * + * Given a little bit of precomputation, Montgomery reduction enables modular + * reductions of products to be calculated rather rapidly, without recourse + * to annoying things like division. + * + * Before starting, you need to do a little work. In particular, the + * following things need to be worked out: + * + * * %$m$%, which is the modulus you'll be working with. This must be odd, + * otherwise the whole thing doesn't work. You're better off using + * Barrett reduction if your modulus might be even. + * + * * %$b$%, the radix of the number system you're in (here, it's + * @MPW_MAX + 1@). + * + * * %$-m^{-1} \bmod b$%, a useful number for the reduction step. (This + * means that the modulus mustn't be even. This shouldn't be a problem.) + * + * * %$R = b^n > m > b^{n - 1}$%, or at least %$\log_2 R$%. + * + * * %$R \bmod m$% and %$R^2 \bmod m$%, which are useful when doing + * calculations such as exponentiation. + * + * The result of a Montgomery reduction of %$x$% is %$x R^{-1} \bmod m$%, + * which doesn't look ever-so useful. The trick is to initially apply a + * factor of %$R$% to all of your numbers so that when you multiply and + * perform a Montgomery reduction you get %$(x R \cdot y R) R^{-1} \bmod m$%, + * which is just %$x y R \bmod m$%. Thanks to distributivity, even additions + * and subtractions can be performed on numbers in this form -- the extra + * factor of %$R$% just runs through all the calculations until it's finally + * stripped out by a final reduction operation. + */ + +/*----- Data structures ---------------------------------------------------*/ + +/* --- A Montgomery reduction context --- */ + +typedef struct mpmont { + mp *m; /* Modulus */ + mp *mi; /* %$-m^{-1} \bmod R$% */ + size_t n; /* %$\log_b R$% */ + mp *r, *r2; /* %$R \bmod m$%, %$R^2 \bmod m$% */ +} mpmont; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @mpmont_create@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *m@ = modulus to use + * + * Returns: Zero on success, nonzero on error. + * + * Use: Initializes a Montgomery reduction context ready for use. + * The argument @m@ must be a positive odd integer. + */ + +extern int mpmont_create(mpmont */*mm*/, mp */*m*/); + +/* --- @mpmont_destroy@ --- * + * + * Arguments: @mpmont *mm@ = pointer to a Montgomery reduction context + * + * Returns: --- + * + * Use: Disposes of a context when it's no longer of any use to + * anyone. + */ + +extern void mpmont_destroy(mpmont */*mm*/); + +/* --- @mpmont_reduce@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *d@ = destination + * @mp *a@ = source, assumed positive + * + * Returns: Result, %$a R^{-1} \bmod m$%. + */ + +extern mp *mpmont_reduce(mpmont */*mm*/, mp */*d*/, mp */*a*/); + +/* --- @mpmont_mul@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *d@ = destination + * @mp *a, *b@ = sources, assumed positive + * + * Returns: Result, %$a b R^{-1} \bmod m$%. + */ + +extern mp *mpmont_mul(mpmont */*mm*/, mp */*d*/, mp */*a*/, mp */*b*/); + +/* --- @mpmont_expr@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$(a R^{-1})^e R \bmod m$%. This is useful if + * further modular arithmetic is to be performed on the result. + */ + +extern mp *mpmont_expr(mpmont */*mm*/, mp */*d*/, mp */*a*/, mp */*e*/); + +/* --- @mpmont_exp@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e \bmod m$%. + */ + +extern mp *mpmont_exp(mpmont */*mm*/, mp */*d*/, mp */*a*/, mp */*e*/); + +/* --- @mpmont_mexpr@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *d@ = fake destination + * @const mp_expfactor *f@ = pointer to array of factors + * @size_t n@ = number of factors supplied + * + * Returns: If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the + * exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result + * is: + * + * %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$% + * + * + * except that the %$g_i$% and result are in Montgomery form. + */ + +extern mp *mpmont_mexpr(mpmont */*mm*/, mp */*d*/, + const mp_expfactor */*f*/, size_t /*n*/); + +/* --- @mpmont_mexp@ --- * + * + * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context + * @mp *d@ = fake destination + * @const mp_expfactor *f@ = pointer to array of factors + * @size_t n@ = number of factors supplied + * + * Returns: Product of bases raised to exponents, all mod @m@. + * + * Use: Convenient interface over @mpmont_mexpr@. + */ + +extern mp *mpmont_mexp(mpmont */*mm*/, mp */*d*/, + const mp_expfactor */*f*/, size_t /*n*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mpmul.c b/math/mpmul.c new file mode 100644 index 0000000..e168bc1 --- /dev/null +++ b/math/mpmul.c @@ -0,0 +1,179 @@ +/* -*-c-*- + * + * Multiply many small numbers together + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpint.h" +#include "mpmul.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mpmul_init@ --- * + * + * Arguments: @mpmul *b@ = pointer to multiplier context to initialize + * + * Returns: --- + * + * Use: Initializes a big multiplier context for use. + */ + +void mpmul_init(mpmul *b) +{ + b->i = 0; +} + +/* --- @mpmul_add@ --- * + * + * Arguments: @mpmul *b@ = pointer to multiplier context + * @mp *x@ = the next factor to multiply in + * + * Returns: --- + * + * Use: Contributes another factor to the mix. It's important that + * the integer lasts at least as long as the multiplication + * context; this sort of rules out @mp_build@ integers. + */ + +#define HWM (MPMUL_DEPTH - 20) +#define LWM (MPMUL_DEPTH / 2) + +void mpmul_add(mpmul *b, mp *x) +{ + size_t i = b->i; + + /* --- Now do the reduction step --- */ + + x = MP_COPY(x); + + while (i > 0) { + if (MP_LEN(b->v[i - 1]) > MP_LEN(x)) + break; + i--; + x = mp_mul(x, x, b->v[i]); + MP_DROP(b->v[i]); + } + + if (i > HWM) { + while (i > LWM || (i > 0 && MP_LEN(b->v[i - 1]) <= MP_LEN(x))) { + i--; + x = mp_mul(x, x, b->v[i]); + MP_DROP(b->v[i]); + } + } + + b->v[i++] = x; + b->i = i; +} + +/* --- @mpmul_done@ --- * + * + * Arguments: @mpmul *b@ = pointer to big multiplication context + * + * Returns: The product of all the numbers contributed. + * + * Use: Returns a (large) product of numbers. The context is + * deallocated. + */ + +mp *mpmul_done(mpmul *b) +{ + size_t i = b->i; + mp *x; + + if (!i) + return (MP_ONE); + i--; + x = b->v[i]; + while (i > 0) { + i--; + x = mp_mul(x, x, b->v[i]); + MP_DROP(b->v[i]); + } + return (x); +} + +/* --- @mp_factorial@ --- * + * + * Arguments: @unsigned long i@ = number whose factorial should be + * computed. + * + * Returns: The requested factorial. + */ + +mp *mp_factorial(unsigned long i) +{ + unsigned long j; + mp *x = MP_NEW; + mpmul b = MPMUL_INIT; + + for (j = 1; j <= i; j++) { + x = mp_fromulong(x, j); + mpmul_add(&b, x); + } + mp_drop(x); + return (mpmul_done(&b)); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +static int vfact(dstr *v) +{ + unsigned long x = *(unsigned long *)v[0].buf; + mp *fx = *(mp **)v[1].buf; + mp *y = mp_factorial(x); + int ok = 1; + if (!MP_EQ(fx, y)) { + fprintf(stderr, "factorial failed\n"); + MP_FPRINTF(stderr, (stderr, "%lu! = ", x), fx); + MP_EPRINT("result", y); + ok = 0; + } + mp_drop(fx); + mp_drop(y); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "factorial", vfact, { &type_ulong, &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, tests, SRCDIR "/t/mp"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpmul.h b/math/mpmul.h new file mode 100644 index 0000000..1dfb587 --- /dev/null +++ b/math/mpmul.h @@ -0,0 +1,139 @@ +/* -*-c-*- + * + * Multiply many small numbers together + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPMUL_H +#define CATACOMB_MPMUL_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +/* --- How the algorithm works --- * + * + * Multiplication on large integers is least wasteful when the numbers + * multiplied are approximately the same size. When a new multiplier is + * added to the system, we push it onto a stack. Then we `reduce' the stack: + * while the value on the top of the stack is not shorter than the value + * below it, replace the top two elements by their product. + * + * Let %$b$% be the radix of our multiprecision integers, and let %$Z$% be + * the maximum number of digits. Then the largest integer we can represent + * is %$M - 1 = b^Z - 1$%. We could assume that all of the integers we're + * given are about the same size. This would give us the same upper bound as + * that derived in `mptext.c'. + * + * However, we're in less control over our inputs. In particular, if a + * sequence of integers with strictly decreasing lengths is input then we're + * sunk. Suppose that the stack contains, from top to bottom, %$b^i$%, + * %$b^{i+1}$%, ..., %$b^n$%. The final product will therefore be + * %$p = b^{(n+i)(n-i+1)/2}$%. We must now find the maximum stack depth + * %$d = n - i$% such that %$p > M$%. + * + * Taking logs of both sides gives that %$(d + 2 i)(d + 1) > 2 Z$%. We can + * maximize %$d$% by taking %$i = 0$%, which gives that %$d^2 + d > 2 Z$%, so + * %$d$% must be approximately %$(\sqrt{8 Z + 1} - 1)/2$%, which is + * uncomfortably large. + * + * We compromise by choosing double the `mptext' bound and imposing high- and + * low-water marks for forced reduction. + */ + +#define MPMUL_DEPTH (2 * (CHAR_BIT * sizeof(size_t) + 10)) + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct mpmul { + size_t i; + mp *v[MPMUL_DEPTH]; +} mpmul; + +#define MPMUL_INIT { 0 } + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @mpmul_init@ --- * + * + * Arguments: @mpmul *b@ = pointer to multiplier context to initialize + * + * Returns: --- + * + * Use: Initializes a big multiplier context for use. + */ + +extern void mpmul_init(mpmul */*b*/); + +/* --- @mpmul_add@ --- * + * + * Arguments: @mpmul *b@ = pointer to multiplier context + * @mp *x@ = the next factor to multiply in + * + * Returns: --- + * + * Use: Contributes another factor to the mix. It's important that + * the integer lasts at least as long as the multiplication + * context; this sort of rules out @mp_build@ integers. + */ + +extern void mpmul_add(mpmul */*b*/, mp */*x*/); + +/* --- @mpmul_done@ --- * + * + * Arguments: @mpmul *b@ = pointer to big multiplication context + * + * Returns: The product of all the numbers contributed. + * + * Use: Returns a (large) product of numbers. The context is + * deallocated. + */ + +extern mp *mpmul_done(mpmul */*b*/); + +/* --- @mp_factorial@ --- * + * + * Arguments: @unsigned long i@ = number whose factorial should be + * computed. + * + * Returns: The requested factorial. + */ + +extern mp *mp_factorial(unsigned long /*i*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mprand.c b/math/mprand.c new file mode 100644 index 0000000..eb779cb --- /dev/null +++ b/math/mprand.c @@ -0,0 +1,138 @@ +/* -*-c-*- + * + * Generate a random multiprecision integer + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "grand.h" +#include "mp.h" +#include "mprand.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mprand@ --- * + * + * Arguments: @mp *d@ = destination integer + * @unsigned b@ = number of bits + * @grand *r@ = pointer to random number source + * @mpw or@ = mask to OR with low-order bits + * + * Returns: A random integer with the requested number of bits. + * + * Use: Constructs an arbitrarily large pseudorandom integer. + * Assuming that the generator @r@ is good, the result is + * uniformly distributed in the interval %$[2^{b - 1}, 2^b)$%. + * The result is then ORred with the given @or@ value. This + * will often be 1, to make the result odd. + */ + +mp *mprand(mp *d, unsigned b, grand *r, mpw or) +{ + size_t sz = (b + 7) >> 3; + arena *a = (d && (d->f & MP_BURN)) ? arena_secure : arena_global; + octet *v = x_alloc(a, sz); + unsigned m; + + /* --- Fill buffer with random data --- */ + + r->ops->fill(r, v, sz); + + /* --- Force into the correct range --- * + * + * This is slightly tricky. Oh, well. + */ + + b = (b - 1) & 7; + m = (1 << b); + v[0] = (v[0] & (m - 1)) | m; + + /* --- Mask, load and return --- */ + + d = mp_loadb(d, v, sz); + d->v[0] |= or; + memset(v, 0, sz); + x_free(a, v); + return (d); +} + +/* --- @mprand_range@ --- * + * + * Arguments: @mp *d@ = destination integer + * @mp *l@ = limit for random number + * @grand *r@ = random number source + * @mpw or@ = mask for low-order bits + * + * Returns: A pseudorandom integer, unformly distributed over the + * interval %$[0, l)$%. + * + * Use: Generates a uniformly-distributed pseudorandom number in the + * appropriate range. + */ + +mp *mprand_range(mp *d, mp *l, grand *r, mpw or) +{ + size_t b = mp_bits(l); + size_t sz = (b + 7) >> 3; + arena *a = (d && (d->f & MP_BURN)) ? arena_secure : arena_global; + octet *v = x_alloc(a, sz); + unsigned m; + + /* --- The algorithm --- * + * + * Rather simpler than most. Find the number of bits in the number %$l$% + * (i.e., the integer %$b$% such that %$2^{b - 1} \le l < 2^b$%), and + * generate pseudorandom integers with %$n$% bits (but not, unlike in the + * function above, with the top bit forced to 1). If the integer is + * greater than or equal to %$l$%, try again. + * + * This is similar to the algorithms used in @lcrand_range@ and friends, + * except that I've forced the `raw' range of the random numbers such that + * %$l$% itself is the largest multiple of %$l$% in the range (since, by + * the inequality above, %$2^b \le 2l$%). This removes the need for costly + * division and remainder operations. + * + * As usual, the number of iterations expected is two. + */ + + b = ((b - 1) & 7) + 1; + m = (1 << b) - 1; + do { + r->ops->fill(r, v, sz); + v[0] &= m; + d = mp_loadb(d, v, sz); + d->v[0] |= or; + } while (MP_CMP(d, >=, l)); + + /* --- Done --- */ + + memset(v, 0, sz); + x_free(a, v); + return (d); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mprand.h b/math/mprand.h new file mode 100644 index 0000000..0c193c0 --- /dev/null +++ b/math/mprand.h @@ -0,0 +1,87 @@ +/* -*-c-*- + * + * Generate a random multiprecision integer + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPRAND_H +#define CATACOMB_MPRAND_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @mprand@ --- * + * + * Arguments: @mp *d@ = destination integer + * @unsigned b@ = number of bits + * @grand *r@ = pointer to random number source + * @mpw or@ = mask to OR with low-order bits + * + * Returns: A random integer with the requested number of bits + * + * Use: Constructs an arbitrarily large pseudorandom integer. + * Assuming that the generator @r@ is good, the result is + * uniformly distributed in the interval %$[2^{b - 1}, 2^b)$%. + * The result is then ORred with the given @or@ value. This + * will often be 1, to make the result odd. + */ + +extern mp *mprand(mp */*d*/, unsigned /*b*/, grand */*r*/, mpw /*or*/); + +/* --- @mprand_range@ --- * + * + * Arguments: @mp *d@ = destination integer + * @mp *l@ = limit for random number + * @grand *r@ = random number source + * @mpw or@ = mask for low-order bits + * + * Returns: A pseudorandom integer, unformly distributed over the + * interval %$[0, l)$%. + * + * Use: Generates a uniformly-distributed pseudorandom number in the + * appropriate range. + */ + +extern mp *mprand_range(mp */*d*/, mp */*l*/, grand */*r*/, mpw /*or*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mpreduce-exp.h b/math/mpreduce-exp.h new file mode 100644 index 0000000..f314514 --- /dev/null +++ b/math/mpreduce-exp.h @@ -0,0 +1,74 @@ +/* -*-c-*- + * + * Exponentiation operations for binary field reduction + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPREDUCE_EXP_H +#define CATACOMB_MPREDUCE_EXP_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Exponentiation definitions ----------------------------------------*/ + +#define EXP_TYPE mp * + +#define EXP_COPY(d, x) d = MP_COPY(x) +#define EXP_DROP(x) MP_DROP(x) + +#define EXP_MUL(a, x) do { \ + mp *t = mp_mul(spare, a, x); \ + spare = a; \ + a = mpreduce_do(mr, t, t); \ +} while (0) + +#define EXP_SQR(a) do { \ + mp *t = mp_sqr(spare, a); \ + spare = a; \ + a = mpreduce_do(mr, t, t); \ +} while (0) + +#define EXP_FIX(x) + +#define EXP_SETMUL(d, x, y) do { \ + d = mp_mul(MP_NEW, x, y); \ + d = mpreduce_do(mr, d, d); \ +} while (0) + +#define EXP_SETSQR(d, x) do { \ + d = mp_sqr(MP_NEW, x); \ + d = mpreduce_do(mr, d, d); \ +} while (0) + +#include "exp.h" + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mpreduce.c b/math/mpreduce.c new file mode 100644 index 0000000..669f516 --- /dev/null +++ b/math/mpreduce.c @@ -0,0 +1,438 @@ +/* -*-c-*- + * + * Efficient reduction modulo nice primes + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include "mp.h" +#include "mpreduce.h" +#include "mpreduce-exp.h" + +/*----- Data structures ---------------------------------------------------*/ + +DA_DECL(instr_v, mpreduce_instr); + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mpreduce_create@ --- * + * + * Arguments: @gfreduce *r@ = structure to fill in + * @mp *x@ = an integer + * + * Returns: Zero if successful; nonzero on failure. + * + * Use: Initializes a context structure for reduction. + */ + +int mpreduce_create(mpreduce *r, mp *p) +{ + mpscan sc; + enum { Z = 0, Z1 = 2, X = 4, X0 = 6 }; + unsigned st = Z; + instr_v iv = DA_INIT; + unsigned long d, i; + unsigned op; + size_t w, b, bb; + + /* --- Fill in the easy stuff --- */ + + if (!MP_POSP(p)) + return (-1); + d = mp_bits(p); + r->lim = d/MPW_BITS; + r->s = d%MPW_BITS; + if (r->s) + r->lim++; + r->p = mp_copy(p); + + /* --- Stash a new instruction --- */ + +#define INSTR(op_, argx_, argy_) do { \ + DA_ENSURE(&iv, 1); \ + DA(&iv)[DA_LEN(&iv)].op = (op_); \ + DA(&iv)[DA_LEN(&iv)].argx = (argx_); \ + DA(&iv)[DA_LEN(&iv)].argy = (argy_); \ + DA_EXTEND(&iv, 1); \ +} while (0) + + /* --- Main loop --- * + * + * A simple state machine decomposes @p@ conveniently into positive and + * negative powers of 2. The pure form of the state machine is left below + * for reference (and in case I need inspiration for a NAF exponentiator). + */ + +#ifdef DEBUG + for (i = 0, mp_scan(&sc, p); mp_step(&sc); i++) { + switch (st | mp_bit(&sc)) { + case Z | 1: st = Z1; break; + case Z1 | 0: st = Z; printf("+ %lu\n", i - 1); break; + case Z1 | 1: st = X; printf("- %lu\n", i - 1); break; + case X | 0: st = X0; break; + case X0 | 1: st = X; printf("- %lu\n", i - 1); break; + case X0 | 0: st = Z; printf("+ %lu\n", i - 1); break; + } + } + if (st >= X) printf("+ %lu\n", i - 1); + st = Z; +#endif + + bb = MPW_BITS - (d + 1)%MPW_BITS; + for (i = 0, mp_scan(&sc, p); i < d && mp_step(&sc); i++) { + switch (st | mp_bit(&sc)) { + case Z | 1: st = Z1; break; + case Z1 | 0: st = Z; op = MPRI_SUB; goto instr; + case Z1 | 1: st = X; op = MPRI_ADD; goto instr; + case X | 0: st = X0; break; + case X0 | 1: st = X; op = MPRI_ADD; goto instr; + case X0 | 0: st = Z; op = MPRI_SUB; goto instr; + instr: + w = (d - i)/MPW_BITS + 1; + b = (bb + i)%MPW_BITS; + INSTR(op | !!b, w, b); + } + } + if (DA_LEN(&iv) && (DA(&iv)[DA_LEN(&iv) - 1].op & ~1u) == MPRI_SUB) { + mp_drop(r->p); + DA_DESTROY(&iv); + return (-1); + } + +#undef INSTR + + /* --- Wrap up --- */ + + r->in = DA_LEN(&iv); + if (!r->in) + r->iv = 0; + else if (!r->s) { + r->iv = xmalloc(r->in * sizeof(mpreduce_instr)); + memcpy(r->iv, DA(&iv), r->in * sizeof(mpreduce_instr)); + } else { + r->iv = xmalloc(r->in * 2 * sizeof(mpreduce_instr)); + for (i = 0; i < r->in; i++) { + r->iv[i] = DA(&iv)[i]; + op = r->iv[i].op & ~1u; + w = r->iv[i].argx; + b = r->iv[i].argy; + b += r->s; + if (b >= MPW_BITS) { + b -= MPW_BITS; + w--; + } + if (b) op |= 1; + r->iv[i + r->in].op = op; + r->iv[i + r->in].argx = w; + r->iv[i + r->in].argy = b; + } + } + DA_DESTROY(&iv); + +#ifdef DEBUG + mpreduce_dump(r, stdout); +#endif + return (0); +} + +/* --- @mpreduce_destroy@ --- * + * + * Arguments: @mpreduce *r@ = structure to free + * + * Returns: --- + * + * Use: Reclaims the resources from a reduction context. + */ + +void mpreduce_destroy(mpreduce *r) +{ + mp_drop(r->p); + if (r->iv) xfree(r->iv); +} + +/* --- @mpreduce_dump@ --- * + * + * Arguments: @mpreduce *r@ = structure to dump + * @FILE *fp@ = file to dump on + * + * Returns: --- + * + * Use: Dumps a reduction context. + */ + +void mpreduce_dump(mpreduce *r, FILE *fp) +{ + size_t i; + static const char *opname[] = { "add", "addshift", "sub", "subshift" }; + + fprintf(fp, "mod = "); mp_writefile(r->p, fp, 16); + fprintf(fp, "\n lim = %lu; s = %d\n", (unsigned long)r->lim, r->s); + for (i = 0; i < r->in; i++) { + assert(r->iv[i].op < N(opname)); + fprintf(fp, " %s %lu %lu\n", + opname[r->iv[i].op], + (unsigned long)r->iv[i].argx, + (unsigned long)r->iv[i].argy); + } + if (r->s) { + fprintf(fp, "tail end charlie\n"); + for (i = r->in; i < 2 * r->in; i++) { + assert(r->iv[i].op < N(opname)); + fprintf(fp, " %s %lu %lu\n", + opname[r->iv[i].op], + (unsigned long)r->iv[i].argx, + (unsigned long)r->iv[i].argy); + } + } +} + +/* --- @mpreduce_do@ --- * + * + * Arguments: @mpreduce *r@ = reduction context + * @mp *d@ = destination + * @mp *x@ = source + * + * Returns: Destination, @x@ reduced modulo the reduction poly. + */ + +static void run(const mpreduce_instr *i, const mpreduce_instr *il, + mpw *v, mpw z) +{ + for (; i < il; i++) { +#ifdef DEBUG + mp vv; + mp_build(&vv, v - i->argx, v + 1); + printf(" 0x"); mp_writefile(&vv, stdout, 16); + printf(" %c (0x%lx << %u) == 0x", + (i->op & ~1u) == MPRI_ADD ? '+' : '-', + (unsigned long)z, + i->argy); +#endif + switch (i->op) { + case MPRI_ADD: MPX_UADDN(v - i->argx, v + 1, z); break; + case MPRI_ADDLSL: mpx_uaddnlsl(v - i->argx, v + 1, z, i->argy); break; + case MPRI_SUB: MPX_USUBN(v - i->argx, v + 1, z); break; + case MPRI_SUBLSL: mpx_usubnlsl(v - i->argx, v + 1, z, i->argy); break; + default: + abort(); + } +#ifdef DEBUG + mp_build(&vv, v - i->argx, v + 1); + mp_writefile(&vv, stdout, 16); + printf("\n"); +#endif + } +} + +mp *mpreduce_do(mpreduce *r, mp *d, mp *x) +{ + mpw *v, *vl; + const mpreduce_instr *il; + mpw z; + +#ifdef DEBUG + mp *_r = 0, *_rr = 0; +#endif + + /* --- If source is negative, divide --- */ + + if (MP_NEGP(x)) { + mp_div(0, &d, x, r->p); + return (d); + } + + /* --- Try to reuse the source's space --- */ + + MP_COPY(x); + if (d) MP_DROP(d); + MP_DEST(x, MP_LEN(x), x->f); + + /* --- Do the reduction --- */ + +#ifdef DEBUG + _r = MP_NEW; + mp_div(0, &_r, x, r->p); + MP_PRINTX("x", x); + _rr = 0; +#endif + + il = r->iv + r->in; + if (MP_LEN(x) >= r->lim) { + v = x->v + r->lim; + vl = x->vl; + while (vl-- > v) { + while (*vl) { + z = *vl; + *vl = 0; + run(r->iv, il, vl, z); +#ifdef DEBUG + MP_PRINTX("x", x); + mp_div(0, &_rr, x, r->p); + assert(MP_EQ(_r, _rr)); +#endif + } + } + if (r->s) { + while (*vl >> r->s) { + z = *vl >> r->s; + *vl &= ((1 << r->s) - 1); + run(r->iv + r->in, il + r->in, vl, z); +#ifdef DEBUG + MP_PRINTX("x", x); + mp_div(0, &_rr, x, r->p); + assert(MP_EQ(_r, _rr)); +#endif + } + } + } + + /* --- Finishing touches --- */ + + MP_SHRINK(x); + if (MP_CMP(x, >=, r->p)) + x = mp_sub(x, x, r->p); + + /* --- Done --- */ + +#ifdef DEBUG + assert(MP_EQ(_r, x)); + mp_drop(_r); + mp_drop(_rr); +#endif + return (x); +} + +/* --- @mpreduce_exp@ --- * + * + * Arguments: @mpreduce *mr@ = pointer to reduction context + * @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e \bmod m$%. + */ + +mp *mpreduce_exp(mpreduce *mr, mp *d, mp *a, mp *e) +{ + mp *x = MP_ONE; + mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; + + MP_SHRINK(e); + MP_COPY(a); + if (MP_ZEROP(e)) + ; + else { + if (MP_NEGP(e)) + a = mp_modinv(a, a, mr->p); + if (MP_LEN(e) < EXP_THRESH) + EXP_SIMPLE(x, a, e); + else + EXP_WINDOW(x, a, e); + } + mp_drop(a); + mp_drop(d); + mp_drop(spare); + return (x); +} + +/*----- Test rig ----------------------------------------------------------*/ + + +#ifdef TEST_RIG + +#define MP(x) mp_readstring(MP_NEW, #x, 0, 0) + +static int vreduce(dstr *v) +{ + mp *d = *(mp **)v[0].buf; + mp *n = *(mp **)v[1].buf; + mp *r = *(mp **)v[2].buf; + mp *c; + int ok = 1; + mpreduce rr; + + mpreduce_create(&rr, d); + c = mpreduce_do(&rr, MP_NEW, n); + if (!MP_EQ(c, r)) { + fprintf(stderr, "\n*** reduction failed\n*** "); + mpreduce_dump(&rr, stderr); + fprintf(stderr, "\n*** n = "); mp_writefile(n, stderr, 10); + fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 10); + fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 10); + fprintf(stderr, "\n"); + ok = 0; + } + mpreduce_destroy(&rr); + mp_drop(n); mp_drop(d); mp_drop(r); mp_drop(c); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vmodexp(dstr *v) +{ + mp *p = *(mp **)v[0].buf; + mp *g = *(mp **)v[1].buf; + mp *x = *(mp **)v[2].buf; + mp *r = *(mp **)v[3].buf; + mp *c; + int ok = 1; + mpreduce rr; + + mpreduce_create(&rr, p); + c = mpreduce_exp(&rr, MP_NEW, g, x); + if (!MP_EQ(c, r)) { + fprintf(stderr, "\n*** modexp failed\n*** "); + fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 10); + fprintf(stderr, "\n*** g = "); mp_writefile(g, stderr, 10); + fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 10); + fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 10); + fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 10); + fprintf(stderr, "\n"); + ok = 0; + } + mpreduce_destroy(&rr); + mp_drop(p); mp_drop(g); mp_drop(r); mp_drop(x); mp_drop(c); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk defs[] = { + { "reduce", vreduce, { &type_mp, &type_mp, &type_mp, 0 } }, + { "modexp", vmodexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/t/mpreduce"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpreduce.h b/math/mpreduce.h new file mode 100644 index 0000000..c90c93f --- /dev/null +++ b/math/mpreduce.h @@ -0,0 +1,126 @@ +/* -*-c-*- + * + * Efficient reduction modulo nice primes + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPREDUCE_H +#define CATACOMB_MPREDUCE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct mpreduce_instr { + unsigned op; /* Instruction opcode */ + size_t argx, argy; /* Immediate arguments */ +} mpreduce_instr; + +enum { + MPRI_ADD, /* Add @p@ offset by @x@ words */ + MPRI_ADDLSL, /* Add @p << y@ offset by @x@ */ + MPRI_SUB, /* Sub @p@ offset by @x@ words */ + MPRI_SUBLSL, /* Sub @p << y@ offset by @x@ */ + MPRI_MAX +}; + +typedef struct mpreduce { + size_t lim; /* Word containing top bit */ + unsigned s; /* Shift for top word */ + mp *p; /* Copy of the modulus */ + size_t in; /* Number of instruction words */ + mpreduce_instr *iv; /* Vector of instructions */ +} mpreduce; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @mpreduce_create@ --- * + * + * Arguments: @gfreduce *r@ = structure to fill in + * @mp *x@ = an integer + * + * Returns: Zero for success, nonzero on error. + * + * Use: Initializes a context structure for reduction. + */ + +extern int mpreduce_create(mpreduce */*r*/, mp */*p*/); + +/* --- @mpreduce_destroy@ --- * + * + * Arguments: @mpreduce *r@ = structure to free + * + * Returns: --- + * + * Use: Reclaims the resources from a reduction context. + */ + +extern void mpreduce_destroy(mpreduce */*r*/); + +/* --- @mpreduce_dump@ --- * + * + * Arguments: @mpreduce *r@ = structure to dump + * @FILE *fp@ = file to dump on + * + * Returns: --- + * + * Use: Dumps a reduction context. + */ + +extern void mpreduce_dump(mpreduce */*r*/, FILE */*fp*/); + +/* --- @mpreduce_do@ --- * + * + * Arguments: @mpreduce *r@ = reduction context + * @mp *d@ = destination + * @mp *x@ = source + * + * Returns: Destination, @x@ reduced modulo the reduction poly. + */ + +extern mp *mpreduce_do(mpreduce */*r*/, mp */*d*/, mp */*x*/); + +/* --- @mpreduce_exp@ --- * + * + * Arguments: @mpreduce *mr@ = pointer to reduction context + * @mp *d@ = fake destination + * @mp *a@ = base + * @mp *e@ = exponent + * + * Returns: Result, %$a^e \bmod m$%. + */ + +extern mp *mpreduce_exp(mpreduce */*mr*/, mp */*d*/, mp */*a*/, mp */*e*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mpscan.c b/math/mpscan.c new file mode 100644 index 0000000..4b8c971 --- /dev/null +++ b/math/mpscan.c @@ -0,0 +1,120 @@ +/* -*-c-*- + * + * Sequential bit scan of multiprecision integers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mpscan.h" + +/*----- Right-to-left scanning --------------------------------------------*/ + +/* --- @mpscan_initx@ --- * + * + * Arguments: @mpscan *m@ = pointer to bitscanner structure + * @const mpw *v, *vl@ = vector of words to scan + * + * Returns: --- + * + * Use: Initializes a bitscanner from a low-level vector-and-length + * representation of an integer. Initially no bit is ready; you + * must call @mpscan_step@ before anything useful will come + * out. + */ + +void mpscan_initx(mpscan *m, const mpw *v, const mpw *vl) +{ + MPSCAN_INITX(m, v, vl); +} + +/* --- @mpscan_step@ --- * + * + * Arguments: @mpscan *m@ = pointer to bitscanner + * + * Returns: Nonzero if there is another bit to read. + * + * Use: Steps on to the next bit in the integer. The macro version + * evaluates its argument multiple times. + */ + +int mpscan_step(mpscan *m) { return (MPSCAN_STEP(m)); } + +/* --- @mpscan_bit@ --- * + * + * Arguments: @const mpscan *m@ = pointer to bitscanner + * + * Returns: The value of the current bit. + * + * Use: Reads the value of the current bit looked at by a + * bitscanner. + */ + +int mpscan_bit(const mpscan *m) { return (MPSCAN_BIT(m)); } + +/*----- Left-to right-scanning --------------------------------------------*/ + +/* --- @mpscan_rinitx@ --- * + * + * Arguments: @mpscan *m@ = pointer to bitscanner structure + * @const mpw *v, *vl@ = vector of words to scan + * + * Returns: --- + * + * Use: Initializes a reverse bitscanner from a low-level + * vector-and-length representation of an integer. Initially no + * bit is ready; you must call @mpscan_rstep@ before anything + * useful will come out. + */ + +void mpscan_rinitx(mpscan *m, const mpw *v, const mpw *vl) +{ + MPSCAN_RINITX(m, v, vl); +} + +/* --- @mpscan_rstep@ --- * + * + * Arguments: @mpscan *m@ = pointer to bitscanner + * + * Returns: Nonzero if there is another bit to read. + * + * Use: Steps on to the next bit in the integer. The macro version + * evaluates its argument multiple times. + */ + +int mpscan_rstep(mpscan *m) { return (MPSCAN_RSTEP(m)); } + +/* --- @mpscan_rbit@ --- * + * + * Arguments: @const mpscan *m@ = pointer to bitscanner + * + * Returns: The value of the current bit. + * + * Use: Reads the value of the current bit looked at by a + * reverse bitscanner. + */ + +int mpscan_rbit(const mpscan *m) { return (MPSCAN_RBIT(m)); } + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpscan.h b/math/mpscan.h new file mode 100644 index 0000000..8ba4bd7 --- /dev/null +++ b/math/mpscan.h @@ -0,0 +1,170 @@ +/* -*-c-*- + * + * Sequential bit scan of multiprecision integers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPSCAN_H +#define CATACOMB_MPSCAN_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MPW_H +# include "mpw.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct mpscan { + const mpw *v, *vl; /* Vector of words to scan */ + mpw w; /* Current word to scan */ + int bits; /* Number of bits left in @w@ */ +} mpscan; + +/*----- Right-to-left scanning --------------------------------------------*/ + +/* --- @mpscan_initx@ --- * + * + * Arguments: @mpscan *m@ = pointer to bitscanner structure + * @const mpw *v, *vl@ = vector of words to scan + * + * Returns: --- + * + * Use: Initializes a bitscanner from a low-level base-and-limit + * representation of an integer. Initially no bit is ready; you + * must call @mpscan_step@ before anything useful will come + * out. + */ + +#define MPSCAN_INITX(m_, v_, vl_) do { \ + mpscan *_m = (m_); \ + _m->v = (v_); \ + _m->vl = (vl_); \ + _m->bits = 0; \ +} while (0) + +extern void mpscan_initx(mpscan */*m*/, const mpw */*v*/, const mpw */*vl*/); + +/* --- @mpscan_step@ --- * + * + * Arguments: @mpscan *m@ = pointer to bitscanner + * + * Returns: Nonzero if there is another bit to read. + * + * Use: Steps on to the next bit in the integer. The macro version + * evaluates its argument multiple times. + */ + +#define MPSCAN_STEP(m) \ + ((m)->bits ? ((m)->w >>= 1, (m)->bits--, 1) : \ + (m)->v < (m)->vl ? ((m)->w = *(m)->v++, \ + (m)->bits = MPW_BITS - 1, 1) : \ + 0) + +extern int mpscan_step(mpscan */*m*/); + +/* --- @mpscan_bit@ --- * + * + * Arguments: @const mpscan *m@ = pointer to bitscanner + * + * Returns: The value of the current bit. + * + * Use: Reads the value of the current bit looked at by a + * bitscanner. + */ + +#define MPSCAN_BIT(m) ((m)->w & 1) + +extern int mpscan_bit(const mpscan */*m*/); + +/*----- Left-to right-scanning --------------------------------------------*/ + +/* --- @mpscan_rinitx@ --- * + * + * Arguments: @mpscan *m@ = pointer to bitscanner structure + * @const mpw *v, *vl@ = vector of words to scan + * + * Returns: --- + * + * Use: Initializes a reverse bitscanner from a low-level + * vector-and-length representation of an integer. Initially no + * bit is ready; you must call @mpscan_rstep@ before anything + * useful will come out. + */ + +#define MPSCAN_RINITX(m_, v_, vl_) do { \ + mpscan *_m = (m_); \ + _m->v = (v_); \ + _m->vl = (vl_); \ + while (_m->vl > _m->v && !_m->vl[-1]) \ + _m->vl--; \ + _m->bits = 0; \ +} while (0) + +extern void mpscan_rinitx(mpscan */*m*/, + const mpw */*v*/, const mpw */*vl*/); + +/* --- @mpscan_rstep@ --- * + * + * Arguments: @mpscan *m@ = pointer to bitscanner + * + * Returns: Nonzero if there is another bit to read. + * + * Use: Steps on to the next bit in the integer. The macro version + * evaluates its argument multiple times. + */ + +#define MPSCAN_RSTEP(m) \ + ((m)->bits ? ((m)->w <<= 1, (m)->bits--, 1) : \ + (m)->vl > (m)->v ? ((m)->w = *--(m)->vl, \ + (m)->bits = MPW_BITS - 1, 1) : \ + 0) + +extern int mpscan_rstep(mpscan */*m*/); + +/* --- @mpscan_rbit@ --- * + * + * Arguments: @const mpscan *m@ = pointer to bitscanner + * + * Returns: The value of the current bit. + * + * Use: Reads the value of the current bit looked at by a + * reverse bitscanner. + */ + +#define MPSCAN_RBIT(m) (((m)->w >> (MPW_BITS - 1)) & 1) + +extern int mpscan_rbit(const mpscan */*m*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mptext-dstr.c b/math/mptext-dstr.c new file mode 100644 index 0000000..bb52390 --- /dev/null +++ b/math/mptext-dstr.c @@ -0,0 +1,86 @@ +/* -*-c-*- + * + * Reading and writing large integers on strings + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "mptext.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- Operations table --- */ + +static int get(void *p) +{ + mptext_dstrctx *c = p; + if (c->i >= c->d->len) + return (EOF); + return ((unsigned char)c->d->buf[c->i++]); +} + +static void unget(int ch, void *p) +{ + mptext_dstrctx *c = p; + if (ch == EOF || c->i == 0) + return; + c->i--; +} + +static int put(const char *s, size_t sz, void *p) +{ + mptext_dstrctx *c = p; + DPUTM(c->d, s, sz); + return (0); +} + +const mptext_ops mptext_dstrops = { get, unget, put }; + +/* --- Convenience functions --- */ + +mp *mp_readdstr(mp *m, dstr *d, size_t *off, int radix) +{ + mptext_dstrctx c; + c.d = d; + c.i = off ? *off : 0; + m = mp_read(m, radix, &mptext_dstrops, &c); + if (off) + *off = c.i; + return (m); +} + +int mp_writedstr(mp *m, dstr *d, int radix) +{ + mptext_dstrctx c; + int rc; + c.d = d; + rc = mp_write(m, radix, &mptext_dstrops, &c); + DPUTZ(d); + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mptext-file.c b/math/mptext-file.c new file mode 100644 index 0000000..aefcd49 --- /dev/null +++ b/math/mptext-file.c @@ -0,0 +1,62 @@ +/* -*-c-*- + * + * Reading and writing large integers on files + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "mptext.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- Operations table --- */ + +static int get(void *p) { FILE *fp = p; return getc(fp); } + +static void unget(int ch, void *p) { FILE *fp = p; ungetc(ch, fp); } + +static int put(const char *s, size_t sz, void *p) +{ + FILE *fp = p; + return (fwrite(s, 1, sz, fp) != sz); +} + +const mptext_ops mptext_fileops = { get, unget, put }; + +/* --- Convenience functions --- */ + +mp *mp_readfile(mp *m, FILE *fp, int radix) +{ + return mp_read(m, radix, &mptext_fileops, fp); +} + +int mp_writefile(mp *m, FILE *fp, int radix) +{ + return mp_write(m, radix, &mptext_fileops, fp); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mptext-len.c b/math/mptext-len.c new file mode 100644 index 0000000..352dba2 --- /dev/null +++ b/math/mptext-len.c @@ -0,0 +1,97 @@ +/* -*-c-*- + * + * Work out length of a number's string representation + * + * (c) 2002 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mptext.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mptext_len@ --- * + * + * Arguments: @mp *x@ = number to work on + * @int r@ = radix the number will be expressed in + * + * Returns: The number of digits needed to represent the number in the + * given base. This will not include space for a leading sign + * (use @MP_NEGP@ to check that, or just add one on for luck); + * neither will it add space for a terminating null. In general + * the answer will be an overestimate. + */ + +size_t mptext_len(mp *x, int r) +{ + unsigned long b = mp_bits(x); + int s, ss = 2; + size_t n; + unsigned d = 0; + + /* --- Huh? --- * + * + * The number of digits is at most %$\lceil b \log 2/\log r \rceil$%. We + * produce an underestimate of %$\log_2 r = \log r/\log 2$% and divide by + * that. How? By linear interpolation between known points on the curve. + * The known points are precisely the powers of 2, so we can find a pair + * efficiently by doubling up. The log curve is convex, so linear + * interpolation between points on the curve is always an underestimate. + * + * The integer maths here is a bit weird, so here's how it works. If + * %$s = 2^d$% is the power of 2 below %$r$% then we want to compute + * %$\lceil b/(d + (r - s)/s) \rceil = \lceil (b s)/(s(d - 1) + r \rceil$% + * which is %$\lfloor (r + s (b + d - 1) - 1)/(r + s(d - 1)) \rfloor$%. + * Gluing the whole computation together like this makes the code hard to + * read, but means that there are fewer possibilities for rounding errors + * and thus we get a tighter bound. + */ + + /* --- Find the right pair of points --- */ + + if (r < 0) r = -r; + do { + s = ss; + d++; + if (r == s) { + n = (b + (d - 1))/d; + goto done; + } + ss = s << 1; + } while (ss <= r); + + /* --- Do the interpolation --- */ + + n = (r + s*(b + d - 1) - 1)/(r + s*(d - 1)); + + /* --- Fixups --- */ + +done: + if (!n) + n = 1; + return (n); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mptext-string.c b/math/mptext-string.c new file mode 100644 index 0000000..c70ca94 --- /dev/null +++ b/math/mptext-string.c @@ -0,0 +1,96 @@ +/* -*-c-*- + * + * Reading and writing large integers on strings + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "mptext.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- Operations table --- */ + +static int get(void *p) +{ + mptext_stringctx *c = p; + if (c->buf >= c->lim) + return (EOF); + return ((unsigned char)*c->buf++); +} + +static void unget(int ch, void *p) +{ + mptext_stringctx *c = p; + if (ch != EOF) + c->buf--; +} + +static int put(const char *s, size_t sz, void *p) +{ + mptext_stringctx *c = p; + int rc = 0; + if (sz > c->lim - c->buf) { + sz = c->lim - c->buf; + rc = EOF; + } + if (sz) { + memcpy(c->buf, s, sz); + c->buf += sz; + } + return (rc); +} + +const mptext_ops mptext_stringops = { get, unget, put }; + +/* --- Convenience functions --- */ + +mp *mp_readstring(mp *m, const char *p, char **end, int radix) +{ + mptext_stringctx c; + c.buf = (/*unconst */ char *)p; + c.lim = c.buf + strlen(p); + m = mp_read(m, radix, &mptext_stringops, &c); + if (end) + *end = c.buf; + return (m); +} + +int mp_writestring(mp *m, char *p, size_t sz, int radix) +{ + mptext_stringctx c; + int rc; + if (!sz) + return (0); + c.buf = p; + c.lim = p + sz - 1; + rc = mp_write(m, radix, &mptext_stringops, &c); + *c.buf = 0; + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mptext.c b/math/mptext.c new file mode 100644 index 0000000..5d4640e --- /dev/null +++ b/math/mptext.c @@ -0,0 +1,849 @@ +/* -*-c-*- + * + * Textual representation of multiprecision numbers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include "mp.h" +#include "mptext.h" +#include "paranoia.h" + +/*----- Magical numbers ---------------------------------------------------*/ + +/* --- Maximum recursion depth --- * + * + * This is the number of bits in a @size_t@ object. Why? + * + * To see this, let %$b = \textit{MPW\_MAX} + 1$% and let %$Z$% be the + * largest @size_t@ value. Then the largest possible @mp@ is %$M - 1$% where + * %$M = b^Z$%. Let %$r$% be a radix to read or write. Since the recursion + * squares the radix at each step, the highest number reached by the + * recursion is %$d$%, where: + * + * %$r^{2^d} = b^Z$%. + * + * Solving gives that %$d = \lg \log_r b^Z$%. If %$r = 2$%, this is maximum, + * so choosing %$d = \lg \lg b^Z = \lg (Z \lg b) = \lg Z + \lg \lg b$%. + * + * Expressing %$\lg Z$% as @CHAR_BIT * sizeof(size_t)@ yields an + * overestimate, since a @size_t@ representation may contain `holes'. + * Choosing to represent %$\lg \lg b$% by 10 is almost certainly sufficient + * for `some time to come'. + */ + +#define DEPTH (CHAR_BIT * sizeof(size_t) + 10) + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mp_read@ --- * + * + * Arguments: @mp *m@ = destination multiprecision number + * @int radix@ = base to assume for data (or zero to guess) + * @const mptext_ops *ops@ = pointer to operations block + * @void *p@ = data for the operations block + * + * Returns: The integer read, or zero if it didn't work. + * + * Use: Reads an integer from some source. If the @radix@ is + * specified, the number is assumed to be given in that radix, + * with the letters `a' (either upper- or lower-case) upwards + * standing for digits greater than 9. Otherwise, base 10 is + * assumed unless the number starts with `0' (octal), `0x' (hex) + * or `nnn_' (base `nnn'). An arbitrary amount of whitespace + * before the number is ignored. + */ + +/* --- About the algorithm --- * + * + * The algorithm here is rather aggressive. I maintain an array of + * successive squarings of the radix, and a stack of partial results, each + * with a counter attached indicating which radix square to multiply by. + * Once the item at the top of the stack reaches the same counter level as + * the next item down, they are combined together and the result is given a + * counter level one higher than either of the results. + * + * Gluing the results together at the end is slightly tricky. Pay attention + * to the code. + * + * This is more complicated because of the need to handle the slightly + * bizarre syntax. + */ + +mp *mp_read(mp *m, int radix, const mptext_ops *ops, void *p) +{ + int ch; /* Current char being considered */ + unsigned f = 0; /* Flags about the current number */ + int r; /* Radix to switch over to */ + mpw rd; /* Radix as an @mp@ digit */ + mp rr; /* The @mp@ for the radix */ + unsigned nf = m ? m->f & MP_BURN : 0; /* New @mp@ flags */ + + /* --- Stacks --- */ + + mp *pow[DEPTH]; /* List of powers */ + unsigned pows; /* Next index to fill */ + struct { unsigned i; mp *m; } s[DEPTH]; /* Main stack */ + unsigned sp; /* Current stack pointer */ + + /* --- Flags --- */ + +#define f_neg 1u +#define f_ok 2u +#define f_start 4u + + /* --- Initialize the stacks --- */ + + mp_build(&rr, &rd, &rd + 1); + pow[0] = &rr; + pows = 1; + + sp = 0; + + /* --- Initialize the destination number --- */ + + if (m) + MP_DROP(m); + + /* --- Read an initial character --- */ + + ch = ops->get(p); + if (radix >= 0) { + while (isspace(ch)) + ch = ops->get(p); + } + + /* --- Handle an initial sign --- */ + + if (radix >= 0 && (ch == '-' || ch == '+')) { + if (ch == '-') + f |= f_neg; + do ch = ops->get(p); while isspace(ch); + } + + /* --- If the radix is zero, look for leading zeros --- */ + + if (radix > 0) { + assert(((void)"ascii radix must be <= 62", radix <= 62)); + rd = radix; + r = -1; + } else if (radix < 0) { + rd = -radix; + assert(((void)"binary radix must fit in a byte", rd <= UCHAR_MAX)); + r = -1; + } else if (ch != '0') { + rd = 10; + r = 0; + } else { + ch = ops->get(p); + switch (ch) { + case 'x': + rd = 16; + goto prefix; + case 'o': + rd = 8; + goto prefix; + case 'b': + rd = 2; + goto prefix; + prefix: + ch = ops->get(p); + break; + default: + rd = 8; + f |= f_ok; + } + r = -1; + } + + /* --- Use fast algorithm for binary radix --- * + * + * This is the restart point after having parsed a radix number from the + * input. We check whether the radix is binary, and if so use a fast + * algorithm which just stacks the bits up in the right order. + */ + +restart: + switch (rd) { + unsigned bit; + + case 2: bit = 1; goto bin; + case 4: bit = 2; goto bin; + case 8: bit = 3; goto bin; + case 16: bit = 4; goto bin; + case 32: bit = 5; goto bin; + case 64: bit = 6; goto bin; + case 128: bit = 7; goto bin; + default: + break; + + /* --- The fast binary algorithm --- * + * + * We stack bits up starting at the top end of a word. When one word is + * full, we write it to the integer, and start another with the left-over + * bits. When the array in the integer is full, we resize using low-level + * calls and copy the current data to the top end. Finally, we do a single + * bit-shift when we know where the end of the number is. + */ + + bin: { + mpw a = 0; + unsigned b = MPW_BITS; + size_t len, n; + mpw *v; + + m = mp_dest(MP_NEW, 1, nf); + len = n = m->sz; + n = len; + v = m->v + n; + for (;; ch = ops->get(p)) { + unsigned x; + + if (ch < 0) + break; + + /* --- Check that the character is a digit and in range --- */ + + if (radix < 0) + x = ch % rd; + else { + if (!isalnum(ch)) + break; + if (ch >= '0' && ch <= '9') + x = ch - '0'; + else { + if (rd <= 36) + ch = tolower(ch); + if (ch >= 'a' && ch <= 'z') /* ASCII dependent! */ + x = ch - 'a' + 10; + else if (ch >= 'A' && ch <= 'Z') + x = ch - 'A' + 36; + else + break; + } + } + if (x >= rd) + break; + + /* --- Feed the digit into the accumulator --- */ + + f |= f_ok; + if (!x && !(f & f_start)) + continue; + f |= f_start; + if (b > bit) { + b -= bit; + a |= MPW(x) << b; + } else { + a |= MPW(x) >> (bit - b); + b += MPW_BITS - bit; + *--v = MPW(a); + n--; + if (!n) { + n = len; + len <<= 1; + v = mpalloc(m->a, len); + memcpy(v + n, m->v, MPWS(n)); + mpfree(m->a, m->v); + m->v = v; + v = m->v + n; + } + a = (b < MPW_BITS) ? MPW(x) << b : 0; + } + } + + /* --- Finish up --- */ + + if (!(f & f_ok)) { + mp_drop(m); + m = 0; + } else { + *--v = MPW(a); + n--; + m->sz = len; + m->vl = m->v + len; + m->f &= ~MP_UNDEF; + m = mp_lsr(m, m, (unsigned long)n * MPW_BITS + b); + } + ops->unget(ch, p); + goto done; + }} + + /* --- Time to start --- */ + + for (;; ch = ops->get(p)) { + unsigned x; + + if (ch < 0) + break; + + /* --- An underscore indicates a numbered base --- */ + + if (ch == '_' && r > 0 && r <= 62) { + unsigned i; + + /* --- Clear out the stacks --- */ + + for (i = 1; i < pows; i++) + MP_DROP(pow[i]); + pows = 1; + for (i = 0; i < sp; i++) + MP_DROP(s[i].m); + sp = 0; + + /* --- Restart the search --- */ + + rd = r; + r = -1; + f &= ~f_ok; + ch = ops->get(p); + goto restart; + } + + /* --- Check that the character is a digit and in range --- */ + + if (radix < 0) + x = ch % rd; + else { + if (!isalnum(ch)) + break; + if (ch >= '0' && ch <= '9') + x = ch - '0'; + else { + if (rd <= 36) + ch = tolower(ch); + if (ch >= 'a' && ch <= 'z') /* ASCII dependent! */ + x = ch - 'a' + 10; + else if (ch >= 'A' && ch <= 'Z') + x = ch - 'A' + 36; + else + break; + } + } + + /* --- Sort out what to do with the character --- */ + + if (x >= 10 && r >= 0) + r = -1; + if (x >= rd) + break; + + if (r >= 0) + r = r * 10 + x; + + /* --- Stick the character on the end of my integer --- */ + + assert(((void)"Number is too unimaginably huge", sp < DEPTH)); + s[sp].m = m = mp_new(1, nf); + m->v[0] = x; + s[sp].i = 0; + + /* --- Now grind through the stack --- */ + + while (sp > 0 && s[sp - 1].i == s[sp].i) { + + /* --- Combine the top two items --- */ + + sp--; + m = s[sp].m; + m = mp_mul(m, m, pow[s[sp].i]); + m = mp_add(m, m, s[sp + 1].m); + s[sp].m = m; + MP_DROP(s[sp + 1].m); + s[sp].i++; + + /* --- Make a new radix power if necessary --- */ + + if (s[sp].i >= pows) { + assert(((void)"Number is too unimaginably huge", pows < DEPTH)); + pow[pows] = mp_sqr(MP_NEW, pow[pows - 1]); + pows++; + } + } + f |= f_ok; + sp++; + } + + ops->unget(ch, p); + + /* --- If we're done, compute the rest of the number --- */ + + if (f & f_ok) { + if (!sp) + return (MP_ZERO); + else { + mp *z = MP_ONE; + sp--; + + while (sp > 0) { + + /* --- Combine the top two items --- */ + + sp--; + m = s[sp].m; + z = mp_mul(z, z, pow[s[sp + 1].i]); + m = mp_mul(m, m, z); + m = mp_add(m, m, s[sp + 1].m); + s[sp].m = m; + MP_DROP(s[sp + 1].m); + + /* --- Make a new radix power if necessary --- */ + + if (s[sp].i >= pows) { + assert(((void)"Number is too unimaginably huge", pows < DEPTH)); + pow[pows] = mp_sqr(MP_NEW, pow[pows - 1]); + pows++; + } + } + MP_DROP(z); + m = s[0].m; + } + } else { + unsigned i; + for (i = 0; i < sp; i++) + MP_DROP(s[i].m); + } + + /* --- Clear the radix power list --- */ + + { + unsigned i; + for (i = 1; i < pows; i++) + MP_DROP(pow[i]); + } + + /* --- Bail out if the number was bad --- */ + +done: + if (!(f & f_ok)) + return (0); + + /* --- Set the sign and return --- */ + + if (f & f_neg) + m->f |= MP_NEG; + MP_SHRINK(m); + return (m); + +#undef f_start +#undef f_neg +#undef f_ok +} + +/* --- @mp_write@ --- * + * + * Arguments: @mp *m@ = pointer to a multi-precision integer + * @int radix@ = radix to use when writing the number out + * @const mptext_ops *ops@ = pointer to an operations block + * @void *p@ = data for the operations block + * + * Returns: Zero if it worked, nonzero otherwise. + * + * Use: Writes a large integer in textual form. + */ + +/* --- Simple case --- * + * + * Use a fixed-sized buffer and single-precision arithmetic to pick off + * low-order digits. Put each digit in a buffer, working backwards from the + * end. If the buffer becomes full, recurse to get another one. Ensure that + * there are at least @z@ digits by writing leading zeroes if there aren't + * enough real digits. + */ + +static int simple(mpw n, int radix, unsigned z, + const mptext_ops *ops, void *p) +{ + int rc = 0; + char buf[64]; + unsigned i = sizeof(buf); + int rd = radix > 0 ? radix : -radix; + + do { + int ch; + mpw x; + + x = n % rd; + n /= rd; + if (radix < 0) + ch = x; + else if (x < 10) + ch = '0' + x; + else if (x < 36) /* Ascii specific */ + ch = 'a' + x - 10; + else + ch = 'A' + x - 36; + buf[--i] = ch; + if (z) + z--; + } while (i && n); + + if (n) + rc = simple(n, radix, z, ops, p); + else { + char zbuf[32]; + memset(zbuf, (radix < 0) ? 0 : '0', sizeof(zbuf)); + while (!rc && z >= sizeof(zbuf)) { + rc = ops->put(zbuf, sizeof(zbuf), p); + z -= sizeof(zbuf); + } + if (!rc && z) + rc = ops->put(zbuf, z, p); + } + if (!rc) + rc = ops->put(buf + i, sizeof(buf) - i, p); + BURN(buf); + return (rc); +} + +/* --- Complicated case --- * + * + * If the number is small, fall back to the simple case above. Otherwise + * divide and take remainder by current large power of the radix, and emit + * each separately. Don't emit a zero quotient. Be very careful about + * leading zeroes on the remainder part, because they're deeply significant. + */ + +static int complicated(mp *m, int radix, mp **pr, unsigned i, unsigned z, + const mptext_ops *ops, void *p) +{ + int rc = 0; + mp *q = MP_NEW; + unsigned d = 1 << i; + + if (MP_LEN(m) < 2) + return (simple(MP_LEN(m) ? m->v[0] : 0, radix, z, ops, p)); + + assert(i); + mp_div(&q, &m, m, pr[i]); + if (MP_ZEROP(q)) + d = z; + else { + if (z > d) + z -= d; + else + z = 0; + rc = complicated(q, radix, pr, i - 1, z, ops, p); + } + if (!rc) + rc = complicated(m, radix, pr, i - 1, d, ops, p); + mp_drop(q); + return (rc); +} + +/* --- Binary case --- * + * + * Special case for binary output. Goes much faster. + */ + +static int binary(mp *m, int bit, int radix, const mptext_ops *ops, void *p) +{ + mpw *v; + mpw a; + int rc = 0; + unsigned b; + unsigned mask; + unsigned long n; + unsigned f = 0; + char buf[8], *q; + unsigned x; + int ch; + +#define f_out 1u + + /* --- Work out where to start --- */ + + n = mp_bits(m); + if (n % bit) + n += bit - (n % bit); + b = n % MPW_BITS; + n /= MPW_BITS; + + if (n >= MP_LEN(m)) { + n--; + b += MPW_BITS; + } + + v = m->v + n; + a = *v; + mask = (1 << bit) - 1; + q = buf; + + /* --- Main code --- */ + + for (;;) { + if (b > bit) { + b -= bit; + x = a >> b; + } else { + x = a << (bit - b); + b += MPW_BITS - bit; + if (v == m->v) + break; + a = *--v; + if (b < MPW_BITS) + x |= a >> b; + } + x &= mask; + if (!x && !(f & f_out)) + continue; + + if (radix < 0) + ch = x; + else if (x < 10) + ch = '0' + x; + else if (x < 36) + ch = 'a' + x - 10; /* Ascii specific */ + else + ch = 'A' + x - 36; + *q++ = ch; + if (q >= buf + sizeof(buf)) { + if ((rc = ops->put(buf, sizeof(buf), p)) != 0) + goto done; + q = buf; + } + f |= f_out; + } + + x &= mask; + if (radix < 0) + ch = x; + else if (x < 10) + ch = '0' + x; + else if (x < 36) + ch = 'a' + x - 10; /* Ascii specific */ + else + ch = 'A' + x - 36; + *q++ = ch; + rc = ops->put(buf, q - buf, p); + +done: + mp_drop(m); + return (rc); + +#undef f_out +} + +/* --- Main driver code --- */ + +int mp_write(mp *m, int radix, const mptext_ops *ops, void *p) +{ + int rc; + + if (MP_EQ(m, MP_ZERO)) + return (ops->put(radix > 0 ? "0" : "\0", 1, p)); + + /* --- Set various things up --- */ + + m = MP_COPY(m); + MP_SPLIT(m); + + /* --- Check the radix for sensibleness --- */ + + if (radix > 0) + assert(((void)"ascii radix must be <= 62", radix <= 62)); + else if (radix < 0) + assert(((void)"binary radix must fit in a byte", -radix <= UCHAR_MAX)); + else + assert(((void)"radix can't be zero in mp_write", 0)); + + /* --- If the number is negative, sort that out --- */ + + if (MP_NEGP(m)) { + assert(radix > 0); + if (ops->put("-", 1, p)) + return (EOF); + m->f &= ~MP_NEG; + } + + /* --- Handle binary radix --- */ + + switch (radix) { + case 2: case -2: return (binary(m, 1, radix, ops, p)); + case 4: case -4: return (binary(m, 2, radix, ops, p)); + case 8: case -8: return (binary(m, 3, radix, ops, p)); + case 16: case -16: return (binary(m, 4, radix, ops, p)); + case 32: case -32: return (binary(m, 5, radix, ops, p)); + case -64: return (binary(m, 6, radix, ops, p)); + case -128: return (binary(m, 7, radix, ops, p)); + } + + /* --- If the number is small, do it the easy way --- */ + + if (MP_LEN(m) < 2) + rc = simple(MP_LEN(m) ? m->v[0] : 0, radix, 0, ops, p); + + /* --- Use a clever algorithm --- * + * + * Square the radix repeatedly, remembering old results, until I get + * something more than half the size of the number @m@. Use this to divide + * the number: the quotient and remainder will be approximately the same + * size, and I'll have split them on a digit boundary, so I can just emit + * the quotient and remainder recursively, in order. + */ + + else { + mp *pr[DEPTH]; + size_t target = (MP_LEN(m) + 1) / 2; + unsigned i = 0; + mp *z = mp_new(1, 0); + + /* --- Set up the exponent table --- */ + + z->v[0] = (radix > 0 ? radix : -radix); + z->f = 0; + for (;;) { + assert(((void)"Number is too unimaginably huge", i < DEPTH)); + pr[i++] = z; + if (MP_LEN(z) > target) + break; + z = mp_sqr(MP_NEW, z); + } + + /* --- Write out the answer --- */ + + rc = complicated(m, radix, pr, i - 1, 0, ops, p); + + /* --- Tidy away the array --- */ + + while (i > 0) + mp_drop(pr[--i]); + } + + /* --- Tidying up code --- */ + + MP_DROP(m); + return (rc); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +static int verify(dstr *v) +{ + int ok = 1; + int ib = *(int *)v[0].buf, ob = *(int *)v[2].buf; + dstr d = DSTR_INIT; + size_t off = 0; + mp *m = mp_readdstr(MP_NEW, &v[1], &off, ib); + if (m) { + if (!ob) { + fprintf(stderr, "*** unexpected successful parse\n" + "*** input [%2i] = ", ib); + if (ib < 0) + type_hex.dump(&v[1], stderr); + else + fputs(v[1].buf, stderr); + mp_writedstr(m, &d, 10); + fprintf(stderr, "\n*** (value = %s)\n", d.buf); + ok = 0; + } else { + mp_writedstr(m, &d, ob); + if (d.len != v[3].len || memcmp(d.buf, v[3].buf, d.len) != 0) { + fprintf(stderr, "*** failed read or write\n" + "*** input [%2i] = ", ib); + if (ib < 0) + type_hex.dump(&v[1], stderr); + else + fputs(v[1].buf, stderr); + fprintf(stderr, "\n*** output [%2i] = ", ob); + if (ob < 0) + type_hex.dump(&d, stderr); + else + fputs(d.buf, stderr); + fprintf(stderr, "\n*** expected [%2i] = ", ob); + if (ob < 0) + type_hex.dump(&v[3], stderr); + else + fputs(v[3].buf, stderr); + fputc('\n', stderr); + ok = 0; + } + } + mp_drop(m); + } else { + if (ob) { + fprintf(stderr, "*** unexpected parse failure\n" + "*** input [%2i] = ", ib); + if (ib < 0) + type_hex.dump(&v[1], stderr); + else + fputs(v[1].buf, stderr); + fprintf(stderr, "\n*** expected [%2i] = ", ob); + if (ob < 0) + type_hex.dump(&v[3], stderr); + else + fputs(v[3].buf, stderr); + fputc('\n', stderr); + ok = 0; + } + } + + if (v[1].len - off != v[4].len || + memcmp(v[1].buf + off, v[4].buf, v[4].len) != 0) { + fprintf(stderr, "*** leftovers incorrect\n" + "*** input [%2i] = ", ib); + if (ib < 0) + type_hex.dump(&v[1], stderr); + else + fputs(v[1].buf, stderr); + fprintf(stderr, "\n*** expected `%s'\n" + "*** found `%s'\n", + v[4].buf, v[1].buf + off); + ok = 0; + } + + dstr_destroy(&d); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "mptext-ascii", verify, + { &type_int, &type_string, &type_int, &type_string, &type_string, 0 } }, + { "mptext-bin-in", verify, + { &type_int, &type_hex, &type_int, &type_string, &type_string, 0 } }, + { "mptext-bin-out", verify, + { &type_int, &type_string, &type_int, &type_hex, &type_string, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/mptext"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mptext.h b/math/mptext.h new file mode 100644 index 0000000..8d9342d --- /dev/null +++ b/math/mptext.h @@ -0,0 +1,184 @@ +/* -*-c-*- + * + * Textual representation of multiprecision numbers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPTEXT_H +#define CATACOMB_MPTEXT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct mptext_ops { + int (*get)(void */*p*/); + void (*unget)(int /*ch*/, void */*p*/); + int (*put)(const char */*s*/, size_t /*len*/, void */*p*/); +} mptext_ops; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @mp_read@ --- * + * + * Arguments: @mp *m@ = destination multiprecision number + * @int radix@ = base to assume for data (or zero to guess) + * @const mptext_ops *ops@ = pointer to operations block + * @void *p@ = data for the operations block + * + * Returns: The integer read, or zero if it didn't work. + * + * Use: Reads an integer from some source. If the @radix@ is + * specified, the number is assumed to be given in that radix, + * with the letters `a' (either upper- or lower-case) upwards + * standing for digits greater than 9. Otherwise, base 10 is + * assumed unless the number starts with `0' (octal), `0x' (hex) + * or `nnn_' (base `nnn'). An arbitrary amount of whitespace + * before the number is ignored. + */ + +extern mp *mp_read(mp */*m*/, int /*radix*/, + const mptext_ops */*ops*/, void */*p*/); + +/* --- @mp_write@ --- * + * + * Arguments: @mp *m@ = pointer to a multi-precision integer + * @int radix@ = radix to use when writing the number out + * @const mptext_ops *ops@ = pointer to an operations block + * @void *p@ = data for the operations block + * + * Returns: Zero if it worked, nonzero otherwise. + * + * Use: Writes a large integer in textual form. + */ + +extern int mp_write(mp */*m*/, int /*radix*/, + const mptext_ops */*ops*/, void */*p*/); + +/* --- @mptext_len@ --- * + * + * Arguments: @mp *x@ = number to work on + * @int r@ = radix the number will be expressed in + * + * Returns: The number of digits needed to represent the number in the + * given base. This will not include space for a leading sign + * (use @MP_NEGP@ to check that, or just add one on for luck); + * neither will it add space for a terminating null. In general + * the answer will be an overestimate. + */ + +extern size_t mptext_len(mp */*x*/, int /*r*/); + +/*----- File I/O ----------------------------------------------------------*/ + +#include + +/* --- Operations table --- * + * + * The @mptext_fileops@ expect the pointer argument to be a @FILE *@. + */ + +extern const mptext_ops mptext_fileops; + +/* --- Convenience functions --- */ + +extern mp *mp_readfile(mp */*m*/, FILE */*fp*/, int /*radix*/); +extern int mp_writefile(mp */*m*/, FILE */*fp*/, int /*radix*/); + +#define MP_DOFPRINTFR(fp, args, m, r) do { \ + fprintf args; \ + if (m) \ + mp_writefile(m, fp, r); \ + else \ + fputs("", fp); \ + fputc('\n', fp); \ +} while (0) + +#define MP_DOFPRINTR(fp, name, m, r) \ + MP_DOFPRINTFR(fp, (fp, "%s = ", name), m, r) + +#define MP_PRINT(name, m) MP_DOFPRINTR(stdout, name, m, 10) +#define MP_EPRINT(name, m) MP_DOFPRINTR(stderr, name, m, 10) +#define MP_PRINTX(name, m) MP_DOFPRINTR(stdout, name, m, 16) +#define MP_EPRINTX(name, m) MP_DOFPRINTR(stderr, name, m, 16) + +#define MP_FPRINTF(fp, args, m) MP_DOFPRINTFR(fp, args, m, 10) +#define MP_FPRINTFX(fp, args, m) MP_DOFPRINTFR(fp, args, m, 16) + +/*----- String I/O --------------------------------------------------------*/ + +/* --- Context format --- */ + +typedef struct mptext_stringctx { + char *buf; + char *lim; +} mptext_stringctx; + +/* --- Operations table --- */ + +extern const mptext_ops mptext_stringops; + +/* --- Convenience functions --- */ + +extern mp *mp_readstring(mp */*m*/, const char */*p*/, char **/*end*/, + int /*radix*/); +extern int mp_writestring(mp */*m*/, char */*p*/, size_t /*sz*/, + int /*radix*/); + +/*----- Dynamic string I/O ------------------------------------------------*/ + +#include + +/* --- Context format --- */ + +typedef struct mptext_dstrctx { + dstr *d; + size_t i; +} mptext_dstrctx; + +/* --- Operations table --- */ + +extern const mptext_ops mptext_dstrops; + +/* --- Convenience functions --- */ + +extern mp *mp_readdstr(mp */*m*/, dstr */*d*/, size_t */*off*/, + int /*radix*/); +extern int mp_writedstr(mp */*m*/, dstr */*d*/, int /*radix*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mptypes.c b/math/mptypes.c new file mode 100644 index 0000000..807ffee --- /dev/null +++ b/math/mptypes.c @@ -0,0 +1,212 @@ +/* -*-c-*- + * + * Generate `mptypes.h' header file for current architecture + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _GNU_SOURCE +#include "config.h" + +#include +#include +#if __STDC_VERSION__ >= 199900l +# include +# include +#endif + +/*----- Data types --------------------------------------------------------*/ + +/* --- Hack for GCC --- * + * + * WG14 in their infinite wisdom decided not to use the GCC constant name. + */ + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91) +# define EXT __extension__ +#else +# define EXT +#endif + +#if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX) +# define ULLONG_MAX ULONG_LONG_MAX +#endif + +/* --- Choose the largest integer type --- */ + +#if defined(UINTMAX_MAX) && defined(PRIuMAX) + typedef uintmax_t umax; +# define P_UMAX PRIuMAX +#elif defined(ULLONG_MAX) + EXT typedef unsigned long long umax; +# define P_UMAX "llu" +#else + typedef unsigned long umax; +# define P_UMAX "lu" +#endif + +/* --- Table of interesting types --- * + * + * These are in preference order. + */ + +enum { + f_stdint = 1u, + f_ext = 2u +}; + +struct itype { + const char *name; + const char *suff; + umax max; + unsigned flags; + unsigned bits; +} tytab[] = { + { "unsigned int", "u", UINT_MAX, 0 }, + { "unsigned short", "u", USHRT_MAX, 0 }, + { "unsigned long", "ul", ULONG_MAX, 0 }, +#ifdef ULLONG_MAX + { "unsigned long long", "ull", EXT ULLONG_MAX, f_ext }, +#endif +#ifdef UINTMAX_MAX + { "uintmax_t", "u", UINTMAX_MAX, f_stdint }, +#endif + { 0, 0 }, +}; + +typedef struct itype itype; + +/*----- Main code ---------------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + itype *i; + itype *largest, *mpw, *mpd; + const static char *extstr = "CATACOMB_MPTYPES_EXTENSION "; + unsigned p2; + + /* --- Find the bitcounts --- */ + + for (i = tytab; i->name; i++) { + unsigned bits; + umax u = i->max; + for (bits = 0; u; bits++) + u >>= 1; + i->bits = bits; + } + + /* --- Now try to find the interesting types --- * + * + * The first thing to do is to find the largest type. Then I find the + * `best' type which is less than half that size, and then the `best' type + * which is twice as big as that one. + */ + +#if defined(FORCE_MPW_CUSSID) + largest = mpd = &tytab[3]; + mpw = &tytab[2]; + mpw->bits = 19; mpw->max = 0x7ffff; + mpd->bits = 38; mpd->max = 0x3fffffffffll; +#elif defined(FORCE_MPW_SHORT) + largest = mpd = &tytab[2]; + mpw = &tytab[1]; + mpw->bits = 16; mpw->max = 0xffff; + mpd->bits = 32; mpd->max = 0xffffffff; +#else + largest = tytab; + for (i = tytab; i->name; i++) { + if (i->bits > largest->bits) + largest = i; + } + for (mpw = 0, i = tytab; i->name; i++) { + if (i->bits * 2 <= largest->bits && (!mpw || i->bits > mpw->bits)) + mpw = i; + } + if (!mpw) + mpw = tytab; + for (mpd = 0, i = tytab; i->name; i++) { + if (i->bits >= mpw->bits * 2 && (!mpd || i->bits < mpd->bits)) + mpd = i; + } + if (!mpd) { + static itype w, d; + d = w = *mpw; + w.bits /= 2; w.max = ~(~((umax)0) << w.bits); + d.bits = w.bits * 2; d.max = ~(~((umax)0) << d.bits); + mpw = &w; mpd = &d; + } +#endif + for (p2 = 1; (p2 << 1) < mpw->bits; p2 <<= 1); + + /* --- Output time --- */ + + puts("\ +/* -*-c-*-\n\ + *\n\ + * mptypes.h [generated]\n\ + */\n\ +\n\ +#ifndef CATACOMB_MPTYPES_H\n\ +#define CATACOMB_MPTYPES_H\n\ +"); + if ((mpd->flags | mpw->flags) & f_stdint) { + puts("\ +#if __STDC_VERSION__ >= 199900l\n\ +# include \n\ +#endif\n\ +"); + } + if ((mpd->flags | mpw->flags) & f_ext) { + printf("\ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91)\n\ +# define %s __extension__\n\ +#else\n\ +# define %s\n\ +#endif\n\ +", extstr, extstr); + } + printf("\ +%stypedef %s mpw;\n\ +#define MPW_BITS %u\n\ +#define MPW_P2 %u\n\ +#define MPW_MAX %s%" P_UMAX "%s\n\ +\n\ +%stypedef %s mpd;\n\ +#define MPD_BITS %u\n\ +#define MPD_MAX %s%" P_UMAX "%s\n\ +\n\ +#endif\n\ +", + mpw->flags & f_ext ? extstr : "", mpw->name, + mpw->bits, p2, + mpw->flags & f_ext ? extstr : "", mpw->max, mpw->suff, + mpd->flags & f_ext ? extstr : "", mpd->name, + mpd->bits, + mpd->flags & f_ext ? extstr : "", mpd->max, mpd->suff); + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpw.h b/math/mpw.h new file mode 100644 index 0000000..fa66316 --- /dev/null +++ b/math/mpw.h @@ -0,0 +1,83 @@ +/* -*-c-*- + * + * Very low-level multiprecision definitions + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPW_H +#define CATACOMB_MPW_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_BITS_H +# include +#endif + +#ifndef CATACOMB_MPTYPES_H +# include "mptypes.h" +#endif + +/*----- Useful macros -----------------------------------------------------*/ + +/* --- @MPW@ --- * + * + * Arguments: @x@ = an unsigned value + * + * Use: Expands to the value of @x@ masked and typecast to a + * multiprecision integer word. + */ + +#define MPW(x) ((mpw)((x) & MPW_MAX)) + +/* --- @MPWS@ --- * + * + * Arguments: @n@ = number of words + * + * Use: Expands to the number of bytes occupied by a given number of + * words. + */ + +#define MPWS(n) ((n) * sizeof(mpw)) + +/* --- @MPW_RQ@ --- * + * + * Arguments: @sz@ = size of an octet array, in octets + * + * Use: Expands to the number of @mpw@ words required to represent + * the number held in the octet array. + */ + +#define MPW_RQ(sz) (((sz) * 8 + MPW_BITS - 1) / MPW_BITS) + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/mpx-kmul.c b/math/mpx-kmul.c new file mode 100644 index 0000000..35a3deb --- /dev/null +++ b/math/mpx-kmul.c @@ -0,0 +1,247 @@ +/* -*-c-*- + * + * Karatsuba's multiplication algorithm + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include "mpx.h" +#include "karatsuba.h" + +/*----- Tweakables --------------------------------------------------------*/ + +#ifdef TEST_RIG +# undef MPK_THRESH +# define MPK_THRESH 4 /* Smallest possible correct value */ +#endif + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mpx_kmul@ --- * + * + * Arguments: @mpw *dv, *dvl@ = pointer to destination buffer + * @const mpw *av, *avl@ = pointer to first argument + * @const mpw *bv, *bvl@ = pointer to second argument + * @mpw *sv, *svl@ = pointer to scratch workspace + * + * Returns: --- + * + * Use: Multiplies two multiprecision integers using Karatsuba's + * algorithm. This is rather faster than traditional long + * multiplication (e.g., @mpx_umul@) on large numbers, although + * more expensive on small ones. + * + * The destination must be three times as large as the larger + * argument. The scratch space must be five times as large as + * the larger argument. + */ + +void mpx_kmul(mpw *dv, mpw *dvl, + const mpw *av, const mpw *avl, + const mpw *bv, const mpw *bvl, + mpw *sv, mpw *svl) +{ + const mpw *avm, *bvm; + size_t m; + + /* --- Dispose of easy cases to @mpx_umul@ --- * + * + * Karatsuba is only a win on large numbers, because of all the + * recursiveness and bookkeeping. The recursive calls make a quick check + * to see whether to bottom out to @mpx_umul@ which should help quite a + * lot, but sometimes the only way to know is to make sure... + */ + + MPX_SHRINK(av, avl); + MPX_SHRINK(bv, bvl); + + if (avl - av <= MPK_THRESH || bvl - bv <= MPK_THRESH) { + mpx_umul(dv, dvl, av, avl, bv, bvl); + return; + } + + /* --- How the algorithm works --- * + * + * Let %$A = xb + y$% and %$B = ub + v$%. Then, simply by expanding, + * %$AB = x u b^2 + b(x v + y u) + y v$%. That's not helped any, because + * I've got four multiplications, each four times easier than the one I + * started with. However, note that I can rewrite the coefficient of %$b$% + * as %$xv + yu = (x + y)(u + v) - xu - yv$%. The terms %$xu$% and %$yv$% + * I've already calculated, and that leaves only one more multiplication to + * do. So now I have three multiplications, each four times easier, and + * that's a win. + */ + + /* --- First things --- * + * + * Sort out where to break the factors in half. I'll choose the midpoint + * of the larger one, since this minimizes the amount of work I have to do + * most effectively. + */ + + if (avl - av > bvl - bv) { + m = (avl - av + 1) >> 1; + avm = av + m; + if (bvl - bv > m) + bvm = bv + m; + else + bvm = bvl; + } else { + m = (bvl - bv + 1) >> 1; + bvm = bv + m; + if (avl - av > m) + avm = av + m; + else + avm = avl; + } + + /* --- Sort out the middle term --- */ + + { + mpw *bsv = sv + m + 1, *ssv = bsv + m + 1; + mpw *rdv = dv + m, *rdvl = rdv + 2 * (m + 2); + + assert(rdvl <= dvl); + assert(ssv <= svl); + UADD2(sv, bsv, av, avm, avm, avl); + UADD2(bsv, ssv, bv, bvm, bvm, bvl); + if (m > MPK_THRESH) + mpx_kmul(rdv, rdvl, sv, bsv, bsv, ssv, ssv, svl); + else + mpx_umul(rdv, rdvl, sv, bsv, bsv, ssv); + } + + /* --- Sort out the other two terms --- */ + + { + mpw *svm = sv + m, *svn = svm + m, *ssv = svn + 4; + mpw *tdv = dv + m; + mpw *rdv = tdv + m; + + if (avl == avm || bvl == bvm) + MPX_ZERO(rdv + m + 1, dvl); + else { + if (m > MPK_THRESH) + mpx_kmul(sv, ssv, avm, avl, bvm, bvl, ssv, svl); + else + mpx_umul(sv, ssv, avm, avl, bvm, bvl); + MPX_COPY(rdv + m + 1, dvl, svm + 1, svn); + UADD(rdv, sv, svm + 1); + USUB(tdv, sv, svn); + } + + if (m > MPK_THRESH) + mpx_kmul(sv, ssv, av, avm, bv, bvm, ssv, svl); + else + mpx_umul(sv, ssv, av, avm, bv, bvm); + MPX_COPY(dv, tdv, sv, svm); + USUB(tdv, sv, svn); + UADD(tdv, svm, svn); + } +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include +#include + +#define ALLOC(v, vl, sz) do { \ + size_t _sz = (sz); \ + mpw *_vv = xmalloc(MPWS(_sz)); \ + mpw *_vvl = _vv + _sz; \ + (v) = _vv; \ + (vl) = _vvl; \ +} while (0) + +#define LOAD(v, vl, d) do { \ + const dstr *_d = (d); \ + mpw *_v, *_vl; \ + ALLOC(_v, _vl, MPW_RQ(_d->len)); \ + mpx_loadb(_v, _vl, _d->buf, _d->len); \ + (v) = _v; \ + (vl) = _vl; \ +} while (0) + +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +static void dumpmp(const char *msg, const mpw *v, const mpw *vl) +{ + fputs(msg, stderr); + MPX_SHRINK(v, vl); + while (v < vl) + fprintf(stderr, " %08lx", (unsigned long)*--vl); + fputc('\n', stderr); +} + +static int umul(dstr *v) +{ + mpw *a, *al; + mpw *b, *bl; + mpw *c, *cl; + mpw *d, *dl; + mpw *s, *sl; + size_t m; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(b, bl, &v[1]); + LOAD(c, cl, &v[2]); + m = MAX(al - a, bl - b) + 1; + ALLOC(d, dl, 3 * m); + ALLOC(s, sl, 5 * m); + + mpx_kmul(d, dl, a, al, b, bl, s, sl); + if (!mpx_ueq(d, dl, c, cl)) { + fprintf(stderr, "\n*** umul failed\n"); + dumpmp(" a", a, al); + dumpmp(" b", b, bl); + dumpmp("expected", c, cl); + dumpmp(" result", d, dl); + ok = 0; + } + + xfree(a); xfree(b); xfree(c); xfree(d); xfree(s); + return (ok); +} + +static test_chunk defs[] = { + { "umul", umul, { &type_hex, &type_hex, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/t/mpx"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpx-ksqr.c b/math/mpx-ksqr.c new file mode 100644 index 0000000..e96040b --- /dev/null +++ b/math/mpx-ksqr.c @@ -0,0 +1,211 @@ +/* -*-c-*- + * + * Karatsuba-based squaring algorithm + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include "mpx.h" +#include "karatsuba.h" + +/*----- Tweakables --------------------------------------------------------*/ + +#ifdef TEST_RIG +# undef MPK_THRESH +# define MPK_THRESH 4 +#endif + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mpx_ksqr@ --- * + * + * Arguments: @mpw *dv, *dvl@ = pointer to destination buffer + * @const mpw *av, *avl@ = pointer to first argument + * @mpw *sv, *svl@ = pointer to scratch workspace + * + * Returns: --- + * + * Use: Squares a multiprecision integers using something similar to + * Karatsuba's multiplication algorithm. This is rather faster + * than traditional long multiplication (e.g., @mpx_umul@) on + * large numbers, although more expensive on small ones, and + * rather simpler than full-blown Karatsuba multiplication. + * + * The destination must be three times as large as the larger + * argument. The scratch space must be five times as large as + * the larger argument. + */ + +void mpx_ksqr(mpw *dv, mpw *dvl, + const mpw *av, const mpw *avl, + mpw *sv, mpw *svl) +{ + const mpw *avm; + size_t m; + + /* --- Dispose of easy cases to @mpx_usqr@ --- * + * + * Karatsuba is only a win on large numbers, because of all the + * recursiveness and bookkeeping. The recursive calls make a quick check + * to see whether to bottom out to @mpx_usqr@ which should help quite a + * lot, but sometimes the only way to know is to make sure... + */ + + MPX_SHRINK(av, avl); + + if (avl - av <= MPK_THRESH) { + mpx_usqr(dv, dvl, av, avl); + return; + } + + /* --- How the algorithm works --- * + * + * The identity for squaring is known to all schoolchildren. + * Let %$A = xb + y$%. Then %$A^2 = x^2 b^2 + 2 x y b + y^2$%. Now, + * %$(x + y)^2 - x^2 - y^2 = 2 x y$%, which means I only need to do three + * squarings. + */ + + /* --- First things --- * + * + * Sort out where to break the factor in half. + */ + + m = (avl - av + 1) >> 1; + avm = av + m; + + /* --- Sort out everything --- */ + + { + mpw *svm = sv + m, *svn = svm + m, *ssv = svn + 4; + mpw *tdv = dv + m; + mpw *rdv = tdv + m; + + assert(rdv + m + 4 < dvl); + assert(ssv < svl); + UADD2(sv, svm, av, avm, avm, avl); + if (m > MPK_THRESH) + mpx_ksqr(tdv, rdv + m + 4, sv, svm + 1, ssv, svl); + else + mpx_usqr(tdv, rdv + m + 4, sv, svm + 1); + + if (m > MPK_THRESH) + mpx_ksqr(sv, ssv, avm, avl, ssv, svl); + else + mpx_usqr(sv, ssv, avm, avl); + MPX_COPY(rdv + m + 1, dvl, svm + 1, svn); + UADD(rdv, sv, svm + 1); + USUB(tdv, sv, svn); + + if (m > MPK_THRESH) + mpx_ksqr(sv, ssv, av, avm, ssv, svl); + else + mpx_usqr(sv, ssv, av, avm); + MPX_COPY(dv, tdv, sv, svm); + UADD(tdv, svm, svn); + USUB(tdv, sv, svn); + } +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include +#include + +#define ALLOC(v, vl, sz) do { \ + size_t _sz = (sz); \ + mpw *_vv = xmalloc(MPWS(_sz)); \ + mpw *_vvl = _vv + _sz; \ + (v) = _vv; \ + (vl) = _vvl; \ +} while (0) + +#define LOAD(v, vl, d) do { \ + const dstr *_d = (d); \ + mpw *_v, *_vl; \ + ALLOC(_v, _vl, MPW_RQ(_d->len)); \ + mpx_loadb(_v, _vl, _d->buf, _d->len); \ + (v) = _v; \ + (vl) = _vl; \ +} while (0) + +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +static void dumpmp(const char *msg, const mpw *v, const mpw *vl) +{ + fputs(msg, stderr); + MPX_SHRINK(v, vl); + while (v < vl) + fprintf(stderr, " %08lx", (unsigned long)*--vl); + fputc('\n', stderr); +} + +static int usqr(dstr *v) +{ + mpw *a, *al; + mpw *c, *cl; + mpw *d, *dl; + mpw *s, *sl; + size_t m; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(c, cl, &v[1]); + m = al - a + 1; + ALLOC(d, dl, 3 * m); + ALLOC(s, sl, 5 * m); + + mpx_ksqr(d, dl, a, al, s, sl); + if (!mpx_ueq(d, dl, c, cl)) { + fprintf(stderr, "\n*** usqr failed\n"); + dumpmp(" a", a, al); + dumpmp("expected", c, cl); + dumpmp(" result", d, dl); + ok = 0; + } + + xfree(a); xfree(c); xfree(d); xfree(s); + return (ok); +} + +static test_chunk defs[] = { + { "usqr", usqr, { &type_hex, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/t/mpx"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpx.c b/math/mpx.c new file mode 100644 index 0000000..1294124 --- /dev/null +++ b/math/mpx.c @@ -0,0 +1,1737 @@ +/* -*-c-*- + * + * Low-level multiprecision arithmetic + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include + +#include "mptypes.h" +#include "mpx.h" +#include "bitops.h" + +/*----- Loading and storing -----------------------------------------------*/ + +/* --- @mpx_storel@ --- * + * + * Arguments: @const mpw *v, *vl@ = base and limit of source vector + * @void *pp@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Stores an MP in an octet array, least significant octet + * first. High-end octets are silently discarded if there + * isn't enough space for them. + */ + +void mpx_storel(const mpw *v, const mpw *vl, void *pp, size_t sz) +{ + mpw n, w = 0; + octet *p = pp, *q = p + sz; + unsigned bits = 0; + + while (p < q) { + if (bits < 8) { + if (v >= vl) { + *p++ = U8(w); + break; + } + n = *v++; + *p++ = U8(w | n << bits); + w = n >> (8 - bits); + bits += MPW_BITS - 8; + } else { + *p++ = U8(w); + w >>= 8; + bits -= 8; + } + } + memset(p, 0, q - p); +} + +/* --- @mpx_loadl@ --- * + * + * Arguments: @mpw *v, *vl@ = base and limit of destination vector + * @const void *pp@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Loads an MP in an octet array, least significant octet + * first. High-end octets are ignored if there isn't enough + * space for them. + */ + +void mpx_loadl(mpw *v, mpw *vl, const void *pp, size_t sz) +{ + unsigned n; + mpw w = 0; + const octet *p = pp, *q = p + sz; + unsigned bits = 0; + + if (v >= vl) + return; + while (p < q) { + n = U8(*p++); + w |= n << bits; + bits += 8; + if (bits >= MPW_BITS) { + *v++ = MPW(w); + w = n >> (MPW_BITS - bits + 8); + bits -= MPW_BITS; + if (v >= vl) + return; + } + } + *v++ = w; + MPX_ZERO(v, vl); +} + +/* --- @mpx_storeb@ --- * + * + * Arguments: @const mpw *v, *vl@ = base and limit of source vector + * @void *pp@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Stores an MP in an octet array, most significant octet + * first. High-end octets are silently discarded if there + * isn't enough space for them. + */ + +void mpx_storeb(const mpw *v, const mpw *vl, void *pp, size_t sz) +{ + mpw n, w = 0; + octet *p = pp, *q = p + sz; + unsigned bits = 0; + + while (q > p) { + if (bits < 8) { + if (v >= vl) { + *--q = U8(w); + break; + } + n = *v++; + *--q = U8(w | n << bits); + w = n >> (8 - bits); + bits += MPW_BITS - 8; + } else { + *--q = U8(w); + w >>= 8; + bits -= 8; + } + } + memset(p, 0, q - p); +} + +/* --- @mpx_loadb@ --- * + * + * Arguments: @mpw *v, *vl@ = base and limit of destination vector + * @const void *pp@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Loads an MP in an octet array, most significant octet + * first. High-end octets are ignored if there isn't enough + * space for them. + */ + +void mpx_loadb(mpw *v, mpw *vl, const void *pp, size_t sz) +{ + unsigned n; + mpw w = 0; + const octet *p = pp, *q = p + sz; + unsigned bits = 0; + + if (v >= vl) + return; + while (q > p) { + n = U8(*--q); + w |= n << bits; + bits += 8; + if (bits >= MPW_BITS) { + *v++ = MPW(w); + w = n >> (MPW_BITS - bits + 8); + bits -= MPW_BITS; + if (v >= vl) + return; + } + } + *v++ = w; + MPX_ZERO(v, vl); +} + +/* --- @mpx_storel2cn@ --- * + * + * Arguments: @const mpw *v, *vl@ = base and limit of source vector + * @void *pp@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Stores a negative MP in an octet array, least significant + * octet first, as two's complement. High-end octets are + * silently discarded if there isn't enough space for them. + * This obviously makes the output bad. + */ + +void mpx_storel2cn(const mpw *v, const mpw *vl, void *pp, size_t sz) +{ + unsigned c = 1; + unsigned b = 0; + mpw n, w = 0; + octet *p = pp, *q = p + sz; + unsigned bits = 0; + + while (p < q) { + if (bits < 8) { + if (v >= vl) { + b = w; + break; + } + n = *v++; + b = w | n << bits; + w = n >> (8 - bits); + bits += MPW_BITS - 8; + } else { + b = w; + w >>= 8; + bits -= 8; + } + b = U8(~b + c); + c = c && !b; + *p++ = b; + } + while (p < q) { + b = U8(~b + c); + c = c && !b; + *p++ = b; + b = 0; + } +} + +/* --- @mpx_loadl2cn@ --- * + * + * Arguments: @mpw *v, *vl@ = base and limit of destination vector + * @const void *pp@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Loads a negative MP in an octet array, least significant + * octet first, as two's complement. High-end octets are + * ignored if there isn't enough space for them. This probably + * means you made the wrong choice coming here. + */ + +void mpx_loadl2cn(mpw *v, mpw *vl, const void *pp, size_t sz) +{ + unsigned n; + unsigned c = 1; + mpw w = 0; + const octet *p = pp, *q = p + sz; + unsigned bits = 0; + + if (v >= vl) + return; + while (p < q) { + n = U8(~(*p++) + c); + c = c && !n; + w |= n << bits; + bits += 8; + if (bits >= MPW_BITS) { + *v++ = MPW(w); + w = n >> (MPW_BITS - bits + 8); + bits -= MPW_BITS; + if (v >= vl) + return; + } + } + *v++ = w; + MPX_ZERO(v, vl); +} + +/* --- @mpx_storeb2cn@ --- * + * + * Arguments: @const mpw *v, *vl@ = base and limit of source vector + * @void *pp@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Stores a negative MP in an octet array, most significant + * octet first, as two's complement. High-end octets are + * silently discarded if there isn't enough space for them, + * which probably isn't what you meant. + */ + +void mpx_storeb2cn(const mpw *v, const mpw *vl, void *pp, size_t sz) +{ + mpw n, w = 0; + unsigned b = 0; + unsigned c = 1; + octet *p = pp, *q = p + sz; + unsigned bits = 0; + + while (q > p) { + if (bits < 8) { + if (v >= vl) { + b = w; + break; + } + n = *v++; + b = w | n << bits; + w = n >> (8 - bits); + bits += MPW_BITS - 8; + } else { + b = w; + w >>= 8; + bits -= 8; + } + b = U8(~b + c); + c = c && !b; + *--q = b; + } + while (q > p) { + b = ~b + c; + c = c && !(b & 0xff); + *--q = b; + b = 0; + } +} + +/* --- @mpx_loadb2cn@ --- * + * + * Arguments: @mpw *v, *vl@ = base and limit of destination vector + * @const void *pp@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Loads a negative MP in an octet array, most significant octet + * first as two's complement. High-end octets are ignored if + * there isn't enough space for them. This probably means you + * chose this function wrongly. + */ + +void mpx_loadb2cn(mpw *v, mpw *vl, const void *pp, size_t sz) +{ + unsigned n; + unsigned c = 1; + mpw w = 0; + const octet *p = pp, *q = p + sz; + unsigned bits = 0; + + if (v >= vl) + return; + while (q > p) { + n = U8(~(*--q) + c); + c = c && !n; + w |= n << bits; + bits += 8; + if (bits >= MPW_BITS) { + *v++ = MPW(w); + w = n >> (MPW_BITS - bits + 8); + bits -= MPW_BITS; + if (v >= vl) + return; + } + } + *v++ = w; + MPX_ZERO(v, vl); +} + +/*----- Logical shifting --------------------------------------------------*/ + +/* --- @mpx_lsl@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = source vector base and limit + * @size_t n@ = number of bit positions to shift by + * + * Returns: --- + * + * Use: Performs a logical shift left operation on an integer. + */ + +void mpx_lsl(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n) +{ + size_t nw; + unsigned nb; + + /* --- Trivial special case --- */ + + if (n == 0) + MPX_COPY(dv, dvl, av, avl); + + /* --- Single bit shifting --- */ + + else if (n == 1) { + mpw w = 0; + while (av < avl) { + mpw t; + if (dv >= dvl) + goto done; + t = *av++; + *dv++ = MPW((t << 1) | w); + w = t >> (MPW_BITS - 1); + } + if (dv >= dvl) + goto done; + *dv++ = MPW(w); + MPX_ZERO(dv, dvl); + goto done; + } + + /* --- Break out word and bit shifts for more sophisticated work --- */ + + nw = n / MPW_BITS; + nb = n % MPW_BITS; + + /* --- Handle a shift by a multiple of the word size --- */ + + if (nb == 0) { + if (nw >= dvl - dv) + MPX_ZERO(dv, dvl); + else { + MPX_COPY(dv + nw, dvl, av, avl); + memset(dv, 0, MPWS(nw)); + } + } + + /* --- And finally the difficult case --- * + * + * This is a little convoluted, because I have to start from the end and + * work backwards to avoid overwriting the source, if they're both the same + * block of memory. + */ + + else { + mpw w; + size_t nr = MPW_BITS - nb; + size_t dvn = dvl - dv; + size_t avn = avl - av; + + if (dvn <= nw) { + MPX_ZERO(dv, dvl); + goto done; + } + + if (dvn > avn + nw) { + size_t off = avn + nw + 1; + MPX_ZERO(dv + off, dvl); + dvl = dv + off; + w = 0; + } else { + avl = av + dvn - nw; + w = *--avl << nb; + } + + while (avl > av) { + mpw t = *--avl; + *--dvl = MPW((t >> nr) | w); + w = t << nb; + } + + *--dvl = MPW(w); + MPX_ZERO(dv, dvl); + } + +done:; +} + +/* --- @mpx_lslc@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = source vector base and limit + * @size_t n@ = number of bit positions to shift by + * + * Returns: --- + * + * Use: Performs a logical shift left operation on an integer, only + * it fills in the bits with ones instead of zeroes. + */ + +void mpx_lslc(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n) +{ + size_t nw; + unsigned nb; + + /* --- Trivial special case --- */ + + if (n == 0) + MPX_COPY(dv, dvl, av, avl); + + /* --- Single bit shifting --- */ + + else if (n == 1) { + mpw w = 1; + while (av < avl) { + mpw t; + if (dv >= dvl) + goto done; + t = *av++; + *dv++ = MPW((t << 1) | w); + w = t >> (MPW_BITS - 1); + } + if (dv >= dvl) + goto done; + *dv++ = MPW(w); + MPX_ZERO(dv, dvl); + goto done; + } + + /* --- Break out word and bit shifts for more sophisticated work --- */ + + nw = n / MPW_BITS; + nb = n % MPW_BITS; + + /* --- Handle a shift by a multiple of the word size --- */ + + if (nb == 0) { + if (nw >= dvl - dv) + MPX_ONE(dv, dvl); + else { + MPX_COPY(dv + nw, dvl, av, avl); + MPX_ONE(dv, dv + nw); + } + } + + /* --- And finally the difficult case --- * + * + * This is a little convoluted, because I have to start from the end and + * work backwards to avoid overwriting the source, if they're both the same + * block of memory. + */ + + else { + mpw w; + size_t nr = MPW_BITS - nb; + size_t dvn = dvl - dv; + size_t avn = avl - av; + + if (dvn <= nw) { + MPX_ONE(dv, dvl); + goto done; + } + + if (dvn > avn + nw) { + size_t off = avn + nw + 1; + MPX_ZERO(dv + off, dvl); + dvl = dv + off; + w = 0; + } else { + avl = av + dvn - nw; + w = *--avl << nb; + } + + while (avl > av) { + mpw t = *--avl; + *--dvl = MPW((t >> nr) | w); + w = t << nb; + } + + *--dvl = MPW((MPW_MAX >> nr) | w); + MPX_ONE(dv, dvl); + } + +done:; +} + +/* --- @mpx_lsr@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = source vector base and limit + * @size_t n@ = number of bit positions to shift by + * + * Returns: --- + * + * Use: Performs a logical shift right operation on an integer. + */ + +void mpx_lsr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n) +{ + size_t nw; + unsigned nb; + + /* --- Trivial special case --- */ + + if (n == 0) + MPX_COPY(dv, dvl, av, avl); + + /* --- Single bit shifting --- */ + + else if (n == 1) { + mpw w = av < avl ? *av++ >> 1 : 0; + while (av < avl) { + mpw t; + if (dv >= dvl) + goto done; + t = *av++; + *dv++ = MPW((t << (MPW_BITS - 1)) | w); + w = t >> 1; + } + if (dv >= dvl) + goto done; + *dv++ = MPW(w); + MPX_ZERO(dv, dvl); + goto done; + } + + /* --- Break out word and bit shifts for more sophisticated work --- */ + + nw = n / MPW_BITS; + nb = n % MPW_BITS; + + /* --- Handle a shift by a multiple of the word size --- */ + + if (nb == 0) { + if (nw >= avl - av) + MPX_ZERO(dv, dvl); + else + MPX_COPY(dv, dvl, av + nw, avl); + } + + /* --- And finally the difficult case --- */ + + else { + mpw w; + size_t nr = MPW_BITS - nb; + + av += nw; + w = av < avl ? *av++ : 0; + while (av < avl) { + mpw t; + if (dv >= dvl) + goto done; + t = *av++; + *dv++ = MPW((w >> nb) | (t << nr)); + w = t; + } + if (dv < dvl) { + *dv++ = MPW(w >> nb); + MPX_ZERO(dv, dvl); + } + } + +done:; +} + +/*----- Bitwise operations ------------------------------------------------*/ + +/* --- @mpx_bitop@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector + * @const mpw *av, *avl@ = first source vector + * @const mpw *bv, *bvl@ = second source vector + * + * Returns: --- + * + * Use; Provides the dyadic boolean functions. + */ + +#define MPX_BITBINOP(string) \ + \ +void mpx_bit##string(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, \ + const mpw *bv, const mpw *bvl) \ +{ \ + MPX_SHRINK(av, avl); \ + MPX_SHRINK(bv, bvl); \ + \ + while (dv < dvl) { \ + mpw a, b; \ + a = (av < avl) ? *av++ : 0; \ + b = (bv < bvl) ? *bv++ : 0; \ + *dv++ = B##string(a, b); \ + } \ +} + +MPX_DOBIN(MPX_BITBINOP) + +void mpx_not(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl) +{ + MPX_SHRINK(av, avl); + + while (dv < dvl) { + mpw a; + a = (av < avl) ? *av++ : 0; + *dv++ = ~a; + } +} + +/*----- Unsigned arithmetic -----------------------------------------------*/ + +/* --- @mpx_2c@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector + * @const mpw *v, *vl@ = source vector + * + * Returns: --- + * + * Use: Calculates the two's complement of @v@. + */ + +void mpx_2c(mpw *dv, mpw *dvl, const mpw *v, const mpw *vl) +{ + mpw c = 0; + while (dv < dvl && v < vl) + *dv++ = c = MPW(~*v++); + if (dv < dvl) { + if (c > MPW_MAX / 2) + c = MPW(~0); + while (dv < dvl) + *dv++ = c; + } + MPX_UADDN(dv, dvl, 1); +} + +/* --- @mpx_ueq@ --- * + * + * Arguments: @const mpw *av, *avl@ = first argument vector base and limit + * @const mpw *bv, *bvl@ = second argument vector base and limit + * + * Returns: Nonzero if the two vectors are equal. + * + * Use: Performs an unsigned integer test for equality. + */ + +int mpx_ueq(const mpw *av, const mpw *avl, const mpw *bv, const mpw *bvl) +{ + MPX_SHRINK(av, avl); + MPX_SHRINK(bv, bvl); + if (avl - av != bvl - bv) + return (0); + while (av < avl) { + if (*av++ != *bv++) + return (0); + } + return (1); +} + +/* --- @mpx_ucmp@ --- * + * + * Arguments: @const mpw *av, *avl@ = first argument vector base and limit + * @const mpw *bv, *bvl@ = second argument vector base and limit + * + * Returns: Less than, equal to, or greater than zero depending on + * whether @a@ is less than, equal to or greater than @b@, + * respectively. + * + * Use: Performs an unsigned integer comparison. + */ + +int mpx_ucmp(const mpw *av, const mpw *avl, const mpw *bv, const mpw *bvl) +{ + MPX_SHRINK(av, avl); + MPX_SHRINK(bv, bvl); + + if (avl - av > bvl - bv) + return (+1); + else if (avl - av < bvl - bv) + return (-1); + else while (avl > av) { + mpw a = *--avl, b = *--bvl; + if (a > b) + return (+1); + else if (a < b) + return (-1); + } + return (0); +} + +/* --- @mpx_uadd@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = first addend vector base and limit + * @const mpw *bv, *bvl@ = second addend vector base and limit + * + * Returns: --- + * + * Use: Performs unsigned integer addition. If the result overflows + * the destination vector, high-order bits are discarded. This + * means that two's complement addition happens more or less for + * free, although that's more a side-effect than anything else. + * The result vector may be equal to either or both source + * vectors, but may not otherwise overlap them. + */ + +void mpx_uadd(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, + const mpw *bv, const mpw *bvl) +{ + mpw c = 0; + + while (av < avl || bv < bvl) { + mpw a, b; + mpd x; + if (dv >= dvl) + return; + a = (av < avl) ? *av++ : 0; + b = (bv < bvl) ? *bv++ : 0; + x = (mpd)a + (mpd)b + c; + *dv++ = MPW(x); + c = x >> MPW_BITS; + } + if (dv < dvl) { + *dv++ = c; + MPX_ZERO(dv, dvl); + } +} + +/* --- @mpx_uaddn@ --- * + * + * Arguments: @mpw *dv, *dvl@ = source and destination base and limit + * @mpw n@ = other addend + * + * Returns: --- + * + * Use: Adds a small integer to a multiprecision number. + */ + +void mpx_uaddn(mpw *dv, mpw *dvl, mpw n) { MPX_UADDN(dv, dvl, n); } + +/* --- @mpx_uaddnlsl@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination and first argument vector + * @mpw a@ = second argument + * @unsigned o@ = offset in bits + * + * Returns: --- + * + * Use: Computes %$d + 2^o a$%. If the result overflows then + * high-order bits are discarded, as usual. We must have + * @0 < o < MPW_BITS@. + */ + +void mpx_uaddnlsl(mpw *dv, mpw *dvl, mpw a, unsigned o) +{ + mpd x = (mpd)a << o; + + while (x && dv < dvl) { + x += *dv; + *dv++ = MPW(x); + x >>= MPW_BITS; + } +} + +/* --- @mpx_usub@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = first argument vector base and limit + * @const mpw *bv, *bvl@ = second argument vector base and limit + * + * Returns: --- + * + * Use: Performs unsigned integer subtraction. If the result + * overflows the destination vector, high-order bits are + * discarded. This means that two's complement subtraction + * happens more or less for free, althuogh that's more a side- + * effect than anything else. The result vector may be equal to + * either or both source vectors, but may not otherwise overlap + * them. + */ + +void mpx_usub(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, + const mpw *bv, const mpw *bvl) +{ + mpw c = 0; + + while (av < avl || bv < bvl) { + mpw a, b; + mpd x; + if (dv >= dvl) + return; + a = (av < avl) ? *av++ : 0; + b = (bv < bvl) ? *bv++ : 0; + x = (mpd)a - (mpd)b - c; + *dv++ = MPW(x); + if (x >> MPW_BITS) + c = 1; + else + c = 0; + } + if (c) + c = MPW_MAX; + while (dv < dvl) + *dv++ = c; +} + +/* --- @mpx_usubn@ --- * + * + * Arguments: @mpw *dv, *dvl@ = source and destination base and limit + * @n@ = subtrahend + * + * Returns: --- + * + * Use: Subtracts a small integer from a multiprecision number. + */ + +void mpx_usubn(mpw *dv, mpw *dvl, mpw n) { MPX_USUBN(dv, dvl, n); } + +/* --- @mpx_uaddnlsl@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination and first argument vector + * @mpw a@ = second argument + * @unsigned o@ = offset in bits + * + * Returns: --- + * + * Use: Computes %$d + 2^o a$%. If the result overflows then + * high-order bits are discarded, as usual. We must have + * @0 < o < MPW_BITS@. + */ + +void mpx_usubnlsl(mpw *dv, mpw *dvl, mpw a, unsigned o) +{ + mpw b = a >> (MPW_BITS - o); + a <<= o; + + if (dv < dvl) { + mpd x = (mpd)*dv - MPW(a); + *dv++ = MPW(x); + if (x >> MPW_BITS) + b++; + MPX_USUBN(dv, dvl, b); + } +} + +/* --- @mpx_umul@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = multiplicand vector base and limit + * @const mpw *bv, *bvl@ = multiplier vector base and limit + * + * Returns: --- + * + * Use: Performs unsigned integer multiplication. If the result + * overflows the desination vector, high-order bits are + * discarded. The result vector may not overlap the argument + * vectors in any way. + */ + +void mpx_umul(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, + const mpw *bv, const mpw *bvl) +{ + /* --- This is probably worthwhile on a multiply --- */ + + MPX_SHRINK(av, avl); + MPX_SHRINK(bv, bvl); + + /* --- Deal with a multiply by zero --- */ + + if (bv == bvl) { + MPX_ZERO(dv, dvl); + return; + } + + /* --- Do the initial multiply and initialize the accumulator --- */ + + MPX_UMULN(dv, dvl, av, avl, *bv++); + + /* --- Do the remaining multiply/accumulates --- */ + + while (dv < dvl && bv < bvl) { + mpw m = *bv++; + mpw c = 0; + const mpw *avv = av; + mpw *dvv = ++dv; + + while (avv < avl) { + mpd x; + if (dvv >= dvl) + goto next; + x = (mpd)*dvv + (mpd)m * (mpd)*avv++ + c; + *dvv++ = MPW(x); + c = x >> MPW_BITS; + } + MPX_UADDN(dvv, dvl, c); + next:; + } +} + +/* --- @mpx_umuln@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = multiplicand vector base and limit + * @mpw m@ = multiplier + * + * Returns: --- + * + * Use: Multiplies a multiprecision integer by a single-word value. + * The destination and source may be equal. The destination + * is completely cleared after use. + */ + +void mpx_umuln(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, mpw m) + { MPX_UMULN(dv, dvl, av, avl, m); } + +/* --- @mpx_umlan@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination/accumulator base and limit + * @const mpw *av, *avl@ = multiplicand vector base and limit + * @mpw m@ = multiplier + * + * Returns: --- + * + * Use: Multiplies a multiprecision integer by a single-word value + * and adds the result to an accumulator. + */ + +void mpx_umlan(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, mpw m) + { MPX_UMLAN(dv, dvl, av, avl, m); } + +/* --- @mpx_usqr@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *av@ = source vector base and limit + * + * Returns: --- + * + * Use: Performs unsigned integer squaring. The result vector must + * not overlap the source vector in any way. + */ + +void mpx_usqr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl) +{ + MPX_ZERO(dv, dvl); + + /* --- Main loop --- */ + + while (av < avl) { + const mpw *avv = av; + mpw *dvv = dv; + mpw a = *av; + mpd c; + + /* --- Stop if I've run out of destination --- */ + + if (dvv >= dvl) + break; + + /* --- Work out the square at this point in the proceedings --- */ + + { + mpd x = (mpd)a * (mpd)a + *dvv; + *dvv++ = MPW(x); + c = MPW(x >> MPW_BITS); + } + + /* --- Now fix up the rest of the vector upwards --- */ + + avv++; + while (dvv < dvl && avv < avl) { + mpd x = (mpd)a * (mpd)*avv++; + mpd y = ((x << 1) & MPW_MAX) + c + *dvv; + c = (x >> (MPW_BITS - 1)) + (y >> MPW_BITS); + *dvv++ = MPW(y); + } + while (dvv < dvl && c) { + mpd x = c + *dvv; + *dvv++ = MPW(x); + c = x >> MPW_BITS; + } + + /* --- Get ready for the next round --- */ + + av++; + dv += 2; + } +} + +/* --- @mpx_udiv@ --- * + * + * Arguments: @mpw *qv, *qvl@ = quotient vector base and limit + * @mpw *rv, *rvl@ = dividend/remainder vector base and limit + * @const mpw *dv, *dvl@ = divisor vector base and limit + * @mpw *sv, *svl@ = scratch workspace + * + * Returns: --- + * + * Use: Performs unsigned integer division. If the result overflows + * the quotient vector, high-order bits are discarded. (Clearly + * the remainder vector can't overflow.) The various vectors + * may not overlap in any way. Yes, I know it's a bit odd + * requiring the dividend to be in the result position but it + * does make some sense really. The remainder must have + * headroom for at least two extra words. The scratch space + * must be at least one word larger than the divisor. + */ + +void mpx_udiv(mpw *qv, mpw *qvl, mpw *rv, mpw *rvl, + const mpw *dv, const mpw *dvl, + mpw *sv, mpw *svl) +{ + unsigned norm = 0; + size_t scale; + mpw d, dd; + + /* --- Initialize the quotient --- */ + + MPX_ZERO(qv, qvl); + + /* --- Perform some sanity checks --- */ + + MPX_SHRINK(dv, dvl); + assert(((void)"division by zero in mpx_udiv", dv < dvl)); + + /* --- Normalize the divisor --- * + * + * The algorithm requires that the divisor be at least two digits long. + * This is easy to fix. + */ + + { + unsigned b; + + d = dvl[-1]; + for (b = MPW_P2; b; b >>= 1) { + if (d <= (MPW_MAX >> b)) { + d <<= b; + norm += b; + } + } + if (dv + 1 == dvl) + norm += MPW_BITS; + } + + /* --- Normalize the dividend/remainder to match --- */ + + if (norm) { + mpx_lsl(rv, rvl, rv, rvl, norm); + mpx_lsl(sv, svl, dv, dvl, norm); + dv = sv; + dvl = svl; + MPX_SHRINK(dv, dvl); + } + + MPX_SHRINK(rv, rvl); + d = dvl[-1]; + dd = dvl[-2]; + + /* --- Work out the relative scales --- */ + + { + size_t rvn = rvl - rv; + size_t dvn = dvl - dv; + + /* --- If the divisor is clearly larger, notice this --- */ + + if (dvn > rvn) { + mpx_lsr(rv, rvl, rv, rvl, norm); + return; + } + + scale = rvn - dvn; + } + + /* --- Calculate the most significant quotient digit --- * + * + * Because the divisor has its top bit set, this can only happen once. The + * pointer arithmetic is a little contorted, to make sure that the + * behaviour is defined. + */ + + if (MPX_UCMP(rv + scale, rvl, >=, dv, dvl)) { + mpx_usub(rv + scale, rvl, rv + scale, rvl, dv, dvl); + if (qvl - qv > scale) + qv[scale] = 1; + } + + /* --- Now for the main loop --- */ + + { + mpw *rvv = rvl - 2; + + while (scale) { + mpw q; + mpd rh; + + /* --- Get an estimate for the next quotient digit --- */ + + mpw r = rvv[1]; + mpw rr = rvv[0]; + mpw rrr = *--rvv; + + scale--; + rh = ((mpd)r << MPW_BITS) | rr; + if (r == d) + q = MPW_MAX; + else + q = MPW(rh / d); + + /* --- Refine the estimate --- */ + + { + mpd yh = (mpd)d * q; + mpd yy = (mpd)dd * q; + mpw yl; + + if (yy > MPW_MAX) + yh += yy >> MPW_BITS; + yl = MPW(yy); + + while (yh > rh || (yh == rh && yl > rrr)) { + q--; + yh -= d; + if (yl < dd) + yh--; + yl = MPW(yl - dd); + } + } + + /* --- Remove a chunk from the dividend --- */ + + { + mpw *svv; + const mpw *dvv; + mpw mc = 0, sc = 0; + + /* --- Calculate the size of the chunk --- * + * + * This does the whole job of calculating @r >> scale - qd@. + */ + + for (svv = rv + scale, dvv = dv; + dvv < dvl && svv < rvl; + svv++, dvv++) { + mpd x = (mpd)*dvv * (mpd)q + mc; + mc = x >> MPW_BITS; + x = (mpd)*svv - MPW(x) - sc; + *svv = MPW(x); + if (x >> MPW_BITS) + sc = 1; + else + sc = 0; + } + + if (svv < rvl) { + mpd x = (mpd)*svv - mc - sc; + *svv++ = MPW(x); + if (x >> MPW_BITS) + sc = MPW_MAX; + else + sc = 0; + while (svv < rvl) + *svv++ = sc; + } + + /* --- Fix if the quotient was too large --- * + * + * This doesn't seem to happen very often. + */ + + if (rvl[-1] > MPW_MAX / 2) { + mpx_uadd(rv + scale, rvl, rv + scale, rvl, dv, dvl); + q--; + } + } + + /* --- Done for another iteration --- */ + + if (qvl - qv > scale) + qv[scale] = q; + r = rr; + rr = rrr; + } + } + + /* --- Now fiddle with unnormalizing and things --- */ + + mpx_lsr(rv, rvl, rv, rvl, norm); +} + +/* --- @mpx_udivn@ --- * + * + * Arguments: @mpw *qv, *qvl@ = storage for the quotient (may overlap + * dividend) + * @const mpw *rv, *rvl@ = dividend + * @mpw d@ = single-precision divisor + * + * Returns: Remainder after divison. + * + * Use: Performs a single-precision division operation. + */ + +mpw mpx_udivn(mpw *qv, mpw *qvl, const mpw *rv, const mpw *rvl, mpw d) +{ + size_t i; + size_t ql = qvl - qv; + mpd r = 0; + + i = rvl - rv; + while (i > 0) { + i--; + r = (r << MPW_BITS) | rv[i]; + if (i < ql) + qv[i] = r / d; + r %= d; + } + return (MPW(r)); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include +#include +#include +#include + +#include "mpscan.h" + +#define ALLOC(v, vl, sz) do { \ + size_t _sz = (sz); \ + mpw *_vv = xmalloc(MPWS(_sz)); \ + mpw *_vvl = _vv + _sz; \ + (v) = _vv; \ + (vl) = _vvl; \ +} while (0) + +#define LOAD(v, vl, d) do { \ + const dstr *_d = (d); \ + mpw *_v, *_vl; \ + ALLOC(_v, _vl, MPW_RQ(_d->len)); \ + mpx_loadb(_v, _vl, _d->buf, _d->len); \ + (v) = _v; \ + (vl) = _vl; \ +} while (0) + +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +static void dumpbits(const char *msg, const void *pp, size_t sz) +{ + const octet *p = pp; + fputs(msg, stderr); + for (; sz; sz--) + fprintf(stderr, " %02x", *p++); + fputc('\n', stderr); +} + +static void dumpmp(const char *msg, const mpw *v, const mpw *vl) +{ + fputs(msg, stderr); + MPX_SHRINK(v, vl); + while (v < vl) + fprintf(stderr, " %08lx", (unsigned long)*--vl); + fputc('\n', stderr); +} + +static int chkscan(const mpw *v, const mpw *vl, + const void *pp, size_t sz, int step) +{ + mpscan mps; + const octet *p = pp; + unsigned bit = 0; + int ok = 1; + + mpscan_initx(&mps, v, vl); + while (sz) { + unsigned x = *p; + int i; + p += step; + for (i = 0; i < 8 && MPSCAN_STEP(&mps); i++) { + if (MPSCAN_BIT(&mps) != (x & 1)) { + fprintf(stderr, + "\n*** error, step %i, bit %u, expected %u, found %u\n", + step, bit, x & 1, MPSCAN_BIT(&mps)); + ok = 0; + } + x >>= 1; + bit++; + } + sz--; + } + + return (ok); +} + +static int loadstore(dstr *v) +{ + dstr d = DSTR_INIT; + size_t sz = MPW_RQ(v->len) * 2, diff; + mpw *m, *ml; + int ok = 1; + + dstr_ensure(&d, v->len); + m = xmalloc(MPWS(sz)); + + for (diff = 0; diff < sz; diff += 5) { + size_t oct; + + ml = m + sz - diff; + + mpx_loadl(m, ml, v->buf, v->len); + if (!chkscan(m, ml, v->buf, v->len, +1)) + ok = 0; + MPX_OCTETS(oct, m, ml); + mpx_storel(m, ml, d.buf, d.sz); + if (memcmp(d.buf, v->buf, oct) != 0) { + dumpbits("\n*** storel failed", d.buf, d.sz); + ok = 0; + } + + mpx_loadb(m, ml, v->buf, v->len); + if (!chkscan(m, ml, v->buf + v->len - 1, v->len, -1)) + ok = 0; + MPX_OCTETS(oct, m, ml); + mpx_storeb(m, ml, d.buf, d.sz); + if (memcmp(d.buf + d.sz - oct, v->buf + v->len - oct, oct) != 0) { + dumpbits("\n*** storeb failed", d.buf, d.sz); + ok = 0; + } + } + + if (!ok) + dumpbits("input data", v->buf, v->len); + + xfree(m); + dstr_destroy(&d); + return (ok); +} + +static int twocl(dstr *v) +{ + dstr d = DSTR_INIT; + mpw *m, *ml; + size_t sz; + int ok = 1; + + sz = v[0].len; if (v[1].len > sz) sz = v[1].len; + dstr_ensure(&d, sz); + + sz = MPW_RQ(sz); + m = xmalloc(MPWS(sz)); + ml = m + sz; + + mpx_loadl(m, ml, v[0].buf, v[0].len); + mpx_storel2cn(m, ml, d.buf, v[1].len); + if (memcmp(d.buf, v[1].buf, v[1].len)) { + dumpbits("\n*** storel2cn failed", d.buf, v[1].len); + ok = 0; + } + + mpx_loadl2cn(m, ml, v[1].buf, v[1].len); + mpx_storel(m, ml, d.buf, v[0].len); + if (memcmp(d.buf, v[0].buf, v[0].len)) { + dumpbits("\n*** loadl2cn failed", d.buf, v[0].len); + ok = 0; + } + + if (!ok) { + dumpbits("pos", v[0].buf, v[0].len); + dumpbits("neg", v[1].buf, v[1].len); + } + + xfree(m); + dstr_destroy(&d); + + return (ok); +} + +static int twocb(dstr *v) +{ + dstr d = DSTR_INIT; + mpw *m, *ml; + size_t sz; + int ok = 1; + + sz = v[0].len; if (v[1].len > sz) sz = v[1].len; + dstr_ensure(&d, sz); + + sz = MPW_RQ(sz); + m = xmalloc(MPWS(sz)); + ml = m + sz; + + mpx_loadb(m, ml, v[0].buf, v[0].len); + mpx_storeb2cn(m, ml, d.buf, v[1].len); + if (memcmp(d.buf, v[1].buf, v[1].len)) { + dumpbits("\n*** storeb2cn failed", d.buf, v[1].len); + ok = 0; + } + + mpx_loadb2cn(m, ml, v[1].buf, v[1].len); + mpx_storeb(m, ml, d.buf, v[0].len); + if (memcmp(d.buf, v[0].buf, v[0].len)) { + dumpbits("\n*** loadb2cn failed", d.buf, v[0].len); + ok = 0; + } + + if (!ok) { + dumpbits("pos", v[0].buf, v[0].len); + dumpbits("neg", v[1].buf, v[1].len); + } + + xfree(m); + dstr_destroy(&d); + + return (ok); +} + +static int lsl(dstr *v) +{ + mpw *a, *al; + int n = *(int *)v[1].buf; + mpw *c, *cl; + mpw *d, *dl; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(c, cl, &v[2]); + ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS); + + mpx_lsl(d, dl, a, al, n); + if (!mpx_ueq(d, dl, c, cl)) { + fprintf(stderr, "\n*** lsl(%i) failed\n", n); + dumpmp(" a", a, al); + dumpmp("expected", c, cl); + dumpmp(" result", d, dl); + ok = 0; + } + + xfree(a); xfree(c); xfree(d); + return (ok); +} + +static int lslc(dstr *v) +{ + mpw *a, *al; + int n = *(int *)v[1].buf; + mpw *c, *cl; + mpw *d, *dl; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(c, cl, &v[2]); + ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS); + + mpx_lslc(d, dl, a, al, n); + if (!mpx_ueq(d, dl, c, cl)) { + fprintf(stderr, "\n*** lslc(%i) failed\n", n); + dumpmp(" a", a, al); + dumpmp("expected", c, cl); + dumpmp(" result", d, dl); + ok = 0; + } + + xfree(a); xfree(c); xfree(d); + return (ok); +} + +static int lsr(dstr *v) +{ + mpw *a, *al; + int n = *(int *)v[1].buf; + mpw *c, *cl; + mpw *d, *dl; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(c, cl, &v[2]); + ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS + 1); + + mpx_lsr(d, dl, a, al, n); + if (!mpx_ueq(d, dl, c, cl)) { + fprintf(stderr, "\n*** lsr(%i) failed\n", n); + dumpmp(" a", a, al); + dumpmp("expected", c, cl); + dumpmp(" result", d, dl); + ok = 0; + } + + xfree(a); xfree(c); xfree(d); + return (ok); +} + +static int uadd(dstr *v) +{ + mpw *a, *al; + mpw *b, *bl; + mpw *c, *cl; + mpw *d, *dl; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(b, bl, &v[1]); + LOAD(c, cl, &v[2]); + ALLOC(d, dl, MAX(al - a, bl - b) + 1); + + mpx_uadd(d, dl, a, al, b, bl); + if (!mpx_ueq(d, dl, c, cl)) { + fprintf(stderr, "\n*** uadd failed\n"); + dumpmp(" a", a, al); + dumpmp(" b", b, bl); + dumpmp("expected", c, cl); + dumpmp(" result", d, dl); + ok = 0; + } + + xfree(a); xfree(b); xfree(c); xfree(d); + return (ok); +} + +static int usub(dstr *v) +{ + mpw *a, *al; + mpw *b, *bl; + mpw *c, *cl; + mpw *d, *dl; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(b, bl, &v[1]); + LOAD(c, cl, &v[2]); + ALLOC(d, dl, al - a); + + mpx_usub(d, dl, a, al, b, bl); + if (!mpx_ueq(d, dl, c, cl)) { + fprintf(stderr, "\n*** usub failed\n"); + dumpmp(" a", a, al); + dumpmp(" b", b, bl); + dumpmp("expected", c, cl); + dumpmp(" result", d, dl); + ok = 0; + } + + xfree(a); xfree(b); xfree(c); xfree(d); + return (ok); +} + +static int umul(dstr *v) +{ + mpw *a, *al; + mpw *b, *bl; + mpw *c, *cl; + mpw *d, *dl; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(b, bl, &v[1]); + LOAD(c, cl, &v[2]); + ALLOC(d, dl, (al - a) + (bl - b)); + + mpx_umul(d, dl, a, al, b, bl); + if (!mpx_ueq(d, dl, c, cl)) { + fprintf(stderr, "\n*** umul failed\n"); + dumpmp(" a", a, al); + dumpmp(" b", b, bl); + dumpmp("expected", c, cl); + dumpmp(" result", d, dl); + ok = 0; + } + + xfree(a); xfree(b); xfree(c); xfree(d); + return (ok); +} + +static int usqr(dstr *v) +{ + mpw *a, *al; + mpw *c, *cl; + mpw *d, *dl; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(c, cl, &v[1]); + ALLOC(d, dl, 2 * (al - a)); + + mpx_usqr(d, dl, a, al); + if (!mpx_ueq(d, dl, c, cl)) { + fprintf(stderr, "\n*** usqr failed\n"); + dumpmp(" a", a, al); + dumpmp("expected", c, cl); + dumpmp(" result", d, dl); + ok = 0; + } + + xfree(a); xfree(c); xfree(d); + return (ok); +} + +static int udiv(dstr *v) +{ + mpw *a, *al; + mpw *b, *bl; + mpw *q, *ql; + mpw *r, *rl; + mpw *qq, *qql; + mpw *s, *sl; + int ok = 1; + + ALLOC(a, al, MPW_RQ(v[0].len) + 2); mpx_loadb(a, al, v[0].buf, v[0].len); + LOAD(b, bl, &v[1]); + LOAD(q, ql, &v[2]); + LOAD(r, rl, &v[3]); + ALLOC(qq, qql, al - a); + ALLOC(s, sl, (bl - b) + 1); + + mpx_udiv(qq, qql, a, al, b, bl, s, sl); + if (!mpx_ueq(qq, qql, q, ql) || + !mpx_ueq(a, al, r, rl)) { + fprintf(stderr, "\n*** udiv failed\n"); + dumpmp(" divisor", b, bl); + dumpmp("expect r", r, rl); + dumpmp("result r", a, al); + dumpmp("expect q", q, ql); + dumpmp("result q", qq, qql); + ok = 0; + } + + xfree(a); xfree(b); xfree(r); xfree(q); xfree(s); xfree(qq); + return (ok); +} + +static test_chunk defs[] = { + { "load-store", loadstore, { &type_hex, 0 } }, + { "2cl", twocl, { &type_hex, &type_hex, } }, + { "2cb", twocb, { &type_hex, &type_hex, } }, + { "lsl", lsl, { &type_hex, &type_int, &type_hex, 0 } }, + { "lslc", lslc, { &type_hex, &type_int, &type_hex, 0 } }, + { "lsr", lsr, { &type_hex, &type_int, &type_hex, 0 } }, + { "uadd", uadd, { &type_hex, &type_hex, &type_hex, 0 } }, + { "usub", usub, { &type_hex, &type_hex, &type_hex, 0 } }, + { "umul", umul, { &type_hex, &type_hex, &type_hex, 0 } }, + { "usqr", usqr, { &type_hex, &type_hex, 0 } }, + { "udiv", udiv, { &type_hex, &type_hex, &type_hex, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/t/mpx"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/mpx.h b/math/mpx.h new file mode 100644 index 0000000..4d6288e --- /dev/null +++ b/math/mpx.h @@ -0,0 +1,789 @@ +/* -*-c-*- + * + * Low level multiprecision arithmetic + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MPX_H +#define CATACOMB_MPX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- The idea ----------------------------------------------------------* + * + * This file provides functions and macros which work on vectors of words as + * unsigned multiprecision integers. The interface works in terms of base + * and limit pointers (i.e., a pointer to the start of a vector, and a + * pointer just past its end) rather than base pointer and length, because + * that requires more arithmetic and state to work on. + * + * The interfaces are slightly bizarre in other ways. Try to use the + * higher-level functions where you can: they're rather better designed to + * actually be friendly and useful. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_MPW_H +# include "mpw.h" +#endif + +/*----- General manipulation ----------------------------------------------*/ + +/* --- @MPX_SHRINK@ --- * + * + * Arguments: @const mpw *v@ = pointer to vector of words + * @const mpw *vl@ = (updated) current limit of vector + * + * Use: Shrinks down the limit of a multiprecision integer vector. + */ + +#define MPX_SHRINK(v, vl) do { \ + const mpw *_vv = (v), *_vvl = (vl); \ + while (_vvl > _vv && !_vvl[-1]) \ + _vvl--; \ + (vl) = (mpw *)_vvl; \ +} while (0) + +/* --- @MPX_BITS@ --- * + * + * Arguments: @unsigned long b@ = result variable + * @const mpw *v@ = pointer to array of words + * @const mpw *vl@ = limit of vector (from @MPX_SHRINK@) + * + * Use: Calculates the number of bits in a multiprecision value. + */ + +#define MPX_BITS(b, v, vl) do { \ + const mpw *_v = (v), *_vl = (vl); \ + MPX_SHRINK(_v, _vl); \ + if (_v == _vl) \ + (b) = 0; \ + else { \ + unsigned long _b = MPW_BITS * (_vl - _v - 1) + 1; \ + mpw _w = _vl[-1]; \ + unsigned _k = MPW_P2; \ + while (_k) { \ + if (_w >> _k) { \ + _w >>= _k; \ + _b += _k; \ + } \ + _k >>= 1; \ + } \ + (b) = _b; \ + } \ +} while (0) + +/* --- @MPX_OCTETS@ --- * + * + * Arguments: @size_t o@ = result variable + * @const mpw *v, *vl@ = pointer to array of words + * + * Use: Calculates the number of octets in a multiprecision value. + */ + +#define MPX_OCTETS(o, v, vl) do { \ + unsigned long _bb; \ + MPX_BITS(_bb, (v), (vl)); \ + (o) = (_bb + 7) >> 3; \ +} while (0) + +/* --- @MPX_OCTETS2C@ --- * + * + * Arguments: @size_t o@ = result variable + * @const mpw *v, *vl@ = pointer to array of words + * + * Use: Calculates the number of octets in a multiprecision value, if + * you represent it as two's complement. + */ + +#define MPX_OCTETS2C(o, v, vl) do { \ + unsigned long _bb; \ + MPX_BITS(_bb, (v), (vl)); \ + (o) = (_bb >> 3) + 1; \ +} while (0) + +/* --- @MPX_COPY@ --- * + * + * Arguments: @dv, dvl@ = destination vector base and limit + * @av, avl@ = source vector base and limit + * + * Use: Copies a multiprecision integer. + */ + +#define MPX_COPY(dv, dvl, av, avl) do { \ + mpw *_dv = (dv), *_dvl = (dvl); \ + size_t _dn = _dvl - _dv; \ + const mpw *_av = (av), *_avl = (avl); \ + size_t _an = _avl - _av; \ + if (_av == _dv) { \ + if (_dvl > _avl) \ + memset(_dv, 0, MPWS(_dn - _an)); \ + } else if (_an >= _dn) \ + memmove(_dv, _av, MPWS(_dn)); \ + else { \ + memmove(_dv, _av, MPWS(_an)); \ + memset(_dv + _an, 0, MPWS(_dn - _an)); \ + } \ +} while (0) + +/* --- @MPX_ZERO@ --- * + * + * Arguments: @v, vl@ = base and limit of vector to clear + * + * Use: Zeroes the area between the two vector pointers. + */ + +#define MPX_ZERO(v, vl) do { \ + mpw *_v = (v), *_vl = (vl); \ + if (_v < _vl) \ + memset(_v, 0, MPWS(_vl - _v)); \ +} while (0) + +/* --- @MPX_ONE@ --- * + * + * Arguments: @v, vl@ = base and limit of vector to clear + * + * Use: Fills the area between the two vector pointers with ones. + */ + +#define MPX_ONE(v, vl) do { \ + mpw * _v = (v); \ + const mpw *_vl = (vl); \ + while (_v < _vl) \ + *_v++ = MPW_MAX; \ +} while (0) + +/*----- Loading and storing -----------------------------------------------*/ + +/* --- @mpx_storel@ --- * + * + * Arguments: @const mpw *v, *vl@ = base and limit of source vector + * @void *p@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Stores an MP in an octet array, least significant octet + * first. High-end octets are silently discarded if there + * isn't enough space for them. + */ + +extern void mpx_storel(const mpw */*v*/, const mpw */*vl*/, + void */*p*/, size_t /*sz*/); + +/* --- @mpx_loadl@ --- * + * + * Arguments: @mpw *v, *vl@ = base and limit of destination vector + * @const void *p@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Loads an MP in an octet array, least significant octet + * first. High-end octets are ignored if there isn't enough + * space for them. + */ + +extern void mpx_loadl(mpw */*v*/, mpw */*vl*/, + const void */*p*/, size_t /*sz*/); + +/* --- @mpx_storeb@ --- * + * + * Arguments: @const mpw *v, *vl@ = base and limit of source vector + * @void *p@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Stores an MP in an octet array, most significant octet + * first. High-end octets are silently discarded if there + * isn't enough space for them. + */ + +extern void mpx_storeb(const mpw */*v*/, const mpw */*vl*/, + void */*p*/, size_t /*sz*/); + +/* --- @mpx_loadb@ --- * + * + * Arguments: @mpw *v, *vl@ = base and limit of destination vector + * @const void *p@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Loads an MP in an octet array, most significant octet + * first. High-end octets are ignored if there isn't enough + * space for them. + */ + +extern void mpx_loadb(mpw */*v*/, mpw */*vl*/, + const void */*p*/, size_t /*sz*/); + +/* --- @mpx_storel2cn@ --- * + * + * Arguments: @const mpw *v, *vl@ = base and limit of source vector + * @void *pp@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Stores a negative MP in an octet array, least significant + * octet first, as two's complement. High-end octets are + * silently discarded if there isn't enough space for them. + * This obviously makes the output bad. + */ + +extern void mpx_storel2cn(const mpw */*v*/, const mpw */*vl*/, + void */*p*/, size_t /*sz*/); + +/* --- @mpx_loadl2cn@ --- * + * + * Arguments: @mpw *v, *vl@ = base and limit of destination vector + * @const void *pp@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Loads a negative MP in an octet array, least significant + * octet first, as two's complement. High-end octets are + * ignored if there isn't enough space for them. This probably + * means you made the wrong choice coming here. + */ + +extern void mpx_loadl2cn(mpw */*v*/, mpw */*vl*/, + const void */*p*/, size_t /*sz*/); + +/* --- @mpx_storeb2cn@ --- * + * + * Arguments: @const mpw *v, *vl@ = base and limit of source vector + * @void *pp@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Stores a negative MP in an octet array, most significant + * octet first, as two's complement. High-end octets are + * silently discarded if there isn't enough space for them, + * which probably isn't what you meant. + */ + +extern void mpx_storeb2cn(const mpw */*v*/, const mpw */*vl*/, + void */*p*/, size_t /*sz*/); + +/* --- @mpx_loadb2cn@ --- * + * + * Arguments: @mpw *v, *vl@ = base and limit of destination vector + * @const void *pp@ = pointer to octet array + * @size_t sz@ = size of octet array + * + * Returns: --- + * + * Use: Loads a negative MP in an octet array, most significant octet + * first as two's complement. High-end octets are ignored if + * there isn't enough space for them. This probably means you + * chose this function wrongly. + */ + +extern void mpx_loadb2cn(mpw */*v*/, mpw */*vl*/, + const void */*p*/, size_t /*sz*/); + + +/*----- Logical shifting --------------------------------------------------*/ + +/* --- @mpx_lsl@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = source vector base and limit + * @size_t n@ = number of bit positions to shift by + * + * Returns: --- + * + * Use: Performs a logical shift left operation on an integer. + */ + +extern void mpx_lsl(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, + size_t /*n*/); + +/* --- @mpx_lslc@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = source vector base and limit + * @size_t n@ = number of bit positions to shift by + * + * Returns: --- + * + * Use: Performs a logical shift left operation on an integer, only + * it fills in the bits with ones instead of zeroes. + */ + +extern void mpx_lslc(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, + size_t /*n*/); + +/* --- @mpx_lsr@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = source vector base and limit + * @size_t n@ = number of bit positions to shift by + * + * Returns: --- + * + * Use: Performs a logical shift right operation on an integer. + */ + +extern void mpx_lsr(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, + size_t /*n*/); + +/*----- Bitwise operations ------------------------------------------------*/ + +/* --- @mpx_bitop@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector + * @const mpw *av, *avl@ = first source vector + * @const mpw *bv, *bvl@ = second source vector + * + * Returns: --- + * + * Use: Provide the dyadic boolean functions. The functions are + * named after the truth table they generate: + * + * a: 0011 + * b: 0101 + * @mpx_bitXXXX@ + */ + +#define MPX_DOBIN(what) \ + what(0000) what(0001) what(0010) what(0011) \ + what(0100) what(0101) what(0110) what(0111) \ + what(1000) what(1001) what(1010) what(1011) \ + what(1100) what(1101) what(1110) what(1111) + +#define MPX_BITDECL(string) \ + extern void mpx_bit##string(mpw */*dv*/, mpw */*dvl*/, \ + const mpw */*av*/, const mpw */*avl*/, \ + const mpw */*bv*/, const mpw */*bvl*/); +MPX_DOBIN(MPX_BITDECL) + +/* --- @mpx_[n]and@, @mpx_[n]or@, @mpx_xor@ --- * + * + * Synonyms for the commonly-used functions above. + */ + +#define mpx_and mpx_bit0001 +#define mpx_or mpx_bit0111 +#define mpx_nand mpx_bit1110 +#define mpx_nor mpx_bit1000 +#define mpx_xor mpx_bit0110 + +/* --- @mpx_not@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector + * @const mpw *av, *avl@ = first source vector + * + * Returns: --- + * + * Use; Bitwise NOT. + */ + +extern void mpx_not(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/); + +/*----- Unsigned arithmetic -----------------------------------------------*/ + +/* --- @mpx_2c@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector + * @const mpw *v, *vl@ = source vector + * + * Returns: --- + * + * Use: Calculates the two's complement of @v@. + */ + +extern void mpx_2c(mpw */*dv*/, mpw */*dvl*/, + const mpw */*v*/, const mpw */*vl*/); + +/* --- @mpx_ueq@ --- * + * + * Arguments: @const mpw *av, *avl@ = first argument vector base and limit + * @const mpw *bv, *bvl@ = second argument vector base and limit + * + * Returns: Nonzero if the two vectors are equal. + * + * Use: Performs an unsigned integer test for equality. + */ + +extern int mpx_ueq(const mpw */*av*/, const mpw */*avl*/, + const mpw */*bv*/, const mpw */*bvl*/); + +/* --- @mpx_ucmp@ --- * + * + * Arguments: @const mpw *av, *avl@ = first argument vector base and limit + * @const mpw *bv, *bvl@ = second argument vector base and limit + * + * Returns: Less than, equal to, or greater than zero depending on + * whether @a@ is less than, equal to or greater than @b@, + * respectively. + * + * Use: Performs an unsigned integer comparison. + */ + +#define MPX_UCMP(av, avl, op, dv, dvl) \ + (mpx_ucmp((av), (avl), (dv), (dvl)) op 0) + +extern int mpx_ucmp(const mpw */*av*/, const mpw */*avl*/, + const mpw */*bv*/, const mpw */*bvl*/); + +/* --- @mpx_uadd@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = first addend vector base and limit + * @const mpw *bv, *bvl@ = second addend vector base and limit + * + * Returns: --- + * + * Use: Performs unsigned integer addition. If the result overflows + * the destination vector, high-order bits are discarded. This + * means that two's complement addition happens more or less for + * free, although that's more a side-effect than anything else. + * The result vector may be equal to either or both source + * vectors, but may not otherwise overlap them. + */ + +extern void mpx_uadd(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, + const mpw */*bv*/, const mpw */*bvl*/); + +/* --- @mpx_uaddn@ --- * + * + * Arguments: @mpw *dv, *dvl@ = source and destination base and limit + * @mpw n@ = other addend + * + * Returns: --- + * + * Use: Adds a small integer to a multiprecision number. + */ + +#define MPX_UADDN(dv, dvl, n) do { \ + mpw *_ddv = (dv), *_ddvl = (dvl); \ + mpw _c = (n); \ + \ + while (_c && _ddv < _ddvl) { \ + mpd _x = (mpd)*_ddv + (mpd)_c; \ + *_ddv++ = MPW(_x); \ + _c = _x >> MPW_BITS; \ + } \ +} while (0) + +extern void mpx_uaddn(mpw */*dv*/, mpw */*dvl*/, mpw /*n*/); + +/* --- @mpx_uaddnlsl@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination and first argument vector + * @mpw a@ = second argument + * @unsigned o@ = offset in bits + * + * Returns: --- + * + * Use: Computes %$d + 2^o a$%. If the result overflows then + * high-order bits are discarded, as usual. We must have + * @0 < o < MPW_BITS@. + */ + +extern void mpx_uaddnlsl(mpw */*dv*/, mpw */*dvl*/, + mpw /*a*/, unsigned /*o*/); + +/* --- @mpx_usub@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = first argument vector base and limit + * @const mpw *bv, *bvl@ = second argument vector base and limit + * + * Returns: --- + * + * Use: Performs unsigned integer subtraction. If the result + * overflows the destination vector, high-order bits are + * discarded. This means that two's complement subtraction + * happens more or less for free, although that's more a side- + * effect than anything else. The result vector may be equal to + * either or both source vectors, but may not otherwise overlap + * them. + */ + +extern void mpx_usub(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, + const mpw */*bv*/, const mpw */*bvl*/); + +/* --- @mpx_usubn@ --- * + * + * Arguments: @mpw *dv, *dvl@ = source and destination base and limit + * @n@ = subtrahend + * + * Returns: --- + * + * Use: Subtracts a small integer from a multiprecision number. + */ + +#define MPX_USUBN(dv, dvl, n) do { \ + mpw *_ddv = (dv), *_ddvl = (dvl); \ + mpw _c = (n); \ + \ + while (_ddv < _ddvl) { \ + mpd _x = (mpd)*_ddv - (mpd)_c; \ + *_ddv++ = MPW(_x); \ + if (_x >> MPW_BITS) \ + _c = 1; \ + else \ + break; \ + } \ +} while (0) + +extern void mpx_usubn(mpw */*dv*/, mpw */*dvl*/, mpw /*n*/); + +/* --- @mpx_usubnlsl@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination and first argument vector + * @mpw a@ = second argument + * @unsigned o@ = offset in bits + * + * Returns: --- + * + * Use: Computes %$d - 2^o a$%. If the result overflows then + * high-order bits are discarded, as usual, so you get two's + * complement. Which might be what you wanted... We must have + * @0 < o < MPW_BITS@. + */ + +extern void mpx_usubnlsl(mpw */*dv*/, mpw */*dvl*/, + mpw /*a*/, unsigned /*o*/); + +/* --- @mpx_umul@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = multiplicand vector base and limit + * @const mpw *bv, *bvl@ = multiplier vector base and limit + * + * Returns: --- + * + * Use: Performs unsigned integer multiplication. If the result + * overflows the desination vector, high-order bits are + * discarded. The result vector may not overlap the argument + * vectors in any way. + */ + +extern void mpx_umul(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, + const mpw */*bv*/, const mpw */*bvl*/); + +/* --- @mpx_umuln@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = multiplicand vector base and limit + * @mpw m@ = multiplier + * + * Returns: --- + * + * Use: Multiplies a multiprecision integer by a single-word value. + * The destination and source may be equal. The destination + * is completely cleared after use. + */ + +#define MPX_UMULN(dv, dvl, av, avl, m) do { \ + mpw *_dv = (dv), *_dvl = (dvl); \ + const mpw *_av = (av), *_avl = (avl); \ + mpw _c = 0; \ + mpd _m = (m); \ + \ + while (_av < _avl) { \ + mpd _x; \ + if (_dv >= _dvl) \ + break; \ + _x = (mpd)_m * (mpd)*_av++ + _c; \ + *_dv++ = MPW(_x); \ + _c = _x >> MPW_BITS; \ + } \ + if (_dv < _dvl) { \ + *_dv++ = MPW(_c); \ + MPX_ZERO(_dv, _dvl); \ + } \ +} while (0) + +extern void mpx_umuln(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, mpw m); + +/* --- @mpx_umlan@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination/accumulator base and limit + * @const mpw *av, *avl@ = multiplicand vector base and limit + * @mpw m@ = multiplier + * + * Returns: --- + * + * Use: Multiplies a multiprecision integer by a single-word value + * and adds the result to an accumulator. + */ + +#define MPX_UMLAN(dv, dvl, av, avl, m) do { \ + mpw *_dv = (dv), *_dvl = (dvl); \ + const mpw *_av = (av), *_avl = (avl); \ + mpw _cc = 0; \ + mpd _m = (m); \ + \ + while (_dv < _dvl && _av < _avl) { \ + mpd _x; \ + _x = (mpd)*_dv + (mpd)_m * (mpd)*_av++ + _cc; \ + *_dv++ = MPW(_x); \ + _cc = _x >> MPW_BITS; \ + } \ + MPX_UADDN(_dv, _dvl, _cc); \ +} while (0) + +extern void mpx_umlan(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, mpw m); + +/* --- @mpx_usqr@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *av@ = source vector base and limit + * + * Returns: --- + * + * Use: Performs unsigned integer squaring. The result vector must + * not overlap the source vector in any way. + */ + +extern void mpx_usqr(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/); + +/* --- @mpx_udiv@ --- * + * + * Arguments: @mpw *qv, *qvl@ = quotient vector base and limit + * @mpw *rv, *rvl@ = dividend/remainder vector base and limit + * @const mpw *dv, *dvl@ = divisor vector base and limit + * @mpw *sv, *svl@ = scratch workspace + * + * Returns: --- + * + * Use: Performs unsigned integer division. If the result overflows + * the quotient vector, high-order bits are discarded. (Clearly + * the remainder vector can't overflow.) The various vectors + * may not overlap in any way. Yes, I know it's a bit odd + * requiring the dividend to be in the result position but it + * does make some sense really. The remainder must have + * headroom for at least two extra words. The scratch space + * must be at least one word larger than the divisor. + */ + +extern void mpx_udiv(mpw */*qv*/, mpw */*qvl*/, mpw */*rv*/, mpw */*rvl*/, + const mpw */*dv*/, const mpw */*dvl*/, + mpw */*sv*/, mpw */*svl*/); + +/* --- @mpx_udivn@ --- * + * + * Arguments: @mpw *qv, *qvl@ = storage for the quotient (may overlap + * dividend) + * @const mpw *rv, *rvl@ = dividend + * @mpw d@ = single-precision divisor + * + * Returns: Remainder after divison. + * + * Use: Performs a single-precision division operation. + */ + +extern mpw mpx_udivn(mpw */*qv*/, mpw */*qvl*/, + const mpw */*rv*/, const mpw */*rvl*/, mpw /*d*/); + +/*----- Karatsuba multiplication algorithms -------------------------------*/ + +/* --- @MPK_THRESH@ --- * + * + * This is the limiting length for using Karatsuba algorithms. It's best to + * use the simpler classical multiplication method on numbers smaller than + * this. It is unsafe to make this constant less than four (i.e., the + * algorithms will fail). + */ + +#define MPK_THRESH 16 + +/* --- @mpx_kmul@ --- * + * + * Arguments: @mpw *dv, *dvl@ = pointer to destination buffer + * @const mpw *av, *avl@ = pointer to first argument + * @const mpw *bv, *bvl@ = pointer to second argument + * @mpw *sv, *svl@ = pointer to scratch workspace + * + * Returns: --- + * + * Use: Multiplies two multiprecision integers using Karatsuba's + * algorithm. This is rather faster than traditional long + * multiplication (e.g., @mpx_umul@) on large numbers, although + * more expensive on small ones. + * + * The destination must be three times as large as the larger + * argument. The scratch space must be five times as large as + * the larger argument. + */ + +extern void mpx_kmul(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, + const mpw */*bv*/, const mpw */*bvl*/, + mpw */*sv*/, mpw */*svl*/); + +/* --- @mpx_ksqr@ --- * + * + * Arguments: @mpw *dv, *dvl@ = pointer to destination buffer + * @const mpw *av, *avl@ = pointer to first argument + * @mpw *sv, *svl@ = pointer to scratch workspace + * + * Returns: --- + * + * Use: Squares a multiprecision integers using something similar to + * Karatsuba's multiplication algorithm. This is rather faster + * than traditional long multiplication (e.g., @mpx_umul@) on + * large numbers, although more expensive on small ones, and + * rather simpler than full-blown Karatsuba multiplication. + * + * The destination must be three times as large as the larger + * argument. The scratch space must be five times as large as + * the larger argument. + */ + +extern void mpx_ksqr(mpw */*dv*/, mpw */*dvl*/, + const mpw */*av*/, const mpw */*avl*/, + mpw */*sv*/, mpw */*svl*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/p-gentab.awk b/math/p-gentab.awk new file mode 100755 index 0000000..f0dd357 --- /dev/null +++ b/math/p-gentab.awk @@ -0,0 +1,100 @@ +#! /usr/bin/awk -f + +function banner(name, s, i) +{ + s = "/*----- " name " "; + while (length(s) < 75) s = s "-"; + return (s "*/"); +} + +function fix(name) +{ + gsub(/[^0-9A-Za-z_]+/, "_", name); + return (name); +} + +BEGIN { + print "/* -*-c-*-"; + print " *"; + print " * Table of prime groups [generated]"; + print " */"; + print ""; + print "#include \"ptab.h\""; + print ""; + print "#define N(x) (sizeof(x)/sizeof(*x))"; + print "#define MP(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }"; + print "#define NOMP { 0, 0, 0, 0, 0 }"; + print ""; + print banner("Prime data"); + print ""; + + d_i = 0; + name = ""; +} + +function putmp(x, d) +{ + if (!(x in data)) { + print "group " name ": missing " x >"/dev/stderr"; + exit 1; + } + d = data[x]; + if (!(d in cache)) { + n = "p_" fix(name) "_" x; + print "static mpw " n "[] = {"; + system("./mpdump " d); + print "};"; + print ""; + cache[d] = n; + } + mp[x] = cache[d]; +} + +function flush() +{ + if (name == "") return; + print "/* --- Group " name " --- */"; + delete mp; + print ""; + putmp("p"); + putmp("q"); + putmp("g"); + print "static pdata p_" fix(name) " = {"; + print " MP(" mp["p"] ")," + print " MP(" mp["q"] ")," + print " MP(" mp["g"] ")" + print "};"; + print ""; + dname[d_i++] = name; + d[name] = name; + r[name] = "p_" fix(name); + name = ""; +} + +/^[ \t]*(#|$)/ { next; } + +$1 == "alias" { flush(); dname[d_i++] = $2; d[$2] = $3; next; } + +$1 == "group" { flush(); delete data; name = $2; next; } + +{ data[$1] = $2; next; } + +END { + flush(); + print banner("Main table"); + print ""; + print "const pentry ptab[] = {"; + for (i = 0; i < d_i; i++) { + name = dname[i]; + rname = d[name]; + if (!rname in r) { + print "group " rname " not found (alias from " name ")" >"/dev/stderr"; + exit 1; + } + print " { \"" name "\", &" r[rname] " },"; + } + print " { 0, 0 }"; + print "};" + print ""; + print banner("That's all, folks"); +} diff --git a/math/pfilt.c b/math/pfilt.c new file mode 100644 index 0000000..de049cb --- /dev/null +++ b/math/pfilt.c @@ -0,0 +1,327 @@ +/* -*-c-*- + * + * Finding and testing prime numbers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpint.h" +#include "pfilt.h" +#include "pgen.h" +#include "primetab.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @smallenough@ --- * + * + * Arguments: @mp *m@ = integer to test + * + * Returns: One of the @PGEN@ result codes. + * + * Use: Assuming that @m@ has been tested by trial division on every + * prime in the small-primes array, this function will return + * @PGEN_DONE@ if the number is less than the square of the + * largest small prime. + */ + +static int smallenough(mp *m) +{ + static mp *max = 0; + int rc = PGEN_TRY; + + if (!max) { + max = mp_fromuint(MP_NEW, MAXPRIME); + max = mp_sqr(max, max); + max->a->n--; /* Permanent allocation */ + } + if (MP_CMP(m, <=, MP_ONE)) + rc = PGEN_FAIL; + else if (MP_CMP(m, <, max)) + rc = PGEN_DONE; + return (rc); +} + +/* --- @pfilt_smallfactor@ --- * + * + * Arguments: @mp *m@ = integer to test + * + * Returns: One of the @PGEN@ result codes. + * + * Use: Tests a number by dividing by a number of small primes. This + * is a useful first step if you're testing random primes; for + * sequential searches, @pfilt_create@ works better. + */ + +int pfilt_smallfactor(mp *m) +{ + int rc = PGEN_TRY; + int i; + size_t sz = MP_LEN(m); + mparena *a = m->a ? m->a : MPARENA_GLOBAL; + mpw *v = mpalloc(a, sz); + + /* --- Fill in the residues --- */ + + for (i = 0; i < NPRIME; i++) { + if (!mpx_udivn(v, v + sz, m->v, m->vl, primetab[i])) { + if (MP_LEN(m) == 1 && m->v[0] == primetab[i]) + rc = PGEN_DONE; + else + rc = PGEN_FAIL; + break; + } + } + + /* --- Check for small primes --- */ + + if (rc == PGEN_TRY) + rc = smallenough(m); + + /* --- Done --- */ + + mpfree(a, v); + return (rc); +} + +/* --- @pfilt_create@ --- * + * + * Arguments: @pfilt *p@ = pointer to prime filtering context + * @mp *m@ = pointer to initial number to test + * + * Returns: One of the @PGEN@ result codes. + * + * Use: Tests an initial number for primality by computing its + * residue modulo various small prime numbers. This is fairly + * quick, but not particularly certain. If a @PGEN_TRY@ + * result is returned, perform Rabin-Miller tests to confirm. + */ + +int pfilt_create(pfilt *p, mp *m) +{ + int rc = PGEN_TRY; + int i; + size_t sz = MP_LEN(m); + mparena *a = m->a ? m->a : MPARENA_GLOBAL; + mpw *v = mpalloc(a, sz); + + /* --- Take a copy of the number --- */ + + mp_shrink(m); + p->m = MP_COPY(m); + + /* --- Fill in the residues --- */ + + for (i = 0; i < NPRIME; i++) { + p->r[i] = mpx_udivn(v, v + sz, m->v, m->vl, primetab[i]); + if (!p->r[i] && rc == PGEN_TRY) { + if (MP_LEN(m) == 1 && m->v[0] == primetab[i]) + rc = PGEN_DONE; + else + rc = PGEN_FAIL; + } + } + + /* --- Check for small primes --- */ + + if (rc == PGEN_TRY) + rc = smallenough(m); + + /* --- Done --- */ + + mpfree(a, v); + return (rc); +} + +/* --- @pfilt_destroy@ --- * + * + * Arguments: @pfilt *p@ = pointer to prime filtering context + * + * Returns: --- + * + * Use: Discards a context and all the resources it holds. + */ + +void pfilt_destroy(pfilt *p) +{ + mp_drop(p->m); +} + +/* --- @pfilt_step@ --- * + * + * Arguments: @pfilt *p@ = pointer to prime filtering context + * @mpw step@ = how much to step the number + * + * Returns: One of the @PGEN@ result codes. + * + * Use: Steps a number by a small amount. Stepping is much faster + * than initializing with a new number. The test performed is + * the same simple one used by @primetab_create@, so @PGEN_TRY@ + * results should be followed up by a Rabin-Miller test. + */ + +int pfilt_step(pfilt *p, mpw step) +{ + int rc = PGEN_TRY; + int i; + + /* --- Add the step on to the number --- */ + + p->m = mp_split(p->m); + mp_ensure(p->m, MP_LEN(p->m) + 1); + mpx_uaddn(p->m->v, p->m->vl, step); + mp_shrink(p->m); + + /* --- Update the residue table --- */ + + for (i = 0; i < NPRIME; i++) { + p->r[i] = (p->r[i] + step) % primetab[i]; + if (!p->r[i] && rc == PGEN_TRY) { + if (MP_LEN(p->m) == 1 && p->m->v[0] == primetab[i]) + rc = PGEN_DONE; + else + rc = PGEN_FAIL; + } + } + + /* --- Check for small primes --- */ + + if (rc == PGEN_TRY) + rc = smallenough(p->m); + + /* --- Done --- */ + + return (rc); +} + +/* --- @pfilt_muladd@ --- * + * + * Arguments: @pfilt *p@ = destination prime filtering context + * @const pfilt *q@ = source prime filtering context + * @mpw m@ = number to multiply by + * @mpw a@ = number to add + * + * Returns: One of the @PGEN@ result codes. + * + * Use: Multiplies the number in a prime filtering context by a + * small value and then adds a small value. The destination + * should either be uninitialized or the same as the source. + * + * Common things to do include multiplying by 2 and adding 0 to + * turn a prime into a jump for finding other primes with @q@ as + * a factor of @p - 1@, or multiplying by 2 and adding 1. + */ + +int pfilt_muladd(pfilt *p, const pfilt *q, mpw m, mpw a) +{ + int rc = PGEN_TRY; + int i; + + /* --- Multiply the big number --- */ + + { + mp *d = mp_new(MP_LEN(q->m) + 2, q->m->f); + mpx_umuln(d->v, d->vl, q->m->v, q->m->vl, m); + mpx_uaddn(d->v, d->vl, a); + if (p == q) + mp_drop(p->m); + mp_shrink(d); + p->m = d; + } + + /* --- Gallivant through the residue table --- */ + + for (i = 0; i < NPRIME; i++) { + p->r[i] = (q->r[i] * m + a) % primetab[i]; + if (!p->r[i] && rc == PGEN_TRY) { + if (MP_LEN(p->m) == 1 && p->m->v[0] == primetab[i]) + rc = PGEN_DONE; + else + rc = PGEN_FAIL; + } + } + + /* --- Check for small primes --- */ + + if (rc == PGEN_TRY) + rc = smallenough(p->m); + + /* --- Finished --- */ + + return (rc); +} + +/* --- @pfilt_jump@ --- * + * + * Arguments: @pfilt *p@ = pointer to prime filtering context + * @const pfilt *j@ = pointer to another filtering context + * + * Returns: One of the @PGEN@ result codes. + * + * Use: Steps a number by a large amount. Even so, jumping is much + * faster than initializing a new number. The test peformed is + * the same simple one used by @primetab_create@, so @PGEN_TRY@ + * results should be followed up by a Rabin-Miller test. + * + * Note that the number stored in the @j@ context is probably + * better off being even than prime. The important thing is + * that all of the residues for the number have already been + * computed. + */ + +int pfilt_jump(pfilt *p, const pfilt *j) +{ + int rc = PGEN_TRY; + int i; + + /* --- Add the step on --- */ + + p->m = mp_add(p->m, p->m, j->m); + + /* --- Update the residue table --- */ + + for (i = 0; i < NPRIME; i++) { + p->r[i] = p->r[i] + j->r[i]; + if (p->r[i] > primetab[i]) + p->r[i] -= primetab[i]; + if (!p->r[i] && rc == PGEN_TRY) { + if (MP_LEN(p->m) == 1 && p->m->v[0] == primetab[i]) + rc = PGEN_DONE; + else + rc = PGEN_FAIL; + } + } + + /* --- Check for small primes --- */ + + if (rc == PGEN_TRY) + rc = smallenough(p->m); + + /* --- Done --- */ + + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/pfilt.h b/math/pfilt.h new file mode 100644 index 0000000..a667614 --- /dev/null +++ b/math/pfilt.h @@ -0,0 +1,155 @@ +/* -*-c-*- + * + * Finding and testing prime numbers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_PFILT_H +#define CATACOMB_PFILT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_PRIMETAB_H +# include "primetab.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct pfilt { + mp *m; + smallprime r[NPRIME]; +} pfilt; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @pfilt_smallfactor@ --- * + * + * Arguments: @mp *m@ = integer to test + * + * Returns: One of the @PGEN@ result codes. + * + * Use: Tests a number by dividing by a number of small primes. This + * is a useful first step if you're testing random primes; for + * sequential searches, @pfilt_create@ works better. + */ + +extern int pfilt_smallfactor(mp */*m*/); + +/* --- @pfilt_create@ --- * + * + * Arguments: @pfilt *p@ = pointer to prime filtering context + * @mp *m@ = pointer to initial number to test + * + * Returns: A @PGEN@ result code. + * + * Use: Tests an initial number for primality by computing its + * residue modulo various small prime numbers. This is fairly + * quick, but not particularly certain. If a @PGEN_TRY@ + * result is returned, perform Rabin-Miller tests to confirm. + */ + +extern int pfilt_create(pfilt */*p*/, mp */*m*/); + +/* --- @pfilt_destroy@ --- * + * + * Arguments: @pfilt *p@ = pointer to prime filtering context + * + * Returns: --- + * + * Use: Discards a context and all the resources it holds. + */ + +extern void pfilt_destroy(pfilt */*p*/); + +/* --- @pfilt_step@ --- * + * + * Arguments: @pfilt *p@ = pointer to prime filtering context + * @mpw step@ = how much to step the number + * + * Returns: One of the @PGEN@ result codes. + * + * Use: Steps a number by a small amount. Stepping is much faster + * than initializing with a new number. The test performed is + * the same simple one used by @primetab_create@, so @PGEN_TRY@ + * results should be followed up by a Rabin-Miller test. + */ + +extern int pfilt_step(pfilt */*p*/, mpw /*step*/); + +/* --- @pfilt_muladd@ --- * + * + * Arguments: @pfilt *p@ = destination prime filtering context + * @const pfilt *q@ = source prime filtering context + * @mpw m@ = number to multiply by + * @mpw a@ = number to add + * + * Returns: One of the @PGEN@ result codes. + * + * Use: Multiplies the number in a prime filtering context by a + * small value and then adds a small value. The destination + * should either be uninitialized or the same as the source. + * + * Common things to do include multiplying by 2 and adding 0 to + * turn a prime into a jump for finding other primes with @q@ as + * a factor of @p - 1@, or multiplying by 2 and adding 1. + */ + +extern int pfilt_muladd(pfilt */*p*/, const pfilt */*q*/, + mpw /*m*/, mpw /*a*/); + +/* --- @pfilt_jump@ --- * + * + * Arguments: @pfilt *p@ = pointer to prime filtering context + * @const pfilt *j@ = pointer to another filtering context + * + * Returns: One of the @PGEN@ result codes. + * + * Use: Steps a number by a large amount. Even so, jumping is much + * faster than initializing a new number. The test peformed is + * the same simple one used by @primetab_create@, so @PGEN_TRY@ + * results should be followed up by a Rabin-Miller test. + * + * Note that the number stored in the @j@ context is probably + * better off being even than prime. The important thing is + * that all of the residues for the number have already been + * computed. + */ + +extern int pfilt_jump(pfilt */*p*/, const pfilt */*j*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/pgen-gcd.c b/math/pgen-gcd.c new file mode 100644 index 0000000..1d205b5 --- /dev/null +++ b/math/pgen-gcd.c @@ -0,0 +1,101 @@ +/* -*-c-*- + * + * Prime search stepper ensuring a low GCD for %$(p - 1)/2$% + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "pgen.h" + +/*----- Main code ---------------------------------------------------------*/ + +int pgen_gcdstep(int rq, pgen_event *ev, void *p) +{ + pgen_gcdstepctx *g = p; + int rc = PGEN_ABORT; + + switch (rq) { + + /* --- Set everything up --- * + * + * Call things off if @p@ and @jp@ have common factors, or if @q@, @r@ + * and @jq@ have common factors greater than @max@. + */ + + case PGEN_BEGIN: { + mp *p = ev->m; + mp_gcd(&g->g, 0, 0, p, g->jp.m); + if (MP_CMP(g->g, >, MP_ONE)) + return (PGEN_ABORT); + g->q = mp_lsr(MP_NEW, p, 1); + g->jq = mp_lsr(MP_NEW, g->jp.m, 1); + mp_gcd(&g->g, 0, 0, g->q, g->jq); + mp_gcd(&g->g, 0, 0, g->g, g->r); + if (MP_CMP(g->g, >, g->max)) { + mp_drop(g->q); + mp_drop(g->jq); + return (PGEN_ABORT); + } + rc = pfilt_create(&g->p, p); + mp_drop(p); + } break; + + /* --- Grind through another iteration --- */ + + case PGEN_TRY: + mp_drop(ev->m); + rc = pfilt_jump(&g->p, &g->jp); + g->q = mp_add(g->q, g->q, g->jq); + break; + + /* --- Finished --- */ + + case PGEN_DONE: + pfilt_destroy(&g->p); + mp_drop(g->q); + mp_drop(g->jq); + return (PGEN_DONE); + } + + /* --- Step on until everything is OK --- */ + + for (;;) { + if (rc != PGEN_FAIL) { + mp_gcd(&g->g, 0, 0, g->r, g->q); + if (MP_CMP(g->g, >, g->max)) + rc = PGEN_FAIL; + } + if (rc != PGEN_FAIL) + break; + rc = pfilt_jump(&g->p, &g->jp); + g->q = mp_add(g->q, g->q, g->jq); + } + + ev->m = MP_COPY(g->p.m); + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/pgen-simul.c b/math/pgen-simul.c new file mode 100644 index 0000000..03deeb1 --- /dev/null +++ b/math/pgen-simul.c @@ -0,0 +1,168 @@ +/* -*-c-*- + * + * Simultaneous prime search + * + * (c) 2006 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#include "mprand.h" +#include "pgen.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rcmerge@ --- * + * + * Arguments: @int a, b@ = a pair of @PGEN@ return codes + * + * Returns: The overall return code capturing both. + */ + +static int rcmerge(int a, int b) +{ +#define FROB(state) \ + if (a == PGEN_##state || b == PGEN_##state) return (PGEN_##state) + FROB(FAIL); + FROB(TRY); + FROB(PASS); +#undef FROB + return (PGEN_DONE); +} + +/* --- @pgen_simulstep@ --- * + * + * Step a collection of numbers simultaneously. + */ + +int pgen_simulstep(int rq, pgen_event *ev, void *p) +{ + pgen_simulctx *ss = p; + pgen_simulprime *sp; + int rc = PGEN_ABORT, nrc; + unsigned i; + mp *q; + + assert(ss->n); + switch (rq) { + case PGEN_BEGIN: + rc = PGEN_DONE; + q = MP_NEW; + for (i = 0; i < ss->n; i++) { + sp = &ss->v[i]; + q = mp_mul(q, ss->step, sp->mul); + if (MP_LEN(q) <= 1) + sp->u.step = q->v[0]; + else { + sp->u.jump = xmalloc(sizeof(pfilt)); + pfilt_create(sp->u.jump, q); + sp->f |= PGENF_JUMP; + } + q = mp_mul(q, ev->m, sp->mul); + q = mp_add(q, q, sp->add); + nrc = pfilt_create(&sp->p, q); + rc = rcmerge(rc, nrc); + } + MP_DROP(q); + if (rc != PGEN_FAIL) + goto done; + case PGEN_TRY: + for (;;) { + rc = PGEN_DONE; + for (i = 0; i < ss->n; i++) { + sp = &ss->v[i]; + if (sp->f & PGENF_JUMP) + nrc = pfilt_jump(&sp->p, sp->u.jump); + else + nrc = pfilt_step(&sp->p, sp->u.step); + rc = rcmerge(rc, nrc); + } + if (rc != PGEN_FAIL) + goto done; + } + done: + mp_drop(ev->m); + ev->m = MP_COPY(ss->v[0].p.m); + break; + case PGEN_DONE: + for (i = 0; i < ss->n; i++) { + sp = &ss->v[i]; + if (sp->f & PGENF_JUMP) { + pfilt_destroy(sp->u.jump); + xfree(sp->u.jump); + } + if (sp->f & PGENF_KEEP) + sp->u.x = MP_COPY(sp->p.m); + pfilt_destroy(&sp->p); + } + rc = PGEN_DONE; + break; + } + return (rc); +} + +/* --- @pgen_simultest@ --- * + * + * Test a collection of numbers simultaneously. + */ + +int pgen_simultest(int rq, pgen_event *ev, void *p) +{ + pgen_simulctx *ss = p; + pgen_simulprime *sp; + int rc; + unsigned i; + mp *m; + + assert(ss->n); + switch (rq) { + case PGEN_BEGIN: + for (i = 0; i < ss->n; i++) + rabin_create(&ss->v[i].r, ss->v[i].p.m); + rc = PGEN_TRY; + break; + case PGEN_TRY: + m = MP_NEW; + for (i = 0; i < ss->n; i++) { + sp = &ss->v[i]; + m = mprand_range(m, sp->p.m, ev->r, 0); + rc = rabin_test(&sp->r, m); + if (rc != PGEN_PASS) + break; + } + mp_drop(m); + break; + case PGEN_DONE: + for (i = 0; i < ss->n; i++) + rabin_destroy(&ss->v[i].r); + rc = PGEN_DONE; + break; + } + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/pgen-stdev.c b/math/pgen-stdev.c new file mode 100644 index 0000000..117fb27 --- /dev/null +++ b/math/pgen-stdev.c @@ -0,0 +1,129 @@ +/* -*-c-*- + * + * Standard event handlers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include "pgen.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @pgen_evspin@ --- * + * + * Displays a spinning baton to show progress. + */ + +int pgen_evspin(int rq, pgen_event *ev, void *p) +{ + static char spinner[] = "/-\\|"; + static char *q = spinner; + + switch (rq) { + case PGEN_PASS: + case PGEN_FAIL: + putchar(*q++); + putchar('\b'); + fflush(stdout); + if (!*q) + q = spinner; + break; + case PGEN_DONE: + case PGEN_ABORT: + putchar(' '); + putchar('\b'); + fflush(stdout); + break; + } + return (0); +} + +/* --- @pgen_ev@ --- * + * + * Traditional event handler, shows dots for each test. + */ + +int pgen_ev(int rq, pgen_event *ev, void *p) +{ + switch (rq) { + case PGEN_BEGIN: + printf("Searching for %s: ", ev->name); + fflush(stdout); + break; + case PGEN_FAIL: + putchar('.'); + fflush(stdout); + break; + case PGEN_PASS: + putchar('+'); + fflush(stdout); + break; + case PGEN_DONE: + puts("+ ok"); + break; + case PGEN_ABORT: + puts(" failed"); + break; + } + return (0); +} + +/* --- @pgen_subev@ --- * + * + * Subsidiary event handler, mainly for Lim-Lee searches and so on. + */ + +int pgen_subev(int rq, pgen_event *ev, void *p) +{ + switch (rq) { + case PGEN_BEGIN: + printf("[%s: ", ev->name); + fflush(stdout); + break; + case PGEN_FAIL: + putchar('.'); + fflush(stdout); + break; + case PGEN_PASS: + putchar('+'); + fflush(stdout); + break; + case PGEN_DONE: + fputs("+]", stdout); + fflush(stdout); + break; + case PGEN_ABORT: + fputs(" failed]", stdout); + fflush(stdout); + break; + } + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/pgen.c b/math/pgen.c new file mode 100644 index 0000000..9a822f5 --- /dev/null +++ b/math/pgen.c @@ -0,0 +1,420 @@ +/* -*-c-*- + * + * Prime generation glue + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include "fibrand.h" +#include "grand.h" +#include "mp.h" +#include "mprand.h" +#include "pgen.h" +#include "pfilt.h" +#include "rabin.h" + +/*----- Standard prime filter ---------------------------------------------*/ + +/* --- @pgen_filter@ --- */ + +int pgen_filter(int rq, pgen_event *ev, void *p) +{ + pgen_filterctx *f = p; + int rc = PGEN_FAIL; + + switch (rq) { + case PGEN_BEGIN: + rc = pfilt_create(&f->f, ev->m); + mp_drop(ev->m); + break; + case PGEN_TRY: + mp_drop(ev->m); + break; + case PGEN_DONE: + pfilt_destroy(&f->f); + return (PGEN_DONE); + default: + rc = PGEN_ABORT; + break; + } + + if (rc == PGEN_FAIL && !((f->step | f->f.m->v[0]) & 1)) + rc = pfilt_step(&f->f, 1); + while (rc == PGEN_FAIL) + rc = pfilt_step(&f->f, f->step); + ev->m = MP_COPY(f->f.m); + return (rc); +} + +/* --- @pgen_jump@ --- * + * + * Similar to the standard @pgen_filter@, but jumps in large steps rather + * than small ones. + */ + +int pgen_jump(int rq, pgen_event *ev, void *p) +{ + pgen_jumpctx *f = p; + int rc = PGEN_ABORT; + + switch (rq) { + case PGEN_BEGIN: { + mp *g = MP_NEW; + mp_gcd(&g, 0, 0, ev->m, f->j->m); + if (MP_CMP(g, >, MP_ONE)) { + mp_drop(g); + return (PGEN_ABORT); + } + mp_drop(g); + rc = pfilt_create(&f->f, ev->m); + mp_drop(ev->m); + } break; + case PGEN_TRY: + mp_drop(ev->m); + rc = pfilt_jump(&f->f, f->j); + break; + case PGEN_DONE: + pfilt_destroy(&f->f); + return (PGEN_DONE); + } + + while (rc == PGEN_FAIL) + rc = pfilt_jump(&f->f, f->j); + ev->m = MP_COPY(f->f.m); + return (rc); +} + +/*----- Standard prime test -----------------------------------------------*/ + +/* --- @pgen_test@ --- */ + +int pgen_test(int rq, pgen_event *ev, void *p) +{ + rabin *r = p; + int rc = PGEN_ABORT; + + switch (rq) { + case PGEN_BEGIN: + rabin_create(r, ev->m); + rc = PGEN_TRY; + break; + case PGEN_TRY: + if (!ev->tests) + rc = rabin_rtest(r, MP_TWO); + else { + mp *a = mprand_range(MP_NEW, ev->m, ev->r, 0); + rc = rabin_rtest(r, a); + mp_drop(a); + } + break; + case PGEN_DONE: + rabin_destroy(r); + rc = PGEN_DONE; + break; + } + + return (rc); +} + +/*----- The main driver ---------------------------------------------------*/ + +/* --- @pgen@ --- * + * + * Arguments: @const char *name@ = name of the value being searched for + * @mp *d@ = destination for the result integer + * @mp *m@ = start value to pass to stepper + * @pgen_proc *event@ = event handler function + * @void *ectx@ = context argument for event andler + * @unsigned steps@ = number of steps to take in search + * @pgen_proc *step@ = stepper function to use + * @void *sctx@ = context argument for stepper + * @unsigned tests@ = number of tests to make + * @pgen_proc *test@ = tester function to use + * @void *tctx@ = context argument for tester + * + * Returns: Pointer to final result, or null. + * + * Use: A generalized prime-number search skeleton. Yes, that's a + * scary number of arguments. + */ + +mp *pgen(const char *name, mp *d, mp *m, pgen_proc *event, void *ectx, + unsigned steps, pgen_proc *step, void *sctx, + unsigned tests, pgen_proc *test, void *tctx) +{ + pgen_event ev; + int rq, rc; + pgen_proc *proc; + void *ctx; + int p; + + enum { P_STEP, P_TEST }; + + /* --- Set up the initial event block --- */ + + ev.name = name; + if (m) + ev.m = MP_COPY(m); + else + ev.m = 0; + ev.steps = 0; + ev.tests = 0; + ev.r = fibrand_create(0); + + /* --- Tell the event handler we're under way --- */ + + if (event && event(PGEN_BEGIN, &ev, ectx) == PGEN_ABORT) { + ev.r->ops->destroy(ev.r); + return (0); + } + + /* --- Set up for the initial call --- */ + + proc = step; ctx = sctx; p = P_STEP; rq = PGEN_BEGIN; + + /* --- Enter the great maelstrom of state transitions --- */ + + for (;;) { + unsigned act = 0; + +#define A_STEP 1u +#define A_TEST 2u +#define A_EVENT 4u +#define A_ENDTEST 8u +#define A_ENDSTEP 16u +#define A_DONE 32u + + /* --- Call the procedure and decide what to do next --- */ + + rc = proc(rq, &ev, ctx); + switch (rc) { + case PGEN_TRY: + if (p == P_TEST) + rq = PGEN_TRY; + else { + act |= A_EVENT; + proc = test; ctx = tctx; p = P_TEST; + rq = PGEN_BEGIN; + } + break; + case PGEN_PASS: + act |= A_TEST | A_EVENT; + if (p == P_TEST) + rq = PGEN_TRY; + else { + proc = test; ctx = tctx; p = P_TEST; + rq = PGEN_BEGIN; + } + break; + case PGEN_FAIL: + act |= A_STEP; + if (p == P_TEST) { + act |= A_ENDTEST | A_EVENT; + proc = step; ctx = sctx; p = P_STEP; + } + rq = PGEN_TRY; + break; + case PGEN_DONE: + act |= A_EVENT | A_DONE | A_ENDSTEP; + if (p == P_TEST) + act |= A_ENDTEST; + break; + case PGEN_ABORT: + act |= A_EVENT | A_DONE; + if (p == P_TEST || rq == PGEN_TRY) + act |= A_ENDSTEP; + if (p == P_TEST && rq != PGEN_BEGIN) + act |= A_ENDTEST; + break; + default: + assert(((void)"Invalid response from function", 0)); + break; + } + + /* --- If decrementing counters is requested, do that --- */ + + if ((act & A_STEP) && steps) { + ev.steps++; + if (ev.steps == steps) { + act |= A_EVENT | A_ENDSTEP | A_DONE; + rc = PGEN_ABORT; + } + ev.tests = 0; + } + + if ((act & A_TEST) && tests) { + ev.tests++; + if (ev.tests == tests) { + act |= A_ENDTEST | A_ENDSTEP | A_DONE; + rc = PGEN_DONE; + } + } + + /* --- Report an event if so directed --- */ + + if ((act & A_EVENT) && event && event(rc, &ev, ectx) == PGEN_ABORT) { + rc = PGEN_ABORT; + if (!(act & A_DONE)) { + act |= A_ENDSTEP | A_DONE; + if (p == P_TEST) + act |= A_ENDTEST; + } + } + + /* --- Close down tester and stepper functions --- */ + + if (act & A_ENDTEST) + test(PGEN_DONE, &ev, tctx); + if (act & A_ENDSTEP) + step(PGEN_DONE, &ev, sctx); + + /* --- Stop the entire test if necessary --- */ + + if (act & A_DONE) + break; + } + + /* --- Tidy up and return --- */ + + if (rc == PGEN_ABORT) { + mp_drop(ev.m); + ev.m = 0; + } + ev.r->ops->destroy(ev.r); + mp_drop(d); + + return (ev.m); +} + +/* --- @pgen_primep@ --- * + * + * Arguments: @mp *p@ = a number to check + * @grand *gr@ = a random number source + * + * Returns: Nonzero if @p@ is really prime. + */ + +int pgen_primep(mp *p, grand *gr) +{ + int i; + rabin r; + mp *x = MP_NEW; + + if (MP_NEGP(p)) return (0); + switch (pfilt_smallfactor(p)) { + case PGEN_DONE: return (1); + case PGEN_FAIL: return (0); + } + rabin_create(&r, p); + for (i = 32; i; i--) { + x = mprand_range(x, p, gr, 0); + if (rabin_rtest(&r, x) == PGEN_FAIL) + break; + } + MP_DROP(x); + rabin_destroy(&r); + return (!i); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +static int t_primep(dstr *v) +{ + mp *m = *(mp **)v[0].buf; + int e = *(int *)v[1].buf; + int r; + grand *rng; + int ok = 1; + + rng = fibrand_create(0); + r = pgen_primep(m, rng); + GR_DESTROY(rng); + if (e != r) { + fputs("\n*** primep failed", stderr); + fputs("\nm = ", stderr); mp_writefile(m, stderr, 10); + fprintf(stderr, "\nexpected %d", e); + fprintf(stderr, "\nreported %d", r); + fputc('\n', stderr); + ok = 0; + } + + mp_drop(m); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int verify(dstr *v) +{ + mp *m = *(mp **)v[0].buf; + mp *q = *(mp **)v[1].buf; + mp *p; + int ok = 1; + + pgen_filterctx pf; + rabin r; + + pf.step = 2; + p = pgen("p", MP_NEW, m, pgen_evspin, 0, 0, pgen_filter, &pf, + rabin_iters(mp_bits(m)), pgen_test, &r); + if (!p || !MP_EQ(p, q)) { + fputs("\n*** pgen failed", stderr); + fputs("\nm = ", stderr); mp_writefile(m, stderr, 10); + fputs("\np = ", stderr); mp_writefile(p, stderr, 10); + fputs("\nq = ", stderr); mp_writefile(q, stderr, 10); + fputc('\n', stderr); + ok = 0; + } + + mp_drop(m); + mp_drop(q); + mp_drop(p); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "pgen", verify, { &type_mp, &type_mp, 0 } }, + { "primep", t_primep, { &type_mp, &type_int, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/pgen"); + return (0); +} +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/pgen.h b/math/pgen.h new file mode 100644 index 0000000..b103c30 --- /dev/null +++ b/math/pgen.h @@ -0,0 +1,289 @@ +/* -*-c-*- + * + * Prime generation glue + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_PGEN_H +#define CATACOMB_PGEN_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_PFILT_H +# include "pfilt.h" +#endif + +#ifndef CATACOMB_RABIN_H +# include "rabin.h" +#endif + +/*----- Event handling ----------------------------------------------------* + * + * Different programs and architectures will want to show progress of prime + * searches and similar processes in different ways. Of course, for simple + * searches, it's possible to use the @pfilt@ and @rabin@ functions and + * maintain control over the general control flow throughout the search. + * + * For more complex cases, this sort of control is undesirable. It's + * possible to specify an event handler which is informed in abstract about + * the search. The event handler can also request the search be aborted. + */ + +/* --- Event code constants --- * + * + * You're allowed to rely on the values of @PGEN_DONE@ and @PGEN_ABORT@. + */ + +enum { + PGEN_BEGIN = 1, /* Search for value begins */ + PGEN_TRY, /* A new candidate has appeared */ + PGEN_FAIL, /* The candidate failed the test */ + PGEN_PASS, /* The candidate passed a test */ + PGEN_DONE = 0, /* A good value has been found */ + PGEN_ABORT = -1 /* The search has been aborted */ +}; + +/* --- Event information --- * + * + * Note that the pseudorandom number generator supplied is not + * cryptographically strong. + */ + +typedef struct pgen_event { + const char *name; /* Which quantity is being found */ + mp *m; /* Current value under test */ + unsigned steps; /* Number of candidates left */ + unsigned tests; /* Tests left before passing */ + grand *r; /* Source of random numbers */ +} pgen_event; + +/*----- Prime search parameters -------------------------------------------* + * + * The prime search is parameterized in a large number of ways, although this + * isn't so much of a surprise given the different sorts of properties + * required from prime numbers in cryptographic applications. + * + * There are two main things which need to be configured: stepping, and + * testing. (Filtering is done as part of stepping.) + * + * The functions here provide a toolkit for constructing stepping and testing + * routines. In a lot of cases, the functions can be used directly; in + * others, simple bits of glue need be written. + * + * Two types of functions are defined: steppers and testers, but their + * interfaces are substantially similar. Each is given a request code, a + * context block and an event block. It is meant to update its context and + * the event block and return an event code. + * + * A call with a request of @PGEN_BEGIN@ asks the stepper or tester to + * initialize itself using the information in its event block and context. A + * return of @PGEN_FAIL@ reports an immediate failure; @PGEN_ABORT@ reports a + * fatal problem; @PGEN_DONE@ reports immediate success. @PGEN_TRY@ reports + * successful initialization and requests test iterations. + * + * A call to a stepper with a request of @PGEN_TRY@ asks it to step to the + * next possible candidate, replacing the value @m@ in the event block with + * the new candidate. A call to a tester with a request of @PGEN_TRY@ + * runs one pass of the test. It should return @PGEN_FAIL@ to report a + * failure, @PGEN_PASS@ to report a success and request another iteration, + * @PGEN_DONE@ to report final acceptance and @PGEN_ABORT@ to terminate the + * search unsuccessfully. Note that even if the search is aborted, a + * shutdown request is still made. + * + * A call with a request of @PGEN_DONE@ closes down the stepper or tester. + * After a successful initialization (i.e., a return of something other than + * @PGEN_ABORT@), a shutdown call is guaranteed. The return code is ignored. + */ + +typedef int pgen_proc(int /*rq*/, pgen_event */*ev*/, void */*p*/); + +/*----- Simple handler functions ------------------------------------------*/ + +/* --- @pgen_filter@ --- * + * + * A prime generation context contains the information required for the + * simple prime filter and tester presented here. + */ + +typedef struct pgen_filterctx { + unsigned step; /* Step size (set by client) */ + pfilt f; /* The rapid prime filter */ +} pgen_filterctx; + +extern pgen_proc pgen_filter; + +/* --- @pgen_jump@ --- * + * + * Similar to the standard @pgen_filter@, but jumps in large steps rather + * than small ones. + */ + +typedef struct pgen_jumpctx { + const pfilt *j; + pfilt f; +} pgen_jumpctx; + +extern pgen_proc pgen_jump; + +/* --- @pgen_test@ --- * + * + * Runs the Rabin-Miller primality test. The context block is simply a + * @rabin@ context. + */ + +extern pgen_proc pgen_test; + +/*----- Simultaneous primality checking -----------------------------------*/ + +typedef struct pgen_simulprime { + mp *mul, *add; /* Arguments from the client */ + unsigned f; /* Flags, set by client, changed */ +#define PGENF_KEEP 1u /* Keep this prime's value */ +#define PGENF_JUMP 8u /* Use jump table, not stepping */ + pfilt p; /* This prime's filter */ + rabin r; /* Rabin testing context */ + union { + mpw step; /* The simple step to use */ + pfilt *jump; /* The jump to move by */ + mp *x; /* The result, if wanted */ + } u; +} pgen_simulprime; + +typedef struct pgen_simulctx { + pgen_simulprime *v; /* Vector of related primes */ + unsigned n; /* Size of the vector */ + mp *step; /* Basic stepping value */ +} pgen_simulctx; + +/* --- @pgen_simulstep@ --- * + * + * Step a collection of numbers simultaneously. + */ + +extern pgen_proc pgen_simulstep; + +/* --- @pgen_simultest@ --- * + * + * Test a collection of numbers simultaneously. + */ + +extern pgen_proc pgen_simultest; + +/*----- Miscellaneous steppers and testers --------------------------------*/ + +typedef struct pgen_gcdstepctx { + pfilt p, jp; /* Prime filter and step filter */ + mp *q, *jq; /* %$p - 1$%, and a step value*/ + mp *r; /* Other argument for GCD */ + mp *g; /* GCD output (must be inited) */ + mp *max; /* Maximum permissible GCD */ +} pgen_gcdstepctx; + +/* --- @pgen_gcdstep@ --- * + * + * Steps @p@ and @q@, until @p@ has no small factors, and + * %$\gcd(p, r) \le max$%. + */ + +extern pgen_proc pgen_gcdstep; + +/*----- Standard event handlers -------------------------------------------*/ + +/* --- @pgen_evspin@ --- * + * + * Displays a spinning baton to show progress. + */ + +extern pgen_proc pgen_evspin; + +/* --- @pgen_ev@ --- * + * + * Traditional event handler, shows dots for each test. + */ + +extern pgen_proc pgen_ev; + +/* --- @pgen_subev@ --- * + * + * Subsidiary event handler, mainly for Lim-Lee searches and so on. + */ + +extern pgen_proc pgen_subev; + +/*----- The main driver ---------------------------------------------------*/ + +/* --- @pgen@ --- * + * + * Arguments: @const char *name@ = name of the value being searched for + * @mp *d@ = destination for resulting integer + * @mp *m@ = start value to pass to stepper + * @pgen_proc *event@ = event handler function + * @void *ectx@ = context argument for event andler + * @unsigned steps@ = number of steps to take in search + * @pgen_proc *step@ = stepper function to use + * @void *sctx@ = context argument for stepper + * @unsigned tests@ = number of tests to make + * @pgen_proc *test@ = tester function to use + * @void *tctx@ = context argument for tester + * + * Returns: The resulting value, or null. + * + * Use: A generalized prime-number search skeleton. Yes, that's a + * scary number of arguments. + */ + +extern mp *pgen(const char */*name*/, mp */*d*/, mp */*m*/, + pgen_proc */*event*/, void */*ectx*/, + unsigned /*steps*/, pgen_proc */*step*/, void */*sctx*/, + unsigned /*tests*/, pgen_proc */*test*/, void */*tctx*/); + +/* --- @pgen_primep@ --- * + * + * Arguments: @mp *p@ = a number to check + * @grand *gr@ = a random number source + * + * Returns: Nonzero if @p@ is really prime. + */ + +extern int pgen_primep(mp */*p*/, grand */*gr*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/prim.c b/math/prim.c new file mode 100644 index 0000000..0003122 --- /dev/null +++ b/math/prim.c @@ -0,0 +1,107 @@ +/* -*-c-*- + * + * Finding primitive elements + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpint.h" +#include "mpmont.h" +#include "mprand.h" +#include "pgen.h" +#include "prim.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @prim_test@ --- */ + +int prim_test(int rq, pgen_event *ev, void *p) +{ + prim_ctx *c = p; + int rc = rq; + + switch (rq) { + case PGEN_BEGIN: + return (PGEN_TRY); + case PGEN_TRY: { + mp *x; + rc = PGEN_FAIL; + + if (!c->exp) + x = mp_copy(ev->m); + else { + x = mpmont_exp(&c->mm, MP_NEW, ev->m, c->exp); + if (MP_EQ(x, MP_ONE)) + goto done; + } + if (c->n == 0) + goto ok; + else { + size_t n = c->n; + mp **f = c->f; + mp *y = MP_NEW; + while (n) { + y = mpmont_exp(&c->mm, y, x, *f); + if (MP_EQ(y, MP_ONE)) { + mp_drop(y); + goto done; + } + n--; f++; + } + mp_drop(y); + } + ok: + rc = PGEN_DONE; + mp_drop(ev->m); + ev->m = x; + break; + done: + mp_drop(x); + } break; + } + + return (rc); +} + +/* --- Trivial stepping functions -----------------------------------------*/ + +/* --- @prim_step@ --- */ + +int prim_step(int rq, pgen_event *ev, void *p) +{ + unsigned *i = p; + switch (rq) { + case PGEN_BEGIN: + case PGEN_TRY: + if (*i >= NPRIME) + return PGEN_FAIL; + ev->m = mp_fromint(ev->m, primetab[(*i)++]); + return (PGEN_TRY); + } + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/prim.h b/math/prim.h new file mode 100644 index 0000000..4b3dff3 --- /dev/null +++ b/math/prim.h @@ -0,0 +1,89 @@ +/* -*-c-*- + * + * Finding primitive elements + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_PRIM_H +#define CATACOMB_PRIM_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_MPMONT_H +# include "mpmont.h" +#endif + +#ifndef CATACOMB_PGEN_H +# include "pgen.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- @prim_ctx@ --- * + * + * All fields must be configured by the client. Set @n@ to zero to discover + * generators of the subgroup of order %$m / f$%. + * + * Let %$p = \prod q_i + 1$% be a prime number. In order to find an element + * %$g$% with order %$o$%, we choose elements %$h_j$% from %$\gf{p}^*$%, + * compute $%g_j = h_j^{p/o}$%, rejecting %$h_j$% where %$g_j = 1$%, and then + * for each proper prime factor %$q_i$% of %$p/o$% we check that + * %$g^{f_i} \ne 1$%, where the %$f_i$% are cofactors of the %$q_i$% + * (%$f_i q_i = p/o$%). + */ + +typedef struct prim_ctx { + mpmont mm; /* Montgomery context for modulus */ + mp *exp; /* Exponent (%$p/o$%; may be zero) */ + size_t n; /* Number of cofactors */ + mp **f; /* Array of cofactors */ +} prim_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @prim_test@ --- */ + +extern pgen_proc prim_test; + +/* --- @prim_step@ --- */ + +extern pgen_proc prim_step; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/primeiter.c b/math/primeiter.c new file mode 100644 index 0000000..463fc47 --- /dev/null +++ b/math/primeiter.c @@ -0,0 +1,254 @@ +/* -*-c-*- + * + * Iterate over small primes efficiently + * + * (c) 2007 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "fibrand.h" +#include "mp.h" +#include "pgen.h" +#include "primeiter.h" +#include "primetab.h" +#include "wheel.h" + +/*----- Theory ------------------------------------------------------------* + * + * For small primes, we can just pluck them out of the small primes table. + * For larger primes, we can test them individually, or build a sieve or + * something, but since we don't know when to stop, that could be tricky. + * + * We've built a `wheel', as follows. Let %$m$% be the product of the first + * %$n$% primes. There are %$\phi(m)$% integers %$n_i$%, with %$0 < n_i < + * m$% coprime to %$m$%, and any integer %$j > n$% must be congruent to some + * %$n_i$% modulo %$m$%. The wheel itself doesn't list the %$n_i$%, but + * rather the differences %$\delta_i = n_i - n_{i-1}$% (wrapping around + * appropriately at the ends), so you can just add simple offsets to step + * onwards. The wheel assumes you start at 1 and move on round. + */ + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @wheelsync@ --- * + * + * Arguments: @primeiter *pi@ = iterator to synchronize + * @mp *where@ = value to synchronize + * + * Returns: --- + * + * Use: Sets up the wheel index to match the given integer. After + * this, we can step along the wheel to find candidate primes. + */ + +static void wheelsync(primeiter *pi, mp *where) +{ + mpw w; + mp t; + mpw rr; + mp *r = MP_NEW; + unsigned i, n; + + w = WHEELMOD; + mp_build(&t, &w, &w + 1); + mp_div(0, &r, where, &t); + rr = MP_ZEROP(r) ? 0 : r->v[0]; + + for (i = 0, n = 1; rr > n; n += wheel[i], i++); + w = n - rr; + pi->p = mp_add(MP_NEW, where, &t); + pi->i = i; + pi->r = fibrand_create(0); + MP_DROP(r); +} + +/* --- @primeiter_create@ --- * + * + * Arguments: @primeiter *pi@ = pointer to an iterator structure + * @mp *start@ = where to start + * + * Returns: --- + * + * Use: Initializes a prime iterator. The first output will be the + * smallest prime not less than @start@. + */ + +void primeiter_create(primeiter *pi, mp *start) +{ + mpw n; + unsigned l, h, m; + + if (!start || MP_CMP(start, <=, MP_TWO)) + start = MP_TWO; + + if (MP_LEN(start) <= 1) { + n = start->v[0]; + if (n <= MAXPRIME) { + l = 0; + h = NPRIME; + for (;;) { + m = l + (h - l)/2; + if (primetab[m] == n) break; + else if (m == l) { m++; break; } + else if (primetab[m] < n) l = m; + else h = m; + } + pi->i = m; + pi->mode = PIMODE_PTAB; + mp_build(&pi->pp, &pi->w, &pi->w + 1); + pi->p = &pi->pp; + return; + } + } + + wheelsync(pi, start); + pi->mode = PIMODE_STALL; +} + +/* --- @primeiter_destroy@ --- * + * + * Arguments: @primeiter *pi@ = pointer to iterator structure + * + * Returns: --- + * + * Use: Frees up an iterator structure when it's no longer wanted. + */ + +void primeiter_destroy(primeiter *pi) +{ + switch (pi->mode) { + case PIMODE_PTAB: + break; + case PIMODE_STALL: + case PIMODE_WHEEL: + MP_DROP(pi->p); + GR_DESTROY(pi->r); + break; + default: + abort(); + } +} + +/* --- @primeiter_next@ --- * + * + * Arguments: @primeiter *pi@ = pointer to an iterator structure + * @mp *d@ = fake destination + * + * Returns: The next prime number from the iterator. + * + * Use: Returns a new prime number. + */ + +mp *primeiter_next(primeiter *pi, mp *d) +{ + mp *p; + + switch (pi->mode) { + case PIMODE_PTAB: + pi->w = primetab[pi->i++]; + if (pi->i >= NPRIME) { + wheelsync(pi, pi->p); + pi->mode = PIMODE_WHEEL; + } + p = MP_COPY(pi->p); + MP_SPLIT(p); + break; + case PIMODE_STALL: + pi->mode = PIMODE_WHEEL; + goto loop; + case PIMODE_WHEEL: + do { + MP_DEST(pi->p, MP_LEN(pi->p) + 1, pi->p->f); + MPX_UADDN(pi->p->v, pi->p->vl, wheel[pi->i++]); + MP_SHRINK(pi->p); + if (pi->i >= WHEELN) pi->i = 0; + loop:; + } while (!pgen_primep(pi->p, pi->r)); + p = MP_COPY(pi->p); + break; + default: + abort(); + } + if (d) MP_DROP(d); + return (p); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include +#include + +static int test(dstr *v) +{ + mp *start = *(mp **)v[0].buf; + mp *pp[5], *ret[5]; + int i; + primeiter pi; + int ok = 1; + + for (i = 0; i < N(pp); i++) + pp[i] = *(mp **)v[i + 1].buf; + primeiter_create(&pi, start); + for (i = 0; i < N(pp); i++) { + ret[i] = primeiter_next(&pi, MP_NEW); + if (!MP_EQ(ret[i], pp[i])) ok = 0; + } + if (!ok) { + fprintf(stderr, "\n*** primeiter test failure:\n*** start = "); + mp_writefile(start, stderr, 10); + for (i = 0; i < N(pp); i++) { + fprintf(stderr, "\n*** p[%d] = ", i); + mp_writefile(ret[i], stderr, 10); + fprintf(stderr, " %s ", MP_EQ(ret[i], pp[i]) ? "==" : "!="); + mp_writefile(pp[i], stderr, 10); + } + fputc('\n', stderr); + } + for (i = 0; i < N(pp); i++) { + MP_DROP(pp[i]); + MP_DROP(ret[i]); + } + primeiter_destroy(&pi); + MP_DROP(start); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "primeiter", test, + { &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, } }, + { 0 } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, tests, SRCDIR "/t/pgen"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/primeiter.h b/math/primeiter.h similarity index 100% rename from primeiter.h rename to math/primeiter.h diff --git a/math/ptab.h b/math/ptab.h new file mode 100644 index 0000000..4ddeeb1 --- /dev/null +++ b/math/ptab.h @@ -0,0 +1,62 @@ +/* -*-c-*- + * + * Table of standard prime groups + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_PTAB_H +#define CATACOMB_PTAB_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct pdata { + mp p; /* The modulus */ + mp q; /* The group order */ + mp g; /* The generator */ +} pdata; + +typedef struct pentry { + const char *name; + pdata *data; +} pentry; + +/*----- Global variables --------------------------------------------------*/ + +extern const pentry ptab[]; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/ptab.in b/math/ptab.in new file mode 100644 index 0000000..162d0c9 --- /dev/null +++ b/math/ptab.in @@ -0,0 +1,217 @@ +# Standard prime groups + +#----- Groups from Oakley (RFC2412) ----------------------------------------- + +group oakley768 + p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff + q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31d1b107fffffffffffffff + g 2 + +group oakley1024 + p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff + q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f67329c0ffffffffffffffff + g 2 + +group oakley1536 + p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff + q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba36046511b993ffffffffffffffff + g 2 + +#----- Groups from RFC3526 -------------------------------------------------- + +group oakley2048 + p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff + q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba36046511b993ffffffffffffffff + g 2 + +group oakley3072 + p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff + q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549d69657fffffffffffffff + g 2 + +group oakley4096 + p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff + q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f4e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f68fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49a0318ccffffffffffffffff + g 2 + +group oakley6144 + p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff + q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f4e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f68fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49a0142491b61fd5a693e381360ea6e593013236f64ba8f3b1edd1bdefc7fca0356cf298772ed9c17a09800d7583529f6c813ec188bcb93d8432d448c6d1f6df5e7cd8a76a267365d676a5d8dedbf8a23f36612a5999028a895ebd7a137dc7a009bc6695facc1e500e325c9767819750ae8b90e81fa416be7373a7f7b6aaf3817a34c06415ad42018c8058e4f2cf3e4bfdf63f47991d4bd3f1b66445f078ea2dbffac2d62a5ea03d915a0aa556647b6bf5fa470ec0a662f6907c01bf053cb8af7794df1940350eac5dbe2ed3b7aa8551ec50fdff8758ce658d189eaae6d2b64f617794b191c3ff46bb71e0234021f47b31fa43077095f96ad85ba3a6b734a7c8f36e620127fffffffffffffff + g 2 + +group oakley8192 + p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff + q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f4e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f68fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49a0142491b61fd5a693e381360ea6e593013236f64ba8f3b1edd1bdefc7fca0356cf298772ed9c17a09800d7583529f6c813ec188bcb93d8432d448c6d1f6df5e7cd8a76a267365d676a5d8dedbf8a23f36612a5999028a895ebd7a137dc7a009bc6695facc1e500e325c9767819750ae8b90e81fa416be7373a7f7b6aaf3817a34c06415ad42018c8058e4f2cf3e4bfdf63f47991d4bd3f1b66445f078ea2dbffac2d62a5ea03d915a0aa556647b6bf5fa470ec0a662f6907c01bf053cb8af7794df1940350eac5dbe2ed3b7aa8551ec50fdff8758ce658d189eaae6d2b64f617794b191c3ff46bb71e0234021f47b31fa43077095f96ad85ba3a6b734a7c8f36df08acba51c937897f72f21c3bbe5b54996fc66c5f626839dc98dd1de4195b46cee9803a0fd3dfc57e23f692bb7b49b5d212331d55b1ce2d727ab41a11da3a15f8e4bc11c78b65f1ceb296f1fedc5f7e42456c911117025201be0389f5abd40d11f8639a39fe3236751835a5e5e44317c1c2eefd4ea5bfd16043f43cb41981f6adee9d03159e7ad9d13c53369509fc1fa27c16ef9887703a55b51b22cbf44cd012aee0b2798e628423428efcd5a40caef6bf50d8ea885ebf73a6b9fd79b5e18f67d1341ac8237a75c3cfc92004a1c5a40e366bc44d00176af71c15e48c86d37e013723caac7223ab3bf4d54f1828713b2b4a6fe40fab74405cb738b064c06ecc76e9efffffffffffffffff + g 2 + +#----- Lim-Lee groups generated by hand ------------------------------------- +# +# I generated these using utils/genpgroups. It took a rather long time. + +# --- catacomb-ll-128-512 --- +# +# keyid = 3db35e07 +# seed = PbNeB774QFw0xJvLDEn3bUx6hJw= +# fingerprint = fb47344e-9bfcd0e-e986c772-48edc231-861cb5fb + +group catacomb-ll-128-512 + p 9749248307666198278625282069621029423614285873414870747628872221551255623823205551438908261067675576856742534707535779666498916029617598868013496631088223 + q 271499434142083095503643289076442321059 + g 572938290446952786361356734705597783874760982871814854106633812061613480394314443743197177265739535298268868306029572450131746639710824513310586144336987 +#:factor 271499434142083095503643289076442321059 +#:factor 251174382438405784142034780246853570853 +#:factor 259658226261043076610234546745792177763 +#:factor 275292752516630714214627215608643381611 + +# --- catacomb-ll-160-1024 --- +# +# keyid = 98f62cc8 +# seed = mPYsyKXF6PoNTkl5uZE64gKEf20= +# fingerprint = 6ab1f087-5614561c-5d388443-b1f02eac-38248fe6 + +group catacomb-ll-160-1024 + p 69775951038073580217048751187698556149910661999359201823421066000439190288124938297116840422332973903349265313226189724474672148172906743149961449018143681316055777549225333684417216672046201528908637006946721694566251047975893301628540057123962444434130461052652526277961662241061299058137499738575071867183 + q 741802303617786660769426556982216255271020758647 + g 24031880137812767104513348688448999056754549625670167617628008814539123937598464069755252337842705625768270002772600104095116713027947418314704258588569425678035630653993833866258334547988915311887541947589468379164053328339235797437698686107421712042993209960764868024283667188725341401853595169622553906137 +#:factor 741802303617786660769426556982216255271020758647 +#:factor 1436145082693042410533997633791272917636904431479 +#:factor 1053371763883815722032496338163704236230178616951 +#:factor 1215995718665420681503927009463070333378310191827 +#:factor 1448192360714741582009673893725822727433041298541 +#:factor 17654251325616983743094122151298023764308424678047987263690296014551 + +# --- catacomb-ll-192-1536 --- +# +# keyid = 7efe5c2c +# seed = fv5cLMXgGO2voYGTQ5K525Xtf9E= +# fingerprint = ae9d47b9-e303daa5-9677023d-764b338b-53f03c4e + +group catacomb-ll-192-1536 + p 271163844483056215974969265313967454661676256266511940924304321373021958106999031565631233996938091358447023677706317722695337026864685384345663120704730255257202847527192911265950638087504732115876440997750045081880863038141607482083211725689822517898206821836185159703555104632867971994304356879518337226475272092974597967943366038800089283400183985773753490774687966167193456249452974119129018696293050595073100284829925638444204379135326678813960293114732959 + q 3265942811645946563242629602041107481841853511350443184197 + g 216185318413290469366405581500018842001794769819261149347277739848511992115259660705539911431188902360038442052949313200461450240469139278699145891151900315976816130082310914969548643710915174155521909660265659882527478738966654443422798664706090262812802264667406360583964285545011889176706871228354070760597031811706100156760441692822039947686308668974200473374152063439445019790248156400822413220452383963514887723177708643429977392740800552485785350546387634 +#:factor 3265942811645946563242629602041107481841853511350443184197 +#:factor 4203281750074745560664516895168522022509720946720609480259 +#:factor 5008750505930402098755083797499946811957880698185704286517 +#:factor 5437815993255342021982036827752826453901545498474314278259 +#:factor 3856915640937851719940744630159301063173277801391043813291 +#:factor 6054082443893470116716978196535076127652382149483455623509 +#:factor 4527580176039500642864307604310793340910014541817043735439 +#:factor 3430016280837410693307976287901159907499384818919106315351 + +# --- catacomb-ll-224-2048 --- +# +# keyid = e2824699 +# seed = 4oJGmZFnxNgns4UExrPWJXJDQYY= +# fingerprint = 5b3631f1-f388bca-554c1df1-3774fee9-cd46747c + +group catacomb-ll-224-2048 + p 3113844893182469436423817481922802329154474934213986369565700235348098440269001480103560846535113493144522446351379349356211385191632945710341444495577638160076546999114567117877732507854868463110804063964212132228977417231690350182211790515961798314443291574015832300281633156990779527484905381392680532643288437519954295652416759988107781937077836044809781096660654460207183523575424301901443740349094152501352983589721328225459512044516684078781305909247963063040562914192132284695886353707336911126238203292592145886841905764429235683487108646920559740458905874135798982283901137307047131586817745416509850061963 + q 18749474022970964965792505501868745784157349746475161167020805104727 + g 1018599075350815414286530684646967825916370747779291600517646276513566802791874935821816063520500873842729343817973803895278528701892043836290994612088035311589900475691176610297248816678701309707300454643927577686742011376684351525767933769045470869869290385506108485669189456183746644562327923152628958690988304340204333382573235567919004822811151873260798098816157572583867825397056414990908538555039226503662448878536483457742053639607062687899859473980884756925814541061907505350254827583321961201313954703462583072253230646667723110441238195386606218014837851495231172030604130800244334912972408067680590879980 +#:factor 18749474022970964965792505501868745784157349746475161167020805104727 +#:factor 26459793266106143518700371316953986751950547842631163615799385478033 +#:factor 23385205652191135191327958583020476187937251160152256504448581299573 +#:factor 17287418736358368314036906794523064561326146990020019216549187737103 +#:factor 16800288948485454351848726052252844830400274721321174607061304165751 +#:factor 14817124042645057452868896146782513905071983176482538876644503596827 +#:factor 24089412810223523640445605527780074479098235298741910558499656689361 +#:factor 18919386933765812741111621380736732547216460099506859126765656541087 +#:factor 68423637472150676252123752731403397187923476268634988015857219241126016100451 + +# --- catacomb-ll-256-3072 --- +# +# keyid = e6a15ce1 +# seed = 5qFc4fL01gTjyvNMZH5BvwETZco= +# fingerprint = 904df4e7-74941baa-40d589c8-fecad932-2b3b7c8d + +group catacomb-ll-256-3072 + p 635937223373484887991140560420669529960468634418212194527199243018802509220923645480563049852948379631872315326364181219863391536284352632127476573990043945919830000350264391397346335414535975554209931971547284463207275833747975949070870172306582775948778222246682185331862354083029804303222690541851195763223409045953191584611635790362191424339883737168342809190665629632289528654983812904611647818546832860081714363504512892885600580448186423533085059295328609139522690627823102925150246378111221377628009667319528150747320084312110336288028683700603719073769314245952464113622780032073817850603131463761017417455806035107984621889773217138911836476354442521466189648565925624512100087534918369360007697883847802211797655614684090408428715299537509886614640500137409891381649298835563011151796284848165977247286439820050405175697064122759870661294968492275655767983096727976056361878300352234381528837008128941375285251387 + q 89271282791461757245617785540129155142212959423277129581512553253419075634703 + g 293025651734044707050351995205142657657141955131408425452312245943331353163428637443799381119408990271553007202915223601376791534187122912295000993316207089139736477148501917083144416322685925261624358336253378688806309805096283386698409139605996997308008266491782991490291726095895573563845937760385377670846794792328581579165150512160132493375389995617711312966986681865792948443127326586291576561351005982500369077653940283008076332825908419690031303502192009860824429031526378047535596212801179578879818504990773143072529887215206211778546705082334239130823956177702608427222251531070457604183947814624087379251368161182770323100074409926426428526795865215674068539423364010352920515052672366811052717283396264950182005583498061313136436293898863077084485762289185337928869086731032780517039420605615746259170222257438835029958473402842467194409561307509136616954789698181252705567549441508247668319257495617674881793988 +#:factor 89271282791461757245617785540129155142212959423277129581512553253419075634703 +#:factor 85831054040144766435760746678768685031101307134949905606966042252247846736739 +#:factor 106974241938861083915762659525277908624697359844432666343676471334975764276049 +#:factor 74188558205228235051388929541366735789893711666871143431413381703129034070571 +#:factor 64157908398727096384500697645883202842334928055247546726538359334678953374533 +#:factor 91888021786522811643506031866522514605588426773858897142365239694153824388723 +#:factor 86202112980065410413258705060295663522206392211838714986438313175672540034679 +#:factor 101718718485667336124248700072690338405530751717394437871691123315096947983183 +#:factor 86666452227843804499517643692692014159268339780015078349842908985056208435853 +#:factor 107755126504421076829573915729759110231793946298489260169446357640494497518059 +#:factor 106001951238340530179427922980522671485637210826387486585015951056665476348869 +#:factor 102183593360154313236939029184315018977616435836107396944951781361526011480879 + +# --- catacomb-ll-384-7680 --- +# +# keyid = 5269085d +# seed = UmkIXe0NUh9EHPOO8u8wF8mhLQE= +# fingerprint = 79071929-98fc59d-90b7743e-c5c2b654-9bb79c2f + +group catacomb-ll-384-7680 + p 216559231449171871041190135626382624797124950735238103903411263023444445882521628396323446917201544947387362748232352479621010825720892522010264595137021526116731147020276163999389935515909942333859243831227670403913428432731504427389273023004939424753052775358161721558889434984752937404659922107755872908503276779890720154023419646466364753857461405783464469564625360217138090672724105361675896756808274354930058114085554600822147968649870032508764648998263671769796991884663568970203225077040350146289614179408735323764473153776149414398483161820946251418283039309221276673125231280207218356527486085198155052448482264858753938528034551335541575510835605019724293894867922725429018142837363943168309374088743910487619039647758175469460668571266467909654776838430687432194443218576000354284573578578313918222270250431668826898042163427173702446261012188950489694384130788197898956349943432660613123480611964086340909829616693038723512697569973817087806925553170590595578662024721424212829104524679861074838515062614572669868082762235959143570965134389478420007029121452023331460602894158087970348076496609174310151629106271427215947168306439928345126945165118709319486831988505313790613950433545275492703644799196726129007271379101141097250063655345163597099147393517021524375283410477077887674889864364373504345856902602031627659096612965600880097793678105801528551273968273016116586602655943987294387646704481664853571904789295943497201543689680443816576374462034616478062083674538453821741357423160686683957869164976227205380757021506255070600142017516211729170052461889059117212201165174680435195480761191462787291840078314124775690821420091760461597315155088442641783854597704388729214697745034805817520117506496545607796864049406793174516710815917428415700817370248228453077064519820749224220930454265603643316849024708084260878037824529368824330161019279087245044637182254878850971615729695143996520927935652887799292993748602455597137301552603377186175439256163850872771856775561289081476860168359000521640192117573827877302113899996287468260783657370603418752653187994927154468272901154316379212588059218864942163650290968975838491996852452140839172227541162524444316754170785930872965059072588210184084993896704348797801907146398460530513820150529386362374102968643080903455218783795163739396580563 + q 33126499307317576797871833023217004335728314922050873541842362900543256622519036793987373377351818708943025119171013 + g 96859294361547047642162231787698695293269170366381491039992704638487946870512955047635144422727688206850890592577601738386271033615655069759857614095318767501569475658225621379418176050399654722867097565799361229947796756782330159878485797280010527792372818398073347477883450716624241650342576251700830368197267161507895940250335059430229713885285808307538641824823453590259949699610056770268667527819173674245700546468626735701216914339359142650715456068873883323510582206093162545301581421872580614739960541059105320799303366751068487975658774037067271201124075671594347915071804828018801863090776942278748696864666275555399479604564578677796647983816263014540144519577131864786690922226752900095101570448042330169808811588582992274222974333043374060077106932770817928804830739464113061207244668378493315384242428432594357567083170258903374723309088233501818385465347016865045003737737429798873421728939731524368763227995005635265743181878570394577251864081145075962862658667595276249717296728684048617249986325764929873684993115348889870151843083280953797610712542442651569528403369291638278579344023829005801861314384307223035852089456550106858884145475380292972702972023699980804060437666725813022897101316874650121913713231347979141680903702045096621935190730276560295174524297300767314797689155407477601193107232938299830541221417725759368288595613473097104008577963940594171976537149511040148774289702490489315160512871522386217608881824304091006999472822494018964857391111674528315676869116824677355671824612095554583261258648450847127015033139359148253652027620146044628375304786435643476708542206375787159378427699020092463186472971399347599749181816424274424067915825882710114752513444732397713670497772986582958901510359579133132479016445445133604454907255125008080844594331635493230874836372234145675198053154029087315214747182882002718722228763467363382722967777319004806095376893995711476881150741027724250087088999020456989167082293444606242846362570237792721708356293491203816603574491100293039203889820292140596922368098350519693304511861932465759110608906269402554390780611082681465359527185555358515709411662470414648813606479086286524570875988991968332315775966514438221552899748093614170849525785168229994381907745855683962639488177828929551456219770877454135407893035439949325975780350 +#:factor 33126499307317576797871833023217004335728314922050873541842362900543256622519036793987373377351818708943025119171013 +#:factor 39355538213779465581327905402419970362362827155309917911796788256581129259700838386618633466328785307910060598484089 +#:factor 24990988056514685939227489925894893740599480412356885556635114159485308445876939770393364881549529860169928180358751 +#:factor 29710393998736802825004025579677917729092552502321819764111039726208854433428942095508492913578932136133436765710137 +#:factor 30739990822741028562742164007270587796692423847729505877569973917995737943042778723217469119645159801429991709987411 +#:factor 38467104071408925475553899301420008676544897864238119086844380566779548268491996551153519861871328607592273248640063 +#:factor 26249202441547885968346939762119297860863007366370739789532392353072352597721946778221716140197625626869457398407943 +#:factor 35113510884533077462576668870689443131037411172656549819745724383911555364605887073198680214468558440325573744139273 +#:factor 22799521027155572453510717469170377645186972219918245680012037643676230864376926993221681405925996643835629140041553 +#:factor 35237903572957790995889936270089932531166269466107290813994448142778414605138387309936585467385466822473088271031989 +#:factor 27428052831286394078655137717030752972732374814011687175621160166365055343004612251793080304507732432129056200291727 +#:factor 20653805003557030567582482355924457431196786739428479408853799555350943953733271029133593962324338862058432369521581 +#:factor 20826184829221859923080357759745090302065026449606341016497732724141145977802307612276509411486570418197846062995143 +#:factor 26186565771074398017481590713676896769947111595943534554546789381717976098676902111563130714755073678247235508588839 +#:factor 25062273677906610062620640227124848504281876654137470308684277968100792708156285085199790540571827305085913619650939 +#:factor 28620246516918127020366359691491908359742867622666550018522929993024502416569436771205673472786682579926850748107811 +#:factor 37856943506407240881326721106883344091018942980536189030625919515240362253893275735656123073145875668656864714642553 +#:factor 22067087486134964177557541373312161142485654981859077450341811542291069526079170766664489890765256439946132722899891 +#:factor 23098926790257626751285008739153477597734517594763012574497649607286859624287080618144594023194033634778511868647877 +#:factor 29874082012645596638985309976826212131328113612069017684649166404247820505933961130580996098120522635385267888074961 + +# --- catacomb-ll-512-15360 --- +# +# keyid = eb8239f8 +# seed = 64I5+NMQg5J7WZeXPpo7dsXLiAs= +# fingerprint = c9addb82-dd632399-3dc1de81-40bf1c07-8ca10f5f + +group catacomb-ll-512-15360 + p 267737496760767722068079882470300794033605836807622482067410964171393411520919176256914869964612479175351332823409449521645606004586415623871847948375817498161847543702485018137658512658395575254789459353699345744602369381934625059696198589413369531883820496222659510755499199435844896264025524352060302680951373940575374076136832975200291005032514098640691398905405952695332479714616633295008654736506041813997134163987333741695846413097366684661344684616003601739167823328153896592432168889551779922529269033348086812310042261625165919052730860791202842844956446296689792441147970214424901342118997798159010536443797638756041327664696059380444566468860999953138675880647585649322318597258428498912095373426547986582540102395757192981849426353427220562438871461011279156327503538285028350335365137967747204548916792891345433172565689300894798309981237564346356082832141951952353587270953547648554401212070076679138112680602893278933373210074307452631417834131238872904464712762382727721405307974548332455937227001307804713345124421010621912271858653169426612004330651882144263970965845286327430353225544353979151213153918381850147302137013870443565447267408929820734324527586605299075224612369180273167439366180804630758969753426630886643792237194705165542753979443278245006454216061793688914453452033873682552924255069369382991399006219888447629091144761962816311838278453426744318329244891747907726689490072483441687762777514940810025483492250932938902924371182177616985098416863622505393245791898509271049937545780547703178646787153221220148776603371623990916784487761937997154509142207118563842540149656720890488789518041789234252783231203642923485126118874925205605743388337049290048102619379144553450612454492744292824661671019548713713568495220254740410669480812494122553523238166010275744321977341774600646768663036548131650974040647199495585196626323527740836162430085342052052727637724463434046775500298250476314587684591403987781101547180153540252142742428325763088665202774890061858211471865412555929191623058633649510807447665649697908545538433271811034260583364231115893882106660460362988412359863944207083315791203817813275002751650497247445133621959259165882426036642183903263726738720790482023621515505915532731458799675555130983697925269194130788271555917528320139537585237789448433361057472038619150612530155365282694361060208517945072413778375766282508764808188838406430261098030072276397680381934641479775177012533402001805227189560517281847643477431969193260714721511089510106902236389858739200666246366584470443084819740458839115330024642751710950508392249199171525940200641812690856715538273687610654143705053231753228288281925749573248819830807718047751291456635357252049651851428004843642993442708365926756086784864901619631645046021861362898457472437142021009316121209673296032419273205690055243737394068612057117222448137828274568145532165778912543711623225896980785464025683101674037519994362712933363700839222229325067956938417486554365785132752607665421070796369679950679278370647133471481601224482043380412158088958751348091674065435762606782309017939064656880665108380755999804750464216396676060064634049102602879726529064753147592949810279608808566906092860843406668537037778792512924649747927350781700804454803517161392276648064085521072720776995493746790698252658256127300427299712765912635964190588872362794322452414626926829451697570056145597909237733397993006318713907266282999209757835954408527578538863449022305050578740139814278853085620493082736691092281414370903171187358162080568284465302364244005694005210033241390491480461570699307912480038911233821105644446152512328525805707483171601688919032664561976430006629718308661207667153016502452884195148963125673969191706827403727809879672157011607257925720399770233625156155404482591336975116607711326594730647784392952199755924399936290034962258677008541859799419880022170446493041811273344503041707889648677394173861246482375736320283850849220544488123549088485079584855817373424359266678858651199243166073560382077730099987468377705636637242565948949985751205620857554830109239961545967537041510571588045286127240744618124771659845616409968497542978672000492769104999131872897737410994487787465125717465733543538344980281077012185860886320520255782307357238375948751409954873680258342250057671086544607706855079362474966284884466968233383764211808745671425930931575698296989086335739534025778159969392356967742191929914522690322438276604838230279525053780117636662663017876019549874233270026169569062088907790243918806941605480559016625665402398248013040463246716327424411605332836931485156524858341673845209004633198457099 + q 10571951456907669779892620647342646690819262609396359690524502534177633120229168340667942575812279188027386527234551758107216468763903236115143427787743501 + g 128598894907195188417229808251635947329739807715046258519185506584473330204570377688022234101083503575628247088869022751684161661116289139941422707052770784716284088672813457818076409289020116060576402861848262767893027233018967673188177319672220467630868456703363498829958429433052255385200803148036151824908127072135772477213206484282052574102804738136991255543544214210006836913841655431369354618035834267490750490209475650037611036969604510775085809840648347935149597993597050657382149424122551607765060905481452516927446598515527477247171478999535528834297030357374539135945862618225434749983777290822601640168801388457093291990583760394365529485898194260738109655976435021259260994433703250576566622543068851481307975157566559105117105696734982421364733215553702481282493676675415951561410801018648748202526310066348347675957920894052908634114299749835690825285958913309859395516637946391466247723186108045362984213928977339986546180336619120165000686737182828914686039307870836014970214762767616169050313307016785283407848979763838796901889533929991249262241241357085858440003100578599589303213283823231174826022087580289633445725655404503623057795603361275581688344479184031083934546255260431689248986625244613768138643274300512818504921212079442823382330541009102805040432664579664706843475903526712081265964789883073385412340566450530204050902742402634241295067292054198743776821135490852456571373786221834566840691504860631528594003016940806795952907191256706618335919348660172917691296581810487025804834121410117485699086165420315964836248122689453219355409068053887775439819365185836341867035959423656535221657069676936301160422526984733243805036094607065902991385803575050051402498313584896099087939918378394590246964040554542516556529955127714323667109459918696040305338316628605973670322139489914621903381403168134305230387553206034949296665589019458435333656497975595505186840554679289490725712215379119708936656398805481443817609780446044759428279250269061044353577054755809478942400511447476504959503019924384501854940670343756700595741830432409860516378561836547983052719529231317929703619794317736666240984610506873930809661048521360303804091987776920298335472932445807825891843426486417538296088228895526448505937443508396033850769937257926518277775854316505029339507246170910597358345642816471561799639718384521695469006324992746905242127842686811730217295508863843618253667094515294426385046337302700840651870607339402514793220932482394311605909804968180513732290422195401488734272875219573971965851758260974945420620612963750578280530090049561109078297429042230921153112538935821627493853510065306244811588574295137834903557863723543417221594934011392570967713979066781470665113263579679078346927299350593423807794432345965954214411279192997560913500420482135209761870894770590428753377060355446520714577823849327411455211803153798853005451969647921330963739815383804967938950844708859220970746343764387380686978388124365668599015606571832777646186264005031394838487124138566127931419400765659300590631175744824203747372760896426041038824093171455170878742081716134501047540584551546098074082811645710233649110893608312835114875022232159365133137870471783950558791394747886849817239478618258433146217414467845273035067690658728958244690182678308246002614307639728716544214919926387449699076757255860035522872191741413862595318802625699582434142963070125555096411118677017567085204173949296857347553686296332447084040218420742023614270285859547357310153777066869597179554114216347704995773693933927290606278271631839500986041846119745101489053876898923820486679517034985529967206488771012442386273647914758788794352696546007225147463040960836917540476556158171204978341050270842436674153236983839541594662370682859252061101201529771658391958638069866925173982823135401442054529882771497178435812973944610940759337374490667655762675502138898683030596178493879840530527200986100162672072577140966652435656059897085134772326082774218777784721364471952331014224241827859689552691557210912017591834455185827870287610792949837996937421382409243563221525985357912277040622211893182331275112628740300448802121194783069108322399073099060064264166221152635853834406853391568903009131371873111346754163371271208724745835028574196362705248110621990890004232459546556494832519339269358637289654972986665902221815201810894863582325166306449650465453223955176919686048223394344108072515484536428726902347665256053780647893633252440024422896973060032376625419596170725316577542832012274755089837231069989343909974684844834831911679673118788567527167638795212119760473587068197787346864147296908951760670987133395 +#:factor 10571951456907669779892620647342646690819262609396359690524502534177633120229168340667942575812279188027386527234551758107216468763903236115143427787743501 +#:factor 9012440645643314246834973626922261248430582884321541587438489180023988737512032104254581442848613136311423618140795155753411152808972231131191495364696113 +#:factor 11664407479888990184202139277551028676651013424643181979060212470678705307128063234525963058666093887020686441365922823734852909082402446828730382752979229 +#:factor 9087876611156307298284101521955646383324933273215705601366986444355710006473522774817841755272381080750837076062838195845188516807677339637355892566997161 +#:factor 7850875653648084112022472229380028253695299668265516016947697170686003077850514907765524197019907612330445487029463301633628025237963893050671557196181037 +#:factor 9811668747595937862696556986818901047696541620978343479470960055182987731849807766456487932153408355304918692734270804755894967739728440775732045253975867 +#:factor 6850528828310882434413759447618080765577150578105428774266564959349750426580886713871673166366380181300391220234049862529092166014652885149727426581950889 +#:factor 6821638102376526854453397172384749542254164092866952888824098621712040405559147454526516007481215285840029382069182522430838260284493396455708010177523951 +#:factor 9678671090017306504471193471606002503207329774194080688795341865275315066168913972420992866933767238945244749299859823721414058505077146271463652017042439 +#:factor 11393931156044806890317196442201195583808258792085050704419049073069764825659064050709401048990965128349659629815212528487569661791997378607235211682046767 +#:factor 9017010040179947675396805634091838536572796142622751259821087175550548949037522734269840576513891007984351108919567391192649737362028379518075599077332061 +#:factor 8471151817163912127252174076707115691748601873337141861143247343372659043906393812132481208054508793108003038614600545971718635646265794386795278691754067 +#:factor 13197493938382376428309109637837242582358905975783852842417135134626200360303237020546312789639222633029539785097700295596040150049781404432593082545583687 +#:factor 8575974070132361564362415034026161716899096825228901868850832979622821929082521380113628505749265007300639809003377137159593961387754096563405572654530453 +#:factor 10685309091824418682668636366538457951831463604934567645475353414106697701363236027779367582469465499678424648685247868794321185827903765405464064983847047 +#:factor 7832579167103862778682606390694147440819353518240318233355101493037014682039100415001767021498559727856779744520541030712369584582339760294936511514528613 +#:factor 11443136038500921044854720404653372565248054144656073888671297768218410197327711069816877279851418893039887799451033119855767890079711768713385653679344477 +#:factor 11688409215583921110956357044321797822832780718093563289058981511879157867538826225803418406379935887495839460956831051786990678735417867002006878510530001 +#:factor 8269373232168928931276034385529570570419130675409379232099124396037402056853784630410470739109999093193671624909979089535332341276117302614326085797220209 +#:factor 9186395703395988275207810642702730047142932136743815395858445937000755684133671310159954341948067614705752787518132853542049279332346920436340054839993081 +#:factor 6795425485592182949378541037739159131046423659599522629955532628051588695375698396588579193598504741404656736703919260744390720003440892800061391975968543 +#:factor 10396118888753141861444655191592919753341123585411878553552147287212817173935858961195926696707128865851883589958560492545922923504442555855283863684690883 +#:factor 9200414943820306382018413241324240995480578531923453792659897506893121059804164387167396258851931504929883516095987516319887977740512884087194394964391023 +#:factor 12530634260640146540037552613265173527563597551474945252217132553909981324169848692185513076985582524700624840690045385961239986165286808674599194021249909 +#:factor 11777196311833624813129143516165715650218942159782423895657055945748378658698548936802659687190537166673298770529607439929019151210938035218664232208577273 +#:factor 7348262210091125168844276092746402631926760996426639974638799774896265368458530624040379440531440039323922186709965290812433008147988187233036235954446539 +#:factor 7495895476596043082228459599736776072884975040533651752897223545444099013720437774241963953093854938504409948988231217421899198126781802901186687835439671 +#:factor 7552446094981741253426497231778914956993354256770700433779133501020398264257537810327407638749096379083785811976115762275583243733103646262540268854635459 +#:factor 11876032185719044257059947481606348236079583968867505900797840767914468036111126560459281957584518925180041310466390015937147792402479266081314053413722009 +#:factor 9583540052593144013269177059658457027998433819569867982260511279574493019496581755069425156501941108339618548765191994601041609651011729970172839875903479 + +#----- That's all, folks ---------------------------------------------------- diff --git a/math/qdparse.c b/math/qdparse.c new file mode 100644 index 0000000..217cc62 --- /dev/null +++ b/math/qdparse.c @@ -0,0 +1,141 @@ +/* -*-c-*- + * + * Quick-and-dirty parser + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include "qdparse.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @qd_skipspc@ --- * + * + * Arguments: @qd_parse *qd@ = context + * + * Returns: --- + * + * Use: Skips spaces in the string. No errors. + */ + +void qd_skipspc(qd_parse *qd) +{ + while (isspace((unsigned char)*qd->p)) + qd->p++; +} + +/* --- @qd_delim@ --- * + * + * Arguments: @qd_parse *qd@ = context + * @int ch@ = character to compare with + * + * Returns: Nonzero if it was, zero if it wasn't. + * + * Use: Checks the next (non-whitespace) character is what we + * expect. If it is, the character is eaten; otherwise it's no + * big deal. + */ + +int qd_delim(qd_parse *qd, int ch) +{ + qd_skipspc(qd); + if (*qd->p != ch) + return (0); + qd->p++; + return (1); +} + +/* --- @qd_enum@ --- * + * + * Arguments: @qd_parse *qd@ = context + * @const char *e@ = list of enum strings, space separated + * + * Returns: Index of the string matched, or @-1@. + * + * Use: Matches a keyword. + */ + +int qd_enum(qd_parse *qd, const char *e) +{ + size_t n; + int i = 0; + + qd_skipspc(qd); + for (;;) { + e += strspn(e, ", "); + if (!*e) break; + n = strcspn(e, ", "); + if (strncmp(qd->p, e, n) == 0 && !isalnum((unsigned char)qd->p[n])) { + qd->p += n; + return (i); + } + i++; e += n; + } + qd->e = "unrecognized keyword"; + return (-1); +} + +/* --- @qd_getmp@ --- * + * + * Arguments: @qd_parse *qd@ = context + * + * Returns: The integer extracted, or null. + * + * Use: Parses a multiprecision integer from a string. + */ + +mp *qd_getmp(qd_parse *qd) +{ + char *q; + mp *m; + + qd_skipspc(qd); + m = mp_readstring(MP_NEW, qd->p, &q, 0); + if (m && !isalnum((unsigned char)*q)) + qd->p = q; + else { + mp_drop(m); + qd->e = "bad number"; + } + return (m); +} + +/* --- @qd_eofp@ --- * + * + * Arguments: @qd_parse *qd@ = context + * + * Returns: Nonzero if at EOF, zero otherwise. + */ + +int qd_eofp(qd_parse *qd) +{ + qd_skipspc(qd); + return (!*qd->p); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/qdparse.h b/math/qdparse.h new file mode 100644 index 0000000..9e56b6b --- /dev/null +++ b/math/qdparse.h @@ -0,0 +1,113 @@ +/* -*-c-*- + * + * Quick-and-dirty parser + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_QDPARSE_H +#define CATACOMB_QDPARSE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct qd_parse { + const char *p; /* Where we are right now */ + const char *e; /* Error string (output) */ +} qd_parse; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @qd_skipspc@ --- * + * + * Arguments: @qd_parse *qd@ = context + * + * Returns: --- + * + * Use: Skips spaces in the string. No errors. + */ + +extern void qd_skipspc(qd_parse */*qd*/); + +/* --- @qd_delim@ --- * + * + * Arguments: @qd_parse *qd@ = context + * @int ch@ = character to compare with + * + * Returns: Nonzero if it was, zero if it wasn't. + * + * Use: Checks the next (non-whitespace) character is what we + * expect. If it is, the character is eaten; otherwise it's no + * big deal. + */ + +extern int qd_delim(qd_parse */*qd*/, int /*ch*/); + +/* --- @qd_enum@ --- * + * + * Arguments: @qd_parse *qd@ = context + * @const char *e@ = list of enum strings, space separated + * + * Returns: Index of the string matched, or @-1@. + * + * Use: Matches a keyword. + */ + +extern int qd_enum(qd_parse */*qd*/, const char */*e*/); + +/* --- @qd_getmp@ --- * + * + * Arguments: @qd_parse *qd@ = context + * + * Returns: The integer extracted, or null. + * + * Use: Parses a multiprecision integer from a string. + */ + +extern mp *qd_getmp(qd_parse */*qd*/); + +/* --- @qd_eofp@ --- * + * + * Arguments: @qd_parse *qd@ = context + * + * Returns: Nonzero if at EOF, zero otherwise. + */ + +extern int qd_eofp(qd_parse */*qd*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/rabin.c b/math/rabin.c new file mode 100644 index 0000000..b543eef --- /dev/null +++ b/math/rabin.c @@ -0,0 +1,197 @@ +/* -*-c-*- + * + * Miller-Rabin primality test + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpbarrett.h" +#include "mpmont.h" +#include "pgen.h" +#include "rabin.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rabin_create@ --- * + * + * Arguments: @rabin *r@ = pointer to Rabin-Miller context + * @mp *m@ = pointer to number to test + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Precomputes some useful values for performing the + * Miller-Rabin probabilistic primality test. + */ + +int rabin_create(rabin *r, mp *m) +{ + mp *m1 = mp_sub(MP_NEW, m, MP_ONE); + if (mpmont_create(&r->mm, m)) { + MP_DROP(m1); + return (-1); + } + r->r = mp_odd(MP_NEW, m1, &r->s); + r->m1 = mp_sub(MP_NEW, m, r->mm.r); + mp_drop(m1); + return (0); +} + +/* --- @rabin_destroy@ --- * + * + * Arguments: @rabin *r@ = pointer to Rabin-Miller context + * + * Returns: --- + * + * Use: Disposes of a Rabin-Miller context when it's no longer + * needed. + */ + +void rabin_destroy(rabin *r) +{ + mp_drop(r->r); + mp_drop(r->m1); + mpmont_destroy(&r->mm); +} + +/* --- @rabin_test@, @rabin_rtest@ --- * + * + * Arguments: @rabin *r@ = pointer to Rabin-Miller context + * @mp *g@ = base to test the number against + * + * Returns: Either @PGEN_FAIL@ if the test failed, or @PGEN_PASS@ + * if it succeeded. + * + * Use: Performs a single iteration of the Rabin-Miller primality + * test. The @rtest@ variant assumes that %$g$% is either + * already in Montgomery representation, or you don't care. + */ + +int rabin_rtest(rabin *r, mp *g) +{ + mp *y; + mp *dd, *spare = MP_NEW; + size_t j; + int rc = PGEN_FAIL; + + /* --- Calculate %$y R = g^r R \bmod m$% --- * + * + * If %$y = 1$% or %$y = m - 1$% then %$m$% is prime. If course, note that + * @y@ here has an extra factor of %$R$%. + */ + + y = mpmont_expr(&r->mm, MP_NEW, g, r->r); + if (MP_EQ(y, r->mm.r) || MP_EQ(y, r->m1)) { + rc = PGEN_PASS; + goto done; + } + + /* --- Now for the main loop --- * + * + * If %$y^{2^j} \ne m - 1$% for any %$0 \le j < s$% then %$m$% is + * composite. Of course, %$j = 0$% has already been tested. + */ + + for (j = 1; j < r->s; j++) { + dd = mp_sqr(spare, y); + dd = mpmont_reduce(&r->mm, dd, dd); + spare = y; y = dd; + if (MP_EQ(y, r->mm.r)) + break; + if (MP_EQ(y, r->m1)) { + rc = PGEN_PASS; + break; + } + } + + /* --- Done --- */ + +done: + if (spare != MP_NEW) + MP_DROP(spare); + MP_DROP(y); + return (rc); +} + +int rabin_test(rabin *r, mp *g) +{ + int rc; + g = mpmont_mul(&r->mm, MP_NEW, g, r->mm.r2); + rc = rabin_rtest(r, g); + mp_drop(g); + return (rc); +} + +/* --- @rabin_iters@ --- * + * + * Arguments: @unsigned len@ = number of bits in value + * + * Returns: Number of iterations recommended. + * + * Use: Returns the recommended number of iterations to ensure that a + * number with @len@ bits is really prime. + */ + +int rabin_iters(unsigned len) +{ + static const struct { + unsigned b; + int i; + } *p, *q, tab[] = { + { 100, 27 }, + { 150, 18 }, + { 200, 15 }, + { 250, 12 }, + { 300, 9 }, + { 350, 8 }, + { 400, 7 }, + { 450, 6 }, + { 550, 5 }, + { 650, 4 }, + { 850, 3 }, + { 1300, 2 } + }; + + unsigned i; + + /* --- Binary search through the table --- */ + + p = tab; + q = tab + (sizeof(tab)/sizeof(tab[0])); + for (;;) { + i = (q - p) / 2; + if (!i) + break; + if (len >= p[i].b && len < p[i + 1].b) + break; + if (len > p[i].b) + p = p + i; + else + q = p + i; + } + return (p[i].i); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/rabin.h b/math/rabin.h new file mode 100644 index 0000000..c3eec72 --- /dev/null +++ b/math/rabin.h @@ -0,0 +1,119 @@ +/* -*-c-*- + * + * Miller-Rabin primality test + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_RABIN_H +#define CATACOMB_RABIN_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_MPMONT_H +# include "mpmont.h" +#endif + +#ifndef CATACOMB_PFILT_H +# include "pfilt.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct rabin { + mpmont mm; /* Montgomery arithmetic context */ + size_t s; /* %$m = 2^s r + 1$% */ + mp *r; /* %$m = 2^s r + 1$% */ + mp *m1; /* %$(m - 1)R \bmod m$% */ +} rabin; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @rabin_create@ --- * + * + * Arguments: @rabin *r@ = pointer to Rabin-Miller context + * @mp *m@ = pointer to number to test + * + * Returns: Zero on success, nonzero for failure. + * + * Use: Precomputes some useful values for performing the + * Miller-Rabin probabilistic primality test. + */ + +extern int rabin_create(rabin */*r*/, mp */*m*/); + +/* --- @rabin_destroy@ --- * + * + * Arguments: @rabin *r@ = pointer to Rabin-Miller context + * + * Returns: --- + * + * Use: Disposes of a Rabin-Miller context when it's no longer + * needed. + */ + +extern void rabin_destroy(rabin */*r*/); + +/* --- @rabin_test@, @rabin_rtest@ --- * + * + * Arguments: @rabin *r@ = pointer to Rabin-Miller context + * @mp *g@ = base to test the number against + * + * Returns: Either @PGEN_FAIL@ if the test failed, or @PGEN_PASS@ + * if it succeeded. + * + * Use: Performs a single iteration of the Rabin-Miller primality + * test. The @rtest@ variant assumes that %$g$% is either + * already in Montgomery representation, or you don't care. + */ + +extern int rabin_rtest(rabin */*r*/, mp */*g*/); +extern int rabin_test(rabin */*r*/, mp */*g*/); + +/* --- @rabin_iters@ --- * + * + * Arguments: @unsigned len@ = number of bits in value + * + * Returns: Number of iterations recommended. + * + * Use: Returns the recommended number of iterations to ensure that a + * number with @len@ bits is really prime. + */ + +extern int rabin_iters(unsigned /*len*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/rho.c b/math/rho.c new file mode 100644 index 0000000..fc5076b --- /dev/null +++ b/math/rho.c @@ -0,0 +1,298 @@ +/* -*-c-*- + * + * Pollard's rho algorithm for discrete logs + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "fibrand.h" +#include "mp.h" +#include "mpmont.h" +#include "mprand.h" +#include "rho.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rho@ --- * + * + * Arguments: @rho_ctx *cc@ = pointer to the context structure + * @void *x, *y@ = two (equal) base values (try 1) + * @mp *a, *b@ = logs of %$x$% (see below) + * + * Returns: The discrete logarithm %$\log_g a$%, or null if the algorithm + * failed. (This is unlikely, though possible.) + * + * Use: Uses Pollard's rho algorithm to compute discrete logs in the + * group %$G$% generated by %$g$%. + * + * The algorithm works by finding a cycle in a pseudo-random + * walk. The function @ops->split@ should return an element + * from %$\{\,0, 1, 2\,\}$% according to its argument, in order + * to determine the walk. At each step in the walk, we know a + * group element %$x \in G$% together with its representation as + * a product of powers of %$g$% and $%a$% (i.e., we know that + * %$x = g^\alpha a^\beta$% for some %$\alpha$%, %$\beta$%). + * + * Locating a cycle gives us a collision + * + * %$g^{\alpha} a^{\beta} = g^{\alpha'} a^{\beta'}$% + * + * Taking logs of both sides (to base %$g$%) gives us that + * + * %$\log a\equiv\frac{\alpha-\alpha'}{\beta'-\beta}\bmod{n}$% + * + * Good initial values are %$x = y = 1$% (the multiplicative + * identity of %$G$%) and %$\alpha\equiv\beta\equiv0\bmod{n}$%. + * If that doesn't work then start choosing more `interesting' + * values. + * + * Note that the algorithm requires minimal space but + * %$O(\sqrt{n})$% time. Don't do this on large groups, + * particularly if you can find a decent factor base. + * + * Finally, note that this function will free the input values + * when it's finished with them. This probably isn't a great + * problem. + */ + +static void step(rho_ctx *cc, void *x, mp **a, mp **b) +{ + switch (cc->ops->split(x)) { + case 0: + cc->ops->mul(x, cc->g, cc->c); + *a = mp_add(*a, *a, MP_ONE); + if (MP_CMP(*a, >=, cc->n)) + *a = mp_sub(*a, *a, cc->n); + break; + case 1: + cc->ops->sqr(x, cc->c); + *a = mp_lsl(*a, *a, 1); + if (MP_CMP(*a, >=, cc->n)) + *a = mp_sub(*a, *a, cc->n); + *b = mp_lsl(*b, *b, 1); + if (MP_CMP(*b, >=, cc->n)) + *b = mp_sub(*b, *b, cc->n); + break; + case 2: + cc->ops->mul(x, cc->a, cc->c); + *b = mp_add(*b, *b, MP_ONE); + if (MP_CMP(*b, >=, cc->n)) + *b = mp_sub(*b, *b, cc->n); + break; + } +} + +mp *rho(rho_ctx *cc, void *x, void *y, mp *a, mp *b) +{ + mp *aa = MP_COPY(a), *bb = MP_COPY(b); + mp *g; + + /* --- Grind through the random walk until we find a collision --- */ + + do { + step(cc, x, &a, &b); + step(cc, y, &aa, &bb); + step(cc, y, &aa, &bb); + } while (!cc->ops->eq(x, y)); + cc->ops->drop(x); + cc->ops->drop(y); + + /* --- Now sort out the mess --- */ + + aa = mp_sub(aa, a, aa); + bb = mp_sub(bb, bb, b); + g = MP_NEW; + mp_gcd(&g, &bb, 0, bb, cc->n); + if (!MP_EQ(g, MP_ONE)) { + mp_drop(aa); + aa = 0; + } else { + aa = mp_mul(aa, aa, bb); + mp_div(0, &aa, aa, cc->n); + } + + /* --- Done --- */ + + mp_drop(bb); + mp_drop(g); + mp_drop(a); + mp_drop(b); + return (aa); +} + +/* --- @rho_prime@ --- * + * + * Arguments: @mp *g@ = generator for the group + * @mp *a@ = value to find the logarithm of + * @mp *n@ = order of the group + * @mp *p@ = prime size of the underlying prime field + * + * Returns: The discrete logarithm %$\log_g a$%. + * + * Use: Computes discrete logarithms in a subgroup of a prime field. + */ + +static void prime_sqr(void *x, void *c) +{ + mp **p = x; + mp *a = *p; + a = mp_sqr(a, a); + a = mpmont_reduce(c, a, a); + *p = a; +} + +static void prime_mul(void *x, void *y, void *c) +{ + mp **p = x; + mp *a = *p; + a = mpmont_mul(c, a, a, y); + *p = a; +} + +static int prime_eq(void *x, void *y) +{ + return (MP_EQ(*(mp **)x, *(mp **)y)); +} + +static int prime_split(void *x) +{ + /* --- Notes on the splitting function --- * + * + * The objective is to produce a simple pseudorandom mapping from the + * underlying field \gf{p} to \{\,0, 1, 2\,\}$%. This is further + * constrained by the fact that we must not have %$1 \mapsto 1$% (since + * otherwise the stepping function above will loop). + * + * The function we choose is very simple: we take the least significant + * word from the integer, add one (to prevent the %$1 \mapsto 1$% property + * described above) and reduce modulo 3. This is slightly biased against + * the result 2, but this doesn't appear to be relevant. + */ + + return (((*(mp **)x)->v[0] + 1) % 3); +} + +static void prime_drop(void *x) +{ + MP_DROP(*(mp **)x); +} + +static const rho_ops prime_ops = { + prime_sqr, prime_mul, prime_eq, prime_split, prime_drop +}; + +mp *rho_prime(mp *g, mp *a, mp *n, mp *p) +{ + rho_ctx cc; + grand *r = 0; + mpmont mm; + mp *x, *y; + mp *aa, *bb; + mp *l; + + /* --- Initialization --- */ + + mpmont_create(&mm, p); + cc.ops = &prime_ops; + cc.c = &mm; + cc.n = n; + cc.g = mpmont_mul(&mm, MP_NEW, g, mm.r2); + cc.a = mpmont_mul(&mm, MP_NEW, a, mm.r2); + x = MP_COPY(mm.r); + y = MP_COPY(x); + aa = bb = MP_ZERO; + + /* --- The main loop --- */ + + while ((l = rho(&cc, &x, &y, aa, bb)) == 0) { + mp_expfactor f[2]; + + if (!r) + r = fibrand_create(0); + aa = mprand_range(MP_NEW, n, r, 0); + bb = mprand_range(MP_NEW, n, r, 0); + f[0].base = cc.g; f[0].exp = aa; + f[1].base = cc.a; f[1].exp = bb; + x = mpmont_mexpr(&mm, MP_NEW, f, 2); + y = MP_COPY(x); + } + + /* --- Throw everything away now --- */ + + if (r) + r->ops->destroy(r); + mp_drop(cc.g); + mp_drop(cc.a); + mpmont_destroy(&mm); + return (l); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +#include "dh.h" + +int main(void) +{ + dh_param dp; + mp *x, *y; + grand *r = fibrand_create(0); + mpmont mm; + mp *l; + int ok; + + fputs("rho: ", stdout); + fflush(stdout); + + dh_gen(&dp, 32, 256, 0, r, pgen_evspin, 0); + x = mprand_range(MP_NEW, dp.q, r, 0); + mpmont_create(&mm, dp.p); + y = mpmont_exp(&mm, MP_NEW, dp.g, x); + mpmont_destroy(&mm); + l = rho_prime(dp.g, y, dp.q, dp.p); + if (MP_EQ(x, l)) { + fputs(". ok\n", stdout); + ok = 1; + } else { + fputs("\n*** rho (discrete logs) failed\n", stdout); + ok = 0; + } + + mp_drop(l); + mp_drop(x); + mp_drop(y); + r->ops->destroy(r); + dh_paramfree(&dp); + assert(mparena_count(MPARENA_GLOBAL) == 0); + + return (ok ? 0 : EXIT_FAILURE); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/rho.h b/math/rho.h new file mode 100644 index 0000000..0817fe8 --- /dev/null +++ b/math/rho.h @@ -0,0 +1,129 @@ +/* -*-c-*- + * + * Pollard's rho algorithm for discrete logs + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_RHO_H +#define CATACOMB_RHO_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- The group operations table --- */ + +typedef struct rho_ops { + void (*sqr)(void *x, void *c); + void (*mul)(void *x, void *y, void *c); + int (*eq)(void *x, void *y); + int (*split)(void *x); + void (*drop)(void *x); +} rho_ops; + +/* --- The Pollard's rho context structure --- */ + +typedef struct rho_ctx { + const rho_ops *ops; /* Group operations table */ + void *c; /* Context for group operations */ + void *g, *a; /* Generator and argument for log */ + mp *n; /* Cyclic group order */ +} rho_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @rho@ --- * + * + * Arguments: @rho_ctx *cc@ = pointer to the context structure + * @void *x, *y@ = two (equal) base values (try 1) + * @mp *a, *b@ = logs of %$x$% (see below) + * + * Returns: The discrete logarithm %$\log_g a$%, or null if the algorithm + * failed. (This is unlikely, though possible.) + * + * Use: Uses Pollard's rho algorithm to compute discrete logs in the + * group %$G$% generated by %$g$%. + * + * The algorithm works by finding a cycle in a pseudo-random + * walk. The function @ops->split@ should return an element + * from %$\{\,0, 1, 2\,\}$% according to its argument, in order + * to determine the walk. At each step in the walk, we know a + * group element %$x \in G$% together with its representation as + * a product of powers of %$g$% and $%a$% (i.e., we know that + * %$x = g^\alpha a^\beta$% for some %$\alpha$%, %$\beta$%). + * + * Locating a cycle gives us a collision + * + * %$g^{\alpha} a^{\beta} = g^{\alpha'} a^{\beta'}$% + * + * Taking logs of both sides (to base %$g$%) gives us that + * + * %$\log a\equiv\frac{\alpha-\alpha'}{\beta'-\beta}\bmod{n}$% + * + * Good initial values are %$x = y = 1$% (the multiplicative + * identity of %$G$%) and %$\alpha\equiv\beta\equiv0\bmod{n}$%. + * If that doesn't work then start choosing more `interesting' + * values. + * + * Note that the algorithm requires minimal space but + * %$O(\sqrt{n})$% time. Don't do this on large groups, + * particularly if you can find a decent factor base. + * + * Finally, note that this function will free the input values + * when it's finished with them. This probably isn't a great + * problem. + */ + +extern mp *rho(rho_ctx */*cc*/, void */*x*/, void */*y*/, + mp */*a*/, mp */*b*/); + +/* --- @rho_prime@ --- * + * + * Arguments: @mp *g@ = generator for the group + * @mp *a@ = value to find the logarithm of + * @mp *n@ = order of the group + * @mp *p@ = prime size of the underlying prime field + * + * Returns: The discrete logarithm %$\log_g a$%. + * + * Use: Computes discrete logarithms in a subgroup of a prime field. + */ + +extern mp *rho_prime(mp */*g*/, mp */*a*/, mp */*n*/, mp */*p*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/strongprime.c b/math/strongprime.c new file mode 100644 index 0000000..6acac17 --- /dev/null +++ b/math/strongprime.c @@ -0,0 +1,203 @@ +/* -*-c-*- + * + * Generate `strong' prime numbers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "grand.h" +#include "mp.h" +#include "mpmont.h" +#include "mprand.h" +#include "pgen.h" +#include "pfilt.h" +#include "rabin.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @strongprime_setup@ --- * + * + * Arguments: @const char *name@ = pointer to name root + * @mp *d@ = destination for search start point + * @pfilt *f@ = where to store filter jump context + * @unsigned nbits@ = number of bits wanted + * @grand *r@ = random number source + * @unsigned n@ = number of attempts to make + * @pgen_proc *event@ = event handler function + * @void *ectx@ = argument for the event handler + * + * Returns: A starting point for a `strong' prime search, or zero. + * + * Use: Sets up for a strong prime search, so that primes with + * particular properties can be found. It's probably important + * to note that the number left in the filter context @f@ is + * congruent to 2 (mod 4). + */ + +mp *strongprime_setup(const char *name, mp *d, pfilt *f, unsigned nbits, + grand *r, unsigned n, pgen_proc *event, void *ectx) +{ + mp *s, *t, *q; + dstr dn = DSTR_INIT; + + mp *rr = d; + pgen_filterctx c; + pgen_jumpctx j; + rabin rb; + + /* --- The bitslop parameter --- * + * + * There's quite a lot of prime searching to be done. The constant + * @BITSLOP@ is a (low) approximation to the base-2 log of the expected + * number of steps to find a prime number. Experimentation shows that + * numbers around 10 seem to be good. + */ + +#define BITSLOP 12 + + /* --- Choose two primes %$s$% and %$t$% of half the required size --- */ + + assert(((void)"nbits too small in strongprime_setup", nbits/2 > BITSLOP)); + nbits = nbits/2 - BITSLOP; + c.step = 1; + + rr = mprand(rr, nbits, r, 1); + DRESET(&dn); dstr_putf(&dn, "%s [s]", name); + if ((s = pgen(dn.buf, MP_NEWSEC, rr, event, ectx, n, pgen_filter, &c, + rabin_iters(nbits), pgen_test, &rb)) == 0) + goto fail_s; + + rr = mprand(rr, nbits, r, 1); + DRESET(&dn); dstr_putf(&dn, "%s [t]", name); + if ((t = pgen(dn.buf, MP_NEWSEC, rr, event, ectx, n, pgen_filter, &c, + rabin_iters(nbits), pgen_test, &rb)) == 0) + goto fail_t; + + /* --- Choose a suitable value for %$r = 2it + 1$% for some %$i$% --- */ + + rr = mp_lsl(rr, t, 1); + pfilt_create(&c.f, rr); + rr = mp_lsl(rr, rr, BITSLOP - 1); + rr = mp_add(rr, rr, MP_ONE); + DRESET(&dn); dstr_putf(&dn, "%s [r]", name); + j.j = &c.f; + nbits += BITSLOP; + q = pgen(dn.buf, MP_NEW, rr, event, ectx, n, pgen_jump, &j, + rabin_iters(nbits), pgen_test, &rb); + pfilt_destroy(&c.f); + if (!q) + goto fail_r; + + /* --- Select a suitable starting-point for finding %$p$% --- * + * + * This computes %$p_0 = 2(s^{r - 2} \bmod r)s - 1$%. + */ + + { + mpmont mm; + + mpmont_create(&mm, q); + rr = mp_sub(rr, q, MP_TWO); + rr = mpmont_exp(&mm, rr, s, rr); + mpmont_destroy(&mm); + rr = mp_mul(rr, rr, s); + rr = mp_lsl(rr, rr, 1); + rr = mp_sub(rr, rr, MP_ONE); + } + + /* --- Now find %$p = p_0 + 2jrs$% for some %$j$% --- */ + + { + mp *x; + x = mp_mul(MP_NEW, q, s); + x = mp_lsl(x, x, 1); + pfilt_create(f, x); + x = mp_lsl(x, x, BITSLOP - 1); + rr = mp_add(rr, rr, x); + mp_drop(x); + } + + /* --- Return the result --- */ + + mp_drop(q); + mp_drop(t); + mp_drop(s); + dstr_destroy(&dn); + return (rr); + + /* --- Tidy up if something failed --- */ + +fail_r: + mp_drop(t); +fail_t: + mp_drop(s); +fail_s: + mp_drop(rr); + dstr_destroy(&dn); + return (0); + +#undef BITSLOP +} + +/* --- @strongprime@ --- * + * + * Arguments: @const char *name@ = pointer to name root + * @mp *d@ = destination integer + * @unsigned nbits@ = number of bits wanted + * @grand *r@ = random number source + * @unsigned n@ = number of attempts to make + * @pgen_proc *event@ = event handler function + * @void *ectx@ = argument for the event handler + * + * Returns: A `strong' prime, or zero. + * + * Use: Finds `strong' primes. A strong prime %$p$% is such that + * + * * %$p - 1$% has a large prime factor %$r$%, + * * %$p + 1$% has a large prime factor %$s$%, and + * * %$r - 1$% has a large prime factor %$t$%. + * + * The numbers produced may be slightly larger than requested, + * by a few bits. + */ + +mp *strongprime(const char *name, mp *d, unsigned nbits, grand *r, + unsigned n, pgen_proc *event, void *ectx) +{ + pfilt f; + pgen_jumpctx j; + rabin rb; + + d = strongprime_setup(name, d, &f, nbits, r, n, event, ectx); + j.j = &f; + d = pgen(name, d, d, event, ectx, n, pgen_jump, &j, + rabin_iters(nbits), pgen_test, &rb); + pfilt_destroy(&f); + return (d); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/math/strongprime.h b/math/strongprime.h new file mode 100644 index 0000000..6f39f50 --- /dev/null +++ b/math/strongprime.h @@ -0,0 +1,103 @@ +/* -*-c-*- + * + * Generate `strong' prime numbers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_STRONGPRIME_H +#define CATACOMB_STRONGPRIME_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_PGEN_H +# include "pgen.h" +#endif + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @strongprime_setup@ --- * + * + * Arguments: @const char *name@ = pointer to name root + * @mp *d@ = destination for search start point + * @pfilt *f@ = where to store filter jump context + * @unsigned nbits@ = number of bits wanted + * @grand *r@ = random number source + * @unsigned n@ = number of attempts to make + * @pgen_proc *event@ = event handler function + * @void *ectx@ = argument for the event handler + * + * Returns: A starting point for a `strong' prime search, or zero. + * + * Use: Sets up for a strong prime search, so that primes with + * particular properties can be found. It's probably important + * to note that the number left in the filter context @f@ is + * congruent to 2 (mod 4). + */ + +extern mp *strongprime_setup(const char */*name*/, mp */*d*/, pfilt */*f*/, + unsigned /*nbits*/, grand */*r*/, + unsigned /*n*/, pgen_proc */*event*/, + void */*ectx*/); + +/* --- @strongprime@ --- * + * + * Arguments: @const char *name@ = pointer to name root + * @mp *d@ = destination integer + * @unsigned nbits@ = number of bits wanted + * @grand *r@ = random number source + * @unsigned n@ = number of attempts to make + * @pgen_proc *event@ = event handler function + * @void *ectx@ = argument for the event handler + * + * Returns: A `strong' prime, or zero. + * + * Use: Finds `strong' primes. A strong prime %$p$% is such that + * + * * %$p - 1$% has a large prime factor %$r$%, + * * %$p + 1$% has a large prime factor %$s$%, and + * * %$r - 1$% has a large prime factor %$t$%. + * + * The numbers produced may be slightly larger than requested, + * by a few bits. + */ + +extern mp *strongprime(const char */*name*/, mp */*d*/, unsigned /*nbits*/, + grand */*r*/, unsigned /*n*/, + pgen_proc */*event*/, void */*ectx*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/math/t/ec b/math/t/ec new file mode 100644 index 0000000..92fb26a --- /dev/null +++ b/math/t/ec @@ -0,0 +1,451 @@ +# Elliptic curve tests + +check { + "prime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 0; + "prime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810" + -1; + "prime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee" + 0; + "prime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411, + 0xdccf19d3e76abfa05d529c07575f54c94fa5fc9f3decc246" + 0; + "prime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 0; + "prime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810" + -1; + "prime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee" + 0; + + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 0; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810" + -1; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee" + 0; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411, + 0xdccf19d3e76abfa05d529c07575f54c94fa5fc9f3decc246" + 0; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 0; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810" + -1; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee" + 0; + + "binpoly: 0x800000000000000000000000000000000000000c9 + bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1" + 0; + "binpoly: 0x800000000000000000000000000000000000000c9 + bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f0" + -1; + "binpoly: 0x800000000000000000000000000000000000000c9 + bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + 0; + "binpoly: 0x800000000000000000000000000000000000000c9 + binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1" + 0; + "binpoly: 0x800000000000000000000000000000000000000c9 + binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f0" + -1; + "binpoly: 0x800000000000000000000000000000000000000c9 + binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + 0; + "binpoly: 0x800000000000000000000000000000000000000c9 + binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0591168d4994637e8343e36, + 0x7fa8423c5ae194b56cdf21998ad8a721ef1201b8c" + 0; +} + +find { + "prime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012 + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"; + "prime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1011 inf; + "prime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + 0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411 + "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411, + 0x2330e62c1895405fa2ad63f8a8a0ab35b05a0360c2133db9"; + + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012 + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1011 inf; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + 0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411 + "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411, + 0x2330e62c1895405fa2ad63f8a8a0ab35b05a0360c2133db9"; + + "binpoly: 0x800000000000000000000000000000000000000c9 + bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + 0x3f0eba16286a2d57ea0991168d4994637e8343e36 + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7"; + "binpoly: 0x800000000000000000000000000000000000000c9 + bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + 0x310eba16386a2d57ea0591168d4997637e8745e36 inf; + "binpoly: 0x800000000000000000000000000000000000000c9 + bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + 0x3f0eba16286a2d57ea0591168d4994637e8343e36 + "0x3f0eba16286a2d57ea0591168d4994637e8343e36, + 0x7fa8423c5ae194b56cdf21998ad8a721ef1201b8c"; +} + +neg { + "prime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; + "prime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; + + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; + + "binpoly: 0x800000000000000000000000000000000000000c9 + bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1"; + "binpoly: 0x800000000000000000000000000000000000000c9 + binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1"; +} + +dbl { + "prime: 23 prime: 1, 1" "4, 0" inf; + "prime: 23 primeproj: 1, 1" "4, 0" inf; + + "prime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; + "prime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; + + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; + + "binpoly: 0x800000000000000000000000000000000000000c9 + bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4, + 0x49ed3be7f510e30e2462c517ad39038e493fc573c"; + "binpoly: 0x800000000000000000000000000000000000000c9 + binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4, + 0x49ed3be7f510e30e2462c517ad39038e493fc573c"; + + "binpoly: 0x020000000000000000000000000000200000000000000001 + bin: 0, 0x1ee9" + "0x18, 0xd" + "0x1bd555555555555555555555555554e8000000000000158, + 0x14e999999999999999999999999998d7000000000001fe6"; +} + +add { + "prime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" + "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, + 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"; + "prime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" + "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, + 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"; + + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" + "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, + 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" + "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, + 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"; + + "binpoly: 0x800000000000000000000000000000000000000c9 + bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4, + 0x49ed3be7f510e30e2462c517ad39038e493fc573c" + "0x634000577f86aa315009d6f9b906691f6edd691fe, + 0x235a3db7a94446301e666cafea5e12cb331f4a140"; + "binpoly: 0x800000000000000000000000000000000000000c9 + binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4, + 0x49ed3be7f510e30e2462c517ad39038e493fc573c" + "0x634000577f86aa315009d6f9b906691f6edd691fe, + 0x235a3db7a94446301e666cafea5e12cb331f4a140"; +} + +sub { + "prime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, + 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; + "prime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, + 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; + + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, + 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, + 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; + + "binpoly: 0x800000000000000000000000000000000000000c9 + bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x634000577f86aa315009d6f9b906691f6edd691fe, + 0x235a3db7a94446301e666cafea5e12cb331f4a140" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4, + 0x49ed3be7f510e30e2462c517ad39038e493fc573c"; + "binpoly: 0x800000000000000000000000000000000000000c9 + binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x634000577f86aa315009d6f9b906691f6edd691fe, + 0x235a3db7a94446301e666cafea5e12cb331f4a140" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4, + 0x49ed3be7f510e30e2462c517ad39038e493fc573c"; +} + +mul { + "prime: 23 prime: 1, 1" "0, 1" 28 inf; + "prime: 23 prime: 1, 1" "0, 1" 29 "0, 1"; + "prime: 23 primeproj: 1, 1" "0, 1" 28 inf; + "prime: 23 primeproj: 1, 1" "0, 1" 29 "0, 1"; + + "prime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 6277101735386680763835789423176059013767194773182842284080 + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; + "prime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 6277101735386680763835789423176059013767194773182842284081 + inf; + "prime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 6277101735386680763835789423176059013767194773182842284080 + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; + "prime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 6277101735386680763835789423176059013767194773182842284081 + inf; + + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 6277101735386680763835789423176059013767194773182842284080 + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 6277101735386680763835789423176059013767194773182842284081 + inf; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 6277101735386680763835789423176059013767194773182842284080 + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; + "niceprime: 6277101735386680763835789423207666416083908700390324961279 + primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 6277101735386680763835789423176059013767194773182842284081 + inf; + + "binpoly: 0x800000000000000000000000000000000000000c9 + bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + 5846006549323611672814742442876390689256843201586 + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0xd51fbc6c71a0094fa2cdd545b11c5c0c797324f1"; + "binpoly: 0x800000000000000000000000000000000000000c9 + bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + 5846006549323611672814742442876390689256843201587 + inf; + "binpoly: 0x800000000000000000000000000000000000000c9 + binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + 5846006549323611672814742442876390689256843201586 + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0xd51fbc6c71a0094fa2cdd545b11c5c0c797324f1"; + "binpoly: 0x800000000000000000000000000000000000000c9 + binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" + "0x3f0eba16286a2d57ea0991168d4994637e8343e36, + 0x325f41d0ef702dc310254c42d65851a3b91471ac7" + 5846006549323611672814742442876390689256843201587 + inf; + + "binpoly: 0x800000000000000000000000000000000000000c9; bin: 1, 1" + "0x2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8, + 0x289070fb05d38ff58321f2e800536d538ccdaa3d9" + 5846006549323611672814741753598448348329118574063 + inf; + "binpoly: 0x800000000000000000000000000000000000000c9; binproj: 1, 1" + "0x2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8, + 0x289070fb05d38ff58321f2e800536d538ccdaa3d9" + 5846006549323611672814741753598448348329118574063 + inf; +} diff --git a/math/t/gf b/math/t/gf new file mode 100644 index 0000000..0ed1c49 --- /dev/null +++ b/math/t/gf @@ -0,0 +1,89 @@ +# Test cases for higher-level binary poly arithmetic. + +add { + 0 0 0; + 1 1 0; + 1 2 3; + 4 5 1; + 0x7fb838a8a0a95046b9d9d9fb4440f7bb + 0xc1a7bd3b4e853fc92d4e1588719986aa + 0xbe1f8593ee2c6f8f9497cc7335d97111; + 0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b21 + 0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b22 3; +} + +mul { + 0 0 0; + 1 0 0; + 0 1 0; + 1 1 1; + 0x7fb838a8a0a95046b9d9d9fb4440f7bb + 0xc1a7bd3b4e853fc92d4e1588719986aa + 0x207ccad257b4ed64447158315bfb9aca5cbc5622cfb8fcbb1380eea1bc5c624e; + 0xc1a7bd3b4e853fc92d4e1588719986aa + 0x283ed59f1226dcefa7ff0ef87ceff5d5 + 0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b22; + 0xbe1f8593ee2c6f8f9497cc7335d97111 + 0x35a8e33503b3695be00528f8b82db931 + 0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b21; +} + +sqr { + 0 0; + 1 1; + 3 5; + 0x7fb838a8a0a95046b9d9d9fb4440f7bb + 0x1555454005404440440044411100101445415141514155451010100055154545; + 0x01f081e69f45d3254530766ab98d55fa612c7bb27ea31bc2621d894be9c0b196b3 + 0x0155004001541441551011510504111011050015141444454140511111554414010450154545041554440501455004140401514041104554415000450141144505; +} + +div { + 0 1 0 0; + 0x207ccad257b4ed64447158315bfb9aca5cbc5622cfb8fcbb1380eea1bc5c624e + 0x7fb838a8a0a95046b9d9d9fb4440f7bb + 0xc1a7bd3b4e853fc92d4e1588719986aa 0; + 0x6e0e2a282a5411ae76767ed1103deef069ef4ed3a14ff24b + 0x5385621c6661aaa35a24150d2c08332e + 0x01c2334cc957151dc7 + 0x398c4111da6d06cdf3d83704ee403101; +} + +exp { + 4 0 1; + 4 1 4; + 0x7 2 0x15; + 3 563 0xf000f000f000f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000f000f000f; +} + +irred { + 0 0; + 1 0; + 2 1; + 0xc1a7bd3b4e853fc92d4e1588719986aa 0; + 0x800000000000000000000000000000000000000c9 1; + 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001 1; +} + +gcd { + 0xc1a7bd3b4e853fc92d4e1588719986aa + 0xbe1f8593ee2c6f8f9497cc7335d97111 + 3 + 0x283ed59f1226dcefa7ff0ef87ceff5d5 + 0x35a8e33503b3695be00528f8b82db931; + 0xbe1f8593ee2c6f8f9497cc7335d97111 + 0xc1a7bd3b4e853fc92d4e1588719986aa + 3 + 0x35a8e33503b3695be00528f8b82db931 + 0x283ed59f1226dcefa7ff0ef87ceff5d5; + 0x800000000000000000000000000000000000000c9 + 4 + 1 + 1 + 0x20000000000000000000000000000000000000032; + 0x800000000000000000000000000000000000000c9 + 0x3f0eba16286a2d57ea0991168d4994637e8343e36 + 1 + 0xa17e704470d80cb5a78f295db0ce543dda16a169 + 0x3c8c172e24598e90b9542e6b8f6571f54be572b50; +} diff --git a/math/t/gfn b/math/t/gfn new file mode 100644 index 0000000..f7720e1 --- /dev/null +++ b/math/t/gfn @@ -0,0 +1,32 @@ +# Normal basis conversions + +gfn { + 0x800000000000000000000000000000000000000c9 + 0x715169c109c612e390d347c748342bcd3b02a0bef + 0 0; + + 0x800000000000000000000000000000000000000c9 + 0x715169c109c612e390d347c748342bcd3b02a0bef + 1 + 0x7ffffffffffffffffffffffffffffffffffffffff; + + 0x800000000000000000000000000000000000000c9 + 0x715169c109c612e390d347c748342bcd3b02a0bef + 0x2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8 + 0x05679b353caa46825fea2d3713ba450da0c2a4541; + + 0x20000000000000000000000000000000000000004000000000000000001 + 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9 + 0x066647ede6c332c7f8c0923bb58213b333b20e9ce4281fe115f7d8f90ad + 0x1a003e0962d4f9a8e407c904a9538163adb825212600c7752ad52233279; + + 0x20000000000000000000000000000000000000004000000000000000001 + 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9 + 0x0fac9dfcbac8313bb2139f1bb755fef65bc391f8b36f8f8eb7371fd558b + 0x18b863524b3cdfefb94f2784e0b116faac54404bc9162a363bab84a14c5; + + 0x20000000000000000000000000000000000000004000000000000000001 + 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9 + 0x1006a08a41903350678e58528bebf8a0beff867a7ca36716f7e01f81052 + 0x04925df77bd8b8ff1a5ff519417822bfedf2bbd752644292c98c7af6e02; +} diff --git a/math/t/gfreduce b/math/t/gfreduce new file mode 100644 index 0000000..f712316 --- /dev/null +++ b/math/t/gfreduce @@ -0,0 +1,79 @@ +# Test efficient polynomial reduction + +reduce { + 0x10000000 + 0x4509823098098435 + 0x8098435; + 0x100000000000000050002 + 0x4509823098098435 + 0x4509823098098435; + 0x100000000000000050002 + 0x450982309809843545609843098560803495 + 0x144f98a2f5cbc4773cfd; + 0xb2ca471b0867d5fae2e4f27a2d2706da + 0xf254423fef93d5d7a76ecf22c656c1352c53257875945d33 + 0x582f783fc210f72814780e69b0bd29ff; +} + +modexp { + 0x20000000000000000000000000000000000000000000000000000000000001001 + 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + 0 + 1; + 0x20000000000000000000000000000000000000000000000000000000000001001 + 0x02 + 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + 1; + 0x20000000000000000000000000000000000000000000000000000000000001001 + 0x435932098459080438094509845 + 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + 1; + 0x10000000000000000000000000000000000000000003 + 0x02 + 0x0fffffffffffffffffffffffffffffffffffffffffff + 1; + 0x10000000000000000000000000000000000000000003 + 0x34235950984598345900983409845690805680985 + 0x0fffffffffffffffffffffffffffffffffffffffffff + 1; + + 0x800000000000000000000000000000000000000c9 + 0x3f0eba16286a2d57ea0991168d4994637e8343e36 + -1 + 0x3c8c172e24598e90b9542e6b8f6571f54be572b50; + 0x800000000000000000000000000000000000000c9 + 0x3c8c172e24598e90b9542e6b8f6571f54be572b50 + 342345 + 0x3521fe2666efe92ca4eb160a286e0fd9427b84a62; + 0x800000000000000000000000000000000000000c9 + 0x3f0eba16286a2d57ea0991168d4994637e8343e36 + -342345 + 0x3521fe2666efe92ca4eb160a286e0fd9427b84a62; +} + +sqrt { + 0x20000000000000000000000000000000000000000000000000000000000001001 + 0x1f081e69f45d3254530766ab98d55fa612c7bb27ea31bc2621d894be9c0b196b3 + 0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa; + 0x10000000000000000000000000000000000000000003 + 0x4594094509835690805698083560980459903450984 + 0x820291881a244a02840a2f8ece3f23f88f38bf0b3a; +} + +halftrace { + 0x20000000000000000000000000000000000000000000000000000000000001001 + 0x174e65c7d14a8ec286df8c7df17662f13f1d3563f13c8c63f23f5d0bd5d1b45cd + 0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9d; +} + +quadsolve { + 0x20000000000000000000000000000000000000000000000000000000000001001 + 0x174e65c7d14a8ec286df8c7df17662f13f1d3563f13c8c63f23f5d0bd5d1b45cd + 0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c; + 0x10000000000000000000000000000000000000000003 + 0x3b818b447e90713da04f13c3b07cb5e2681d08e4700 + 0x27aa17c97dfa80bbdef9f91b243c6e6ddba1a223cac; + 0x800000000000000000000000000000000000000c9 + 0x158fe327cc763a2fd7371ee80641ed1871a32aaa8 + 0x29ab0d7da05ffc3f1b3f97ac10e2092694aadbb7c; +} diff --git a/math/t/gfx b/math/t/gfx new file mode 100644 index 0000000..c0a873a --- /dev/null +++ b/math/t/gfx @@ -0,0 +1,527 @@ +# Test vectors for low-level GF functions + +# --- Addition (and subtraction) --- + +add { + # --- Simple sanity tests --- + + 01 01 00; + 02 02 00; + 03 01 02; + + # --- Random data tests --- + + 7fb838a8a0a95046b9d9d9fb4440f7bb + c1a7bd3b4e853fc92d4e1588719986aa + be1f8593ee2c6f8f9497cc7335d97111; + 8d68905434b020ccb849e17a03a5c441 + d2a104aaf523699c1cc7a93174d21d9c + 5fc994fec1934950a48e484b7777d9dd; + 027aa17c97dfa80bbdef9f91b243c6e6 + ddba1a223cad8a39e9c986879ad21b75 + dfc0bb5eab722232542619162891dd93; + d668328b2594570198fd840b4783f5d9 + f474e9ef071c418acf1f71b9cccdd179 + 221cdb642288168b57e2f5b28b4e24a0; + 509e024b27fb8b3655da3938d0c04f92 + 3fa219832f73843c0ae8c4f4715f633c + 6f3c1bc808880f0a5f32fdcca19f2cae; + 13e8b9d83c66bc5fa56e2debbab3c9c2 + 6bb190b76e090abd7f6375a6921ad17e + 7859296f526fb6e2da0d584d28a918bc; + 3c98c1fd7d6e4ff9adae43a38ed0f2b3 + 101f88d732a51bbe40080cabd06002 + 3c88de75aa5ceae213ee4baf250092b1; + 2774d74b7453e63c2d314e0be52eaf79 + 54c0dc1a0bedbafcb0b707fe5e496a20 + 73b40b517fbe5cc09d8649f5bb67c559; + 75b9d1662c48f8c40ee4e9b3138a0b59 + 0ca3e9d4c75a6e2b493d7efb8554e9f8 + 791a38b2eb1296ef47d9974896dee2a1; + 501591c68468a7d8ecfcae3f419ecb52 + b0ad24cd246361f779e8317e94977c57 + e0b8b50ba00bc62f95149f41d509b705; + 6fa69209a292924f04fb5b3469a1068b + d9a06e9ac90f02ad095ff84f30a9addd + b606fc936b9d90e20da4a37b5908ab56; + ce596f2830ab988dfa7dc0add68214af + 860c30b9a27c7b2759666dd71ec578c3 + 48555f9192d7e3aaa31bad7ac8476c6c; + 862361325b5f7a6b506b948d55697ce3 + 95142973169fbae5410a22bb88ca63ee + 133748414dc0c08e1161b636dda31f0d; + 237495a82a6755689df073af2a56f88c + ab46613ddf7787fd1be42272fcb1be44 + 8832f495f510d295861451ddd6e746c8; + 6b2d8d2b513277cfb03d8a5731234a3d + 9cc41fbd7189a3b5b0ff2f3746eb9bc6 + f7e9929620bbd47a00c2a56077c8d1fb; + af7baf1a8ce5d42eca4353de181d085a + c59bde6136dda59a839605252d1dd390 + 6ae0717bba3871b449d556fb3500dbca; + 566a7c0f9adc5a021c1759e2c80708c0 + 28d1c20f2b8613b5e1ba8e3005aef30f + 7ebbbe00b15a49b7fdadd7d2cda9fbcf; + a7d716d198bf6bb3d32ba364f722de52 + 4c9a1fa66d2d0cf7935d45e83b9ce326 + eb4d0977f59267444076e68cccbe3d74; + 310d8bb131c4bed327529185c4d46db8 + 2742ea95019b5f186c3c848744743d4a + 164f6124305fe1cb4b6e150280a050f2; + 70f5bfbf5f18a3deef4230b875b3a0af + 93c9240145720297b96a404941792a21 + e33c9bbe1a6aa149562870f134ca8a8e; + 1ff7c9eaebd3b76791632b609a962992 + bc3aca2e99d965238d8433eafd717279 + a3cd03c4720ad2441ce7188a67e75beb; + 3d1693836d0964dea42c5e80a4307b6c + aed5dcd2e9e918e0ff9577f5ceb66256 + 93c34f5184e07c3e5bb929756a86193a; + 35706029aec609b55c48ab09df59744e + 6d9b5b4dbeb1779580cba9bbc9fb8921 + 58eb3b6410777e20dc8302b216a2fd6f; + 7a166f842cc6c36c09508e2b23dbad97 + 01e3fc1cacc040e96217a7281a4273d2 + 7bf59398800683856b4729033999de45; + 510ce80a4ab0f9eae5f6c3281e7506c5 + 06351138a1ecb6be56a84f1b28a26368 + 5739f932eb5c4f54b35e8c3336d765ad; + 31bfc6590de44898c40c31bb3aaddebc + 82b37993094c9ff6498c55ba1cced0f8 + b30cbfca04a8d76e8d80640126630e44; + d00d48a90eb9e89586cc3566b28fa5ea + 0f502f973c2f17ad79543b20a92f2905 + df5d673e3296ff38ff980e461ba08cef; + df63dead9d7aea0d3fca68123b0812ae + ae059fd909978bc6b8824b04e113fa2a + 7166417494ed61cb87482316da1be884; + 4c982bd2b93a027fd08ad69227a51506 + bdc1112c061be0756685473011c61067 + f1593afebf21e20ab60f91a236630561; + dc241c84816a1a50a7ad21519e6abd3a + f2c4d8d96bf32d999fdc7c37cfddac67 + 2ee0c45dea9937c938715d6651b7115d; + a466ee3984566e4947a28704ecd99d2f + 0a5e90153ae473c9bee43aafaec08446 + ae387e2cbeb21d80f946bdab42191969; + 8698e5d4eede21f8d4791d69fc4cfb22 + 7b4bb531b633dfcb80d9bd35e10d4f6b + fdd350e558edfe3354a0a05c1d41b449; + 4d2462e835a51ee5be30ea2bc6abbb1b + fb36217f8dd0fe234bb7dcb778130156 + b6124397b875e0c6f587369cbeb8ba4d; + abf5c76c26bf952d64667f5049bbe6b5 + 436fbd0ad52336b0c9d2987ac79d2909 + e89a7a66f39ca39dadb4e72a8e26cfbc; + 8943b34ab9bc6f6839c09a9852492238 + 38b2304265ac16c80f84be3d61a82628 + b1f18308dc1079a0364424a533e10410; + ae2730b3374140b33de67be248766cc7 + 1831ce84d756a4bda1c1ee22ed047d61 + b616fe37e017e40e9c2795c0a57211a6; + 4a87ef0f6bc691cab6d79253876ca89e + c0c2f4c479ffc90aeafe0598a4ac4d4b + 8a451bcb123958c05c2997cb23c0e5d5; + 63b2aad38a2d3b4cf681d892ed460110 + d707531874bbc8fa22a49fd26142c631 + b4b5f9cbfe96f3b6d42547408c04c721; + f44ef4d8cd19e4f6f6264c59360de94e + eb619a0c5fb3c490d382ff4a5d47a0f9 + 1f2f6ed492aa206625a4b3136b4a49b7; + 786fa5572011847269ba3f51db1226 + a1c8ac92fa365013326e0daac2dce7b9 + a1b0c337ad1641974007b7959307f59f; +} + +mul { + # --- Simple sanity tests --- + + 00 05 00; + 01 05 05; + 05 01 05; + 05 00 00; + + # --- Random data tests --- + + 7fb838a8a0a95046b9d9d9fb4440f7bb + c1a7bd3b4e853fc92d4e1588719986aa + 207ccad257b4ed64447158315bfb9aca5cbc5622cfb8fcbb1380eea1bc5c624e; + 8d68905434b020ccb849e17a03a5c441 + d2a104aaf523699c1cc7a93174d21d9c + 6c75a24ff82d63e8f9425d862be997fd7517511b2563189a6f0a238b33e60a9c; + 027aa17c97dfa80bbdef9f91b243c6e6 + ddba1a223cad8a39e9c986879ad21b75 + 019d5567c392730cf1fbc627f1de7ff20438e649e5ba7e7299fcea4ad4c7ac5e; + d668328b2594570198fd840b4783f5d9 + f474e9ef071c418acf1f71b9cccdd179 + 4a7d1a3b7b904b1b135cb89e6f37a38d7f20fcc9bd7b9ec9f0c38114d2a742e1; + 509e024b27fb8b3655da3938d0c04f92 + 3fa219832f73843c0ae8c4f4715f633c + 0c0ff0782f813600eda5b73c0d2deaf072ed8b9e98e94991bd2578b776063fb8; + 13e8b9d83c66bc5fa56e2debbab3c9c2 + 6bb190b76e090abd7f6375a6921ad17e + 0626e9a14f2ada51ad47ae2385248d361142636fed5f062be9fa0a0567f14c7c; + 3c98c1fd7d6e4ff9adae43a38ed0f2b3 + 101f88d732a51bbe40080cabd06002 + 03cb092534c593a9f834c21f1af0da8e604c416ec14e3fca1a72ba4c2b4566; + 2774d74b7453e63c2d314e0be52eaf79 + 54c0dc1a0bedbafcb0b707fe5e496a20 + 0b2dd510554c5442d5871586392f81d08322aa0cf052f64ee507d59ef730b520; + 75b9d1662c48f8c40ee4e9b3138a0b59 + 0ca3e9d4c75a6e2b493d7efb8554e9f8 + 024ff62a8d33d8c51560088e304cc9b13ccec97899ba476083b86f8c1dc28fb8; + 501591c68468a7d8ecfcae3f419ecb52 + b0ad24cd246361f779e8317e94977c57 + 2728b02f09e5cfc78d1b5e45d0b65d58aa353e8e5a928dc80a3fd523b464291e; + 6fa69209a292924f04fb5b3469a1068b + d9a06e9ac90f02ad095ff84f30a9addd + 29e8250c13db619580291b6d03317cf82d3f97c58aa1dc247c4d4ad25870b80f; + ce596f2830ab988dfa7dc0add68214af + 860c30b9a27c7b2759666dd71ec578c3 + 658c3e0257c6986e4d0b7fd1c2296182f48c395f7a01acdb623702a83c0be9b1; + 862361325b5f7a6b506b948d55697ce3 + 95142973169fbae5410a22bb88ca63ee + 49e7469f9f53f214425455d15b9b5cc6309617f18db3e02b98aabe1b134dbd72; + 237495a82a6755689df073af2a56f88c + ab46613ddf7787fd1be42272fcb1be44 + 14a2fbfb8b9621a60325ba6fc7c979b0caa46c7a5ffb865d01859f058621c930; + 6b2d8d2b513277cfb03d8a5731234a3d + 9cc41fbd7189a3b5b0ff2f3746eb9bc6 + 31ff31cfbb97615558ec4becb92036b6b8715ab6df7ed6dc18caff6e0641d24e; + af7baf1a8ce5d42eca4353de181d085a + c59bde6136dda59a839605252d1dd390 + 7e281956a0ae84282a4a600a9a434bcca6f89a9a661f03ac47dcd20ef2b066a0; + 566a7c0f9adc5a021c1759e2c80708c0 + 28d1c20f2b8613b5e1ba8e3005aef30f + 0845bd0d5a46401395876a7992ee9762842ea8d7202222e29b973a042a703c40; + a7d716d198bf6bb3d32ba364f722de52 + 4c9a1fa66d2d0cf7935d45e83b9ce326 + 2e09cac5254876c45a7dacddd71f13b394ca8ab95413ab681f554c50737839ac; + 310d8bb131c4bed327529185c4d46db8 + 2742ea95019b5f186c3c848744743d4a + 06baa3a8c8864b5ea1f998b6138db08924f3a49ddf1ecc22fa93110323aac0b0; + 70f5bfbf5f18a3deef4230b875b3a0af + 93c9240145720297b96a404941792a21 + 3fc325d1e5c637ab818172e3fdb51be97a28903ee232125797ead652b391734f; + 1ff7c9eaebd3b76791632b609a962992 + bc3aca2e99d965238d8433eafd717279 + 0d78c92f0d674c76fd9e71ace29b1ca58da8a67530a148bcf8815b395de46ee2; + 3d1693836d0964dea42c5e80a4307b6c + aed5dcd2e9e918e0ff9577f5ceb66256 + 185d9d9d173a78a2ea8a86cef12ac9a560f5c1fd96a3e40d47f2d34798d02ea8; + 35706029aec609b55c48ab09df59744e + 6d9b5b4dbeb1779580cba9bbc9fb8921 + 0aa132382fb96e788f85a52888a8ef7fa645e17dfaaf35444566c2a56584c38e; + 7a166f842cc6c36c09508e2b23dbad97 + 01e3fc1cacc040e96217a7281a4273d2 + 567d64a30f28d71578a9ced5624a950fe065d706cf3318c80c3883f126c51e; + 510ce80a4ab0f9eae5f6c3281e7506c5 + 06351138a1ecb6be56a84f1b28a26368 + 01e80b50adeebb3790d5249eb4170d093b88ab1d42d0737d3dad6825e181f0c8; + 31bfc6590de44898c40c31bb3aaddebc + 82b37993094c9ff6498c55ba1cced0f8 + 18a13563df977554b9d470e4c5009f7ec1c62f561a9cb2041a51e7af81e2f8a0; + d00d48a90eb9e89586cc3566b28fa5ea + 0f502f973c2f17ad79543b20a92f2905 + 048955ee72a928a69b16cc80502568ece68198c8947935283c725a2e6f00c842; + df63dead9d7aea0d3fca68123b0812ae + ae059fd909978bc6b8824b04e113fa2a + 706606ae02e140bbf3783da276f47110834defb48e89270797e86251e27369ec; + 4c982bd2b93a027fd08ad69227a51506 + bdc1112c061be0756685473011c61067 + 283989fcc502efa3d0006b67465f3ebe7950cac8d54daf45215e09bd6058ea52; + dc241c84816a1a50a7ad21519e6abd3a + f2c4d8d96bf32d999fdc7c37cfddac67 + 4ebfbaf107e1e74583f1a0c6de06f2a4c230c1a96329d8bac1d95d122ce8a266; + a466ee3984566e4947a28704ecd99d2f + 0a5e90153ae473c9bee43aafaec08446 + 044e0764b72ad37e86d87cca3b32c4d6797a7a9b2e8ab414e0c33617d2113922; + 8698e5d4eede21f8d4791d69fc4cfb22 + 7b4bb531b633dfcb80d9bd35e10d4f6b + 3c8785b738a800087fb26dc2562ebd676188a1f5e3b60d51463172a5ef5906b6; + 4d2462e835a51ee5be30ea2bc6abbb1b + fb36217f8dd0fe234bb7dcb778130156 + 3a1f7deaeed3275707c611b83b64b4514d9b8508ed4b0827a7001be9488af62a; + abf5c76c26bf952d64667f5049bbe6b5 + 436fbd0ad52336b0c9d2987ac79d2909 + 2b38ad58100db6e6bffc52c6e7622581cc5daf65c0b4f7b87dab8313af786e1d; + 8943b34ab9bc6f6839c09a9852492238 + 38b2304265ac16c80f84be3d61a82628 + 1daa464b09e5db4bef2c404c1be1fb6d6e0c5911ee10a1d7eba409e33b26c6c0; + ae2730b3374140b33de67be248766cc7 + 1831ce84d756a4bda1c1ee22ed047d61 + 0f8cb866e66f56fdfd530784d441c8b37d6e0b2a87e3ea6a0a2d6f4387e076e7; + 4a87ef0f6bc691cab6d79253876ca89e + c0c2f4c479ffc90aeafe0598a4ac4d4b + 37d54041b0e7d641ee3495897524f1ef4a4dad9671261e4aa03fba0bfadb0cd2; + 63b2aad38a2d3b4cf681d892ed460110 + d707531874bbc8fa22a49fd26142c631 + 2e25fc4f13fd3839c0698ca373d24ca2bfe572ad3ae46a50c1294237d30c5210; + f44ef4d8cd19e4f6f6264c59360de94e + eb619a0c5fb3c490d382ff4a5d47a0f9 + 5f20a07a81d4ed9f3d1fd9fef61318d01a58ea810b12ae3976dbe6c2406b2a9e; + 786fa5572011847269ba3f51db1226 + a1c8ac92fa365013326e0daac2dce7b9 + 336397c17a1fde4e90cbb9113a5fcd48239d39fee0807e66f8622d97b144b6; +} + +sqr { + # --- Simple sanity tests --- + + 00 00; + 01 01; + 03 05; + + # --- Random data tests --- + + 7fb838a8a0a95046b9d9d9fb4440f7bb + 1555454005404440440044411100101445415141514155451010100055154545; + c1a7bd3b4e853fc92d4e1588719986aa + 5001441545510545105440110555504104511054011140401501414140144444; + 8d68905434b020ccb849e17a03a5c441 + 4051144041001110051045000400505045401041540115440005441150101001; + d2a104aaf523699c1cc7a93174d21d9c + 5104440100104444551104051441415001505015444105011510510401514150; + 027aa17c97dfa80bbdef9f91b243c6e6 + 04154444011550411551554440004545515455415541014504100550145414; + ddba1a223cad8a39e9c986879ad21b75 + 5151454401440404055044514044054154415041401440154144510401451511; + d668328b2594570198fd840b4783f5d9 + 5114144005044045041141101115000141405551401000451015400555115141; + f474e9ef071c418acf1f71b9cccdd179 + 5510151054415455001501501001404450550155150145415050505151011541; + 509e024b27fb8b3655da3938d0c04f92 + 1100415400041045041555454045051411115144054105405100500010554104; + 3fa219832f73843c0ae8c4f4715f633c + 0555440401414005045515054010055000445440501055101501115514050550; + 13e8b9d83c66bc5fa56e2debbab3c9c2 + 0105544045415140055014144550115544111454045154454544450550415004; + 6bb190b76e090abd7f6375a6921ad17e + 1445450141004515145400410044455115551405151144144104014451011554; + 3c98c1fd7d6e4ff9adae43a38ed0f2b3 + 0550414050015551155114541055554144514454100544054054510055044505; + 101f88d732a51bbe40080cabd06002 + 010001554040511505044411014545541000004000504445510014000004; + 2774d74b7453e63c2d314e0be52eaf79 + 0415151051151045151011055414055004510501105400455411045444551541; + 54c0dc1a0bedbafcb0b707fe5e496a20 + 1110500051500144004554514544555045004515001555541154104114440400; + 75b9d1662c48f8c40ee4e9b3138a0b59 + 1511454151011414045010405540501000545410544145050105404400451141; + 0ca3e9d4c75a6e2b493d7efb8554e9f8 + 50440554415110501511441454044510410551155455454011111054415540; + 501591c68468a7d8ecfcae3f419ecb52 + 1100011141015014401014404415514054505550445405551001415450451104; + b0ad24cd246361f779e8317e94977c57 + 4500445104105051041014051401551515415440050115544110411515501115; + 6fa69209a292924f04fb5b3469a1068b + 1455441441040041440441044104105500105545114505101441440100144045; + d9a06e9ac90f02ad095ff84f30a9addd + 5141440014544144504100550004445100411155554010550500444144515151; + ce596f2830ab988dfa7dc0add68214af + 5054114114550440050044454140405155441551500044515114400401104455; + 860c30b9a27c7b2759666dd71ec578c3 + 4014005005004541440415501545041511411414145151150154501115405005; + 862361325b5f7a6b506b948d55697ce3 + 4014040514010504114511551544144511001445411040511111144115505405; + 95142973169fbae5410a22bb88ca63ee + 4111011004411505011441554544541110010044040445454040504414055454; + 237495a82a6755689df073af2a56f88c + 0405151041114440044414151111144041515500150544550444111455404050; + ab46613ddf7787fd1be42272fcb1be44 + 4445101414010551515515154015555101455410040415045550450145541010; + 6b2d8d2b513277cfb03d8a5731234a3d + 1445045140510445110105041515505545000551404411150501040510440551; + 9cc41fbd7189a3b5b0ff2f3746eb9bc6 + 4150501001554551150140414405451145005555045505151014544541455014; + af7baf1a8ce5d42eca4353de181d085a + 4455154544550144405054115110045450441005110551540140015100401144; + c59bde6136dda59a839605252d1dd390 + 5011414551541401051451514411414440054114001104110451015151054100; + 566a7c0f9adc5a021c1759e2c80708c0 + 1114144415500055414451501144000401500115114154045040001500405000; + 28d1c20f2b8613b5e1ba8e3005aef30f + 0440510150040055044540140105451154014544405405000011445455050055; + a7d716d198bf6bb3d32ba364f722de52 + 4415511501145101414045551445450551050445440514105515040451541104; + 4c9a1fa66d2d0cf7935d45e83b9ce326 + 1050414401554414145104510050551541051151101154400545415054050414; + 310d8bb131c4bed327529185c4d46db8 + 0501005140454501050150104554510504151104410140115010511014514540; + 2742ea95019b5f186c3c848744743d4a + 0415100454444111000141451155014014500550401040151010151005511044; + 70f5bfbf5f18a3deef4230b875b3a0af + 1500551145554555115501404405515454551004050045401511450544004455; + 93c9240145720297b96a404941792a21 + 4105504104100001101115040004411545411444100010411001154104440401; + + # --- Regression --- + + 01f081e69f45d3254530766ab98d55fa612c7bb27ea31bc2621d894be9c0b196b3 + 0155004001541441551011510504111011050015141444454140511111554414010450154545041554440501455004140401514041104554415000450141144505; +} + +div { + # --- Random data tests --- + + 6e0e2a282a5411ae76767ed1103deef069ef4ed3a14ff24b + 5385621c6661aaa35a24150d2c08332e + 01c2334cc957151dc7 + 398c4111da6d06cdf3d83704ee403101; + 785e80e9711074a8412abd48da670731ea + 4c5d348767009ea85f25f7ea02ef7be7 + 01c4 + 0b17de61cc808487285b72f14fa23336; + d921e3736edd0d111e56c51cf4e4c343cd690dbaeb34194592ca2b80cc7e + c205a3c1faecfa3a74f7838e20c5678f + 012492f38367090dbc739e8a15c414 + 34570d4431e79cc4d3ff2a583c3a56b2; + 06e7333745e54278092c9fee2cd95768e4e343013e48fe88660cbdce + 10f02ba313d1c57d8cf04fa2e760f19a + 6c1708dd11c7305e9d0a1974 + 0dd6757486f880c40590ed673c22ddc6; + bf4adc5bd775679384d763216edc12157afec6eb4d2435a2fc793183fafadc + 9ff35b5c87471da1e56600203f11ae65 + 014fd82ad3ab0ef9bda71f5d88ab3fe1 + 3b599b787383608d59ba518513d7d0d9; + 0377c80101957a0c0044ee9ae96e8a7cc785a629c1 + 7ca5d5ef2a981b83417db75f9616e0ff + 0b71080c88 + 2d21297ee7c68552c11b6199fa1d55b9; + 1c92d440eb73a2cc5891f1881dc9d366271416b21947d3a98eb4dc5692 + 7afdf70aa9d3f0a02b238d08d14fb1d9 + 4c61f24d2263168cc50b2d3126 + 2674528444adc656d5bfe3915849a064; + 0ae3f419ecb52b0ad24cd246361f779e8317e94977c576fa69209a292924f04f + b5b3469a1068bd9a06e9ac90f02ad095 + 13ecfde29e5a9f5ff20fae44744397d7 + 58be1a2775d5b0424b7e9ef4450e9e34; + 613cc2a6b7773965bca0c2ae6237e9f702b75a0852be1830c2e689f1ec9d6599 + b75c7b15e30e188d84c96d7de9ad41ae + e3c34ccd80ca28706fdcd10562bd60cd + 466ece9c2f57ebe70b744c210507d37f; + 3555a5f38e5450a5cc5a7eeb9504288aee23298fb8 + 8dd256a0a99d55a277c1cebca95be232 + 6fa74dc1f5 + 0fdf1eba1901a220dce11aff114ba7a2; + 23309eefbbc3fe8df211397e58df223596c695a8993be7d81ec52b + 9891a51ece620fdeb8c4d1dad87f979b + 4be153fb895358027814ae + 7d23cf0b5d1b872877af14ab1b35ea49; + 0175cde357bdd78d4672ea176521a9ef0c0e842d62cdef309b6ed2 + cd41cb0292968ee9c82b353e07cd6e2d + 037f62f06af153d6ad8c01 + 3d1533e7afd150b592fb196354585cff; + 8705d678b201c2300a347083cae184ed + 786ea38c016bbcc3e9f5c5b4662fdaec + 03 + 0fb632ecb1bd0774302a3e5f6091ebd9; + 0195d1b27b916f29264d0fd33696867bc9aea2f41dce71931886c5d898e25f69 + 93a948c2e26a36dc13a1754a80cdaf8c + 034aeb96693c049c2af77e1a7b277a5e + 3d9d04738de1dc0a7654b8115a7ee1e1; + 79090e88e87a94e1eb7f7ebe3147bdde846170 + eb67415f279248028ae4052f72d48092 + 9686d1 + 7100e616ea381ee5d0b2ffb7a67ee942; + f254423fef93d5d7a76ecf22c656c1352c53257875945d33 + b2ca471b0867d5fae2e4f27a2d2706da + 01bad680bd4a0132ee + 582f783fc210f72814780e69b0bd29ff; + c9bd4858bd014860f6d95dabb9a5d3d231 + c1ff2aefeb9d6cc4ac6ae0c0535d8c13 + 011f + 17949a58ebcb086a5350c3aceffbc4e0; + 0b8915613beb2e89cdb36b69b7d62ef2b0197537793f71 + 242f42cdf08598d86d812a11c5647b75 + 56ddd25003c7e7 + 1aa0da3ff44f29eb5db54ea6a970dd5a; + e03c7f839598081d2c42f4e503484e7a4a219d0149561f3d5cbed8 + 6503cea0d8a0c6a227143d96d7cad509 + 02c53788cff1530e65640225 + 078acf15737c0320afbac57f23098cd5; + 0165144c6d0637f8cb21bc8913188186376755bbd790566f32612993fec931 + 8ab74399da1f1a01a91521d73d12b0d9 + 02ed5b96b580b772606cb77ff49191 + 58d92bf9fb6f5fb9f0975b3e2f5ad1f8; + 02b35947d2f507a817cb9e178bd6bcaa1d9054979482efb1ef + 56cebd75069fe534091d8409575702cf + 08114f9866c8343218 + 2504e1784d51b5c26cad8df6357b0567; + 109978bc6b8824b04e113fa2a4c982bd2b93a027fd08ad69227a51506bdc11 + 12c061be0756685473011c61067dc241 + 012013fcb240a4d4f394c40f357c666b + 040d8ec7359c8fa7cb6864bb6fe2b6ba; + 0240b50d2853d690a8cf355e9d79626c6cb5f996cccfee3e1be7eed633 + d233771cc22b3724a3d14382766cce97 + 07b0d38444572f483317b557d4 + 7b499146cd46dab3812cf4691d3bbe5f; + 025e90153ae473c9bee43aafaec084468698e5d4eede21f8d4 + 791d69fc4cfb227b4bb531b633dfcb80 + 0d396769c6e551b981 + 0f0854faf0c35a4ffa142b21d0047354; + 0de9af086a7b5a69231741ad28f72df187515e355dd8dfd9b10bfc6e87f1 + 1a5dbee5bbc0980ab55fae3b6135fca9 + 89b00eb8894915d87ca6943ac6fd + 06fa712cefe56e4dddbccc3b389d7bc4; + 12333fa824ddf35aa1b7de856a919b5864e94c3d63ce94 + 84c4a1d9a55cde37b41ce04d4c292491 + 257b652b91361c + 6b6611dde69c73a3bdde7b6fd01d6748; + 038b2304265ac16c80f84be3d61a82628ae2 + 730b3374140b33de67be248766cc7183 + 0864 + 1519f8ad4b7430e93c72ce04104d044e; + 1d09aead497b4383dc45da08fac2950fde1e + d78d23956daf24a70ed9513d8185e988 + 2b5e + 227af9cc9eff71a25a89d3a5f95fc5ee; + 01ff9215d5fc0b3149589a96c76555a7145a7699ed03b125da8c0221ae0ea630 + e97791f445493fa4c2858c63e89de9b1 + 027c8467e27a018bbb903b85aeeff4c1 + 79ff4a78de0c7c1a9a87d63368ddcf41; + 033c9edec4c98b26c1bd29dd6c33418bf678921a705fe94ba8f4 + 1f200f0df4aae402308e4d3747ea3b62 + 2b085586f038a6997a7a + 095479470eacc695a289163c245933c0; + 01a8722b24be8d9404cc9b836ab0b739ee57ae60ed + 0ba579d54afea4a7386c2ae3664c3d93 + 3e54693717 + 0619d78694ac997bedf949a21bf9a024; + 112bf3440706f9935e8221356e908bdd1972bc0b7d4540a76c779d845f604fc2 + 2d27eaf11c8af56eab46d787c409293a + b779548b4b726be09029b5b6e414316b + 1498f6cd6bbed85fe55529a41188ce9c; + 5fbb399787dc1c088ae1b1a868a8fd68071662aebe6859d764d8c66d + 0ae272c16095b2e0b88f60f0bb2c77c1 + 09593fefe3ac800d34fa59a9d1 + 022c8aa8970653e5946394aaf55db47c; + 0ba36adf7f6695ffcaf3cb4f671fcf1167c79f + d24e71e6be0662a608ddaac25c3174b7 + 1836b1 + 5a783d61e236025be73de15c60fb1738; + 28b2a0867669dbc51f86661c3a1f6a1d5565284547a3f4f2f934 + 22bd5df7bc0c1e6a863a1a1c448733e7 + 01540ca5dc8900d40c3dd7 + 0eb263f6f9b698becce9b975cac485b1; + 15503e6802be9c85711f75250539c76426f91b77 + 91cc2ed96c4eee210ed0cb5251934085 + 2f2129de + 5430a3c98a336b14edef0d41d93dfad1; + 011816c74ce3765423825661feba199268be5453932b36d6 + a8a09df55f7606d260f79ad1825ec8ac + 02b46a057ab9b6d8 + 5d970c88da5e61edfcf5b0afb7112c76; + 0e58c4591e74eede082861a82117d4d41239247c + 22afdfd47592ee3f4e9777003ee9e7ad + 7437cb93 + 0faa41dc7710ab02ea755b778975ffdb; + 019717a6f636f25b0467f5ae365c2ba5b8 + 801bf58c5282787aec5c66702e80efd5 + 03 + 173bb862c174d38b531104a62faa95c7; + 1af0354e3dfc333b46c5efa3354f8a0cb6bb41 + 8d59fafe11fd9b7a2f687a13696d4315 + 375fa9 + 1993cbf7dfda1e1ce89c043dc306dbdc; +} diff --git a/math/t/group b/math/t/group new file mode 100644 index 0000000..a2a820f --- /dev/null +++ b/math/t/group @@ -0,0 +1,318 @@ +# Test group abstraction, and a bunch of other things. + +check { + "prime { 29, 7, 16 }" "ok"; + "prime { 29, 6, 5 }" "not a subgroup"; + "prime { 21, 2, 2 }" "p is not prime"; + "prime { 29, 14, 9 }" "group order not prime"; + + "ec { secp224r1 }" "ok"; + + "prime { catacomb-ll-160-1024 }" "ok"; + + "ec { + prime: + 0xdb7c2abf62e35e668076bead208b + primeproj: + 0xdb7c2abf62e35e668076bead2088, 0x659ef8ba043916eede8911702b22 + 0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500 + 0xdb7c2abf62e35e7628dfac6561c5 * 1 + }" "ok"; + + "ec { + prime: + 0xdb7c2abf62e35e668076bead208b + primeproj: + 0xdb7c2abf62e35e668076bead2088, 0x659ef8ba043916eede8911702b22 + 0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500 + 0xdb7c2abf62e35e7628dfac6561c5 * 2 + }" "incorrect or ambiguous cofactor"; + + # --- This one's oakley-155 --- + + "ec { + binpoly: 0x0800000000000000000000004000000000000001 + binproj: 0, 0x7338F + 0xaa089ae4666a422e714651ad9372213fa65a93, + 0x12d29c630dda76010397809a6816be6d2ffa815 + 0xaaaaaaaaaaaaaaaaaab1fcf1e206f421a3ea1b * 12 + }" "degree not prime"; + +} + +checkelt { + "prime { 29, 7, 16 }" 16 0; + "prime { 29, 7, 16 }" 2 -1; + + "ec { secp112r1 } " + "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500" + 0; + + "ec { + binpoly: 0x0800000000000000000000004000000000000001 + binproj: 0, 0x7338F + 0xaa089ae4666a422e714651ad9372213fa65a93, + 0x12d29c630dda76010397809a6816be6d2ffa815 + 0xaaaaaaaaaaaaaaaaaab1fcf1e206f421a3ea1b * 12 + }" + "0x7b, 0x1c8" + -1; + +} + +mul { + "prime { 29, 7, 16 }" 8 7 27; + + "prime { catacomb-ll-128-512 }" + 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 + 32459289443738057373904596685867555624839649360339363831766212033645755638497600605981483758068704145575847399920657057013890131443911836862688141735006 + 3947634573386515057215934636174241616115542585724861166389751782289048647501330677434616929656928819642658111077814577650964230037753641582364366136933940; + + "ec { nist-p192 }" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" + "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, + 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"; +} + +sqr { + "prime { 29, 7, 16 }" 8 6; + + "prime { catacomb-ll-128-512 }" + 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 + 1140714521254648115393410274780412972862841854751618635120376750594285456137894804866135103112174518443866054055338095672091997366768745026933347678925721; + + "ec { nist-p192 }" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; +} + +inv { + "prime { 29, 7, 16 }" 9 13; + + "prime { catacomb-ll-128-512 }" + 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 + 5876676858790113051879264634636727534122591023949326683791506203503263391580079717512212895466773363712551406785344528808275608153699681298608650332072384; + + "ec { nist-p192 }" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; +} + +div { + "prime { 29, 7, 16 }" 9 5 25; + + "prime { catacomb-ll-128-512 }" + 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 + 1926426135381827210395257472845875618319108487720857260583372274154852182951667715700282388176779441854588992736540698662997833538400244234146123792411051 + 24069337702503046127918930405335466791703796668849861281722901639361967869381088162761943434867448224639537469251486209856612215080111132649928233405085; + + "ec { nist-p192 }" + "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, + 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, + 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; +} + +exp { + "prime { 29, 7, 16 }" 3 12 16; + + "prime { 29, 7, 16 }" 3 -12 20; + + "prime { catacomb-ll-128-512 }" + 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 + 147362842169670001895012880214773009850 + 5743039465765061017258257285641279669186626264432710496849307123351095219091264933384359874588390730293795471675184250790999035405886273905917889887366080; + + "prime { catacomb-ll-128-512 }" + 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 + -147362842169670001895012880214773009850 + 3548613102603269389984811279864031309564549180885835723408511495891024326106890973751615845620404633717662823827170012116865930893524976817060348977482376; + + "ec { nist-p192 }" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 6277101735386680763835789423176059013767194773182842284081 + inf; + + "ec { nist-p192 }" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 3131675836296406071791252329528905062261497366991742517193 + "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71, + 0xc6e91094cb34131e539c3db25f7f32670ef8dfe03a88b6fb"; + + "ec { nist-p192 }" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 3131675836296406071791252329528905062261497366991742517193 + "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71, + 0xc6e91094cb34131e539c3db25f7f32670ef8dfe03a88b6fb"; + + "ec { nist-p192 }" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + -3131675836296406071791252329528905062261497366991742517193 + "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71, + 0x3916ef6b34cbece1ac63c24da080cd97f107201fc5774904"; +} + +mexp-1 { + "prime { 29, 7, 16 }" 3 12 16; + "prime { 29, 7, 16 }" 3 -12 20; + + "ec { nist-p192 }" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 3131675836296406071791252329528905062261497366991742517193 + "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71, + 0xc6e91094cb34131e539c3db25f7f32670ef8dfe03a88b6fb"; + + "ec { nist-p192 }" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + -3131675836296406071791252329528905062261497366991742517193 + "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71, + 0x3916ef6b34cbece1ac63c24da080cd97f107201fc5774904"; +} + +mexp-2 { + "prime { 29, 7, 16 }" 3 12 8 2 9; + "prime { 29, 7, 16 }" 3 -12 8 2 4; + + "prime { catacomb-ll-128-512 }" + 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 + -147362842169670001895012880214773009850 + 130340428707563070626027539288099297037336608388990593367322442443880297841210613523501678207607756678300142264348927299637006055881968995671289567513600 + 91626412351157168611316239052073981423 + 1022777063245982511046303002728993765008184164346724419524981660559588777350492245381260023136750231183070065817596986237402046431653662723677455952067221; + + "ec { nist-p192 }" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + -3131675836296406071791252329528905062261497366991742517193 + "0xea711858c23d92f9964655910bc90a197a915e90111cf11b, + 0x664189a1d8b2bb24f2b2ac64b19e2178118842e6ba9f4ad5" + 1110875761630725856340142297645383444629395595869672555585 + "0xaa25bb0bf38b06821e8641c1afb8bc078dbe11c3cf9bc97, + 0xf1a4c09d621fb52736f6010ae90e9bc9771ac017a62098f9"; +} + +toint { + "prime { 29, 7, 16 }" 15 0 15; + "prime { 29, 7, 16 }" 0 0 0; + + "ec { nist-p192 }" inf -1 0; + + "ec { nist-p192 }" + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + 0 602046282375688656758213480587526111916698976636884684818; +} + +fromint { + "prime { 29, 7, 16 }" 15 0 15; + "prime { 29, 7, 16 }" 0 0 0; + "prime { 29, 7, 16 }" 39527306161272833161358334459 0 19; + + "ec { nist-p192 }" 1 -1 inf; + "ec { nist-p192 }" 0 + 0 "0, 0x7b685605ee600cb363db5ea912f2bb5e3a0a2e0e60360f12"; +} + +toec { + "prime { 29, 7, 16 }" 0 -1 inf; + "ec { nist-p192 }" inf 0 inf; + "ec { secp112r1 }" + "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500" + 0 + "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"; +} + +fromec { + "prime { 29, 7, 16 }" inf -1 0; + "prime { 29, 7, 16 }" "39527306161272833161358334459, 9" 0 19; + + "ec { secp112r1 }" inf 0 inf; + "ec { nist-p192 }" "1, 5" -1 inf; + + "ec { secp112r1 }" + "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500" + 0 + "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"; +} + +tobuf { + "prime { 29, 7, 16 }" 22 -1 "00"; + "prime { 29, 7, 16 }" 22 0 "000116"; + "prime { 29, 7, 16 }" 0 -1 "0000"; + "prime { 29, 7, 16 }" 0 0 "000100"; + + "ec { secp112r1 }" inf 0 "0000"; + "ec { secp112r1 }" + "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500" + 0 "000e09487239995a5ee76b55f9c2f098000ea89ce5af8724c0a23e0e0ff77500"; + "ec { nist-p192 }" + "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed" + 0 "00010000188497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed"; +} + +frombuf { + "prime { 29, 7, 16 }" "00" -1 0; + "prime { 29, 7, 16 }" "000116" 3 22; + "prime { 29, 7, 16 }" "00000e" 2 0; + "prime { 29, 7, 16 }" "000100ff" 3 0; + + "ec { secp112r1 }" "0000" 2 inf; + "ec { secp112r1 }" + "000e09487239995a5ee76b55f9c2f098000ea89ce5af8724c0a23e0e0ff77500f00d" + 32 "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"; + "ec { secp112r1 }" "0001000001001ee7" -1 inf; + "ec { nist-p192 }" + "00010000188497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0eddead" + 29, "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed"; +} + +toraw { + "prime { 29, 7, 16 }" 22 -1 ""; + "prime { 29, 7, 16 }" 22 0 "16"; + "prime { 29, 7, 16 }" 0 -1 ""; + "prime { 29, 7, 16 }" 0 0 "00"; + "prime { 4294967311, 364289, 18767 }" 4285559121 0 "00ff707151"; + "prime { 4294967311, 364289, 18767 }" 4285559121 -1 "ff707151"; + + "ec { secp112r1 }" inf 0 "00"; + "ec { secp112r1 }" + "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500" + 0 "0409487239995a5ee76b55f9c2f098a89ce5af8724c0a23e0e0ff77500"; + "ec { nist-p192 }" + "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed" + 0 "040000000000000000000000000000000000000000000000008497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed"; +} + +fromraw { + "prime { 29, 7, 16 }" "" -1 0; + "prime { 29, 7, 16 }" "160bad" 1 22; + "prime { 29, 7, 16 }" "00" 1 0; + "prime { 4294967311, 364289, 18767 }" "00ff707151e7c0" 5 4285559121; + "prime { 4294967311, 364289, 18767 }" "ff707151" -1 0; + + "ec { secp112r1 }" "" -1 inf; + "ec { secp112r1 }" "00" 1 inf; + "ec { secp112r1 }" + "0409487239995a5ee76b55f9c2f098a89ce5af8724c0a23e0e0ff775" -1 inf; + "ec { secp112r1 }" + "0409487239995a5ee76b55f9c2f098a89ce5af8724c0a23e0e0ff77500" + 29 "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"; + "ec { nist-p192 }" + "070000000000000000000000000000000000000000000000008497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed00deadbeef" + 49 "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed"; +} diff --git a/math/t/mp b/math/t/mp new file mode 100644 index 0000000..fe74f07 --- /dev/null +++ b/math/t/mp @@ -0,0 +1,326 @@ +# Test vectors for MP functions + +add { + 5 4 9; 5 -4 1; -5 4 -1; -5 -4 -9; + 0xffffffff 1 0x100000000; +} + +sub { + 5 4 1; 5 -4 9; -5 4 -9; -5 -4 -1; + 4 5 -1; 4 -5 9; -4 5 -9; -4 -5 1; +} + +mul { + 5 4 20; -5 4 -20; 5 -4 -20; -5 -4 20; + 0x10000 0x10000 0x100000000; +} + +div { + 9 4 2 1; -9 4 -3 3; 9 -4 -3 -3; -9 -4 2 -1; + -3 6277101735386680763835789423207666416083908700390324961279 + -1 6277101735386680763835789423207666416083908700390324961276; + 3131675836296406071791252329528905062261497366991742517193 + 1110875761630725856340142297645383444629395595869672555585 + 2 909924313034954359110967734238138173002706175252397406023; + 3131675836296406071791252329528905062261497366991742517193 + 53 + 59088223326347284373419855274130284193613157867768726739 26; + 1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919 + 776259046150354467565459065629240877815667024717257156601175597451483119974551053629334726938295821221455003840144432114575401859459023171316363806515641491872190410445098144254585345658296587683734775881559921685818610503605288959 + 2 1; +} + +exp { + 4 0 1; + 4 1 4; + 7 2 49; + 3 564 124849745640593184256214502788000232711984346194239284918599169775251467106591187580476305077269760425019686159071753053924227569816588462643229463821875763427430576080998505780547826368760514503807579784278708008217584939464444237989070811887584423210788916656247499281; +} + +bin2c { + and 5 3 1; + or 5 3 7; + xor 5 3 6; + 1111 0 0 -1; + or 45 -7 -3; + xor 0x343cd5 -0x6a49c -0x32984f; +} + +lsr2c { + -1 5 -1; + 1 5 0; + -6 2 -2; + 5 0 5; + -4 0 -4; + 7 2 1; + -7 2 -2; + -7 20 -1; +} + +lsl2c { + -1 5 -32; + 5 0 5; + -4 0 -4; + 7 2 28; + -7 2 -28; + 0xc0000000 1 0x180000000; + -0xc0000000 1 -0x180000000; + -1 32 -0x100000000; +} + +setbit { + 0 40 0x10000000000; + 0x87348 40 0x10000087348; + 5 1 7; + 7 1 7; + -3 1 -1; +} + +clrbit { + 0x10000000000 40 0; + 0x87348 40 0x87348; + 5 1 5; + 7 1 5; + -1 1 -3; +} + +neg { + 0 0; + 15 -15; + -15 15; +} + +odd { + 1 0 1; + 2 1 1; + 4 2 1; + 12 2 3; + 0x10000000000000 52 1; + 0x10000000400000 22 0x40000001; +} + +sqrt { + 0 0; + 1 1; + 4 2; + 9 3; + 16 4; + 99 9; +100 10; +101 10; +120 10; +121 11; + +10106623487257186586 3179091613; +14565040310136678240 3816417208; +} + +gcd { + # --- Simple tests --- + + 16 12 4 -11 15; + 12 16 4 -1 1; + 693 609 21 -7 8; + 4398082908043 90980984098081324 1 -32483863573352089 1570292150447; + + # --- Negative argument tests --- + + 16 -12 4 -11 -15; + -16 12 4 11 15; + -12 -16 4 1 -1; + -12 16 4 1 1; + -693 609 21 7 8; + 693 -609 21 -7 -8; + + # --- Zero argument tests --- + + 15 0 15 1 0; + 0 15 15 0 1; + -5 0 5 -1 0; + 0 -5 5 0 -1; + 0 0 0 0 0; + + # --- Random number tests --- + + 829561629303257626084392170900075 32498098450983560651904114638965 + 5 -29340810037249902802634060204608 748967211613630574419802053172497; + + 5509672937670943767152343650729669537671508 + 398326674296699796695672966992514673531 + 17 + -4158709420138833210339208344965073815 + 57523460582278135926717203882531035926727; + + 324098408098290809832490802984098208098324 + 23430980840982340982098409823089098443 + 1 + -4158709420138833210339208344965073815 + 57523460582278135926717203882531035926727; + + # --- RSA test --- + # + # The first number is (p - 1)(q - 1) from `mpmont'. The second is a + # random number (it's actually prime, but that doesn't matter) which I + # can use as an RSA encryption exponent. The last is the partner + # decryption exponent, produced using the extended GCD algorithm. + + 665251164384574309450646977867043764321191240895546832784045453360 + 5945908509680983480596809586040589085680968709809890671 + 1 + -4601007896041464028712478963832994007038251361995647370 + 514778499400157641662814932021958856708417966520837469125919104431; + + # --- Misery --- + # + # Some bugs discovered during RSA testing. + + 100000423751500546004561515884626739136961367515520675987004088469753859696407139054406989735113827981148062449057870561788973142250811838720214530386151198455545176591384352343648452329042764530196327665219224050630680827543991306749402959935685172017409062967157813233001567797128414009962262840951763040181 + 44895767034162990997987303986882660674722497505237491649296190658571471979065889234144353811843706629535512848235473808330181517421970135930320187227697512315919757806204341545022714991717913006031724818461724742069401359454784533576615919680949125073761586043027941204059690093447093117249681641020785611986 + 1 + -44146175664861261172356293340716833133750232401287328189797639296698679436925232375473973898100363205157703913050824405116878299310008848005045714833814493992539429428295945643439440068026313232881493081836812480325977761600303456915493177366981470223898994906470419007730670657168179659899713837827764669213 + 98330790743257232930640417364963717704786040860302439189781385170246412183980882564239377268174203679366339563908361674571088519452885615348465535190260914996055274486493192655677181637142116473172979503236297658204730543049175626205461452256333155750566288282331419748434569978343545573401114593095927172889; + + 44895767034162990997987303986882660674722497505237491649296190658571471979065889234144353811843706629535512848235473808330181517421970135930320187227697512315919757806204341545022714991717913006031724818461724742069401359454784533576615919680949125073761586043027941204059690093447093117249681641020785611986 + 100000423751500546004561515884626739136961367515520675987004088469753859696407139054406989735113827981148062449057870561788973142250811838720214530386151198455545176591384352343648452329042764530196327665219224050630680827543991306749402959935685172017409062967157813233001567797128414009962262840951763040181 + 1 + -1669633008243313073921098519663021432175326655218236797222703299507447512426256490167612466939624301781722885149508887217884622797926223371748995195890283459489902104891159687971270691900648057023348161982926392425950284494815680543941507679352016266842774684826393484566997818784868436561148247855835867292 + 749591369301729825631010646165827540972265103950163459498551361872792542140656858670379913743343424377808935184649403213303218111961287925274472393883018323380328377908395901583274923691599773150231736624912261743423597854481076661122742313967654849862591136557522196329019436278913457349967803193020942773; + + # --- Some other bugs --- + + 19504439280113284806725522136967618725661733412699408177537810327183285842670 + 1 + 1 + 0 + 1; +} + +modinv { + 5 9 2; + 15 64 47; + 564566436 546457643 408896426; +} + +jacobi { + 4 5 1; + 6 7 -1; + 15 27 0; + 2132498039840981 98729378979237498798347932749951 1; + 98729378979237498798347932749951 2132498039840981 1; + + # --- Kronecker extension --- + + 0 0 0; + 1 0 1; + -1 0 -1; + 2 0 0; + + 2132498039840981 197458757958474997596695865499902 -1; + 98729378979237498798347932749951 4264996079681962 1; + 98729378979237498798347932749951 -4264996079681962 1; + -98729378979237498798347932749951 -4264996079681962 -1; + + # --- Random tests made by PARI/gp --- + + 22 -19 -1; + 48 -37 1; + -13 29 1; + -19 2 -1; + -43 31 1; + -12 -7 -1; + -14 -34 0; + -30 -29 -1; + 25 26 1; + -27 20 -1; + -5 -45 0; + 9 -42 0; + -51 -3 0; + -39 35 -1; + 37 30 1; + 13 18 -1; + -28 6 0; + -49 -15 1; + -1 1 1; + -9 13 1; + -47 44 -1; + -14 -30 0; + 37 -36 1; + 45 9 0; + -29 30 -1; + 49 49 0; + -27 -10 -1; + -35 -25 0; + 17 14 -1; + -35 29 1; + -1 33 1; + 38 -11 1; + 3 -24 0; + 5 -25 0; + -31 22 -1; + 40 30 0; + -43 26 -1; + -22 10 0; + 11 -29 -1; + 40 -18 0; +} + +modsqrt { + 1 3 1; + 4 5 2; + 9775592058107450692 13391974640168007623 3264570455655810730; + 8155671698868891620 10189552848261357803 2073812183305821596; + 3248339460720824413 8976233780911635437 1220523478429582717; + 3447751741648956439 10155704720805654949 2812971608818169892; + 1453601744816463433 3095659104519735473 1260511572497628526; + 3366261317119810224 3756232416311497601 610261287187759737; + 3869491397135339653 5762828162167967567 2788500156455085147; + 660864223630638896 1729533840094059799 671335997718840076; +} + +modexp { + + # --- Montgomery exponentiation --- + + 435365332435654643667 8745435676786567758678547 + 4325987397987458979875737589783 + 2439674515119108242643169132064; + 0xfffffffdfffffffffffffffffffffffe 0 0xfffffffdffffffffffffffffffffffff 1; + 1804289383 -8939035539979879765 8939489893434234331 6139425926295484741; + + # --- Barrett exponentiation --- + + 435365332435654643667 8745435676786567758678547 + 4325987397987458979875737589782 + 2425191520487853884024972777945; +} + +factorial { + 0 1; + 1 1; + 2 2; + 3 6; + 4 24; + 5 120; + 30 265252859812191058636308480000000; + 100 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000; + 500 + 1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; +} + +fibonacci { + -20 -6765; + -19 4181; + -10 -55; + -9 34; + -2 -1; + -1 1; + 0 0; + 1 1; + 2 1; + 5 5; + 10 55; + 19 4181; + 20 6765; + 100 354224848179261915075; + 1000 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875; +} diff --git a/math/t/mpbarrett b/math/t/mpbarrett new file mode 100644 index 0000000..c492ece --- /dev/null +++ b/math/t/mpbarrett @@ -0,0 +1,133 @@ +# Test vectors for Barrett modular reduction + +mpbarrett-reduce { + 17 11 6; + -17 11 5; + + 0x8ab316d0d1a2e88535cf77c1172881ead70d592c59e9c5fbc16e4b0c4dc49481 + 0x18ca3bf7ee3c6d7bab3f144b015ccc6c25472843d346b461 + 0x02c1815029b766b96ad4507dc1af8151307961c6d161d065; + + 0x8117d1663ee63341eb8faeff304549f0f8b32d587acc2fd5597ea6a31625881d + 0xdc85df77dfb61876805623bcbed325b99d00c2cd65c252c879 + 0x395da02e8a6c66476467c4e04f328d8208cc411e3d1e96e14c; + + 0x63791966f2ad44a6df11bcc87c6b7c2400c74e69f7e3ca02fcac12b3bf56238b + 0xa49e473b8f7539d89cdb002d73182558773eec10db93cc6049d8c5533e + 0x65caf6833baa118b53c7bdc44a831605ca382b5993beead59f3971d13f; + + 0x9ca438db3e0f79305987292e8ec6174e6c313f7904ebb35a349a700e3ae63a37 + 0xb24c93d499c7073b8f7aac718c1f12da1a8fc8bccdd47b49 + 0x46393cb15e38cbbc8a85698151a113f28081b4c8f6ed232e; + + 0x8214fd17858a4a913015412b5331eb9654faeb5156a674b1e5f6550a68957146 + 0xc4f0ebaad6c0ee0111c57667ea8e0a254f3068f212949e20ededa89a7da6 + 0x3fde916ba21d19414d4316041420ca59d8b01aa2acf3f3ef106245c1915c; + + 0x367aa8f5ba9ac4e8e2ea198b8af2c3b3081deab392ffc05715783b245a62a6fa + 0x72e2c37447f8bca34c4a39b130ea8e5c9a7d8b54564aa88ea773 + 0x08e8c03ebf398c63d71d8fd7ca4ece12367a8dde180ca650afb6; + + 0xae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c + 0xc33c890f030644d88cc65f8ccf99c625c9b9fa21d4eb153e52ef89df54130855 + 0xae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c; + + 0x65901dcdad8dd0625d4d158f99b666fee10480d1df15e3bdac640584b9b746bc + 0xd8a1d326fee87d55f39f15b5b2cfe71f5146083928 + 0x859c41164983547c03134b99530e25a0f874315964; + + -0x65901dcdad8dd0625d4d158f99b666fee10480d1df15e3bdac640584b9b746bc + 0xd8a1d326fee87d55f39f15b5b2cfe71f5146083928 + 0x53059210b56528d9f08bca1c5fc1c17e58d1d6dfc4; +} + +mpbarrett-exp { + 4325987397987458979875737589783 + 435365332435654643667 + 8745435676786567758678547 + 2439674515119108242643169132064; + + 8939489893434234331 1804289383 454353454354565 6139425926295484741; + 8939489893434234331 1804289383 8939489893434234330 1; + + # --- Negative exponents --- + + 0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1; + 8939489893434234331 1804289383 -8939035539979879765 6139425926295484741; + + # --- DSA public key derivation --- + + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5 + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + 0x1234 + 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47; + + 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7 + 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 + 0x23a252f60bae4907a8ed5b6203e2b1da32848cd9 + 0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074; + + # --- Quick RSA test --- + + 905609324890967090294090970600361 # This is p + 3 + 905609324890967090294090970600360 # This is (p - 1) + 1; # Fermat test: p is prime + + 734589569806680985408670989082927 # This is q + 5 + 734589569806680985408670989082926 # And this is (q - 1) + 1; # Fermat again: q is prime + + # --- Encrypt a message --- + # + # The public and private exponents are from the GCD test. The message + # is just obvious. The modulus is the product of the two primes above. + + 665251164384574309450646977867045404520085938543622535546005136647 + 123456789012345678901234567890123456789012345678901234567890 + 5945908509680983480596809586040589085680968709809890671 + 25906467774034212974484417859588980567136610347807401817990462701; + + # --- And decrypt it again --- + + 665251164384574309450646977867045404520085938543622535546005136647 + 25906467774034212974484417859588980567136610347807401817990462701 + 514778499400157641662814932021958856708417966520837469125919104431 + 123456789012345678901234567890123456789012345678901234567890; + + # --- Strange bug --- + # + # Strange memory corruption bug causing mpbarrett_reduce to hang. + # Seems to have vanished on a clean rebuild so maybe this was just build + # fluff or something. Leave it here to pick up regression. + + 30916300184138066757562815127455898754391418637651479989257882011612153138316483396290143656363307389355307404813205623380378799585065876990874918745873480056891738964426752 + 2 44329 + 10975270953088118598390528358454369816072092233138947812823085741431681835772475760228604878294514156761050649439713085882651077696501584961485141097470430535290622475239424; +} + +# --- Simultaneous exponentiation --- + +mexp-1 { + 4325987397987458979875737589783 + 435365332435654643667 + 8745435676786567758678547 + 2439674515119108242643169132064; +} + +mexp-2 { + 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 + 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 + 0xbf655bd046f0b35ec791b004804afcbb8ef7d69d + 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 + 0x821a926312e97adeabcc8d082b5278978a2df4b0 + 0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e; + + 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 + 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 + 0xbf655bd046f0b35ec791b004804afcbb8ef7d69d + 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 + -0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adabb090e849367fc31d4c6a97bac0b4be56a79a0de0 + 0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e; +} diff --git a/math/t/mpcrt b/math/t/mpcrt new file mode 100644 index 0000000..89665b6 --- /dev/null +++ b/math/t/mpcrt @@ -0,0 +1,19 @@ +# Test vectors for Chinese Remainder Theorem solution (Gauss's algorithm) + +crt-1 { + 1 5 1; + 3498243289823 4534543545463431 3498243289823; +} + +crt-2 { + 3 7 7 13 59; + 39845 435435221 43534545 32423423467 13736097689153284731; + + 2200541929485233317342398 498459898455435345676576793 + 13046769915260439091721075347560767438958354488807168684311588308214063361125238823412234206191582332588 40831929843180254171317254073271577309351168965431122042755102715326515941762786951037109689522493526197 + 14756532044160797319048143986538019326281096778844833416304858521742332925502855547148214406728673769162624068049034315018936294558; +} + +crt-4 { + 2 5 1 7 3 11 8 13 2192; +} diff --git a/math/t/mpint b/math/t/mpint new file mode 100644 index 0000000..9c3263d --- /dev/null +++ b/math/t/mpint @@ -0,0 +1,50 @@ +# Test vectors for conversion between MP ints and C ints +# +# The tests look messy because I'm fighting with atoi here as well as the +# integer conversion routines I'm trying to test. + +fromuint { + 0 0; + 1 1; + -5 0xfffffffb; + 0x7ffff 0x7ffff; + 0x80000 0x80000; + 0xfffff 0xfffff; + 0x7fffffff 0x7fffffff; + 0x80000000 0x80000000; # Bastard torture test + 0xffffffff 0xffffffff; +} + +fromint { + 0 0; + 1 1; + -5 -5; + 0x7ffff 0x7ffff; + 0x80000 0x80000; + 0xfffff 0xfffff; + 0x7fffffff 0x7fffffff; + -0x80000000 -0x80000000; # Bastard torture test +} + +touint { + 0 0; + 1 1; + -5 -5; + 0x7ffff 0x7ffff; + 0x80000 0x80000; + 0xfffff 0xfffff; + 0x7fffffff 0x7fffffff; + 0x80000000 -0x80000000; # Bastard torture test + 0xffffffff 0xffffffff; +} + +toint { + 0 0; + 1 1; + -5 -5; + 0x7ffff 0x7ffff; + 0x80000 0x80000; + 0xfffff 0xfffff; + 0x7fffffff 0x7fffffff; + -0x80000000 -0x80000000; # Bastard torture test +} diff --git a/math/t/mpmont b/math/t/mpmont new file mode 100644 index 0000000..27e03c1 --- /dev/null +++ b/math/t/mpmont @@ -0,0 +1,113 @@ +# Test vectors for Montgomery reduction + +create { + 340809809850981098423498794792349 # m + 266454859 # -m^{-1} mod b + 130655606683780235388773757767708 # R mod m + 237786678640282040194246459306177; # R^2 mod m +} + +mul { + 43289823545 + 234324324 + 6456542564 + 10807149256; + + 51518627314818829164222247085233898246715229794943812733936714788310185005015428803253311691709787911812368198649776769324928993075889524373913555618270874746833913595051625422038974326537979654635530320271853851973343513053953211672797425464186157719021174955241645388345195723368057041032310152242301620397 + 7041548659011846562361842096561083537784928869240554198760844555642215260669458833049231069318370838770180094409088437631986867239713464317243824963669990014087444248250948204574690463940534304651099653802302150197753463246181762684347288736386534346725039618007392334267637262008343417972878515511486456037 + 21451817224897484023627307128311082613304580637202546848860538836010530320943159719981586919811151828606838777812233053319458755053306547823820900602281867134174742586071226220962576712633552196944784360512851517812225731562588375896089193406088239903885470354101095713609394462435076126493339021945199401247 + 48192532305912989641372170084506981675917951543147719789775743631071830656350879578731578070582102149232280305157616093002880139716311910835926678896882798493523792373475521651115163420137602661060123597773253524671874189844988793471524978853764238038494563159505836018994860909028653670132922744758133798212; +} + +exp { + 4325987397987458979875737589783 + 435365332435654643667 + 8745435676786567758678547 + 2439674515119108242643169132064; + + # --- Bizarre bug --- + # + # This was caused by omission of the test-and-subtract step in the + # Montgomery reduction. + + 8939489893434234331 1804289383 454353454354565 6139425926295484741; + 8939489893434234331 1804289383 8939489893434234330 1; + + # --- Negative and zero exponents --- + + 0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1; + 8939489893434234331 1804289383 -8939035539979879765 6139425926295484741; + + # --- DSA public key derivation --- + + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5 + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + 0x1234 + 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47; + + 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7 + 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 + 0x23a252f60bae4907a8ed5b6203e2b1da32848cd9 + 0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074; + + # --- Quick RSA test --- + + 905609324890967090294090970600361 # This is p + 3 + 905609324890967090294090970600360 # This is (p - 1) + 1; # Fermat test: p is prime + + 734589569806680985408670989082927 # This is q + 5 + 734589569806680985408670989082926 # And this is (q - 1) + 1; # Fermat again: q is prime + + # --- Encrypt a message --- + # + # The public and private exponents are from the GCD test. The message + # is just obvious. The modulus is the product of the two primes above. + + 665251164384574309450646977867045404520085938543622535546005136647 + 123456789012345678901234567890123456789012345678901234567890 + 5945908509680983480596809586040589085680968709809890671 + 25906467774034212974484417859588980567136610347807401817990462701; + + # --- And decrypt it again --- + + 665251164384574309450646977867045404520085938543622535546005136647 + 25906467774034212974484417859588980567136610347807401817990462701 + 514778499400157641662814932021958856708417966520837469125919104431 + 123456789012345678901234567890123456789012345678901234567890; + + # --- Regression --- + + 3986624077014487421577005607434178981611827907415414229383186257799185035259267946499319317546248903815958429965343062841026732183070884484415037389112766124480881891335541864933360040451772640848433986354946570483859801429553601029855169093153120649968457991955067742589996787220443833463413655161718521778024152687493646856649224308444934694934177848997119462792993163729623894124424825605063456003809024630116233635811919734143467917391222413748618664640084816819791040047135721631646389562380726980090637225607902904093720467390446340147754975063914238763877962986901317873962501987398883284691263121949707967483 + 2169501609694605731113683435915932024263931111070470928071742781553833481227229665038394569450673541955381439893533586899516369125587996614390351130855433932967123352056637148142399218614659226596196082977912512097782590337133839376057748669786776861900003976657975002808400242688631641605350346310303557783077961976578644612942618488786721156576047036803063809499458142391930097492829437793780428298460587910313123127299017105180518995858168981798364124607742910479678852164938149352363613709839015911625193499208078080300810729238501127706236236987807659841302058153641198634312186169690290317377895433013774581020 + 51190650099377934681679689372059155651634030541122059023228371179527051284414 + 2182336244564627050476203952083643687109210844491929333865487949231032236266424033053219865356293652087346833773990958617081657598928894294027838097457060132084513275728637155311686562443969707442331856969523833049082440569661820589637161378175422424940183890787723213162895088451684485064228413121825045190532424942855250521728705814032313019282814300698512615465322506857392325469773301168485302267577566759375501214494771698910873834970265937979350795050000891405548412798945017578510891723221844676960980502437259841806090144299798005080365645221451715661064400809603224286845878809241930399832108000526121054958; +} + +# --- Simultaneous exponentiation --- + +mexp-1 { + 4325987397987458979875737589783 + 435365332435654643667 + 8745435676786567758678547 + 2439674515119108242643169132064; +} + +mexp-2 { + 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 + 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 + 0xbf655bd046f0b35ec791b004804afcbb8ef7d69d + 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 + 0x821a926312e97adeabcc8d082b5278978a2df4b0 + 0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e; + + 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 + 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 + 0xbf655bd046f0b35ec791b004804afcbb8ef7d69d + 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 + -0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adabb090e849367fc31d4c6a97bac0b4be56a79a0de0 + 0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e; +} diff --git a/math/t/mpreduce b/math/t/mpreduce new file mode 100644 index 0000000..2fb8f09 --- /dev/null +++ b/math/t/mpreduce @@ -0,0 +1,31 @@ +# Tests for efficient reduction + +reduce { + 0xc000 0x16cb3 0xacb3; + 0x8000 0x345545 0x5545; + + 0xfffef 0x100000 0x11; + + 0x1ffffffe 0x26fc6567 0x6fc6569; + 0x3ffffffe 0x45445dc0 0x5445dc2; + 0x7ffffffe 0xd4827a70 0x54827a72; + + 0x72e2c37447f8bca34c4a39b130ea8e5c9a7d8b54564aa88ea773 + 0x367aa8f5ba9ac4e8e2ea198b8af2c3b3081deab392ffc05715783b245a62a6fa + 0x08e8c03ebf398c63d71d8fd7ca4ece12367a8dde180ca650afb6; + + 0xfffffffdffffffffffffffffffffffff + 0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b + 0xa019c198b9d9d9fb4440f7bc415ff5e4; +} + +modexp { + 0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1; + 0xfffffffdffffffffffffffffffffffff 2 + 0xfffffffdfffffffffffffffffffffffe 1; + 0xfffffffdffffffffffffffffffffffff 2 + 0xfffffffdfffffffffffffffffffffffd + 0x7fffffff000000000000000000000000; + 8939489893434234331 1804289383 + -8939035539979879765 6139425926295484741; +} diff --git a/math/t/mptext b/math/t/mptext new file mode 100644 index 0000000..fadaef6 --- /dev/null +++ b/math/t/mptext @@ -0,0 +1,88 @@ +# Test vectors for MP textual I/O + +mptext-ascii { + # --- Perfectly valid things --- + + 10 0 10 0 ""; + 0 0 10 0 ""; + 10 52 10 52 ""; + 10 654365464655464577673765769678 10 654365464655464577673765769678 ""; + 10 654365464655464577673765769678 16 8425e6d06f272b9a2d73ed1ce ""; + 10 596569802840985608098409867 8 366570443501403714657464766613 ""; + 16 8425E6D06F272B9A2D73ED1CE 10 654365464655464577673765769678 ""; + 0 654365464655464577673765769678 16 8425e6d06f272b9a2d73ed1ce ""; + 0 16_8425E6D06F272B9A2D73ED1CE 10 654365464655464577673765769678 ""; + 0 -0x8425E6D06F272B9A2D73ED1CE 10 -654365464655464577673765769678 ""; + 0 -8_366570443501403714657464766613 10 -596569802840985608098409867 ""; + 8 -366570443501403714657464766613 10 -596569802840985608098409867 ""; + 0 0366570443501403714657464766613 10 596569802840985608098409867 ""; + + # --- Bogus things --- + + 10 "" 0 0 ""; # Empty string fails + 10 foo 0 0 "foo"; # Non-numeric character + 10 134f 10 134 "f"; # Stop parsing when reaching `f' + 4 12345 10 27 "45"; # Stop parsing when reaching `4' + 0 63_ 10 63 "_"; # 37 is an invalid base, so stop at `_' + 0 36_ 0 0 ""; # 36 is a valid base, so restart and fail + + # --- Big bases --- + + 62 0 10 0 ""; + 10 0 62 0 ""; + 36 A 10 10 ""; + 36 Z 10 35 ""; + 37 A 10 36 ""; + 10 36 37 A ""; + 62 Z 10 61 ""; + + 0 36_a 10 10 ""; + 0 36_A 10 10 ""; + 0 37_A 10 36 ""; + + 0 0x10 10 16 ""; + 0 0o10 10 8 ""; + 0 0b10 10 2 ""; + 0 010 10 8 ""; + + # --- Word-boundary tests for binary-radix translation --- + + 0 0 16 0 ""; + 8 1234567012 8 1234567012 ""; + 8 12345670123 8 12345670123 ""; + 8 123456701234 8 123456701234 ""; + + 16 1234567 16 1234567 ""; + 16 12345678 16 12345678 ""; + 16 123456789 16 123456789 ""; + + 10 -4009356060 16 -eef9eb1c ""; + + # --- Cussidness --- + + 0 -0 10 0 ""; + + # --- Bugs --- + + 16 84d192cd06ae59691897fa409da6198d5269325d + 16 84d192cd06ae59691897fa409da6198d5269325d ""; + + 16 -9802d5c5d5a73f9d4e694a8920f95231b4017f3ec6a4654ace3fa3d85879e5964dade0e051d57f13c275dab1df3da5331f39271efb2792d1dad4460fd5eb5c21fbf355456f523e5631e623074ff9b3e85cf5e0a9336c8d8b8621b24c4e625800ee0152d12c8e22658a66ade38cb4453ab6e4958114717355186649a6cc20d9f5ae2207f99814965035072a9f2121c8f9dd22ab134181378906291aae97287b62a2f592bbceb4198c9cd78e1968bf1e16865c3c6ce9c777232f186b5da240a24523a07faca9de44eba510c91917e099372e67a6a66e93fe7aaefcb9c5485e1a889eae721ab6407586880a95575a968b43bdf50323627aa0fcddfa4e198b0008 + 10 -74959454570640520505374182178324326240748657042677990093617716411759477136824854815262670168473667077524864904515489090301434501507378472350618141578200289566815110468728966378289347050752371322168328511598641143081017162500179880923097593329564317427467179672704707842937085621549781627579801356509572397210965270406925309382945647493757499822518272539171346319468210919037390479279679328187057939609889863122790083219768061816093131875491575840052493376341193028052061557296969558099473333023971577236615940525630787016398581105441977909848659239970133974969366933817929047771871736452423855320657946133173829640 ""; + + 10 687036505685680036980563991304827689190226068191165515873309582371531653761560838357887565473014960851061079052387145199258972778940173525017542879674305252823453991900595437468144352005006881129612951699750949026636206282574720840178116341517038998609517724307448384647380133273761360084019113505091720961437658149042479826982973196933684563380877276612883608481996579884762706391098995123384485837872544276099219443948234067623442105312332114374763392077663374681230289067615025968182722516808457505932863951619224171887832194148545132638772027329666389477813640620737624951105503846166715576529533580414958055708947608220960395455545922617914622611716584821091744228076205865701038484061060900340103461251087987631583104425599437283952841086221737575051158322973751353914369450945591184550003693808660890173148206999627057352641910478408389852121815588924208719373851205997267929487223022997903565246821511833717944887785333763131071163649350968541111796906733695518487580626938892775883629672280655177072837819344983336811201072380418330154409415723975489649421805372088286721361996667976678161505679350285875598457893785891475462099191282531966080162136450154198672623485698300307676277037616099696441730508788295411634665370788798384809584417102543248560317224205079917990766513568040641690632751952309869792602319263342525778046078743231821682847703178976601855555261436480615639995150308874740741630953255447186244703692652027199198662385455033073594432232250325046519267763604243367272471024553800469955272676941568451192546782745963075159357666087761637705388608592656535848292947073782242206595438203903079185128849386496430347274188109070907185471363018498891836986716946253163675821471661778024303689714601286352436391739170368727508436484115845640636653283093361670039386061546795520151041150800979484160765783927564359393959237330742523328888527872599693558141880251962681735003114604660394550415472363991770499647732372855076408144546777820449665557724138072899691283182780416000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + 10 687036505685680036980563991304827689190226068191165515873309582371531653761560838357887565473014960851061079052387145199258972778940173525017542879674305252823453991900595437468144352005006881129612951699750949026636206282574720840178116341517038998609517724307448384647380133273761360084019113505091720961437658149042479826982973196933684563380877276612883608481996579884762706391098995123384485837872544276099219443948234067623442105312332114374763392077663374681230289067615025968182722516808457505932863951619224171887832194148545132638772027329666389477813640620737624951105503846166715576529533580414958055708947608220960395455545922617914622611716584821091744228076205865701038484061060900340103461251087987631583104425599437283952841086221737575051158322973751353914369450945591184550003693808660890173148206999627057352641910478408389852121815588924208719373851205997267929487223022997903565246821511833717944887785333763131071163649350968541111796906733695518487580626938892775883629672280655177072837819344983336811201072380418330154409415723975489649421805372088286721361996667976678161505679350285875598457893785891475462099191282531966080162136450154198672623485698300307676277037616099696441730508788295411634665370788798384809584417102543248560317224205079917990766513568040641690632751952309869792602319263342525778046078743231821682847703178976601855555261436480615639995150308874740741630953255447186244703692652027199198662385455033073594432232250325046519267763604243367272471024553800469955272676941568451192546782745963075159357666087761637705388608592656535848292947073782242206595438203903079185128849386496430347274188109070907185471363018498891836986716946253163675821471661778024303689714601286352436391739170368727508436484115845640636653283093361670039386061546795520151041150800979484160765783927564359393959237330742523328888527872599693558141880251962681735003114604660394550415472363991770499647732372855076408144546777820449665557724138072899691283182780416000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ""; +} + +mptext-bin-in { + -10 010203040506070809 10 123456789 ""; + -100 01172d4359 10 123456789 ""; + -90 09124709 10 6713199 ""; +} + +mptext-bin-out { + 10 123456789 -10 010203040506070809 ""; + 10 123456789 -100 01172d4359 ""; + 10 6713199 -90 09124709 ""; + 10 0 -10 00 ""; +} diff --git a/math/t/mpx b/math/t/mpx new file mode 100644 index 0000000..bf104e9 --- /dev/null +++ b/math/t/mpx @@ -0,0 +1,888 @@ +# Test vectors for low-level MP functions + +# --- Load-store tests --- +# +# The test loads each number, as both big- and little-endian, and compares it +# against the original octet version using a different method. It then +# stores the value to another octet array and compares. This is done for +# various sizes of MP, to ensure that truncation works correctly. + +load-store { + ""; + 00; + 0123; + 0123456789abcdef0123456789abcdef0123456789ab; + 00000123456789abcdef01234789abcdef0123456789ab; + 0123456789abcdef23456789abcdef0123456789ab0000; + 80f8c5606bff51bac932859a4fb6331c4023b32b65cd95f4edc1d1c919fcc078; + 522f8b1de257972a25ec49c9ff56340e2684e847ef2fa4d5714d7c8d454e90f6; +} + +# --- Two's complement tests --- + +2cb { + "" ""; + 00 00; + 000000 00000000000000000000; + 01 ff; + 0123456789abcdef fedcba9876543211; + 0123456789abcdef fffffffedcba9876543211; + 0100000000 ffffff00000000; + 00000000c1a4bc4b ffffffff3e5b43b5; + ffffffff3e5b43b5 00000000c1a4bc4b; +} + +2cl { + "" ""; + 00 00; + 000000 00000000000000000000; + 01 ff; + efcdab8967452301 1132547698badcfe; + efcdab8967452301 1132547698badcfeffffffff; + 0000000001 00000000ffffffff; + 4bbca4c100000000 b5435b3effffffff; + b5435b3effffffff 4bbca4c100000000; +} + +# --- Shift tests --- + +lsl { + # --- Simple sanity checks --- + + 01 2 04; + 01 4 10; + + 7 -1 0; + + # --- Copy shifts --- + + 01 0 01; + 0123456789abcdef0123456789abcdef 0 0123456789abcdef0123456789abcdef; + + # --- Single bit shifts --- + + 01 1 02; + ff000000 1 01fe000000; + + # --- Word-size shifts (assumes 32-bit words) --- + + 0123456789abcdef0123456789abcdef 32 + 0123456789abcdef0123456789abcdef00000000; + + # --- Random tests --- + + 13bbec3a734e0b8b5155600b0826b913 90 + 4eefb0e9cd382e2d4555802c209ae44c0000000000000000000000; + + d6ca6a99fe49b256f80e9643e2bd4f3e 80 + d6ca6a99fe49b256f80e9643e2bd4f3e00000000000000000000; + + c94784b40d54de614084915915531ddc 59 + 064a3c25a06aa6f30a04248ac8aa98eee000000000000000; + + a63c314a39cc37f950b3d530c95ead00 84 + 0a63c314a39cc37f950b3d530c95ead00000000000000000000000; + + 842d03a339f5004cfd311e2bb23216ac 62 + 210b40e8ce7d40133f4c478aec8c85ab0000000000000000; + + 9a8e659739bf9ee7aa908b7c058c5e7e 123 + 04d4732cb9cdfcf73d54845be02c62f3f0000000000000000000000000000000; + + 287f5774f212db87bcd83a1bbb7b1ad5 6 + 0a1fd5dd3c84b6e1ef360e86eedec6b540; + + ec1739174d9d4438d3093cf378605a5c 63 + 760b9c8ba6cea21c69849e79bc302d2e0000000000000000; + + 3dfa8ad6a60a783639d05aa5fbfd993d 46 + 0f7ea2b5a9829e0d8e7416a97eff664f400000000000; + + e4e93a80b6d25b34c23aca3a0d06d76c 63 + 72749d405b692d9a611d651d06836bb60000000000000000; + + 5a4cf5becb4b64a1a31637c91b6415fd 102 + 16933d6fb2d2d92868c58df246d9057f40000000000000000000000000; + + d92f60928b67416c1e20bd9e09026115 69 + 1b25ec12516ce82d83c417b3c1204c22a00000000000000000; + + eae78f56200d7734f7eb68479fe09d51 18 + 03ab9e3d588035dcd3dfada11e7f8275440000; + + 4c9c215ead951513d969d66614016f6e 28 + 04c9c215ead951513d969d66614016f6e0000000; + + 5cb1e4d625eac0393644fe6a7e3ff788 33 + b963c9ac4bd580726c89fcd4fc7fef1000000000; + + 68b23795968766c77b1897c88a5d6ba8 78 + 1a2c8de565a1d9b1dec625f222975aea00000000000000000000; + + 3d96cd168c74f9015afb691d629f3f6d 72 + 3d96cd168c74f9015afb691d629f3f6d000000000000000000; + + 38fa8f63dc426399e0f9b5c01231e02c 95 + 1c7d47b1ee2131ccf07cdae00918f016000000000000000000000000; + + 90176b493061899ec95677ccc58b8cdf 78 + 2405dad24c186267b2559df33162e337c0000000000000000000; + + 0706e95da68f32a4231ab184d16cbff7 33 + 0e0dd2bb4d1e654846356309a2d97fee00000000; +} + +lslc { + # --- Simple sanity checks --- + + 01 2 07; + 01 4 1f; + + 7 -1 0; + + # --- Copy shifts --- + + 01 0 01; + 0123456789abcdef0123456789abcdef 0 0123456789abcdef0123456789abcdef; + + # --- Single bit shifts --- + + 01 1 03; + ff000000 1 01fe000001; + + # --- Word-size shifts (assumes 32-bit words) --- + + 0123456789abcdef0123456789abcdef 32 + 0123456789abcdef0123456789abcdefffffffff; + + # --- Random tests --- + + 13bbec3a734e0b8b5155600b0826b913 90 + 4eefb0e9cd382e2d4555802c209ae44fffffffffffffffffffffff; + + d6ca6a99fe49b256f80e9643e2bd4f3e 80 + d6ca6a99fe49b256f80e9643e2bd4f3effffffffffffffffffff; + + c94784b40d54de614084915915531ddc 59 + 064a3c25a06aa6f30a04248ac8aa98eee7ffffffffffffff; + + a63c314a39cc37f950b3d530c95ead00 84 + 0a63c314a39cc37f950b3d530c95ead00fffffffffffffffffffff; + + 842d03a339f5004cfd311e2bb23216ac 62 + 210b40e8ce7d40133f4c478aec8c85ab3fffffffffffffff; + + 9a8e659739bf9ee7aa908b7c058c5e7e 123 + 04d4732cb9cdfcf73d54845be02c62f3f7ffffffffffffffffffffffffffffff; + + 287f5774f212db87bcd83a1bbb7b1ad5 6 + 0a1fd5dd3c84b6e1ef360e86eedec6b57f; + + ec1739174d9d4438d3093cf378605a5c 63 + 760b9c8ba6cea21c69849e79bc302d2e7fffffffffffffff; + + 3dfa8ad6a60a783639d05aa5fbfd993d 46 + 0f7ea2b5a9829e0d8e7416a97eff664f7fffffffffff; + + e4e93a80b6d25b34c23aca3a0d06d76c 63 + 72749d405b692d9a611d651d06836bb67fffffffffffffff; + + 5a4cf5becb4b64a1a31637c91b6415fd 102 + 16933d6fb2d2d92868c58df246d9057f7fffffffffffffffffffffffff; + + d92f60928b67416c1e20bd9e09026115 69 + 1b25ec12516ce82d83c417b3c1204c22bfffffffffffffffff; + + eae78f56200d7734f7eb68479fe09d51 18 + 03ab9e3d588035dcd3dfada11e7f827547ffff; + + 4c9c215ead951513d969d66614016f6e 28 + 04c9c215ead951513d969d66614016f6efffffff; + + 5cb1e4d625eac0393644fe6a7e3ff788 33 + b963c9ac4bd580726c89fcd4fc7fef11ffffffff; + + 68b23795968766c77b1897c88a5d6ba8 78 + 1a2c8de565a1d9b1dec625f222975aea3fffffffffffffffffff; + + 3d96cd168c74f9015afb691d629f3f6d 72 + 3d96cd168c74f9015afb691d629f3f6dffffffffffffffffff; + + 38fa8f63dc426399e0f9b5c01231e02c 95 + 1c7d47b1ee2131ccf07cdae00918f0167fffffffffffffffffffffff; + + 90176b493061899ec95677ccc58b8cdf 78 + 2405dad24c186267b2559df33162e337ffffffffffffffffffff; + + 0706e95da68f32a4231ab184d16cbff7 33 + 0e0dd2bb4d1e654846356309a2d97fefffffffff; +} + +lsr { + # --- Simple sanity checks --- + + 04 2 01; + 10 4 01; + 7 -1 0; + 7 32 0; + + # --- Copy shifts --- + + 01 0 01; + 0123456789abcdef0123456789abcdef 0 0123456789abcdef0123456789abcdef; + + # --- Single bit shifts --- + + 02 1 01; + 01fe000000 1 ff000000; + + # --- Word-size shifts (assumes 32-bit words) --- + + 0123456789abcdef0123456789abcdef 32 + 0123456789abcdef01234567; + + # --- Random tests --- + + eb4f57af83f78c0d67b3a6ad84e62378 120 + eb; + + c6a207d80522139f1fe168028d6afa8c 45 + 0635103ec029109cf8ff0b; + + 6027a129cf726a80445bf42a310ecd30 51 + 0c04f42539ee4d50088b; + + fb0cc20512774733c783bfea0ea3b503 36 + 0fb0cc20512774733c783bfe; + + 4f9884d0ec9fc9e3be6ac15382803eaa 107 + 09f310; + + e47895de118466ac7b16188284b35fb9 55 + 01c8f12bbc2308cd58f6; + + 22dfd1386bd2a5c4b6da0d619485e735 10 + 08b7f44e1af4a9712db68358652179; + + 489fab826eb8ce9f41084c2b4ea3bb25 117 + 0244; + + f6f7735e7d89edfa05482a6b19b1d7b6 53 + 07b7bb9af3ec4f6fd02a; + + bd4eda78b316190a28840f382a90bc63 80 + bd4eda78b316; + + af9f01ddcecf1d21b0af4c318df98e4f 39 + 015f3e03bb9d9e3a43615e98; + + 64d53464e8524ef2529389b14f2b9940 19 + 0c9aa68c9d0a49de4a52713629e5; + + ce49d3be79896131d044f41274ff13ee 99 + 19c93a77; + + 25a05fcae2ed3d9e2486cd633bd51070 18 + 096817f2b8bb4f678921b358cef5; + + 8a29be64acc97626d097231c4f3df4aa 82 + 228a6f992b32; + + ac27fc4590675fb16ecfbf774dc8e591 14 + 02b09ff116419d7ec5bb3efddd3723; + + b72f02eb26b965133db98adcedfe1e37 44 + 0b72f02eb26b965133db98; + + afc634103a039f37b8f9f98b1d94ac85 52 + 0afc634103a039f37b8f; + + f670a78a3801b81e0a00e5b5deb81a47 57 + 7b3853c51c00dc0f05; + + 3a1d23d0d00fa4e165ba2b54eccd8f8d 92 + 03a1d23d0d; +} + +# --- Arithmetic tests --- +# +# For each of the fundamental operations, there's a sequence of simple tests +# which ensure that the functions are working even slightly correctly. Then +# there are some tests aimed at limit conditions in the algorithm. Finally, +# some random tests dreamed up by the Perl script `mpx-gen.pl' are given. + +uadd { + + # --- Simple sanity checks --- + + 00 00 00; + 00 01 01; + 01 00 01; + + # --- Carry propagation tests --- + + ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + 01 + 0100000000000000000000000000000000000000000000000000000000; + + 01 + ffffffffffffffffffffffffffffffffffffffffffffffffffffffff + 0100000000000000000000000000000000000000000000000000000000; + + 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f80 + 80808080808080808080808080808080 + 0100000000000000000000000000000000; + + # --- Random data tests --- + + 272724be3cc4179a4b387bcd1acf24e1107be9bbb4dbd68408303df3537c83e0 + c80ff7173b00d75c83bb38948118fecd9c16ec3bc2d5d051057a1ad8dbfa3349 + ef371bd577c4eef6cef3b4619be823aeac92d5f777b1a6d50daa58cc2f76b729; + + 257099bff6868847d89969cfc691e1f5e0af7516360493a8dae919704eea7385 + b4408b380c648d50175dfa8b9c1d8aa68f71f67b540045ed3f92f2aa19145cb2 + d9b124f802eb1597eff7645b62af6c9c70216b918a04d9961a7c0c1a67fed037; + + 11978446632ed887ce26aeabf9997a9ae9600da7cb6d431e6ab5dc932b427eec + 652931ca2eb81d3113453615d16e60de08b3777a6060d7f1775c916253b1e666 + 76c0b61091e6f5b8e16be4c1cb07db78f21385222bce1b0fe2126df57ef46552; + + 73d3697b4f886a8b242c21cb39151055937f36a6000849d0d1e526ce666a7d52 + 209e8d770ab7352e5441f74af428a2e9b791dabb655fd78d8a722055e896d7fe + 9471f6f25a3f9fb9786e19162d3db33f4b1111616568215e5c5747244f015550; + + 3e47ae33e633861903e0960b1ef8c8c8900a659cb3e03a1cf1ba04eed5e3f93d + b844b1b685b21fce078e0db2b960e22dd1e81aac33062b6d9ed1ab68b8cbbd67 + f68c5fea6be5a5e70b6ea3bdd859aaf661f28048e6e6658a908bb0578eafb6a4; + + 23156b15f2b9a6598b6703cda3177d7432016bb388989d5e33a5cb8778aca38f + 77197a3167c282ed511bf0eb865be89624e4b5e1e9dd4b7d44acd59d41287639 + 9a2ee5475a7c2946dc82f4b92973660a56e621957275e8db7852a124b9d519c8; + + ed61746de1ab76f33cf25878088b24a389d79ecd65df792954a5788a887982a7 + b673af9ad91712c6d64f05cc14fbd503b04345aca5695ef26cad9ca1f1460496 + 01a3d52408bac289ba13415e441d86f9a73a1ae47a0b48d81bc153152c79bf873d; + + 46a147c2b345b5ba782b600d1811975cd6a75b9bb6fa6db6bd8c594ecead30b3 + 3dff366370a27aef1ec46b32c4946f90ef75c7263f71703be87074ba18705391 + 84a07e2623e830a996efcb3fdca606edc61d22c1f66bddf2a5fcce08e71d8444; + + a1756514e2f8c5805538ad1b85bafebeb1d4ba9c61d19fbf2f286518eeac08fe + 4646f60744b71c5d7e2a5f66250e0295fc6ddf5acae1f2397ad37403a6881e24 + e7bc5b1c27afe1ddd3630c81aac90154ae4299f72cb391f8a9fbd91c95342722; + + cf5f959a7c1d3d0027f62303d4a517bd5acadde74db6f18bee67aed2ee1bbb23 + 76e38874ce5c3b7fe616b20f2ace6cf550190d9bad4b2fd80bf6deaff8a329c5 + 0146431e0f4a7978800e0cd512ff7384b2aae3eb82fb022163fa5e8d82e6bee4e8; + + 1dee3d9ad0cc6212e5843a57d736fad4675c422efbbac6d625a0f45ee90b7d73 + d6df29c49292fe633ec60e597d0c5688eb0ba6c134b7c041689fed3e72535c55 + f4cd675f635f6076244a48b15443515d5267e8f0307287178e40e19d5b5ed9c8; + + 3ba228e4e40cb50141845ae8b7318b43c6643765ace7ce83a069f1787ece6058 + 06b3792dbbde4db5f47be20035524962224fdaa18be7dd9eda23f1671e6ad33d + 4255a2129feb02b736003ce8ec83d4a5e8b4120738cfac227a8de2df9d393395; + + e7ff758bb68a5a6106962113f72f9705dc0641ad029741f7c57a5320d030ad32 + 7fd185b393c432dba9892a0b67aa12a85be6e1643cdfe8404963fe92f4f668bb + 0167d0fb3f4a4e8d3cb01f4b1f5ed9a9ae37ed23113f772a380ede51b3c52715ed; + + a5bb634cb6ffda70661189874605f802cc34a8960a137130f238638d9a9e72c1 + ddccdab554733987e04a5aa8674b5eba27f594f37cdec51b3b5745dfa159aab7 + 0183883e020b7313f8465be42fad5156bcf42a3d8986f2364c2d8fa96d3bf81d78; + + 76888f3fc82690a4681e30b5f94efd08d03b7eb1c814ed01cde866847e3c75a4 + 78d0869abb1b1fafc582ccd8bb0c27d7ba51de9832d3b0cd8ca366d27d268788 + ef5915da8341b0542da0fd8eb45b24e08a8d5d49fae89dcf5a8bcd56fb62fd2c; + + 24fbb9214449c926753d15573ca07552ff219c97c43824182a6dbabed6872610 + be3795a426052f168129345d33c6dded8ae8de0e0cbdbcc7c2b3f3386031b548 + e3334ec56a4ef83cf66649b4706753408a0a7aa5d0f5e0dfed21adf736b8db58; + + 97b74ea8ef087496a84b73ee7d8713a13a511f40cc9a19f613a10891774fbc9a + fe8dd31272be1f79ee524d736c7fbd3a2c1718b918b072025612a1f2176cf53b + 01964521bb61c69410969dc161ea06d0db666837f9e54a8bf869b3aa838ebcb1d5; + + 66a6b572a25f6f97ec5b7e7e393bfd686b69c083cd673feab076b9923133a46a + e7b501c43dafc08bc521b15be8a1ca9dffe174c282111ea9eb0bac34fd0584b7 + 014e5bb736e00f3023b17d2fda21ddc8066b4b35464f785e949b8265c72e392921; + + 59a803f729f14d54c35de20cdf9ce5b8e2f430016448c80e9d3e2ec608f8bd67 + 7a5a9cf43d1d70e200c5bc7baf4dad57e5892866bb3ced09eb0ed096214509b3 + d402a0eb670ebe36c4239e888eea9310c87d58681f85b518884cff5c2a3dc71a; + + d26914575527153ca24945f0e83df5b0480c8840e1e6807b71d008068b082c7d + 281c235d8f8773649c75baba0c302f99f3c526c971cf3daf976deba0bdb3f38f + fa8537b4e4ae88a13ebf00aaf46e254a3bd1af0a53b5be2b093df3a748bc200c; +} + +usub { + + # --- Simple sanity tests --- + + 01 00 01; + 02 01 01; + 05 03 02; + + # --- Carry propagation tests --- + + 0100000000 01 ffffffff; + 010000000000000000 01 ffffffffffffffff; + + # --- Random data tests --- + + a024729f63161b8fbb711008eb863b9e2044a77ccc7bccf19437471e51a4beec + 9239ec16929055e3a156768fa1432c56d997ba51c1efbed4c791f062d95641a5 + 0dea8688d085c5ac1a1a99794a430f4746aced2b0a8c0e1ccca556bb784e7d47; + + 8ab8ea06c7afbdfe6636590f748fdd376a2dd9c708e7923541e134687fbfd526 + 8896da6b7c98b78a0ea2c9cae23d7065a94daea56d1c919a7db2583da936bd8d + 02220f9b4b17067457938f4492526cd1c0e02b219bcb009ac42edc2ad6891799; + + fedfecaf26399ad6eda68c7c5cada4aed095e82182e3df696cae47e521c382a4 + 7510069be2896480db0beedc6c5497e79bd7ac5e9fc14bf9ca460c7f99aa6834 + 89cfe61343b03656129a9d9ff0590cc734be3bc2e322936fa2683b6588191a70; + + ffb81ed18909fda98730e146735c21d3914122faf84882dc688237371825739b + d7eb8f85d95888d2c4dc7b9fbbe689e2ce529f8870b2487ce28d192ef3ac2317 + 27cc8f4bafb174d6c25465a6b77597f0c2ee837287963a5f85f51e0824795084; + + c3c2c77bc0867d30c58c1eb786ab7feed60f9e0e2dcfd6ed97725fff364c7b5b + a936ff836dd8dd063ab05e4fc7176e8c05a45ddaa7f701e4184b4fd371ce968a + 1a8bc7f852ada02a8adbc067bf941162d06b403385d8d5097f27102bc47de4d1; + + ef76a6e2dc6ba3317dcec6e338a20cf12eb852388204efe290a3b1536f6b198b + 3eb8d18b7903d682d713859f258ddbc13aae32392a4267b0cd1481c036ab5baf + b0bdd5576367ccaea6bb41441314312ff40a1fff57c28831c38f2f9338bfbddc; + + 5cf09a0f0488a077e2983b4a854c28fc7a11f7befc196824f7990fadacfc26db + 0f46fbc396b81c512b7a0ec003759de05a967101a3ec50b7cbf84f42708f396c + 4da99e4b6dd08426b71e2c8a81d68b1c1f7b86bd582d176d2ba0c06b3c6ced6f; + + ea9b202602ad3219e3d3a8fbaf042c3cec8a3d7f16923855b0ae67b8ebf57b50 + 850568cdebe8fe9f91c3d8bb4bc525158bd8590b235f46d6d556bf969e2f24f4 + 6595b75816c4337a520fd040633f072760b1e473f332f17edb57a8224dc6565c; + + fab03a9f849f408b4af55746316f8e3a81c6359b3c3ba1ebd1d8b9e7a983a03b + a60ecaf59c0c7d0ce3ef4d6d9006880efc9c6e0edcafbf7291b009e7b3cb03e4 + 54a16fa9e892c37e670609d8a169062b8529c78c5f8be2794028affff5b89c57; + + ef7de9bf497c4c47d323a379a42789925606f700e786622b280aec1ee6e13901 + 8a4197e881f1d2f6a09296e6d826ea628aec658b4bf7e9c436ab7e70746c4c87 + 653c51d6c78a795132910c92cc009f2fcb1a91759b8e7866f15f6dae7274ec7a; + + 9cf0d943545ee18ca59af6f547cfb45de41b1d52c996f482728fe68993d3a966 + 58ad4b10fc09cf4f4f4a1488e36ed3beb0a2a9e8c8ec042aba113b2144ff1939 + 44438e325855123d5650e26c6460e09f3378736a00aaf057b87eab684ed4902d; + + 3e0e637d1f4ff5b6d58549f8011ae0a885bbdcb5c478777417e6293c108c7c0c + 09e06b0b986110817123a2a5aad0c178bac3005315628424d849216a43b71ac4 + 342df87186eee5356461a752564a1f2fcaf8dc62af15f34f3f9d07d1ccd56148; + + c3b4cb636f76027a876150753e266774af9350d3e68713adcc39cff5e389e285 + a4abec0b5d38bc91310f3b9e3e12d0c4af2984ba710a6309544340ac3c94e121 + 1f08df58123d45e9565214d7001396b00069cc19757cb0a477f68f49a6f50164; + + 175402d43706fcdb3caf41cd8de6822447e39f3a0ed2f00d4d315a1cc03b5bfa + 0ffd7d0692776dbce6e112902472edba5ec4c1500412d9bcd24472da90889b7e + 075685cda48f8f1e55ce2f3d69739469e91eddea0ac016507aece7422fb2c07c; + + f6060bfae1e558606d44496967e0eafe805e6f60d1c4a8f886574c9d6c6989da + e933391716ffc61eda9c547e7bdd41799ecc56e05178ebd7e2068d32467aace6 + 0cd2d2e3cae5924192a7f4eaec03a984e1921880804bbd20a450bf6b25eedcf4; + + cfd8ba6b7173b72451f370c7a7dad7754ea2323e52f622c1490ff2d3ccf5753e + b4e23f1700a3fe1d5f0465cf3666235f1c7460ffebce87c8b8d551ceab09ed1b + 1af67b5470cfb906f2ef0af87174b416322dd13e67279af8903aa10521eb8823; + + ebf9500e9cda50607204618fa6cf2f29f2e0af023237034f1a3e72787364370d + 0e826c97712e73f32d850d4cf63925fe8c8ed86396350432b9971900a4068cbe + dd76e3772babdc6d447f5442b096092b6651d69e9c01ff1c60a75977cf5daa4f; + + c4f9d29310ea767aa8dd0af418447dd3dc2c220c48591f99b6dbf0521f7a5640 + 6d72f5441ca9dbafcbf4db9701d6c667c1d5376251de09468e3efbf1fb04cd95 + 5786dd4ef4409acadce82f5d166db76c1a56eaa9f67b1653289cf460247588ab; + + 91af1ae9122ba385deae3f9b478c8270a2d2221396fb3639b44e06e3a1ae9817 + 08966b342d42332d2155fe03fef2d3f84b415d1fda1168a5c63d0f9b86b77cce + 8918afb4e4e97058bd5841974899ae785790c4f3bce9cd93ee10f7481af71b49; + + 976e1fa5146093d794691c63d1aff7ceb5851bb6196909eb51fbe4640829b208 + 1e8a3a0a9050c307cd94a65793371f88eebe42ae8893b1ff984357d597c884d1 + 78e3e59a840fd0cfc6d4760c3e78d845c6c6d90790d557ebb9b88c8e70612d37; +} + +umul { + + # --- Simple sanity tests --- + + 01 00 00; + 00 01 00; + 01 45 45; + 45 01 45; + + # --- Random tests --- + + 4162c300b3e157e9cd1301d499c20121 + 10549901fc6dcb85882440087bd398ff + 042bc7ac8fe08ceefb098f286cdd84fd037906ead144324e361c488a221db7df; + + f4c0a35591d6567a3ead2846f4350141 + 58bb07247f8a7591b7acfa727118ad8d + 54d507b0e32175976a30766da14de0726a8ffbdc7ef0291a7389759422229dcd; + + 5d0965f58c9d794ca477ca2349900193 + 2cbff5f50dbae1965e3aec1108c36d17 + 104360ec53eef2e669285143dc0d01c9ccf31a77dc302bf8d45356feb794bb35; + + 1a438b12e1babb4c68ae4606694fd1be + 5bac6d40fdea39c2f1f6ce285f028d36 + 0967b3069413a0fac34c03fdf67e2f5187232be344bbc6011849688052d7e414; + + 59e648d1f656407efc7c9b622de6bc6f + 0dd07d6e4dc035816236aa0cd512e424 + 04d9e8da01ea1a42b1b9670a4a14694cd104406f346a0598b65e0ae58f135b9c; + + 55c69d7a662a945e6a535911e7abdfc4 + 9883a7ea2c89f5a873b5bae63cf5ac73 + 331a0a66497eb713fb09b260f8774aa97765c13bb040d7917a4b7cb9a321350c; + + bb15812991a5a01c6e803475d5f2f1c8 + 66782adade0952e8ab51a2fda6a5f611 + 4ae262dc95488914177d07869caf42dd008ecfc3c092df3007fca8702f603e48; + + b06a37683348e8e46ccd954ff0348a82 + e158b834e442cf83aa863dde751525b7 + 9b4a7e266b977f83598e6288efafd0f517d9658a2bda86adec7e1835143dccee; + + b7f66a5ca27d276bdbad5995aac0f676 + 8f05519b9acbe85369aad7a865a0bc5e + 66c677de9ba98e4c527c86b80ad1485c41782c3e0be53dba2f547fa0ff992754; + + b7f43225f41056548b095f359b6a3b83 + 966a8ba6772991700ead0e01bde39120 + 6c15a4d835ec2367ec41c566ce63a098c496aec8a5b041fc7c91e6601525a360; + + 87277faca81e1bb28e0e24e4bbf5e8c3 + 5f126e08716855110489045453e69dcc + 3231633f7a7eb05793df2c7761d793a634faeb021fda1a404f05b2edefe71264; + + 3358074e192e79ba42c186ead80404a9 + dc1df51ac8c3328107638e83b17f777a + 2c25a8688faf32cb8b1d4b454cd4a2ad1130df69188cd2ec44cc8806f8ebc78a; + + 7ad1d7a04f7588af0ff7bf29c13533c9 + 0785d4d4d5f1d25aa6dcf744662ab2d6 + 039bf2064b716e3befa638d510131596518b1d91833200ba19ae6aff15750c06; + + 8b8a4c2ef785abd1607b663b3088e37c + fcc67dfa767e06d97cfd5341ded07e42 + 89c854a034d2cc29ebb34f379d6a74a9996d261774b1e7ba965e98204001adf8; + + 1c9ea6a1b9aba96124dd8abfd3dd78b1 + 93ecdfc3f4c188819e777f082b77e4c6 + 108994f4961164206f1a97cc0f39edc29faf2bad99d164fc60c06ccff20ffce6; + + c6d9a8a4760fffb11ac2d38b62f62a89 + c0989f4e8aabd21f7a2b38ec27afb783 + 9599cb75abf86c37db000858bd671992ecde9d440cc765855287391f8f06b31b; + + 5d48ba3dba86c0e9d3922cab8d88c5b7 + 5186010a8c3fc4e3499534669a13f219 + 1db4d7602500cc34de718d5892f79db44096a6c6705cf6e9ca8b438cdfd74cdf; + + d009f15fd77915f113e471884e464462 + cad68bffeb24842cc083f5496b10e36a + a4d6328ac530f0615ca3b0aebeaf104960e120609c58710eee206cc3f3db3694; + + 343f0033e5648741936c20439bf044c3 + 9b26545821fb1270515566d970e566bb + 1fa9f7b01c40607bdc8f554e57555de879784cdb1eebfcc3a75918d27656ec71; + + 08d95fc1d6dd6b9423c7bb033598df0c + 6c03f5958677efd383509141bf257375 + 03bbd76f19ba19e3f255c24063f6384d4ac913d9e582392589a525195bcc547c; + + # --- Karatsuba regression --- + # + # This bug was caused by kmul (a) choosing the split point too low on + # odd-sized inputs and (b) not allocating enough workspace. + + 21a9269d7b8b63cf18faa933b3c868ba1e8cb3f00b57e197709abf96eeb9bf12e8fe22b3 + 0144c992b68e3ca712678215d5bc968702ccfea17717737ba501a38d26fa5091ba + 2ab495f91afd7c36f85ece6fd58577f995de88d62a98a07c6d9e3500ae67b0f100bc709d1f30894662774d0cadfba091788c427cc6f4bacb26e42cf92f6e4494e03c990e; + + # --- Larger number tests for Karatsuba --- + + 416e63549e2cf08fb225058b3545cb4a47cbf9 + de38c473c27f7bdef02a084192b3e17f435cf7 + 38cc3c7f360737411df7b52a222a3672c6e0d39f0a868479176a6143e1129d44d5aa61be493f; + + aa20b1355073f21c57530d2f90bc40e47ac463 + 8315dfa60e97ff3dab7a6f61fcec2cd5b6f127 + 571d43fda6ce14a78534ac72c50b58738d62630766a59a7cec1a63433e499b1b5eac5ef71e15; + + f641594177c8c364d922c659a8f7ae0460c7d74b266c8cc258ad5f + 5948dd29fc5172c37c31da6957779a1bebe452d8deba26c5d3d390 + 55e2cf27aa49f938584dca4044d944077e226206c6f8c7688e8760f3b5c106413fd0ef4b63a97991da86fd113ff4822a41f76913d270; + + a4170f55dfa135c4bdd3a921a8c1567eebc6b799fb62b0dd27b089 + 7b7d619e07a5d01427348c05605f67196b2923b074787c375977ac + 4f277232c75290f0c5fed384dba2aaa23fe4a360ea63ee45fb6c0134b36a09a9163f3c767d498b8dcd31e5deaef386d4a9b7d85b4b0c; + + 250e7a0c7035df81429572d3f772720e723b710d54b9eb5f16814117980f0559bf12b82e00c5b3904e + 1be3c88b01ce53a70c12f74dcc247823846ac6c06a9cb41b86794900006045f05e29da23b81523aa9f + 04097fbcf75616fef7b6b91680963f7e0cf1bf72bc5f453e46136fc92b20ae8a30d7ae7965f8271de854442b93562ebaa9ee09fba4a7b79ef8b26718b12424419dc301496dc0d6cfb04e4f7a3a3729046c72; + + af3148a72dcf1340f6b5a3b2fc1cacd7e6f9e60a13de5c91c37bb850f0e930683c2dc96882a9f62b76 + 48603cc656908b34c70ed826da8c3414d5845100f53cb6f9f370a4c7708a9b8ffd787537048f89493a + 3187b8818bf644805c880d189bbf606ca23e01431cf5b3b633db48a1202aa346f6a0e3958c7264fa1de2d92660345e820f4f3659cf0040a28fb9b725f7ab83610c9c056062326f776ce871696eede0507ebc; + + 0b1cc934a2f6244b93c8ac10881de20349d133642ac19fa0be3acacbf4429d0ec7bbad2f41534a693647b7c02e683cde249e36f008fb68e96de65c8a268eb1ea + 12444899c13f0ee85a4f47024f06d8a5746f0d9fec02e57c6d87a7bba17c1454fe6387bff5b96e38ce6142b9eebe249865c52b617b8966e6f93b16f612a91155 + cafcf1ea9f16a56f9ac4635d58992a789c51b6d7e53b5e1d8b59d5c1850c5c6ac2297839af44b29d5cf440772f98fd9d090ccec2d56adeb113bd3459d620b0b02679b72f3170ea8e2bd4486eebf2496d8be01cfe86923e5bbeb6f91582dfb95c6ef0a52cbc068081dc363b31dbd2ed80e3267d973ea39f82e276002eab9cb2; + + 3ba5a9c550b8cf6c3b87cc106b6551221a0dc90ac193ebcc526e4e5f53cf012fa6e05b155dcb3c4c0e1a90a01062a67ec434f6744195349194770711ea836a8b + 54f04f121d22db842523e9bf75727d5b0e9ef17e6d727918894927fade87ceeb2106684c4af7c49653425e29f7a91abf8adec4de2ca499df2534644397e454ac + 13ca59703f4c087c16a9a7bc7022904a37a469c1d0fd9fa7ffabe8f7d887fe1572c0bf5c75fde6913b565f8106bba9c26c9bbce190a9b8967112d74c0ac3d4ff9d2a385b96833e3c456d5601c74d8d2c9fff35abc60e7cc15d7c680f20757c13a415f1b8fbe3c6c32434aa36c528473dd20ea39f0e5ee22d1cd23040900d3164; + + # --- More Karatsuba bugs --- + + 3fef06998b0ddd140e01527426ea409b2b9e640f223dfd652229fd17eb99d44f6be6d4935505df676f48c8fcbfe2d5096345d6509267aa40c54d427f0cce45cd0f8fa7e4a22492d7ed4ffa45e3c0e5e3c25c841943fb2cecd6ee9275ae93c4e15e2d9f8f317c44c541ed52a6338b0fb9f7f7f4dea78cf7ef5201837c00a6d4d2 + 0260acc6378341b2b894dacab3a44b914f19292bb32898b155584a406161bb04ad9c14db20888dfcdab613b368b5c699305c4e9b226d90f9523fbcb6293407bd2bb18bf7bdba8539fb577f19b72124c2d83a2bc31f44366e917ddc705085b79fe9e0df0e98e4f6ae3df63d9b321382c18b95de1dc4d1db93b3092c9c6f8c9764 + 9802d5c5d5a73f9d4e694a8920f951ce4bfe80c13a35cd5332a556136b83495a2e9b4d2ed53aae1218d2e1c41349311f86b1ee1f2ad5cd3c5b264e8e68906ca45bd7d0fc8e8a5a9648f458cecba41fd0848a04f506bb11ddb378f3214085cf865ba5533cfd73b28b1e12784f447b156f59a3b68e6ec68303ddfce59ce33ca386ff3316e6a5e6f9b4201682aa9e59a6d7cb9315a492457640acca19fc7dc3a25a316fea9a0f1d32838b7f911650647f996551263c2d001fa1c720753afca316c7137300ff93f2ddd2846ce14c55d0ead626f681bd11707f9674905396a9bc9a889eae721ab6407586880a95575a968b43bdf50323627aa0fcddfa4e198b0008; +} + +usqr { + + # --- Sanity check tests --- + + 00 00; + 01 01; + 02 04; + ff fe01; + + # --- Random tests --- + + d573446554727d0f05ad3ccd03665c2f + b1f903b723d65fefeb935ef5c50ab18da09777b28b8a093adab73a5cb0a5d0a1; + + 27ed6604397ef6acdb3f1906e5c0be25 + 063a313b55fe82206c4e69624c2afd726dcf52c1efc9d0f81c948907f6baf159; + + 869593eda5bbb87109593218d3c99f86 + 46c0ee42519e3a8ce80f19b6bd60332254e1e144350898d77e803ce2c7d3ba24; + + 94edc3ffcbd975677c95b44e7f4a8164 + 56a3c77441629088100fea8b3e510352c9904877e9705b9e150e7b004735ef10; + + 4a3b7b546f9f15a09bd35d6de3b33f82 + 1586711ee4ddaaf121f7e4311d3e182948ed5569def0257e099be8d66b8d3e04; + + adf038609b8f95940806994831db9409 + 762e8d9c53ce25e6641019bd974169acd1aa3e95968b13e80c97d2120f006851; + + 337e87847e2ddf24444fac6f64c6cc66 + 0a5ba888786f7db6d9c28a7482545e31ce687996024edfdc05ae3a8480fab8a4; + + 0b2c882b8a7dcad93cffc77be4436e62 + 7cdb72d54cb539de9fc55d68b9ca4731ad6b1bef79fd0dd12c9c8d86e45d84; + + 298a1b9f23f7e77dc288c177a492843c + 06bd875ac41323efd9b958064f96e74d84faf58a2c43f4bec525750ff8bdee10; + + f58345742a51bd04c80b3791a688871e + eb74864080bb96f90ac10021b82af6ea9acd21af8b8c103739a14c06bf30a784; + + 0c720ed1384848bc57e6f92cd98541cd + 9ae434d07874574a5702724fcaf6d27f5686744f03aa444afe9762f9ebbe29; + + 37e91e1c9a3f237a08dda2e6919dbfa8 + 0c35ff381de29f85eb03c278ca9623be8603ac9f744c826d08e91630f38c1e40; + + 8b270d9328ea8561db59a8ac4e651d05 + 4ba36eb2f1fd6b0cbd6f71ac36aabe1be53e21ae9afd4c9ce1715456f53c2219; + + 5e64af22a077e8832538dc9ff235bea0 + 22ce1836b8b5c880ea1e00f95f339ee776d8edda0563e498c98f726efc31e400; + + 8e6d67cd33ac976b183475e54afdb715 + 4f3d8de934283d046ebdb7263c73978e60c2e68179cb3edf79c266dd867107b9; + + 27f566956e3fa7141088402630e929e8 + 063cb07f0ab7d5d22828664724da2dd261c14526d80f7760aa04b4f44f2c2240; + + e26c74de93a02296693ee98e552d5524 + c843ac4bcdcdc37c3ef17997e8d013d1d4ecff5a58a22e2be50d1e80f2f8ed10; + + ca53baed02dd4ba78cf7a3963b438395 + 9fe83e60c6b25a7b58d1f84a5905081769b4c5b5c9b1d63a5bec2110d19fd4b9; + + d6e517000ade8ef62963e890a472d530 + b463cf763a508b234fbf75a75781c97b5a9963b8f8456d23d05a2aa81048e900; + + c4245e0ce04fe1151ca17eb8aeb6e3e3 + 9647b52e4da6dc80171bd5495ab519835e871bf915ee7e59f1fe2ac165a05b49; + + # --- Large tests for Karatsuba --- + + 8390d2dfc9770526e8c4820e1cccca0e8e19d2 + 439d89bef1a65f537e59e74590df3ef10b7e78066ac2af7b5c910e1929de102b491b9f92b044; + + 26c4cb564d57970bc3dd00c0c1690c7f1a2e9a + 05df03a59c9e6ab7bfed79ff8f32811303e46f94c2e8d9abcab5bdac1040e7fdaf5a4bc3b4a4; + + 599b3cceca39690c06425127a95b84310cddef + 1f5d4e6a797662648e4b09abeee439415b76cae52e7cf9db1a54b7f99afb9c00b6130cce8521; + + 485b65b3d5edb34810402943ccfbe37a137f8f + 147389d69e9730f86b04a1782fd15611e6f8dc2e99abc812be0cb82efb2a1ad538aa7ac931e1; + + 5a243e54da1f87a8fe23c8b0988b3574aa77c1fe620a5d25b8e03295aebe6c6e135a17 + 1fbd80f54068ba081e793c1aad443094416a75e2e708337618e4ff02ca9dd26bad87cdc0f758342df39a56625c956c971b1f7f18f7d3cb6a1880a574bb7b06a6ca4a431e2e11; + + f5c57a7610feec56586de369136ee25aaf5d3861ad80033410c410658332ca856e4cce + ebf394bbb0d2d75ba78b75ae018c77f417cc1c67f0aa587d070980386e14f2b59d9a580d8d483b4df7f6a8d4a44ec8786a87d1da031bb5c288c3afc65d931471786c2412f5c4; + + 5bc4457e00bcacf257200a96eadf90359cbd9f6a2c2c69b5ea2e4c5d3939f0ce100c06 + 20e51fe210546e478bfb9d2b0418df921974417799951533f317498439caed52a75c4c66db81910b3fc4f4fb3711cc25f2b4ef151a2023b6e52e64e1d5b7dffb0b9b29509024; + + 4b51f1e0a9206173d39a0f1f4eea558dbd9d1ca2d41671b2d27b1b77391e76504e14c0 + 16291df497ccc32ee92a9037b78ff10828c2645dfbf91541f3a0d963892d59c5cd966ffe1e1ebb2dfe6f434fae44da11ae2d2357876b711feba596612c102b8905c8a6ae9000; + + 10f63541b2bc5a7d241f887d0b3d182dc473a06c4fb275259112b2fecc9455d7b1eb5b2e9b5c3646c35121d05f1ae99f1ad990c7f0e48b002bd5fdd253c68b56 + 011fb3729baf522bcaed9a966645754804b2cc80168de9f93544e17d5b6d6b81c516f68b72580257f15e3f95bc6eec22608c3055de04051598bf4a76975d111a59d6b02a2fc42de65926cee5d5b97b6c7fc85e00dd59bfdac2c95bc80b7657582b2853244e55b507594a83d5bd87b7a83016dbbc104ce596bdaaed6d98de80e4; + + 9e40b3c041505a5e266109f752d85ae3abcbdd28bfc70bbb2c7228bc1564ea893cdda0350689610b74babfe45b14da9708f28c22e3999c841fc70075dd0535cb + 61d3ee3baef64371ce0416d3f5a6e687903413ad06e85ebbffb9ea0ae9e8cc290fe9dc1cec429e0a294b18121ee29755baf4306861e092e5c1f1def03953f559766787a222368b64594b7be2eeea0698d1fc630446714e681210b5a66e0433b6c43038c0ff213cd14fc0a1fb71789d57b097ab44d859f8bc912f2a89a33baef9; + + d35af50f523d29f53bf0126ccddf4f3052ddb44eeaead360b5f36aad902ba105a921880cefb12caf5e1b3719a40596732d265e996e491f82ca2edf08adca131e + ae7f10487aecfa7f91217020f96a1cb00d81545deaf9730daa2c7113e84e76c7e54a1b14971d26750816a696d55622ae1dbd56befdc12a656e66e1d10e87c3bc209e0903635784af6d48a4d7ec84634efb91b7efbfff724bb50ace7d4684d2e72eb7eef84ed5cfd14a7602ceded675da541646febcaa285396b23338b8c57784; + + 3df659f884c6a31c5b332efc44fbd70fea46b81adb241fc651af038380f8c476a471f06382ebe55eba339d84edb33a03002ac505d93c61a42ba20e36a691c287 + 0eff53f178849510a118db72c5620423c2991365b06e8caa76300f3df554cf8830c9833f6ec1d33c850b1bb380e33a486a9963b63b5228229fd7e9bdd308bc810aa5e74ccc0e65a2af40c9a287c67e69e841495b0221110f35ed6319bda0dcb0b02174b666df4766eea05481f6a80fe4b93a06fe475d58ae3002303904bee331; +} + +udiv { + + # --- Simple tests --- + + 09 04 02 01; + ffe3 01 ffe3 00; + cdef fedc 00 cdef; + + # --- Random tests --- + + 8ab316d0d1a2e88535cf77c1172881ead70d592c59e9c5fbc16e4b0c4dc49481 + 18ca3bf7ee3c6d7bab3f144b015ccc6c25472843d346b461 + 059850f995ddeb799c + 02c1815029b766b96ad4507dc1af8151307961c6d161d065; + + 8117d1663ee63341eb8faeff304549f0f8b32d587acc2fd5597ea6a31625881d + dc85df77dfb61876805623bcbed325b99d00c2cd65c252c879 + 95dc734282eb19 + 395da02e8a6c66476467c4e04f328d8208cc411e3d1e96e14c; + + 63791966f2ad44a6df11bcc87c6b7c2400c74e69f7e3ca02fcac12b3bf56238b + a49e473b8f7539d89cdb002d73182558773eec10db93cc6049d8c5533e + 9ab11a + 65caf6833baa118b53c7bdc44a831605ca382b5993beead59f3971d13f; + + 9ca438db3e0f79305987292e8ec6174e6c313f7904ebb35a349a700e3ae63a37 + b24c93d499c7073b8f7aac718c1f12da1a8fc8bccdd47b49 + e0e779304869fdc1 + 46393cb15e38cbbc8a85698151a113f28081b4c8f6ed232e; + + 8214fd17858a4a913015412b5331eb9654faeb5156a674b1e5f6550a68957146 + c4f0ebaad6c0ee0111c57667ea8e0a254f3068f212949e20ededa89a7da6 + a917 + 3fde916ba21d19414d4316041420ca59d8b01aa2acf3f3ef106245c1915c; + + 55a487a70935360158bd55542eb46271f90f7312e77344c4ca6a580a80810612 + 8996dd0613f846 + 9f58fe011d73a8750454d9bffb55906e9bcf563e0c48b5b608 + 4cfd95e3e17fe2; + + 6a13e1be50ecdd7011f9ced42269615efb38fcd3e5477bc57377138cf1ff9519 + fda103ff99ff21 + 6b11bf2670bf080ef7c5aa0fa5989324e88e3e581c0e7507ba + 717db69e0d501f; + + 367aa8f5ba9ac4e8e2ea198b8af2c3b3081deab392ffc05715783b245a62a6fa + 72e2c37447f8bca34c4a39b130ea8e5c9a7d8b54564aa88ea773 + 7965572732ac + 08e8c03ebf398c63d71d8fd7ca4ece12367a8dde180ca650afb6; + + 6da07a0a1f9a7dd93e1f82be23fd5e7814b84fc74d4566dd83914adf368c1689 + 3cc71e64 + 01cdc15d7d825955c50ccca72fc5a16f9a7dd04363b12d8354d3088e51 + 299000e5; + + 001f5d985f594315d8c58f2d654304c8417f683b65d6d3246b89960e5f6c133c + 5bbc034d956a17998a30a3 + 5787e7e94449592b493486bd9a323f939ad9bfde + 1298fecf49a80ad72148e2; + + ae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c + c33c890f030644d88cc65f8ccf99c625c9b9fa21d4eb153e52ef89df54130855 + 00 + ae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c; + + 65901dcdad8dd0625d4d158f99b666fee10480d1df15e3bdac640584b9b746bc + d8a1d326fee87d55f39f15b5b2cfe71f5146083928 + 7805090edf620d22dac08f + 859c41164983547c03134b99530e25a0f874315964; + + 5d9e7037d70e822c2ce4b3d93f3e20d437a047aa94103296cc041e1b7ea0d9ae + d2b14235853f6bac6fdba208897d + 71c036bc8940293745e65c49f9b0bc1a8aa3 + 700473d994c1cd61ab24f661ed17; + + 3a826450bde36cf03de1d6829f7e21af52beb2655e2c902ed634f84e135b241c + 3023b54e1deda493ad0b4558 + 01372549e716f70dd3c6bb31f193682b7a9355a7fc + 04359aabd8bfdf8dd3ce797c; + + bdcfd9593348eb1567377e0d4f4bfe8a26acac14b56f7dfd82beddb4f11c2373 + 1f0356b60ad66f4fd7dda57cfc6d1aa374108bd4841127c8 + 061ed1e07aff1c094d + 0e313b6052859863725786d1459434762ccad8540bad244b; + + 293be875d1251920e18102446ceec021da8d8d24aabe49c5911d19ddc3db516d + b66e4ce3aa7390a9d888c5d22176bea5c36ae962ae8f252cdf3642556641271c + 00 + 293be875d1251920e18102446ceec021da8d8d24aabe49c5911d19ddc3db516d; + + 5f1085256c5fb856ceab16f2372b6b7024c7d1fcfa7039a0555bb1496c0bc92b + c46c1fcd4a8a9cb91775f901af0ab42e39015e09fc737ae2011899b34322cd + 7b + b091ddc98f1f09e065684e681146ddef6429ce2e24bd95bed4df704aca10ac; + + 82ea5bd086409cf3681e55e6133626ce9579db9eb01a0411db9c8521c3c66c2c + 605a13a7d4b75f1094260227cd4cab + 015bd5405d6bfd4571e54bc47a1b089abfd7 + 3074a3c84ec3bfa32e0db1b349738f; + + 3b68662228026ec9e9be8206d3226edd265552a3dbe15a7aa399eba05a69a6c3 + a0f4265e8f59474132846bfb15 + 5e7d40f138e2a107a52f85a0eb6f92a1c3ec97 + 1508f62d27e7fad09e3d423160; + + 82a5058150e570c9eef1f4e5d55d3cf261de28a17f4735caec8bb38e1813978a + 620d87bb63872a40fc2092b0ed7d3ec4b648be41 + 0155177e99a8a5113226ff8270 + 2ea2205327e66d75990cc999fc2380883ee4591a; + + # --- Bugs --- + + 1a923b3406cbe81b093ce418f6a73107f504502b2e3d1b200762fcf6062723de405cab0aea00000000000000000000000000000000 + 184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000 + 0117d3db34ad005954459be9abedd0e5deb4ea0000000000000000 + 00; + + ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff + 7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31d1b107fffffffffffffff + 02 01; + + 26737e 0ffffc 02 067386; +} diff --git a/math/t/mpx-gen b/math/t/mpx-gen new file mode 100755 index 0000000..891e4d6 --- /dev/null +++ b/math/t/mpx-gen @@ -0,0 +1,118 @@ +#! /usr/bin/awk -f +# +# Generate test vectors for MPX testing + +# --- Generate an `l'-byte hex number --- + +function r(l, i, s, x) +{ + if (!l) l = len; + s = ""; + for (i = 0; i < l; i++) { + x = int(rand() * 256); + s = s sprintf("%02X", x); + } + return (s); +} + +# --- Main code --- + +BEGIN { + + # --- Initialization --- + + i = 1; + if (i in ARGV) len = ARGV[i++]; else len = 32; + if (i in ARGV) op = ARGV[i++]; else op = "+"; + if (i in ARGV) rep = ARGV[i++]; else rep = 1; + + # --- Output filters --- + # + # This is complicated. `bc' emits numbers split over multiple lines with + # backslashes. It also doesn't pad to an even number of digits, which the + # test rig is expecting, or use lower-case, which looks nicer. + # + # The first bit matches a line ending with a backslash. If it finds one, + # it appends the next line, removes the backslash/newline pair, and loops + # around to the top. + # + # The next substitution translates the whole kaboodle into lower-case. + # + # The next one looks for an off number of hex digits and prepends a zero if + # it finds one. + # + # The one after that just indents by two spaces. The final one sticks a + # semicolon on the end. + + bc = "bc | sed '\ +:top\n\ +/\\\\$/ {\n\ + N\n\ + s/\\\\\\\n\ +//;\n\ + b top;\n\ +}\n\ +y/ABCDEF/abcdef/\n\ +s/^[0-9a-f]\\([0-9a-f][0-9a-f]\\)*$/0&/\n\ +s/^/ /\n\ +$ s/$/;/'"; + out = "sed 'y/ABCDEF/abcdef/; s/^/ /'" + + # --- Main code --- + + srand(); + + while (rep--) { + x = r(); + + print "obase = 16" | bc; + print "ibase = 16" | bc; + + # --- Shifting operations --- + + if (op == "<<" || op == ">>") { + y = int(rand() * len * 4) + int(rand() * len * 4); + rop = (op == "<<" ? "*" : "/"); + z = sprintf("%X", y); + print x, y | out; + print x, rop, "(2 ^ " z ")" | bc; + } + + # --- Division --- + + else if (op == "/") { + ylen = int(rand() * len) + 1; + y = r(ylen); + print x | out; + print y | out; + print x, "/", y | bc; + print x, "%", y | bc; + } + + # --- Squaring --- + + else if (op == "2") { + print x | out; + print x, "*", x | bc; + } + + # --- Other operations --- + + else { + y = r(); + if (op == "-" && x < y) { + t = x; x = y; y = t; + } + print x | out; + print y | out; + print x, op, y | bc; + } + + close(out); + close(bc); + if (rep) + print; + } + + exit 0; +} diff --git a/math/t/pgen b/math/t/pgen new file mode 100644 index 0000000..8d52d19 --- /dev/null +++ b/math/t/pgen @@ -0,0 +1,38 @@ +# Test vectors for prime number finder + +pgen { + 2 2; + 3 3; + 245 251; + + 4294967295 4294967311; + + # --- These can take a little while --- + + 498459898455435345676576789 498459898455435345676576793; + 40831929843180254171317254073271577309351168965431122042755102715326515941762786951037109689522493525769 40831929843180254171317254073271577309351168965431122042755102715326515941762786951037109689522493526197; + 166359567317705838255275971708060308423814413741683015010175247351623188739655446196925981468626681882384215574706593049022467680136399439302347043107836749816290369600677730213469006507173065402294688841278559283358390567733443050775707749725690534182003442070447739085348456478911335969765393755383551520173 166359567317705838255275971708060308423814413741683015010175247351623188739655446196925981468626681882384215574706593049022467680136399439302347043107836749816290369600677730213469006507173065402294688841278559283358390567733443050775707749725690534182003442070447739085348456478911335969765393755383551520257; +} + +primep { + -5 0; + -1 0; + 0 0; + 1 0; + 2 1; + 3 1; + 4 0; + 40301809 1; + 40301811 0; +} + +primeiter { + 0 2 3 5 7 11; + 2 2 3 5 7 11; + 3 3 5 7 11 13; + 4 5 7 11 13 17; + + 2309 2309 2311 2333 2339 2341; + 7878 7879 7883 7901 7907 7919; + 7879 7879 7883 7901 7907 7919; +} diff --git a/maurer.c b/maurer.c deleted file mode 100644 index a6dd31a..0000000 --- a/maurer.c +++ /dev/null @@ -1,235 +0,0 @@ -/* -*-c-*- - * - * $Id: maurer.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Maurer's universal statistical test - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include -#include - -#include "maurer.h" - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct bitscan { - const octet *p; - unsigned b; - uint32 a; -} bitscan; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @maurer_init@ --- * - * - * Arguments: @maurer_ctx *m@ = pointer to a context to initialize - * @unsigned l@ = number of bits to take at a time - * - * Returns: Minimum recommended amount of data to test. - * - * Use: Initializes a Maurer testing context. Note that @l@ values - * larger than 16 are not supported, and values less than 6 can - * give bizarre results. - */ - -unsigned long maurer_init(maurer_ctx *m, unsigned l) -{ - size_t i; - - assert(((void)"(maurer_init): chunks larger than 16 bits not supported", - 0 < l && l <= 16)); - - m->l = l; - m->a = 0; - m->b = 0; - m->n = 0; - m->x = 0; - - m->t = xmalloc(sizeof(unsigned long) << l); - for (i = 0; i < (1 << l); i++) - m->t[i] = 0; - return (((1000ul << l) * l + 7)/8); -} - -/* --- @bits@ --- * - * - * Arguments: @maurer_ctx *m@ = pointer to testing context - * @const octet **p@ = address of a buffer pointer - * @const octet *q@ = limit of the buffer pointer - * @unsigned *x@ = address to store next chunk - * - * Returns: Nonzero if some more bits arrived. - * - * Use: Reads some bits from a buffer. - */ - -static int bits(maurer_ctx *m, const octet **p, const octet *q, unsigned *x) -{ - while (m->b < m->l) { - if (*p >= q) - return (0); - m->a |= U8(*(*p)++) << m->b; - m->b += 8; - } - *x = m->a & ((1 << m->l) - 1); - m->a >>= m->l; - m->b -= m->l; - m->n++; - return (1); -} - -/* --- @maurer_test@ --- * - * - * Arguments: @maurer_ctx *m@ = pointer to a Maurer testing context - * @const void *buf@ = pointer to a buffer of data - * @size_t sz@ = size of the buffer - * - * Returns: --- - * - * Use: Scans a buffer of data and updates the testing context. - */ - -void maurer_test(maurer_ctx *m, const void *buf, size_t sz) -{ - const octet *p = buf, *l = p + sz; - unsigned long q = 10 << m->l; - unsigned x; - - /* --- Initialize the table --- */ - - while (m->n < q) { - if (!bits(m, &p, l, &x)) - return; - m->t[x] = m->n; - } - - /* --- Update the statistic --- */ - - while (bits(m, &p, l, &x)) { - m->x += log(m->n - m->t[x]); - m->t[x] = m->n; - } -} - -/* --- @maurer_done@ --- * - * - * Arguments: @maurer_ctx *m@ = pointer to a Maurer testing context - * - * Returns: The statistic %$Z_u = (X_u - \mu)/\sigma$%, which should be - * normally distributed with a mean of 0 and variance of 1. - * - * Use: Returns the result of Maurer's universal statistical test. - * Also frees the memory allocated during initialization. - * - * If insufficient data was received, the value @HUGE_VAL@ is - * returned. - */ - -double maurer_done(maurer_ctx *m) -{ - double x, mu, c, sigma; - unsigned long q = 10 << m->l, k; - - /* --- Table for means and variances --- */ - - struct { double mu, var_1; } vtab[] = { - { 0.7326495, 0.690 }, - { 1.5374383, 1.338 }, - { 2.4016068, 1.901 }, - { 3.3112247, 2.358 }, - { 4.2534266, 2.705 }, - { 5.2177052, 2.945 }, - { 6.1962507, 3.125 }, - { 7.1836656, 3.238 }, - { 8.1764248, 3.311 }, - { 9.1723243, 3.356 }, - { 10.170032 , 3.384 }, - { 11.168765 , 3.401 }, - { 12.168070 , 3.410 }, - { 13.167693 , 3.416 }, - { 14.167488 , 3.419 }, - { 15.167379 , 3.421 } - }; - - /* --- Check for bogus requests --- */ - - if (m->n < q) { - x = HUGE_VAL; - goto done; - } - - /* --- Do the maths --- * - * - * This produces %$X_u$%, which should be normally distributed with a mean - * and variance we can compute. - */ - - k = m->n - q; - x = m->x/(k * log(2)); - - /* --- Now translate this into %$Z_u$% distributed as %$N(0, 1)$% --- */ - - mu = vtab[m->l - 1].mu; - c = 0.7 - 0.8/m->l + (1.6 + 12.8/m->l) * pow(k, -4.0/m->l); - sigma = sqrt(c * c * vtab[m->l - 1].var_1 / k); - x = (x - mu)/sigma; - - /* --- Done (phew!) --- */ - -done: - xfree(m->t); - return (x); -} - -/* --- @maurer@ --- * - * - * Arguments: @const octet *p@ = pointer to a buffer of data - * @size_t sz@ = size of the buffer - * @unsigned l@ = number of bits to take at a time - * - * Returns: The statistic %$Z_u$%. - * - * Use: Simple interface to Maurer's universal statistical test. For - * large %$l$% you should use the more complicated restartable - * interface. - */ - -double maurer(const octet *p, size_t sz, unsigned l) -{ - maurer_ctx m; - - maurer_init(&m, l); - maurer_test(&m, p, sz); - return (maurer_done(&m)); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/maurer.h b/maurer.h deleted file mode 100644 index 7373660..0000000 --- a/maurer.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -*-c-*- - * - * $Id: maurer.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Maurer's universal statistical test - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MAURER_H -#define CATACOMB_MAURER_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct maurer_ctx { - unsigned l; /* Chunk size, in bits */ - uint32 a; /* Bitscanner accumulator */ - unsigned b; /* Number of bits in accumulator */ - unsigned long n; /* Number of chunks read so far */ - double x; /* Statistic value */ - unsigned long *t; /* Offset table */ -} maurer_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @maurer_init@ --- * - * - * Arguments: @maurer_ctx *m@ = pointer to a context to initialize - * @unsigned l@ = number of bits to take at a time - * - * Returns: Minimum recommended amount of data to test. - * - * Use: Initializes a Maurer testing context. Note that @l@ values - * larger than 16 are not supported, and values less than 6 can - * give bizarre results. - */ - -extern unsigned long maurer_init(maurer_ctx */*m*/, unsigned /*l*/); - -/* --- @maurer_test@ --- * - * - * Arguments: @maurer_ctx *m@ = pointer to a Maurer testing context - * @const void *buf@ = pointer to a buffer of data - * @size_t sz@ = size of the buffer - * - * Returns: --- - * - * Use: Scans a buffer of data and updates the testing context. - */ - -extern void maurer_test(maurer_ctx */*m*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @maurer_done@ --- * - * - * Arguments: @maurer_ctx *m@ = pointer to a Maurer testing context - * - * Returns: The statistic %$Z_u = (X_u - \mu)/\sigma$%, which should be - * normally distributed with a mean of 0 and variance of 1. - * - * Use: Returns the result of Maurer's universal statistical test. - * Also frees the memory allocated during initialization. - * - * If insufficient data was received, the value @HUGE_VAL@ is - * returned. - */ - -extern double maurer_done(maurer_ctx */*m*/); - -/* --- @maurer@ --- * - * - * Arguments: @const octet *p@ = pointer to a buffer of data - * @size_t sz@ = size of the buffer - * @unsigned l@ = number of bits to take at a time - * - * Returns: The statistic %$Z_u$%. - * - * Use: Simple interface to Maurer's universal statistical test. For - * large %$l$% you should use the more complicated restartable - * interface. - */ - -extern double maurer(const octet */*p*/, size_t /*sz*/, unsigned /*l*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/md2-tab.h b/md2-tab.h deleted file mode 100644 index 4217e77..0000000 --- a/md2-tab.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*-c-*- - * - * $Id: md2-tab.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Tables for MD2 - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MD2_TAB_H -#define CATACOMB_MD2_TAB_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- S-box table -------------------------------------------------------*/ - -#define MD2_S { \ - 0x29, 0x2e, 0x43, 0xc9, 0xa2, 0xd8, 0x7c, 0x01, \ - 0x3d, 0x36, 0x54, 0xa1, 0xec, 0xf0, 0x06, 0x13, \ - 0x62, 0xa7, 0x05, 0xf3, 0xc0, 0xc7, 0x73, 0x8c, \ - 0x98, 0x93, 0x2b, 0xd9, 0xbc, 0x4c, 0x82, 0xca, \ - 0x1e, 0x9b, 0x57, 0x3c, 0xfd, 0xd4, 0xe0, 0x16, \ - 0x67, 0x42, 0x6f, 0x18, 0x8a, 0x17, 0xe5, 0x12, \ - 0xbe, 0x4e, 0xc4, 0xd6, 0xda, 0x9e, 0xde, 0x49, \ - 0xa0, 0xfb, 0xf5, 0x8e, 0xbb, 0x2f, 0xee, 0x7a, \ - 0xa9, 0x68, 0x79, 0x91, 0x15, 0xb2, 0x07, 0x3f, \ - 0x94, 0xc2, 0x10, 0x89, 0x0b, 0x22, 0x5f, 0x21, \ - 0x80, 0x7f, 0x5d, 0x9a, 0x5a, 0x90, 0x32, 0x27, \ - 0x35, 0x3e, 0xcc, 0xe7, 0xbf, 0xf7, 0x97, 0x03, \ - 0xff, 0x19, 0x30, 0xb3, 0x48, 0xa5, 0xb5, 0xd1, \ - 0xd7, 0x5e, 0x92, 0x2a, 0xac, 0x56, 0xaa, 0xc6, \ - 0x4f, 0xb8, 0x38, 0xd2, 0x96, 0xa4, 0x7d, 0xb6, \ - 0x76, 0xfc, 0x6b, 0xe2, 0x9c, 0x74, 0x04, 0xf1, \ - 0x45, 0x9d, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, \ - 0x86, 0x5b, 0xcf, 0x65, 0xe6, 0x2d, 0xa8, 0x02, \ - 0x1b, 0x60, 0x25, 0xad, 0xae, 0xb0, 0xb9, 0xf6, \ - 0x1c, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7e, 0x0f, \ - 0x55, 0x47, 0xa3, 0x23, 0xdd, 0x51, 0xaf, 0x3a, \ - 0xc3, 0x5c, 0xf9, 0xce, 0xba, 0xc5, 0xea, 0x26, \ - 0x2c, 0x53, 0x0d, 0x6e, 0x85, 0x28, 0x84, 0x09, \ - 0xd3, 0xdf, 0xcd, 0xf4, 0x41, 0x81, 0x4d, 0x52, \ - 0x6a, 0xdc, 0x37, 0xc8, 0x6c, 0xc1, 0xab, 0xfa, \ - 0x24, 0xe1, 0x7b, 0x08, 0x0c, 0xbd, 0xb1, 0x4a, \ - 0x78, 0x88, 0x95, 0x8b, 0xe3, 0x63, 0xe8, 0x6d, \ - 0xe9, 0xcb, 0xd5, 0xfe, 0x3b, 0x00, 0x1d, 0x39, \ - 0xf2, 0xef, 0xb7, 0x0e, 0x66, 0x58, 0xd0, 0xe4, \ - 0xa6, 0x77, 0x72, 0xf8, 0xeb, 0x75, 0x4b, 0x0a, \ - 0x31, 0x44, 0x50, 0xb4, 0x8f, 0xed, 0x1f, 0x1a, \ - 0xdb, 0x99, 0x8d, 0x33, 0x9f, 0x11, 0x83, 0x14 \ -} - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/md2.c b/md2.c deleted file mode 100644 index 987eb39..0000000 --- a/md2.c +++ /dev/null @@ -1,223 +0,0 @@ -/* -*-c-*- - * - * $Id: md2.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The MD2 message digest function - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "md2.h" -#include "md2-tab.h" - -/*----- Tables ------------------------------------------------------------*/ - -static const octet s[256] = MD2_S; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @md2_compress@ --- * - * - * Arguments: @md2_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: MD2 compression and checksum function. - */ - -void md2_compress(md2_ctx *ctx, const void *sbuf) -{ - unsigned i; - unsigned t; - octet x[MD2_BUFSZ]; - octet y[MD2_BUFSZ]; - - /* --- Handy macro for doing something lots of times --- */ - -#define DO(what, where) do { \ - what(where, 0); what(where, 1); what(where, 2); what(where, 3); \ - what(where, 4); what(where, 5); what(where, 6); what(where, 7); \ - what(where, 8); what(where, 9); what(where, 10); what(where, 11); \ - what(where, 12); what(where, 13); what(where, 14); what(where, 15); \ -} while (0) - - /* --- Do the hashing first to avoid corrupting the checksum --- */ - - memcpy(x, sbuf, sizeof(x)); -#define X(z, i) y[i] = z[i] ^ ctx->h[i] - DO(X, x); -#undef X - - t = 0; - for (i = 0; i < 18; i++) { -#define X(z, i) t = z[i] ^= s[t]; - DO(X, ctx->h); - DO(X, x); - DO(X, y); -#undef X - t = U8(t + i); - } - - /* --- Now compute the checksum --- */ - - t = ctx->c[MD2_BUFSZ - 1]; -#define X(z, i) t = ctx->c[i] ^= s[z[i] ^ t] - DO(X, ((const octet *)sbuf)); -#undef X - -#undef DO -} - -/* --- @md2_init@ --- * - * - * Arguments: @md2_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void md2_init(md2_ctx *ctx) -{ - memset(ctx->c, 0, sizeof(ctx->c)); - memset(ctx->h, 0, sizeof(ctx->h)); - ctx->off = 0; -} - -/* --- @md2_set@ --- * - * - * Arguments: @md2_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -void md2_set(md2_ctx *ctx, const void *buf, unsigned long count) -{ - const octet *p = buf; - memcpy(ctx->h, p, MD2_BUFSZ); - memcpy(ctx->c, p + MD2_BUFSZ, MD2_BUFSZ); - ctx->off = 0; -} - -/* --- @md2_hash@ --- * - * - * Arguments: @md2_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void md2_hash(md2_ctx *ctx, const void *buf, size_t sz) -{ - const octet *bbuf = (octet *)buf; - - /* --- Code automatically expanded from @HASH_BUFFER@ and tidied --- */ - - if (ctx->off + sz < MD2_BUFSZ) { - memcpy(ctx->buf + ctx->off, bbuf, sz); - ctx->off += sz; - } else { - if (ctx->off) { - size_t s = MD2_BUFSZ - ctx->off; - memcpy(ctx->buf + ctx->off, bbuf, s); - md2_compress(ctx, ctx->buf); - sz -= s; - bbuf += s; - } - while (sz >= MD2_BUFSZ) { - md2_compress(ctx, bbuf); - sz -= MD2_BUFSZ; bbuf += MD2_BUFSZ; - } - if (sz) - memcpy(ctx->buf, bbuf, sz); - ctx->off = sz; - } -} - -/* --- @md2_done@ --- * - * - * Arguments: @md2_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -void md2_done(md2_ctx *ctx, void *hash) -{ - unsigned pad = MD2_BUFSZ - ctx->off; - unsigned i; - for (i = ctx->off; i < MD2_BUFSZ; i++) - ctx->buf[i] = pad; - md2_compress(ctx, ctx->buf); - md2_compress(ctx, ctx->c); - memcpy(hash, ctx->h, MD2_BUFSZ); -} - -/* --- @md2_state@ --- * - * - * Arguments: @md2_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @md2_set@. - */ - -unsigned long md2_state(md2_ctx *ctx, void *state) -{ - octet *p = state; - memcpy(p, ctx->h, MD2_BUFSZ); - memcpy(p + MD2_BUFSZ, ctx->c, MD2_BUFSZ); - return (0); -} - -/* --- Generic interface --- */ - -GHASH_DEF(MD2, md2) - -/* --- Test code --- */ - -HASH_TEST(MD2, md2) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/md2.h b/md2.h deleted file mode 100644 index 4d2b884..0000000 --- a/md2.h +++ /dev/null @@ -1,158 +0,0 @@ -/* -*-c-*- - * - * $Id: md2.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The MD2 message digest function - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the MD2 hash function ------------------------------------* - * - * MD2 was designed by Ron Rivest. It's not recommended for new applications - * because only the `checksum' part of the function resists collision-finding - * attacks. It's not very fast either. However, it's still used in - * standards, and having it available can be useful. - */ - -#ifndef CATACOMB_MD2_H -#define CATACOMB_MD2_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define MD2_BUFSZ 16 -#define MD2_HASHSZ 16 -#define MD2_STATESZ 32 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct md2_ctx { - octet c[MD2_BUFSZ]; /* Checksum buffer */ - octet h[MD2_BUFSZ]; /* Hash result buffer */ - octet buf[MD2_BUFSZ]; /* Input buffer */ - unsigned off; /* Offset into buffer */ -} md2_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @md2_compress@ --- * - * - * Arguments: @md2_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: MD2 compression function. - */ - -extern void md2_compress(md2_ctx */*ctx*/, const void */*sbuf*/); - -/* --- @md2_init@ --- * - * - * Arguments: @md2_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -extern void md2_init(md2_ctx */*ctx*/); - -/* --- @md2_set@ --- * - * - * Arguments: @md2_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -extern void md2_set(md2_ctx */*ctx*/, const void */*buf*/, - unsigned long /*count*/); - -/* --- @md2_hash@ --- * - * - * Arguments: @md2_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -extern void md2_hash(md2_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/); - -/* --- @md2_done@ --- * - * - * Arguments: @md2_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -extern void md2_done(md2_ctx */*ctx*/, void */*hash*/); - -/* --- @md2_state@ --- * - * - * Arguments: @md2_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @md2_set@. - */ - -extern unsigned long md2_state(md2_ctx */*ctx*/, void */*state*/); - -/*----- Generic hash interface --------------------------------------------*/ - -extern const gchash md2; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/md4.c b/md4.c deleted file mode 100644 index 5d43817..0000000 --- a/md4.c +++ /dev/null @@ -1,259 +0,0 @@ -/* -*-c-*- - * - * $Id: md4.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * The MD4 message digest function - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "md4.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @md4_compress@ --- * - * - * Arguments: @md4_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: RIPEMD-160 compression function. - */ - -void md4_compress(md4_ctx *ctx, const void *sbuf) -{ - uint32 a, b, c, d; - uint32 buf[16]; - - /* --- Fetch the chaining variables --- */ - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - - /* --- Fetch the buffer contents --- */ - - { - int i; - const octet *p; - - for (i = 0, p = sbuf; i < 16; i++, p += 4) - buf[i] = LOAD32_L(p); - } - - /* --- Definitions for round functions --- */ - -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) - -#define T(w, x, y, z, i, r, k, f) do { \ - uint32 _t = w + f(x, y, z) + buf[i] + k; \ - w = ROL32(_t, r); \ -} while (0) - -#define FF(w, x, y, z, i, r) T(w, x, y, z, i, r, 0x00000000, F) -#define GG(w, x, y, z, i, r) T(w, x, y, z, i, r, 0x5a827999, G) -#define HH(w, x, y, z, i, r) T(w, x, y, z, i, r, 0x6ed9eba1, H) - - /* --- The main compression function --- */ - - FF(a, b, c, d, 0, 3); - FF(d, a, b, c, 1, 7); - FF(c, d, a, b, 2, 11); - FF(b, c, d, a, 3, 19); - FF(a, b, c, d, 4, 3); - FF(d, a, b, c, 5, 7); - FF(c, d, a, b, 6, 11); - FF(b, c, d, a, 7, 19); - FF(a, b, c, d, 8, 3); - FF(d, a, b, c, 9, 7); - FF(c, d, a, b, 10, 11); - FF(b, c, d, a, 11, 19); - FF(a, b, c, d, 12, 3); - FF(d, a, b, c, 13, 7); - FF(c, d, a, b, 14, 11); - FF(b, c, d, a, 15, 19); - - GG(a, b, c, d, 0, 3); - GG(d, a, b, c, 4, 5); - GG(c, d, a, b, 8, 9); - GG(b, c, d, a, 12, 13); - GG(a, b, c, d, 1, 3); - GG(d, a, b, c, 5, 5); - GG(c, d, a, b, 9, 9); - GG(b, c, d, a, 13, 13); - GG(a, b, c, d, 2, 3); - GG(d, a, b, c, 6, 5); - GG(c, d, a, b, 10, 9); - GG(b, c, d, a, 14, 13); - GG(a, b, c, d, 3, 3); - GG(d, a, b, c, 7, 5); - GG(c, d, a, b, 11, 9); - GG(b, c, d, a, 15, 13); - - HH(a, b, c, d, 0, 3); - HH(d, a, b, c, 8, 9); - HH(c, d, a, b, 4, 11); - HH(b, c, d, a, 12, 15); - HH(a, b, c, d, 2, 3); - HH(d, a, b, c, 10, 9); - HH(c, d, a, b, 6, 11); - HH(b, c, d, a, 14, 15); - HH(a, b, c, d, 1, 3); - HH(d, a, b, c, 9, 9); - HH(c, d, a, b, 5, 11); - HH(b, c, d, a, 13, 15); - HH(a, b, c, d, 3, 3); - HH(d, a, b, c, 11, 9); - HH(c, d, a, b, 7, 11); - HH(b, c, d, a, 15, 15); - - /* --- Update the chaining variables --- */ - - ctx->a += a; - ctx->b += b; - ctx->c += c; - ctx->d += d; -} - -/* --- @md4_init@ --- * - * - * Arguments: @md4_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void md4_init(md4_ctx *ctx) -{ - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; - ctx->off = 0; - ctx->nl = ctx->nh = 0; -} - -/* --- @md4_set@ --- * - * - * Arguments: @md4_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -void md4_set(md4_ctx *ctx, const void *buf, unsigned long count) -{ - const octet *p = buf; - ctx->a = LOAD32_L(p + 0); - ctx->b = LOAD32_L(p + 4); - ctx->c = LOAD32_L(p + 8); - ctx->d = LOAD32_L(p + 12); - ctx->off = 0; - ctx->nl = U32(count); - ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); -} - -/* --- @md4_hash@ --- * - * - * Arguments: @md4_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void md4_hash(md4_ctx *ctx, const void *buf, size_t sz) -{ - HASH_BUFFER(MD4, md4, ctx, buf, sz); -} - -/* --- @md4_done@ --- * - * - * Arguments: @md4_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -void md4_done(md4_ctx *ctx, void *hash) -{ - octet *p = hash; - HASH_MD5STRENGTH(MD4, md4, ctx); - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); -} - -/* --- @md4_state@ --- * - * - * Arguments: @md4_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @md4_set@. - */ - -unsigned long md4_state(md4_ctx *ctx, void *state) -{ - octet *p = state; - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); - return (ctx->nl | ((ctx->nh >> 16) >> 16)); -} - -/* --- Generic interface --- */ - -GHASH_DEF(MD4, md4) - -/* --- Test rig --- */ - -HASH_TEST(MD4, md4) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/md4.h b/md4.h deleted file mode 100644 index d33d8ce..0000000 --- a/md4.h +++ /dev/null @@ -1,159 +0,0 @@ -/* -*-c-*- - * - * $Id: md4.h,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * The MD4 message digest function - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the MD4 hash function ------------------------------------* - * - * MD4 was designed by Ron Rivest. It's now well and truly broken: not only - * have collisions been discovered, a slightly cut-down version has been - * shown to be non-preimage-resistant. On the other hand, MD4 is fast and - * makes a good heavy-duty checksum. Just don't rely on it being - * cryptographically strong, 'cos it ain't. - */ - -#ifndef CATACOMB_MD4_H -#define CATACOMB_MD4_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define MD4_BUFSZ 64 -#define MD4_HASHSZ 16 -#define MD4_STATESZ 16 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct md4_ctx { - uint32 a, b, c, d; /* Chaining variables */ - uint32 nl, nh; /* Byte count so far */ - unsigned off; /* Offset into buffer */ - octet buf[MD4_BUFSZ]; /* Accumulation buffer */ -} md4_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @md4_compress@ --- * - * - * Arguments: @md4_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: MD4 compression function. - */ - -extern void md4_compress(md4_ctx */*ctx*/, const void */*sbuf*/); - -/* --- @md4_init@ --- * - * - * Arguments: @md4_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -extern void md4_init(md4_ctx */*ctx*/); - -/* --- @md4_set@ --- * - * - * Arguments: @md4_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -extern void md4_set(md4_ctx */*ctx*/, const void */*buf*/, - unsigned long /*count*/); - -/* --- @md4_hash@ --- * - * - * Arguments: @md4_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -extern void md4_hash(md4_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/); - -/* --- @md4_done@ --- * - * - * Arguments: @md4_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -extern void md4_done(md4_ctx */*ctx*/, void */*hash*/); - -/* --- @md4_state@ --- * - * - * Arguments: @md4_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @md4_set@. - */ - -extern unsigned long md4_state(md4_ctx */*ctx*/, void */*state*/); - -/*----- Generic hash interface --------------------------------------------*/ - -extern const gchash md4; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/md5.c b/md5.c deleted file mode 100644 index a062c72..0000000 --- a/md5.c +++ /dev/null @@ -1,278 +0,0 @@ -/* -*-c-*- - * - * $Id: md5.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * The MD5 message digest function - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "md5.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @md5_compress@ --- * - * - * Arguments: @md5_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: MD5 compression function. - */ - -void md5_compress(md5_ctx *ctx, const void *sbuf) -{ - uint32 a, b, c, d; - uint32 buf[16]; - - /* --- Fetch the chaining variables --- */ - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - - /* --- Fetch the buffer contents --- */ - - { - int i; - const octet *p; - - for (i = 0, p = sbuf; i < 16; i++, p += 4) - buf[i] = LOAD32_L(p); - } - - /* --- Definitions for round functions --- */ - -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define I(x, y, z) ((y) ^ ((x) | ~(z))) - -#define T(w, x, y, z, i, r, k, f) do { \ - uint32 _t = w + f(x, y, z) + buf[i] + k; \ - w = ROL32(_t, r) + x; \ -} while (0) - -#define FF(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, F) -#define GG(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, G) -#define HH(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, H) -#define II(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, I) - - /* --- The main compression function --- */ - - FF(a, b, c, d, 0, 7, 0xd76aa478); - FF(d, a, b, c, 1, 12, 0xe8c7b756); - FF(c, d, a, b, 2, 17, 0x242070db); - FF(b, c, d, a, 3, 22, 0xc1bdceee); - FF(a, b, c, d, 4, 7, 0xf57c0faf); - FF(d, a, b, c, 5, 12, 0x4787c62a); - FF(c, d, a, b, 6, 17, 0xa8304613); - FF(b, c, d, a, 7, 22, 0xfd469501); - FF(a, b, c, d, 8, 7, 0x698098d8); - FF(d, a, b, c, 9, 12, 0x8b44f7af); - FF(c, d, a, b, 10, 17, 0xffff5bb1); - FF(b, c, d, a, 11, 22, 0x895cd7be); - FF(a, b, c, d, 12, 7, 0x6b901122); - FF(d, a, b, c, 13, 12, 0xfd987193); - FF(c, d, a, b, 14, 17, 0xa679438e); - FF(b, c, d, a, 15, 22, 0x49b40821); - - GG(a, b, c, d, 1, 5, 0xf61e2562); - GG(d, a, b, c, 6, 9, 0xc040b340); - GG(c, d, a, b, 11, 14, 0x265e5a51); - GG(b, c, d, a, 0, 20, 0xe9b6c7aa); - GG(a, b, c, d, 5, 5, 0xd62f105d); - GG(d, a, b, c, 10, 9, 0x02441453); - GG(c, d, a, b, 15, 14, 0xd8a1e681); - GG(b, c, d, a, 4, 20, 0xe7d3fbc8); - GG(a, b, c, d, 9, 5, 0x21e1cde6); - GG(d, a, b, c, 14, 9, 0xc33707d6); - GG(c, d, a, b, 3, 14, 0xf4d50d87); - GG(b, c, d, a, 8, 20, 0x455a14ed); - GG(a, b, c, d, 13, 5, 0xa9e3e905); - GG(d, a, b, c, 2, 9, 0xfcefa3f8); - GG(c, d, a, b, 7, 14, 0x676f02d9); - GG(b, c, d, a, 12, 20, 0x8d2a4c8a); - - HH(a, b, c, d, 5, 4, 0xfffa3942); - HH(d, a, b, c, 8, 11, 0x8771f681); - HH(c, d, a, b, 11, 16, 0x6d9d6122); - HH(b, c, d, a, 14, 23, 0xfde5380c); - HH(a, b, c, d, 1, 4, 0xa4beea44); - HH(d, a, b, c, 4, 11, 0x4bdecfa9); - HH(c, d, a, b, 7, 16, 0xf6bb4b60); - HH(b, c, d, a, 10, 23, 0xbebfbc70); - HH(a, b, c, d, 13, 4, 0x289b7ec6); - HH(d, a, b, c, 0, 11, 0xeaa127fa); - HH(c, d, a, b, 3, 16, 0xd4ef3085); - HH(b, c, d, a, 6, 23, 0x04881d05); - HH(a, b, c, d, 9, 4, 0xd9d4d039); - HH(d, a, b, c, 12, 11, 0xe6db99e5); - HH(c, d, a, b, 15, 16, 0x1fa27cf8); - HH(b, c, d, a, 2, 23, 0xc4ac5665); - - II(a, b, c, d, 0, 6, 0xf4292244); - II(d, a, b, c, 7, 10, 0x432aff97); - II(c, d, a, b, 14, 15, 0xab9423a7); - II(b, c, d, a, 5, 21, 0xfc93a039); - II(a, b, c, d, 12, 6, 0x655b59c3); - II(d, a, b, c, 3, 10, 0x8f0ccc92); - II(c, d, a, b, 10, 15, 0xffeff47d); - II(b, c, d, a, 1, 21, 0x85845dd1); - II(a, b, c, d, 8, 6, 0x6fa87e4f); - II(d, a, b, c, 15, 10, 0xfe2ce6e0); - II(c, d, a, b, 6, 15, 0xa3014314); - II(b, c, d, a, 13, 21, 0x4e0811a1); - II(a, b, c, d, 4, 6, 0xf7537e82); - II(d, a, b, c, 11, 10, 0xbd3af235); - II(c, d, a, b, 2, 15, 0x2ad7d2bb); - II(b, c, d, a, 9, 21, 0xeb86d391); - - /* --- Update the chaining variables --- */ - - ctx->a += a; - ctx->b += b; - ctx->c += c; - ctx->d += d; -} - -/* --- @md5_init@ --- * - * - * Arguments: @md5_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void md5_init(md5_ctx *ctx) -{ - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; - ctx->off = 0; - ctx->nl = ctx->nh = 0; -} - -/* --- @md5_set@ --- * - * - * Arguments: @md5_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -void md5_set(md5_ctx *ctx, const void *buf, unsigned long count) -{ - const octet *p = buf; - ctx->a = LOAD32_L(p + 0); - ctx->b = LOAD32_L(p + 4); - ctx->c = LOAD32_L(p + 8); - ctx->d = LOAD32_L(p + 12); - ctx->off = 0; - ctx->nl = U32(count); - ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); -} - -/* --- @md5_hash@ --- * - * - * Arguments: @md5_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void md5_hash(md5_ctx *ctx, const void *buf, size_t sz) -{ - HASH_BUFFER(MD5, md5, ctx, buf, sz); -} - -/* --- @md5_done@ --- * - * - * Arguments: @md5_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -void md5_done(md5_ctx *ctx, void *hash) -{ - octet *p = hash; - HASH_MD5STRENGTH(MD5, md5, ctx); - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); -} - -/* --- @md5_state@ --- * - * - * Arguments: @md5_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @md5_set@. - */ - -unsigned long md5_state(md5_ctx *ctx, void *state) -{ - octet *p = state; - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); - return (ctx->nl | ((ctx->nh << 16) << 16)); -} - -/* --- Generic interface --- */ - -GHASH_DEF(MD5, md5) - -/* --- Test code --- */ - -HASH_TEST(MD5, md5) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/md5.h b/md5.h deleted file mode 100644 index 291ceca..0000000 --- a/md5.h +++ /dev/null @@ -1,160 +0,0 @@ -/* -*-c-*- - * - * $Id: md5.h,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * The MD5 message digest function - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the MD5 hash function ------------------------------------* - * - * MD5 was designed by Ron Rivest. It was intended to be a more conservative - * design than the slightly earlier MD4, and indeed while MD4 has been pretty - * much demolished by subsequent cryptanalysis, MD5 is still standing - * shakily. It's provided here not because the author recommends its use but - * because it's a common standard, and is often handy in non-cryptographic - * applications. It's also still useful in constructions such as HMAC. - */ - -#ifndef CATACOMB_MD5_H -#define CATACOMB_MD5_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define MD5_BUFSZ 64 -#define MD5_HASHSZ 16 -#define MD5_STATESZ 16 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct md5_ctx { - uint32 a, b, c, d; /* Chaining variables */ - uint32 nl, nh; /* Byte count so far */ - unsigned off; /* Offset into buffer */ - octet buf[MD5_BUFSZ]; /* Accumulation buffer */ -} md5_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @md5_compress@ --- * - * - * Arguments: @md5_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: MD5 compression function. - */ - -extern void md5_compress(md5_ctx */*ctx*/, const void */*sbuf*/); - -/* --- @md5_init@ --- * - * - * Arguments: @md5_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -extern void md5_init(md5_ctx */*ctx*/); - -/* --- @md5_set@ --- * - * - * Arguments: @md5_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -extern void md5_set(md5_ctx */*ctx*/, const void */*buf*/, - unsigned long /*count*/); - -/* --- @md5_hash@ --- * - * - * Arguments: @md5_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -extern void md5_hash(md5_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/); - -/* --- @md5_done@ --- * - * - * Arguments: @md5_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -extern void md5_done(md5_ctx */*ctx*/, void */*hash*/); - -/* --- @md5_state@ --- * - * - * Arguments: @md5_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @md5_set@. - */ - -extern unsigned long md5_state(md5_ctx */*ctx*/, void */*state*/); - -/*----- Generic hash interface --------------------------------------------*/ - -extern const gchash md5; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mgf-def.h b/mgf-def.h deleted file mode 100644 index 6d9f4e5..0000000 --- a/mgf-def.h +++ /dev/null @@ -1,460 +0,0 @@ -/* -*-c-*- - * - * $Id: mgf-def.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Definitions for the MGF-1 mask generator - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MGF_DEF_H -#define CATACOMB_MGF_DEF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include -#include - -#ifndef CATACOMB_ARENA_H -# include "arena.h" -#endif - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -#ifndef CATACOMB_PARANOIA_H -# include "paranoia.h" -#endif - -/*----- Macros ------------------------------------------------------------*/ - -#define MGF_DEF(PRE, pre) \ - \ -/* --- Useful constants --- */ \ - \ -const octet pre##_mgfkeysz[] = { KSZ_ANY, PRE##_HASHSZ }; \ - \ -/* --- @pre_mgfkeybegin@, @pre_mgfkeyadd@ --- * \ - * \ - * Arguments: @pre_mgfctx *k@ = pointer to context to initialize \ - * @const void *p@ = pointer to data to contribute \ - * \ - * Returns: --- \ - * \ - * Use: A multi-step keying procedure for initializing an MGF \ - * context. The data is contributed to a hashing context \ - * which is then used for mask generation. If you only \ - * have a fixed buffer, you can save a lot of effort by \ - * simply calling @pre_mgfinit@. \ - */ \ - \ -void pre##_mgfkeybegin(pre##_mgfctx *k) \ -{ \ - k->c = 0; \ - k->bsz = 0; \ - pre##_init(&k->k); \ -} \ - \ -void pre##_mgfkeyadd(pre##_mgfctx *k, const void *p, size_t sz) \ -{ \ - pre##_hash(&k->k, p, sz); \ -} \ - \ -/* ---- @pre_mgfinit@ --- * \ - * \ - * Arguments: @pre_mgfctx *k@ = pointer to context to initialize \ - * @const void *p@ = pointer to data to contribute \ - * @size_t sz@ = size of data to contribute \ - * \ - * Returns: --- \ - * \ - * Use: A simpler interface to initialization if all of your \ - * keying material is in one place. \ - */ \ - \ -void pre##_mgfinit(pre##_mgfctx *k, const void *p, size_t sz) \ -{ \ - k->c = 0; \ - k->bsz = 0; \ - pre##_init(&k->k); \ - pre##_hash(&k->k, p, sz); \ -} \ - \ -/* --- @pre_mgfencrypt@ --- * \ - * \ - * Arguments: @pre_mgfctx *k@ = pointer to masking context \ - * @const void *s@ = pointer to source buffer \ - * @void *d@ = pointer to destination buffer \ - * @size_t sz@ = size of buffers \ - * \ - * Returns: --- \ - * \ - * Use: Outputs pseudorandom data, or masks an input buffer. \ - * \ - * If @s@ is nonzero, the source material is exclusive- \ - * orred with the generated mask. If @d@ is zero, the \ - * generator is simply spun around for a while, which \ - * isn't very useful. \ - */ \ - \ -void pre##_mgfencrypt(pre##_mgfctx *k, const void *s, \ - void *d, size_t sz) \ -{ \ - const octet *ss = s; \ - octet *dd = d; \ - \ - /* --- Empty the buffer if there's anything there --- */ \ - \ - if (k->bsz) { \ - const octet *p = k->buf + PRE##_HASHSZ - k->bsz; \ - size_t n = sz > k->bsz ? k->bsz : sz; \ - sz -= n; \ - k->bsz -= n; \ - if (dd) { \ - if (!ss) { \ - memcpy(dd, p, n); \ - dd += n; \ - } else { \ - while (n) { \ - *dd++ = *ss++ ^ *p++; \ - n--; \ - } \ - } \ - } \ - } \ - \ - /* --- While necessary, generate some more mask --- */ \ - \ - while (sz) { \ - pre##_ctx c = k->k; /* Not quick! */ \ - size_t n; \ - \ - STORE32(k->buf, k->c); \ - k->c++; \ - pre##_hash(&c, k->buf, 4); \ - pre##_done(&c, k->buf); \ - n = sz > PRE##_HASHSZ ? PRE##_HASHSZ : sz; \ - k->bsz = PRE##_HASHSZ - n; \ - sz -= n; \ - if (dd) { \ - const octet *p = k->buf; \ - if (!ss) { \ - memcpy(dd, p, n); \ - dd += n; \ - } else { \ - while (n) { \ - *dd++ = *ss++ ^ *p++; \ - n--; \ - } \ - } \ - } \ - } \ -} \ - \ -/* --- @pre_mgfsetindex@ --- * \ - * \ - * Arguments: @pre_mgfctx *k@ = pointer to masking context \ - * @uint32 *c@ = new index to set \ - * \ - * Returns: --- \ - * \ - * Use: Sets a new index. This may be used to step around the \ - * output stream in a rather crude way. \ - */ \ - \ -void pre##_mgfsetindex(pre##_mgfctx *k, uint32 c) \ -{ \ - k->c = c; \ - k->bsz = 0; \ -} \ - \ -/* --- Generic cipher interface --- */ \ - \ -static const gcipher_ops gops; \ - \ -typedef struct gctx { \ - gcipher c; \ - pre##_mgfctx k; \ -} gctx; \ - \ -static gcipher *ginit(const void *k, size_t sz) \ -{ \ - gctx *g = S_CREATE(gctx); \ - g->c.ops = &gops; \ - pre##_mgfinit(&g->k, k, sz); \ - return (&g->c); \ -} \ - \ -static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_mgfencrypt(&g->k, s, t, sz); \ -} \ - \ -static void gdestroy(gcipher *c) \ -{ \ - gctx *g = (gctx *)c; \ - BURN(*g); \ - S_DESTROY(g); \ -} \ - \ -static const gcipher_ops gops = { \ - &pre##_mgf, \ - gencrypt, gencrypt, gdestroy, 0, 0 \ -}; \ - \ -const gccipher pre##_mgf = { \ - #pre "-mgf", pre##_mgfkeysz, 0, \ - ginit \ -}; \ - \ -/* --- Generic random number generator interface --- */ \ - \ -typedef struct grctx { \ - grand r; \ - pre##_mgfctx k; \ -} grctx; \ - \ -static void grdestroy(grand *r) \ -{ \ - grctx *g = (grctx *)r; \ - BURN(*g); \ - S_DESTROY(g); \ -} \ - \ -static int grmisc(grand *r, unsigned op, ...) \ -{ \ - grctx *g = (grctx *)r; \ - va_list ap; \ - int rc = 0; \ - va_start(ap, op); \ - \ - switch (op) { \ - case GRAND_CHECK: \ - switch (va_arg(ap, unsigned)) { \ - case GRAND_CHECK: \ - case GRAND_SEEDINT: \ - case GRAND_SEEDUINT32: \ - case GRAND_SEEDBLOCK: \ - case GRAND_SEEDRAND: \ - rc = 1; \ - break; \ - default: \ - rc = 0; \ - break; \ - } \ - break; \ - case GRAND_SEEDINT: \ - pre##_mgfsetindex(&g->k, va_arg(ap, unsigned)); \ - break; \ - case GRAND_SEEDUINT32: \ - pre##_mgfsetindex(&g->k, va_arg(ap, uint32)); \ - break; \ - case GRAND_SEEDBLOCK: { \ - const void *p = va_arg(ap, const void *); \ - size_t sz = va_arg(ap, size_t); \ - pre##_hash(&g->k.k, p, sz); \ - } break; \ - case GRAND_SEEDRAND: { \ - octet buf[PRE##_BUFSZ]; \ - grand *rr = va_arg(ap, grand *); \ - rr->ops->fill(rr, buf, sizeof(buf)); \ - pre##_hash(&g->k.k, buf, sizeof(buf)); \ - } break; \ - default: \ - GRAND_BADOP; \ - break; \ - } \ - \ - va_end(ap); \ - return (rc); \ -} \ - \ -static octet grbyte(grand *r) \ -{ \ - grctx *g = (grctx *)r; \ - octet o; \ - pre##_mgfencrypt(&g->k, 0, &o, 1); \ - return (o); \ -} \ - \ -static uint32 grword(grand *r) \ -{ \ - grctx *g = (grctx *)r; \ - octet b[4]; \ - pre##_mgfencrypt(&g->k, 0, b, sizeof(b)); \ - return (LOAD32(b)); \ -} \ - \ -static void grfill(grand *r, void *p, size_t sz) \ -{ \ - grctx *g = (grctx *)r; \ - pre##_mgfencrypt(&g->k, 0, p, sz); \ -} \ - \ -static const grand_ops grops = { \ - #pre "-mgf", \ - GRAND_CRYPTO, 0, \ - grmisc, grdestroy, \ - grword, grbyte, grword, grand_range, grfill \ -}; \ - \ -/* --- @pre_mgfrand@ --- * \ - * \ - * Arguments: @const void *k@ = pointer to key material \ - * @size_t sz@ = size of key material \ - * \ - * Returns: Pointer to a generic random number generator instance. \ - * \ - * Use: Creates a random number interface wrapper around an \ - * MGF-1-mode hash function. \ - */ \ - \ -extern grand *pre##_mgfrand(const void *k, size_t sz) \ -{ \ - grctx *g = S_CREATE(grctx); \ - g->r.ops = &grops; \ - pre##_mgfinit(&g->k, k, sz); \ - return (&g->r); \ -} \ - \ -MGF_TEST(PRE, pre) - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#include "daftstory.h" - -/* --- @MGF_TEST@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions - * - * Use: Standard test rig for MGF functions. - */ - -#define MGF_TEST(PRE, pre) \ - \ -/* --- Initial plaintext for the test --- */ \ - \ -static const octet text[] = TEXT; \ - \ -/* --- Key and IV to use --- */ \ - \ -static const octet key[] = KEY; \ - \ -/* --- Buffers for encryption and decryption output --- */ \ - \ -static octet ct[sizeof(text)]; \ -static octet pt[sizeof(text)]; \ - \ -static void hexdump(const octet *p, size_t sz) \ -{ \ - const octet *q = p + sz; \ - for (sz = 0; p < q; p++, sz++) { \ - printf("%02x", *p); \ - if ((sz + 1) % PRE##_HASHSZ == 0) \ - putchar(':'); \ - } \ -} \ - \ -int main(void) \ -{ \ - size_t sz = 0, rest; \ - pre##_mgfctx ctx; \ - int status = 0; \ - int done = 0; \ - \ - size_t keysz = strlen((const char *)key); \ - \ - fputs(#pre "-mgf: ", stdout); \ - \ - pre##_mgfinit(&ctx, key, keysz); \ - \ - while (sz <= sizeof(text)) { \ - rest = sizeof(text) - sz; \ - memcpy(ct, text, sizeof(text)); \ - pre##_mgfsetindex(&ctx, 0); \ - pre##_mgfencrypt(&ctx, ct, ct, sz); \ - pre##_mgfencrypt(&ctx, ct + sz, ct + sz, rest); \ - memcpy(pt, ct, sizeof(text)); \ - pre##_mgfsetindex(&ctx, 0); \ - pre##_mgfencrypt(&ctx, pt, pt, rest); \ - pre##_mgfencrypt(&ctx, pt + rest, pt + rest, sz); \ - if (memcmp(pt, text, sizeof(text)) == 0) { \ - done++; \ - if (sizeof(text) < 40 || done % 8 == 0) \ - fputc('.', stdout); \ - if (done % 480 == 0) \ - fputs("\n\t", stdout); \ - fflush(stdout); \ - } else { \ - printf("\nError (sz = %lu)\n", (unsigned long)sz); \ - status = 1; \ - printf("\tplaintext = "); hexdump(text, sz); \ - printf(", "); hexdump(text + sz, rest); \ - fputc('\n', stdout); \ - printf("\tciphertext = "); hexdump(ct, sz); \ - printf(", "); hexdump(ct + sz, rest); \ - fputc('\n', stdout); \ - printf("\trecovered text = "); hexdump(pt, sz); \ - printf(", "); hexdump(pt + sz, rest); \ - fputc('\n', stdout); \ - fputc('\n', stdout); \ - } \ - if (sz < 63) \ - sz++; \ - else \ - sz += 9; \ - } \ - \ - fputs(status ? " failed\n" : " ok\n", stdout); \ - return (status); \ -} - -#else -# define MGF_TEST(PRE, pre) -#endif - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mgf.h b/mgf.h deleted file mode 100644 index 273d5b0..0000000 --- a/mgf.h +++ /dev/null @@ -1,164 +0,0 @@ -/* -*-c-*- - * - * $Id: mgf.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The MGF mask generation function - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the MGF-1 mask generating function -----------------------* - * - * The idea of a mask-generating function is that given an input of arbitrary - * size, it can emit a pseudorandom output `mask' of arbitrary size. This is - * used in PKCS#1 OAEP (RFC2437). My recommendation would be to use a decent - * stream cipher instead, like RC4 or SEAL. MGF-1 isn't very fast. - */ - -#ifndef CATACOMB_MGF_H -#define CATACOMB_MGF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -/*----- Macros ------------------------------------------------------------*/ - -#define MGF_DECL(PRE, pre) \ - \ -/* --- An MGF generation context --- */ \ - \ -typedef struct pre##_mgfctx { \ - pre##_ctx k; /* Underlying key context */ \ - uint32 c; /* Counter */ \ - octet buf[PRE##_HASHSZ]; /* Output buffer */ \ - size_t bsz; /* Size of buffered data */ \ -} pre##_mgfctx; \ - \ -/* --- Other useful constants --- */ \ - \ -extern const octet pre##_mgfkeysz[]; \ - \ -/* --- @pre_mgfkeybegin@, @pre_mgfkeyadd@ --- * \ - * \ - * Arguments: @pre_mgfctx *k@ = pointer to context to initialize \ - * @const void *p@ = pointer to data to contribute \ - * @size_t sz@ = size of data to contribute \ - * \ - * Returns: --- \ - * \ - * Use: A multi-step keying procedure for initializing an MGF \ - * context. The data is contributed to a hashing context \ - * which is then used for mask generation. If you only \ - * have a fixed buffer, you can save a lot of effort by \ - * simply calling @pre_mgfinit@. \ - */ \ - \ -extern void pre##_mgfkeybegin(pre##_mgfctx */*k*/); \ -extern void pre##_mgfkeyadd(pre##_mgfctx */*k*/, \ - const void */*p*/, size_t /*sz*/); \ - \ -/* ---- @pre_mgfinit@ --- * \ - * \ - * Arguments: @pre_mgfctx *k@ = pointer to context to initialize \ - * @const void *p@ = pointer to data to contribute \ - * @size_t sz@ = size of data to contribute \ - * \ - * Returns: --- \ - * \ - * Use: A simpler interface to initialization if all of your \ - * keying material is in one place. \ - */ \ - \ -extern void pre##_mgfinit(pre##_mgfctx */*k*/, \ - const void */*p*/, size_t /*sz*/); \ - \ -/* --- @pre_mgfencrypt@ --- * \ - * \ - * Arguments: @pre_mgfctx *k@ = pointer to masking context \ - * @const void *s@ = pointer to source buffer \ - * @void *d@ = pointer to destination buffer \ - * @size_t sz@ = size of buffers \ - * \ - * Returns: --- \ - * \ - * Use: Outputs pseudorandom data, or masks an input buffer. \ - * \ - * If @s@ is nonzero, the source material is exclusive- \ - * orred with the generated mask. If @d@ is zero, the \ - * generator is simply spun around for a while, which \ - * isn't very useful. \ - */ \ - \ -extern void pre##_mgfencrypt(pre##_mgfctx */*k*/, const void */*s*/, \ - void */*d*/, size_t /*sz*/); \ - \ -/* --- @pre_mgfsetindex@ --- * \ - * \ - * Arguments: @pre_mgfctx *k@ = pointer to masking context \ - * @uint32 *c@ = new index to set \ - * \ - * Returns: --- \ - * \ - * Use: Sets a new index. This may be used to step around the \ - * output stream in a rather crude way. \ - */ \ - \ -extern void pre##_mgfsetindex(pre##_mgfctx */*k*/, uint32 /*c*/); \ - \ -/* --- @pre_mgfrand@ --- * \ - * \ - * Arguments: @const void *k@ = pointer to key material \ - * @size_t sz@ = size of key material \ - * \ - * Returns: Pointer to a generic random number generator instance. \ - * \ - * Use: Creates a random number interface wrapper around an \ - * MGF-1-mode hash function. \ - */ \ - \ -extern grand *pre##_mgfrand(const void */*k*/, size_t /*sz*/); \ - \ -/* --- Generic cipher interface --- */ \ - \ -extern const gccipher pre##_mgf; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/misc/Makefile.am b/misc/Makefile.am new file mode 100644 index 0000000..f5f380a --- /dev/null +++ b/misc/Makefile.am @@ -0,0 +1,51 @@ +### -*-makefile-*- +### +### Build script for miscellaneous cryptography +### +### (c) 2013 Straylight/Edgeware +### + +###----- Licensing notice --------------------------------------------------- +### +### This file is part of Catacomb. +### +### Catacomb is free software; you can redistribute it and/or modify +### it under the terms of the GNU Library General Public License as +### published by the Free Software Foundation; either version 2 of the +### License, or (at your option) any later version. +### +### Catacomb is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU Library General Public License for more details. +### +### You should have received a copy of the GNU Library General Public +### License along with Catacomb; if not, write to the Free +### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +### MA 02111-1307, USA. + +include $(top_srcdir)/vars.am + +noinst_LTLIBRARIES = libmisc.la +libmisc_la_SOURCES = + +###-------------------------------------------------------------------------- +### Secret sharing. + +## Efficient sharing over GF(2^8). +pkginclude_HEADERS += gfshare.h +libmisc_la_SOURCES += gfshare.c +gfshare.lo: gfshare-tab.h +CLEANFILES += gfshare-tab.h +noinst_PROGRAMS += gfshare-mktab +gfshare-tab.h: gfshare-mktab$e + $(AM_V_GEN)./gfshare-mktab >gfshare-tab.h.new && \ + mv gfshare-tab.h.new gfshare-tab.h +TESTS += gfshare.$t + +## Number-theoretic sharing over GF(p). +pkginclude_HEADERS += share.h +libmisc_la_SOURCES += share.c +TESTS += share.$t + +###----- That's all, folks -------------------------------------------------- diff --git a/misc/gfshare-mktab.c b/misc/gfshare-mktab.c new file mode 100644 index 0000000..9fc073f --- /dev/null +++ b/misc/gfshare-mktab.c @@ -0,0 +1,106 @@ +/* -*-c-*- + * + * Generate tables for %$\gf{2^8}$% multiplication + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +/*----- Magic numbers -----------------------------------------------------*/ + +#define MOD 0x11d + +/*----- Main code ---------------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + octet log[256], alog[256]; + unsigned x; + unsigned i; + + x = 1; + for (i = 0; i < 255; i++) { + alog[i] = x; + log[x] = i; + x <<= 1; + if (x & 0x100) + x ^= MOD; + } + log[0] = 0; + alog[255] = 1; + + fputs("\ +/* -*-c-*-\n\ + *\n\ + * Log tables for secret sharing in %$\\gf{2^8}$% [generated]\n\ + */\n\ +\n\ +#ifndef GFSHARE_TAB_H\n\ +#define GFSHARE_TAB_H\n\ +\n\ +#define GFSHARE_LOG { \\\n\ + ", stdout); + + for (i = 0; i < 256; i++) { + printf("0x%02x", log[i]); + if (i == 255) + puts(" \\\n}\n"); + else if (i % 8 == 7) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + fputs("\ +#define GFSHARE_EXP { \\\n\ + ", stdout); + + for (i = 0; i < 510; i++) { + printf("0x%02x", alog[i % 255]); + if (i == 509) + puts(" \\\n}\n"); + else if (i % 8 == 7) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + /* --- Done --- */ + + fputs("#endif\n", stdout); + + if (fclose(stdout)) { + fprintf(stderr, "error writing data\n"); + exit(EXIT_FAILURE); + } + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/misc/gfshare.c b/misc/gfshare.c new file mode 100644 index 0000000..0eb076b --- /dev/null +++ b/misc/gfshare.c @@ -0,0 +1,339 @@ +/* -*-c-*- + * + * Secret sharing over %$\gf{2^8}$% + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include +#include + +#include "arena.h" +#include "gfshare.h" +#include "gfshare-tab.h" +#include "grand.h" + +/*----- Static variables --------------------------------------------------*/ + +static const octet gflog[] = GFSHARE_LOG, gfexp[] = GFSHARE_EXP; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gfshare_create@ --- * + * + * Arguments: @gfshare *s@ = pointer to share context to initialize + * @unsigned t@ = threshold for the system + * @size_t sz@ = size of the secret + * + * Returns: --- + * + * Use: Initializes a sharing context. + */ + +void gfshare_create(gfshare *s, unsigned t, size_t sz) +{ + s->t = t; + s->i = 0; + s->sz = sz; + s->v = 0; +} + +/* --- @gfshare_destroy@ --- * + * + * Arguments: @gfshare *s@ = pointer to share context to destroy + * + * Returns: --- + * + * Use: Disposes of a sharing context. The allocations for the + * individual shares and the vector @v@ are freed; the secret is + * left alone. + */ + +void gfshare_destroy(gfshare *s) +{ + if (s->v) + XS_FREE(s->v); +} + +/* --- @gfshare_mkshares@ --- * + * + * Arguments: @gfshare *s@ = pointer to share context to fill in + * @grand *r@ = pointer to random number source + * @const void *buf@ = pointer to the secret to share + * + * Returns: --- + * + * Use: Initializes a sharing context to be able to create shares. + * The context structure is expected to be mostly filled in. In + * particular, @t@ must be initialized. If @v@ is zero, a + * vector of appropriate size is allocated. You should use the + * macro @GFSHARE_INIT@ or @gfshare_create@ to construct sharing + * contexts. + */ + +void gfshare_mkshares(gfshare *s, grand *r, const void *buf) +{ + s->v = XS_ALLOC(s->sz * s->t); + r->ops->fill(r, s->v, s->sz * (s->t - 1)); + memcpy(s->v + s->sz * (s->t - 1), buf, s->sz); +} + +/* --- @gfshare_get@ --- * + * + * Arguments: @gfshare *s@ = pointer to share conext + * @unsigned x@ = share index to fetch + * @void *buf@ = pointer to output buffer + * + * Returns: --- + * + * Use: Extracts a share from the system. You may extract up to 255 + * shares from the system. Shares are indexed from 0. + */ + +void gfshare_get(gfshare *s, unsigned x, void *buf) +{ + unsigned i; + const octet *p = s->v; + unsigned ilog = gflog[x + 1]; + + /* --- Evaluate the polynomial at %$x = i + 1$% --- */ + + memcpy(buf, p, s->sz); + p += s->sz; + + for (i = 1; i < s->t; i++) { + octet *q = buf; + unsigned k; + for (k = 0; k < s->sz; k++) { + unsigned qq = *q; + if (qq) + qq = gfexp[ilog + gflog[qq]]; + *q++ = qq ^ *p++; + } + } +} + +/* --- @gfshare_addedp@ --- * + * + * Arguments: @gfshare *s@ = pointer to sharing context + * @unsigned x@ = which share number to check + * + * Returns: Nonzero if share @x@ has been added already, zero if it + * hasn't. + */ + +int gfshare_addedp(gfshare *s, unsigned x) +{ + unsigned i; + + for (i = 0; i < s->i; i++) { + if (GFSHARE_INDEX(s, i) == x + 1) + return (1); + } + return (0); +} + +/* --- @gfshare_add@ --- * + * + * Arguments: @gfshare *s@ = pointer to sharing context + * @unsigned x@ = which share number this is + * @const void *y@ = the share value + * + * Returns: Number of shares required before recovery may be performed. + * + * Use: Adds a share to the context. The context must have been + * initialized with the correct threshold @t@. + */ + +unsigned gfshare_add(gfshare *s, unsigned x, const void *y) +{ + octet *p; + + assert(((void)"Share context is full", s->i < s->t)); + assert(((void)"Share already present", !gfshare_addedp(s, x))); + + /* --- If no vector has been allocated, create one --- */ + + if (!s->v) { + s->v = XS_ALLOC(s->t * (s->sz + 1)); + s->i = 0; + } + + /* --- Store the share in the vector --- */ + + p = &GFSHARE_INDEX(s, s->i); + *p++ = x + 1; + memcpy(p, y, s->sz); + s->i++; + + /* --- Done --- */ + + return (s->t - s->i); +} + +/* --- @gfshare_combine@ --- * + * + * Arguments: @gfshare *s@ = pointer to share context + * @void *buf@ = pointer to output buffer for the secret + * + * Returns: --- + * + * Use: Reconstructs a secret, given enough shares. + */ + +void gfshare_combine(gfshare *s, void *buf) +{ + unsigned i, j; + unsigned xi, xj; + + /* --- Sanity checking --- */ + + assert(((void)"Not enough shares yet", s->i == s->t)); + + /* --- Grind through the shares --- */ + + memset(buf, 0, s->sz); + + for (i = 0; i < s->t; i++) { + octet *p = buf; + octet *q = &GFSHARE_INDEX(s, i); + unsigned c = 0, ci = 0; + + /* --- Compute the magic coefficient --- */ + + xi = *q++; + for (j = 0; j < s->t; j++) { + if (i == j) + continue; + xj = GFSHARE_INDEX(s, j); + c += gflog[xj]; + if (c >= 0xff) + c -= 0xff; + ci += gflog[xi ^ xj]; + if (ci >= 0xff) + ci -= 0xff; + } + if (ci > c) + c += 0xff; + c -= ci; + + /* --- Work out another layer of the secret --- */ + + p = buf; + for (j = 0; j < s->sz; j++) { + if (*q) + *p ^= gfexp[c + gflog[*q]]; + p++, q++; + } + } +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include "fibrand.h" + +static int verify(grand *r) +{ + unsigned n = r->ops->range(r, 16) + 8; + unsigned t = r->ops->range(r, n - 1) + 1; + unsigned len = r->ops->range(r, 32) + 1; + + octet *v = xmalloc(t * len); + unsigned *p = xmalloc(n * sizeof(unsigned)); + octet *sec = xmalloc(len), *sbuf = xmalloc(len); + gfshare s; + unsigned i; + + int ok = 1; + + for (i = 0; i < n; i++) + p[i] = i; + for (i = 0; i < t; i++) { + unsigned long j = r->ops->range(r, n - i); + unsigned x = p[i]; + p[i] = p[i + j]; + p[i + j] = x; + } + + r->ops->fill(r, sec, len); + + gfshare_create(&s, t, len); + + gfshare_mkshares(&s, r, sec); + for (i = 0; i < t; i++) + gfshare_get(&s, p[i], v + (i * len)); + gfshare_destroy(&s); + + gfshare_create(&s, t, len); + for (i = 0; i < t; i++) + gfshare_add(&s, p[i], v + (i * len)); + gfshare_combine(&s, sbuf); + gfshare_destroy(&s); + + if (memcmp(sec, sbuf, len) != 0) { + ok = 0; + fprintf(stderr, "\nbad recombination of shares\n"); + }; + + xfree(sec); + xfree(sbuf); + + xfree(v); + xfree(p); + + return (ok); +} + +int main(void) +{ + grand *r = fibrand_create(0); + unsigned i; + int ok = 1; + + fputs("gfshare: ", stdout); + for (i = 0; i < 40; i++) { + if (!verify(r)) + ok = 0; + fputc('.', stdout); + fflush(stdout); + } + + if (ok) + fputs(" ok\n", stdout); + else + fputs(" failed\n", stdout); + return (ok ? EXIT_SUCCESS : EXIT_FAILURE); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/misc/gfshare.h b/misc/gfshare.h new file mode 100644 index 0000000..3337e3b --- /dev/null +++ b/misc/gfshare.h @@ -0,0 +1,180 @@ +/* -*-c-*- + * + * Secret sharing over %$\gf{2^8}$% + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the system -----------------------------------------------* + * + * This uses a variant of Shamir's secret sharing system. Shamir's original + * system used polynomials modulo a large prime. This implementation instead + * uses the field %$\gf{2^8}$%, represented by + * + * %$\gf{2}[x]/(x^8 + x^4 + x^3 + x^2 + 1)$% + * + * and shares each byte of the secret independently. It is therefore limited + * to 255 players, although this probably isn't a serious limitation in + * practice. + * + * Share creation and reconstruction is extremely efficient. Contrast the + * performance of the straightforward implementation based on multiprecision + * arithmetic. + */ + +#ifndef CATACOMB_GFSHARE_H +#define CATACOMB_GFSHARE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- A secret sharing context --- */ + +typedef struct gfshare { + unsigned t; /* Threshold */ + unsigned i; /* Next free slot in vector */ + size_t sz; /* Size of the secret and shares */ + octet *v; /* Vector of share information */ +} gfshare; + +#define GFSHARE_INIT(t, sz) { t, 0, sz, 0 } + +#define GFSHARE_INDEX(s, i) ((s)->v[(i) * ((s)->sz + 1)]) + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @gfshare_create@ --- * + * + * Arguments: @gfshare *s@ = pointer to share context to initialize + * @unsigned t@ = threshold for the system + * @size_t sz@ = size of the secret + * + * Returns: --- + * + * Use: Initializes a sharing context. + */ + +extern void gfshare_create(gfshare */*s*/, unsigned /*t*/, size_t /*sz*/); + +/* --- @gfshare_destroy@ --- * + * + * Arguments: @gfshare *s@ = pointer to share context to destroy + * + * Returns: --- + * + * Use: Disposes of a sharing context. The allocations for the + * individual shares and the vector @v@ are freed; the secret is + * left alone. + */ + +extern void gfshare_destroy(gfshare */*s*/); + +/* --- @gfshare_mkshares@ --- * + * + * Arguments: @gfshare *s@ = pointer to share context to fill in + * @grand *r@ = pointer to random number source + * @const void *buf@ = pointer to the secret to share + * + * Returns: --- + * + * Use: Initializes a sharing context to be able to create shares. + * The context structure is expected to be mostly filled in. In + * particular, @t@ must be initialized. If @v@ is zero, a + * vector of appropriate size is allocated. You should use the + * macro @GFSHARE_INIT@ or @gfshare_create@ to construct sharing + * contexts. + */ + +extern void gfshare_mkshares(gfshare */*s*/, grand */*r*/, + const void */*buf*/); + +/* --- @gfshare_get@ --- * + * + * Arguments: @gfshare *s@ = pointer to share conext + * @unsigned x@ = share index to fetch + * @void *buf@ = pointer to output buffer + * + * Returns: --- + * + * Use: Extracts a share from the system. You may extract up to 255 + * shares from the system. Shares are indexed from 0. + */ + +extern void gfshare_get(gfshare */*s*/, unsigned /*x*/, void */*buf*/); + +/* --- @gfshare_addedp@ --- * + * + * Arguments: @gfshare *s@ = pointer to sharing context + * @unsigned x@ = which share number to check + * + * Returns: Nonzero if share @x@ has been added already, zero if it + * hasn't. + */ + +extern int gfshare_addedp(gfshare */*s*/, unsigned /*x*/); + +/* --- @gfshare_add@ --- * + * + * Arguments: @gfshare *s@ = pointer to sharing context + * @unsigned x@ = which share number this is + * @const void *y@ = the share value + * + * Returns: Number of shares required before recovery may be performed. + * + * Use: Adds a share to the context. The context must have been + * initialized with the correct threshold @t@. + */ + +extern unsigned gfshare_add(gfshare */*s*/, + unsigned /*x*/, const void */*y*/); + +/* --- @gfshare_combine@ --- * + * + * Arguments: @gfshare *s@ = pointer to share context + * @void *buf@ = pointer to output buffer for the secret + * + * Returns: --- + * + * Use: Reconstructs a secret, given enough shares. + */ + +extern void gfshare_combine(gfshare */*s*/, void */*buf*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/misc/share.c b/misc/share.c new file mode 100644 index 0000000..e99781e --- /dev/null +++ b/misc/share.c @@ -0,0 +1,380 @@ +/* -*-c-*- + * + * Shamir's secret sharing + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include "grand.h" +#include "mp.h" +#include "mpint.h" +#include "mpbarrett.h" +#include "mprand.h" +#include "pgen.h" +#include "rabin.h" +#include "share.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @share_create@ --- * + * + * Arguments: @share *s@ = pointer to share context to initialize + * @unsigned t@ = threshold for the system + * + * Returns: --- + * + * Use: Initializes a sharing context. + */ + +void share_create(share *s, unsigned t) +{ + s->t = t; + s->i = 0; + s->p = 0; + s->v = 0; +} + +/* --- @share_destroy@ --- * + * + * Arguments: @share *s@ = pointer to share context to destroy + * + * Returns: --- + * + * Use: Disposes of a sharing context. All memory is freed, all + * integers are dropped. + */ + +void share_destroy(share *s) +{ + unsigned i; + + /* --- Dispose of the share vector --- */ + + if (s->v) { + for (i = 0; i < s->t; i++) + mp_drop(s->v[i].y); + xfree(s->v); + } + + /* --- Other stuff --- */ + + mp_drop(s->p); +} + +/* --- @share_mkshares@ --- * + * + * Arguments: @share *s@ = pointer to share context to fill in + * @grand *r@ = pointer to random number source + * @mp *n@ = the secret to share + * + * Returns: --- + * + * Use: Initializes a sharing context to be able to create shares. + * The context structure is expected to be mostly filled in. In + * particular, @t@ must be initialized. If @p@ is zero, a prime + * number of appropriate size is generated automatically. If + * @v@ is zero, a vector of appropriate size is allocated. You + * should use the macro @SHARE_INIT@ or @share_create@ to + * construct sharing contexts. + */ + +void share_mkshares(share *s, grand *r, mp *n) +{ + unsigned i; + + /* --- If there's no prime, construct one --- */ + + if (!s->p) { + pgen_filterctx pf; + rabin pr; + mp *p; + unsigned bits = (mp_octets(n) + 1) * 8; + + pf.step = 2; + p = mprand(MP_NEW, bits, r, 1); + s->p = pgen("p", p, p, 0, 0, 0, pgen_filter, &pf, + rabin_iters(bits), pgen_test, &pr); + } + + /* --- Construct the polynomial --- */ + + if (!s->v) + s->v = xmalloc(s->t * sizeof(share_pt)); + for (i = 0; i < s->t - 1; i++) + s->v[i].y = mprand_range(MP_NEWSEC, s->p, r, 0); + s->v[s->t - 1].y = mp_copy(n); +} + +/* --- @share_get@ --- * + * + * Arguments: @share *s@ = pointer to share conext + * @mp *d@ = destination for the share + * @unsigned x@ = share index to fetch + * + * Returns: The share, as requested. + * + * Use: Extracts a share from the system. You may extract @MPW_MAX@ + * shares, or @s->p@ shares from the system, whichever is + * smaller. Shares are indexed from 0. + */ + +mp *share_get(share *s, mp *d, unsigned x) +{ + mpbarrett mb; + mpw uw = x + 1; + mp u; + unsigned i; + + /* --- Various bits of initialization --- */ + + mp_build(&u, &uw, &uw + 1); + mp_drop(d); + + /* --- Evaluate the polynomial at %$x = i + 1$% --- */ + + d = MP_ZERO; + mpbarrett_create(&mb, s->p); + for (i = 0; i < s->t; i++) { + d = mp_mul(d, d, &u); + d = mp_add(d, d, s->v[i].y); + d = mpbarrett_reduce(&mb, d, d); + } + mpbarrett_destroy(&mb); + + return (d); +} + +/* --- @share_addedp@ --- * + * + * Arguments: @share *s@ = pointer to sharing context + * @unsigned x@ = which share number to check + * + * Returns: Nonzero if share @x@ has been added already, zero if it + * hasn't. + */ + +int share_addedp(share *s, unsigned x) +{ + unsigned i; + + for (i = 0; i < s->i; i++) { + if (s->v[i].x == x + 1) + return (1); + } + return (0); +} + +/* --- @share_add@ --- * + * + * Arguments: @share *s@ = pointer to sharing context + * @unsigned x@ = which share number this is + * @mp *y@ = the share value + * + * Returns: Number of shares required before recovery may be performed. + * + * Use: Adds a share to the context. The context must have been + * initialized with the correct prime @p@ and threshold @t@. + */ + +unsigned share_add(share *s, unsigned x, mp *y) +{ + assert(((void)"Share context is full", s->i < s->t)); + assert(((void)"Share already present", !share_addedp(s, x))); + + /* --- If no vector has been allocated, create one --- */ + + if (!s->v) { + unsigned i; + s->v = xmalloc(s->t * sizeof(share_pt)); + s->i = 0; + for (i = 0; i < s->t; i++) + s->v[i].y = 0; + } + + /* --- Store the share in the vector --- */ + + s->v[s->i].x = x + 1; + s->v[s->i].y = mp_copy(y); + s->i++; + + /* --- Done --- */ + + return (s->t - s->i); +} + +/* --- @share_combine@ --- * + * + * Arguments: @share *s@ = pointer to share context + * + * Returns: The secret, as a multiprecision integer. + * + * Use: Reconstructs a secret, given enough shares. + */ + +mp *share_combine(share *s) +{ + mp *a = MP_ZERO; + mpbarrett mb; + unsigned i, j; + mp ii, jj; + mpw iiw, jjw; + mp *m = MP_NEW; + + /* --- Sanity checking --- */ + + assert(((void)"Not enough shares yet", s->i == s->t)); + + /* --- Initialization --- */ + + mpbarrett_create(&mb, s->p); + mp_build(&ii, &iiw, &iiw + 1); + mp_build(&jj, &jjw, &jjw + 1); + + /* --- Grind through the shares --- */ + + for (i = 0; i < s->t; i++) { + mp *c = MP_ONE; + + iiw = s->v[i].x; + for (j = 0; j < s->t; j++) { + if (i == j) + continue; + jjw = s->v[j].x; + if (s->v[j].x >= s->v[i].x) + m = mp_sub(m, &jj, &ii); + else { + m = mp_sub(m, &ii, &jj); + m = mp_sub(m, s->p, m); + } + m = mp_modinv(m, m, s->p); + c = mp_mul(c, c, &jj); + c = mpbarrett_reduce(&mb, c, c); + c = mp_mul(c, c, m); + c = mpbarrett_reduce(&mb, c, c); + } + c = mp_mul(c, c, s->v[i].y); + c = mpbarrett_reduce(&mb, c, c); + a = mp_add(a, a, c); + mp_drop(c); + } + + a = mpbarrett_reduce(&mb, a, a); + mp_drop(m); + mpbarrett_destroy(&mb); + return (a); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include "fibrand.h" + +static int verify(grand *r) +{ + unsigned n = r->ops->range(r, 16) + 8; + unsigned t = r->ops->range(r, n - 1) + 1; + unsigned len = r->ops->range(r, 160); + + mp **v = xmalloc(t * sizeof(mp *)); + unsigned *p = xmalloc(n * sizeof(unsigned)); + mp *sec = mprand(MP_NEW, len, r, 0); + share s; + mp *pp; + mp *ss; + unsigned i; + + int ok = 1; + + for (i = 0; i < n; i++) + p[i] = i; + for (i = 0; i < t; i++) { + unsigned long j = r->ops->range(r, n - i); + unsigned x = p[i]; + p[i] = p[i + j]; + p[i + j] = x; + } + + share_create(&s, t); + share_mkshares(&s, r, sec); + for (i = 0; i < t; i++) + v[i] = share_get(&s, MP_NEW, p[i]); + pp = mp_copy(s.p); + share_destroy(&s); + assert(mparena_count(MPARENA_GLOBAL) + mparena_count(MPARENA_SECURE) == t + 2); + + share_create(&s, t); + s.p = pp; + for (i = 0; i < t; i++) + share_add(&s, p[i], v[i]); + ss = share_combine(&s); + share_destroy(&s); + + if (!MP_EQ(sec, ss)) { + ok = 0; + fprintf(stderr, "\nbad recombination of shares\n"); + }; + + mp_drop(sec); + mp_drop(ss); + + for (i = 0; i < t; i++) + mp_drop(v[i]); + + xfree(v); + xfree(p); + + assert(mparena_count(MPARENA_GLOBAL) + mparena_count(MPARENA_SECURE) == 0); + return (ok); +} + +int main(void) +{ + grand *r = fibrand_create(0); + unsigned i; + int ok = 1; + + fputs("share: ", stdout); + for (i = 0; i < 40; i++) { + if (!verify(r)) + ok = 0; + fputc('.', stdout); + fflush(stdout); + } + + if (ok) + fputs(" ok\n", stdout); + else + fputs(" failed\n", stdout); + return (ok ? EXIT_SUCCESS : EXIT_FAILURE); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/misc/share.h b/misc/share.h new file mode 100644 index 0000000..9b82fdd --- /dev/null +++ b/misc/share.h @@ -0,0 +1,177 @@ +/* -*-c-*- + * + * Shamir's secret sharing + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the sharing system ---------------------------------------* + * + * Shamir's secret-sharing system is based on polynomial interpolation modulo + * a prime number. It is `perfect' in that fewer participants than the + * threshold can derive no information about the secret by pooling their + * shares, and `ideal' in that the shares are the same size as the secret. + * + * This implementation stays close to the definition, in order to support + * other schemes for (e.g.) threshold cryptography. It is, however, rather + * slow. + */ + +#ifndef CATACOMB_SHARE_H +#define CATACOMB_SHARE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- A secret sharing context --- */ + +typedef struct share_pt { + unsigned x; /* Index of this share */ + mp *y; /* Payload of this share */ +} share_pt; + +typedef struct share { + unsigned t; /* Threshold */ + unsigned i; /* Next free slot in the vector */ + mp *p; /* Modulus for arithmetic */ + share_pt *v; /* Vector of share information */ +} share; + +#define SHARE_INIT(t) { t, 0, 0, 0 } + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @share_create@ --- * + * + * Arguments: @share *s@ = pointer to share context to initialize + * @unsigned t@ = threshold for the system + * + * Returns: --- + * + * Use: Initializes a sharing context. + */ + +extern void share_create(share */*s*/, unsigned /*t*/); + +/* --- @share_destroy@ --- * + * + * Arguments: @share *s@ = pointer to share context to destroy + * + * Returns: --- + * + * Use: Disposes of a sharing context. All memory is freed, all + * integers are dropped. + */ + +extern void share_destroy(share */*s*/); + +/* --- @share_mkshares@ --- * + * + * Arguments: @share *s@ = pointer to share context to fill in + * @grand *r@ = pointer to random number source + * @mp *n@ = the secret to share + * + * Returns: --- + * + * Use: Initializes a sharing context to be able to create shares. + * The context structure is expected to be mostly filled in. In + * particular, @t@ must be initialized. If @p@ is zero, a prime + * number of appropriate size is generated automatically. If + * @v@ is zero, a vector of appropriate size is allocated. You + * should use the macro @SHARE_INIT@ or @share_create@ to + * construct sharing contexts. + */ + +extern void share_mkshares(share */*s*/, grand */*r*/, mp */*n*/); + +/* --- @share_get@ --- * + * + * Arguments: @share *s@ = pointer to share conext + * @mp *d@ = destination for the share + * @unsigned x@ = share index to fetch + * + * Returns: The share, as requested. + * + * Use: Extracts a share from the system. You may extract @MPW_MAX@ + * shares, or @s->p@ shares from the system, whichever is + * smaller. Shares are indexed from 0. + */ + +extern mp *share_get(share */*s*/, mp */*d*/, unsigned /*x*/); + +/* --- @share_addedp@ --- * + * + * Arguments: @share *s@ = pointer to sharing context + * @unsigned x@ = which share number to check + * + * Returns: Nonzero if share @x@ has been added already, zero if it + * hasn't. + */ + +extern int share_addedp(share */*s*/, unsigned /*x*/); + +/* --- @share_add@ --- * + * + * Arguments: @share *s@ = pointer to sharing context + * @unsigned x@ = which share number this is + * @mp *y@ = the share value + * + * Returns: Number of shares required before recovery may be performed. + * + * Use: Adds a share to the context. The context must have been + * initialized with the correct prime @p@ and threshold @t@. + */ + +extern unsigned share_add(share */*s*/, unsigned /*x*/, mp */*y*/); + +/* --- @share_combine@ --- * + * + * Arguments: @share *s@ = pointer to share context + * + * Returns: The secret, as a multiprecision integer. + * + * Use: Reconstructs a secret, given enough shares. + */ + +extern mp *share_combine(share */*s*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/mkpgroups b/mkpgroups deleted file mode 100755 index b40c23b..0000000 --- a/mkpgroups +++ /dev/null @@ -1,42 +0,0 @@ -#! /usr/bin/python - -import catacomb as C -import mLib as M -from sys import stdin - -kf = C.KeyFile('pgroups.kr', C.KOPEN_WRITE) - -for line in stdin: - line = line.strip() - if line == '' or (line.startswith('#') and not line.startswith('#:')): - continue - F = line.split() - if F[0] == 'group': - name = F[1] - if not name.startswith('catacomb'): - continue - def snarf(what): - F = stdin.next().split() - assert F[0] == what - return F[1] - p = C.MP(snarf('p')) - q = C.MP(snarf('q')) - g = C.MP(snarf('g')) - ff = [] - while True: - F = stdin.next().split() - if not F or F[0] != '#:factor': - break - ff.append(C.MP(F[1])) - seed = C.rmd160().hash(name).done() - k = kf.newkey(C.ReadBuffer(seed).getu32(), 'dh-param') - k.tag = name - k.data = C.KeyDataStructured({ - 'p': C.KeyDataMP(p, 'shared'), - 'q': C.KeyDataMP(q, 'shared'), - 'g': C.KeyDataMP(g, 'shared') - }) - k.attr['factor'] = ', '.join([f.tostring() for f in ff]) - k.attr['genseed'] = M.base64_encode(seed) - k.attr['seedalg'] = 'rmd160-mgf' -kf.save() diff --git a/mkphrase.c b/mkphrase.c deleted file mode 100644 index 1a5beab..0000000 --- a/mkphrase.c +++ /dev/null @@ -1,458 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Generate passphrases from word lists - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "grand.h" -#include "noise.h" -#include "rand.h" - -/*----- Global state ------------------------------------------------------*/ - -static unsigned min = 0, max = 256; /* Word length bounds */ -static unsigned minbits = 128, maxbits = UINT_MAX; /* Acceptable entropy */ -static unsigned count = 1; /* How many passphrases to make */ - -static const char wchars[] = "abcdefghijklmnopqrstuvwxyz'"; - -typedef struct ppgen_ops { - const char *name; /* Name of the generator */ - void *(*init)(void); /* Initialize generator */ - void (*scan)(FILE */*fp*/, void */*p*/); /* Scan an input word list */ - void (*endscan)(void */*p*/); /* Scanning phase completed */ - double (*gen)(dstr */*d*/, grand */*r*/, void */*p*/); - /* Emit word and return entropy */ - void (*done)(void */*p*/); /* Close down generator */ -} ppgen_ops; - -/*----- Word list ---------------------------------------------------------*/ - -#ifndef STRING_V -# define STRING_V - DA_DECL(string_v, char *); -#endif - -typedef struct wlist { - string_v sv; - sym_table tab; - char *buf; - double logp; -} wlist; - -static void *wordlist_init(void) -{ - wlist *w = xmalloc(sizeof(wlist)); - sym_create(&w->tab); - w->logp = 0; - return (w); -} - -static void wordlist_scan(FILE *fp, void *p) -{ - wlist *w = p; - dstr d = DSTR_INIT; - unsigned f = 0; - - for (;;) { - int ch = getc(fp); - if (ch == EOF || isspace(ch)) { - DPUTZ(&d); - if (f && d.len >= min && d.len <= max) - sym_find(&w->tab, d.buf, d.len + 1, sizeof(sym_base), 0); - f = 0; - DRESET(&d); - if (ch == EOF) - break; - continue; - } - ch = tolower(ch); - if (strchr(wchars, ch)) { - DPUTC(&d, ch); - f = 1; - } - } - - dstr_destroy(&d); -} - -static void wordlist_endscan(void *p) -{ - wlist *w = p; - size_t buflen = 0; - sym_iter i; - sym_base *b; - char *q; - - for (sym_mkiter(&i, &w->tab); (b = sym_next(&i)) != 0; ) - buflen += b->len; - w->buf = xmalloc(buflen); - q = w->buf; - DA_CREATE(&w->sv); - for (sym_mkiter(&i, &w->tab); (b = sym_next(&i)) != 0; ) { - memcpy(q, SYM_NAME(b), b->len); - DA_PUSH(&w->sv, q); - q += b->len; - } - sym_destroy(&w->tab); - w->logp = log(DA_LEN(&w->sv))/log(2); -} - -static double wordlist_gen(dstr *d, grand *r, void *p) -{ - wlist *w = p; - uint32 i = r->ops->range(r, DA_LEN(&w->sv)); - DPUTS(d, DA(&w->sv)[i]); - return (w->logp); -} - -static void wordlist_done(void *p) -{ - wlist *w = p; - xfree(w->buf); - DA_DESTROY(&w->sv); - xfree(w); -} - -static ppgen_ops wordlist_ops = { - "wordlist", - wordlist_init, wordlist_scan, wordlist_endscan, wordlist_gen, wordlist_done -}; - -/*----- Markov word model -------------------------------------------------*/ - -enum { - C_START = 27, - C_END, - VECSZ -}; - -typedef struct node { - uint32 count; - uint32 p[VECSZ]; -} node; - -static void *markov_init(void) -{ - node (*model)[VECSZ][VECSZ][VECSZ] = xmalloc(sizeof(*model)); - unsigned i, j, k, l; - - for (i = 0; i < VECSZ; i++) { - for (j = 0; j < VECSZ; j++) { - for (k = 0; k < VECSZ; k++) { - node *n = &(*model)[i][j][k]; - n->count = 0; - for (l = 0; l < VECSZ; l++) - n->p[l] = 0; - } - } - } - - return (model); -} - -static void markov_scan(FILE *fp, void *p) -{ - node (*model)[VECSZ][VECSZ][VECSZ] = p; - unsigned i = C_START, j = C_START, k = C_START, l = C_END; - - for (;;) { - int ch = getc(fp); - const char *q; - node *n = &(*model)[i][j][k]; - - if (ch == EOF || isspace(ch)) { - if (l != C_END) { - l = C_END; - n->count++; - n->p[l]++; - i = j = k = C_START; - } - if (ch == EOF) - break; - continue; - } - - if ((q = strchr(wchars, tolower(ch))) == 0) - continue; - l = q - wchars; - n->count++; - n->p[l]++; - i = j; j = k; k = l; - } -} - -static double markov_gen(dstr *d, grand *r, void *p) -{ - node (*model)[VECSZ][VECSZ][VECSZ] = p; - unsigned i = C_START, j = C_START, k = C_START, l; - double logp = 0; - double log2 = log(2); - - for (;;) { - node *n = &(*model)[i][j][k]; - uint32 z = r->ops->range(r, n->count); - for (l = 0; z >= n->p[l]; z -= n->p[l++]) - ; - logp -= log((double)n->p[l]/(double)n->count)/log2; - if (l == C_END) - break; - DPUTC(d, wchars[l]); - i = j; j = k; k = l; - } - - return (logp); -} - -static void markov_done(void *p) -{ - node (*model)[VECSZ][VECSZ][VECSZ] = p; - xfree(model); -} - -static ppgen_ops markov_ops = { - "markov", - markov_init, markov_scan, 0, markov_gen, markov_done -}; - -/*----- Main code ---------------------------------------------------------*/ - -static ppgen_ops *ppgentab[] = { - &markov_ops, - &wordlist_ops, - 0 -}; - -static void version(FILE *fp) -{ - pquis(fp, "$, Catacomb version " VERSION "\n"); -} - -static void usage(FILE *fp) -{ - pquis(fp, "\ -Usage: $ [-p] [-b MIN[-MAX]] [-g GEN] [-n COUNT]\n\ -\t[-r [MIN-]MAX] WORDLIST...\n \ -"); -} - -static void help(FILE *fp) -{ - ppgen_ops **ops; - version(fp); - fputc('\n', fp); - usage(fp); - pquis(fp, "\n\ -Generates random passphrases with the requested level of entropy. Options\n\ -supported are:\n\ -\n\ --h, --help Show this help text.\n\ --v, --version Show the program's version number.\n\ --u, --usage Show a terse usage summary.\n\ --b, --bits=MIN[-MAX] Minimum and maximum bits of entropy.\n\ --g, --generator=GEN Use passphrase generator GEN.\n\ --n, --count=COUNT Generate COUNT passphrases.\n\ --p, --probability Show -log_2 of probability for each phrase.\n\ --r, --range=[MIN-]MAX Supply minimum and maximum word lengths.\n\ -\n\ -Generators currently available:"); - for (ops = ppgentab; *ops; ops++) - fprintf(fp, " %s", (*ops)->name); - fputc('\n', fp); -} - -int main(int argc, char *argv[]) -{ - ppgen_ops *ops = ppgentab[0]; - unsigned f = 0; - void *ctx; - dstr d = DSTR_INIT; - dstr dd = DSTR_INIT; - unsigned i; - -#define f_bogus 1u -#define f_showp 2u - - ego(argv[0]); - for (;;) { - static struct option opts[] = { - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'v' }, - { "usage", 0, 0, 'u' }, - { "bits", OPTF_ARGREQ, 0, 'b' }, - { "generator", OPTF_ARGREQ, 0, 'g' }, - { "count", OPTF_ARGREQ, 0, 'n' }, - { "probability", 0, 0, 'p' }, - { "range", OPTF_ARGREQ, 0, 'r' }, - { 0, 0, 0, 0 } - }; - int i = mdwopt(argc, argv, "hvu b:g:n:pr:", opts, 0, 0, 0); - - if (i < 0) - break; - switch (i) { - case 'h': - help(stdout); - exit(0); - case 'v': - version(stdout); - exit(0); - case 'u': - usage(stdout); - exit(0); - case 'b': { - char *p; - minbits = strtoul(optarg, &p, 0); - if (*p == '-') - maxbits = strtoul(p + 1, &p, 0); - else - maxbits = UINT_MAX; - if (*p || minbits > maxbits) - die(EXIT_FAILURE, "bad entropy range `%s'", optarg); - } break; - case 'g': { - ppgen_ops **p; - size_t n = strlen(optarg); - ops = 0; - for (p = ppgentab; *p; p++) { - if (strncmp(optarg, (*p)->name, n) == 0) { - if (!(*p)->name[n]) { - ops = *p; - break; - } else if (ops) - die(EXIT_FAILURE, "ambiguous generator name `%s'", optarg); - ops = *p; - } - } - if (!ops) - die(EXIT_FAILURE, "unknown generator name `%s'", optarg); - } break; - case 'n': { - char *p; - unsigned long n = strtoul(optarg, &p, 0); - if (*p) - die(EXIT_FAILURE, "bad integer `%s'", optarg); - count = n; - } break; - case 'p': - f |= f_showp; - break; - case 'r': { - char *p; - unsigned long n = min, nn = max; - nn = strtoul(optarg, &p, 0); - if (*p == '-') { - n = nn; - nn = strtoul(p + 1, &p, 0); - } - if (*p || min > max) - die(EXIT_FAILURE, "bad range string `%s'", optarg); - min = n; max = nn; - } break; - default: - f |= f_bogus; - break; - } - } - - argc -= optind; - argv += optind; - if ((f & f_bogus) || !argc) { - usage(stderr); - exit(EXIT_FAILURE); - } - - rand_noisesrc(RAND_GLOBAL, &noise_source); - rand_seed(RAND_GLOBAL, 160); - - ctx = ops->init(); - while (*argv) { - if (strcmp(*argv, "-") == 0) - ops->scan(stdin, ctx); - else { - FILE *fp = fopen(*argv, "r"); - if (!fp) { - die(EXIT_FAILURE, "error opening file `%s': %s", - *argv, strerror(errno)); - } - ops->scan(fp, ctx); - fclose(fp); - } - argv++; - } - if (ops->endscan) - ops->endscan(ctx); - - for (i = 0; !count || i < count; ) { - double logp = 0; - DRESET(&d); - while (logp < minbits) { - double pp; - DRESET(&dd); - pp = ops->gen(&dd, &rand_global, ctx); - if (!pp || dd.len < min || dd.len > max) - continue; - if (logp) - DPUTC(&d, ' '); - DPUTD(&d, &dd); - logp += pp; - } - if (logp >= (double)maxbits + 1) - continue; - dstr_write(&d, stdout); - if (f & f_showp) - printf(" [%g]", logp); - fputc('\n', stdout); - i++; - } - - ops->done(ctx); - dstr_destroy(&d); - dstr_destroy(&dd); - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/modes.am.in b/modes.am.in deleted file mode 100644 index 88ee217..0000000 --- a/modes.am.in +++ /dev/null @@ -1,67 +0,0 @@ -%## -*-makefile-*- -%# -### -*-makefile-*- GENERATED from modes.make.in -### -### Lots of lists of crypto primitives in various modes of operation. - -SYMM_TESTS = - -GENMODES_C = -GENMODES_H = - -%repeat -GENMODES_C += @blkc-@blkcmode.c -GENMODES_H += @blkc-@blkcmode.h -SYMM_TESTS += @blkc-@blkcmode.$t -%end - -%repeat -GENMODES_C += @hash-@hashmode.c -GENMODES_H += @hash-@hashmode.h -SYMM_TESTS += @hash-@hashmode.$t -%end - -MODE_H = -%repeat -MODE_H += @blkcmode.h @blkcmode-def.h -%end -%repeat -MODE_H += @hashmode.h @hashmode-def.h -%end - -BLKC_C = -BLKC_H = -%repeat -BLKC_C += @blkc.c -BLKC_H += @blkc.h -SYMM_TESTS += @blkc.$t -%end - -HASH_C = -HASH_H = -%repeat -HASH_C += @hash.c -HASH_H += @hash.h -SYMM_TESTS += @hash.$t -%end - -CIPHER_MODES = -%repeat -CIPHER_MODES += @blkc-@blkcciphermode -%end -%repeat -CIPHER_MODES += @hash-@hashciphermode -%end - -MAC_MODES = -%repeat -MAC_MODES += @hash-@hashmacmode -%end - -SYMM_TEST_FILES = -%repeat -SYMM_TEST_FILES += tests/@blkc -%end -%repeat -SYMM_TEST_FILES += tests/@hash -%end diff --git a/mp-arith.c b/mp-arith.c deleted file mode 100644 index f00af54..0000000 --- a/mp-arith.c +++ /dev/null @@ -1,931 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Basic arithmetic on multiprecision integers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" - -/*----- Macros ------------------------------------------------------------*/ - -#define MAX(x, y) ((x) >= (y) ? (x) : (y)) - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mp_lsl@, @mp_lslc@, @mp_lsr@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = source - * @size_t n@ = number of bits to move - * - * Returns: Result, @a@ shifted left or right by @n@. - * - * Use: Bitwise shift operators. @mp_lslc@ fills the bits introduced - * on the right with ones instead of zeroes: it's used - * internally by @mp_lsl2c@, though it may be useful on its - * own. - */ - -mp *mp_lsl(mp *d, mp *a, size_t n) -{ - MP_DEST(d, MP_LEN(a) + (n + MPW_BITS - 1) / MPW_BITS, a->f); - mpx_lsl(d->v, d->vl, a->v, a->vl, n); - d->f = a->f & (MP_NEG | MP_BURN); - MP_SHRINK(d); - return (d); -} - -mp *mp_lslc(mp *d, mp *a, size_t n) -{ - MP_DEST(d, MP_LEN(a) + (n + MPW_BITS - 1) / MPW_BITS, a->f); - mpx_lslc(d->v, d->vl, a->v, a->vl, n); - d->f = a->f & (MP_NEG | MP_BURN); - MP_SHRINK(d); - return (d); -} - -mp *mp_lsr(mp *d, mp *a, size_t n) -{ - MP_DEST(d, MP_LEN(a), a->f); - mpx_lsr(d->v, d->vl, a->v, a->vl, n); - d->f = a->f & (MP_NEG | MP_BURN); - MP_SHRINK(d); - return (d); -} - -/* --- @mp_lsl2c@, @mp_lsr2c@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = source - * @size_t n@ = number of bits to move - * - * Returns: Result, @a@ shifted left or right by @n@. Handles the - * pretence of sign-extension for negative numbers. - */ - -mp *mp_lsl2c(mp *d, mp *a, size_t n) -{ - if (!MP_NEGP(a)) - return (mp_lsl(d, a, n)); - d = mp_not2c(d, a); - d = mp_lslc(d, d, n); - d = mp_not2c(d, d); - return (d); -} - -mp *mp_lsr2c(mp *d, mp *a, size_t n) -{ - if (!MP_NEGP(a)) - return (mp_lsr(d, a, n)); - d = mp_not2c(d, a); - d = mp_lsr(d, d, n); - d = mp_not2c(d, d); - return (d); -} - -/* --- @mp_testbit@ --- * - * - * Arguments: @mp *x@ = a large integer - * @unsigned long n@ = which bit to test - * - * Returns: Nonzero if the bit is set, zero if not. - */ - -int mp_testbit(mp *x, unsigned long n) -{ - if (n > MPW_BITS * MP_LEN(x)) - return (0); - return ((x->v[n/MPW_BITS] >> n%MPW_BITS) & 1u); -} - -/* --- @mp_testbit2c@ --- * - * - * Arguments: @mp *x@ = a large integer - * @unsigned long n@ = which bit to test - * - * Returns: Nonzero if the bit is set, zero if not. Fakes up two's - * complement representation. - */ - -int mp_testbit2c(mp *x, unsigned long n) -{ - int r; - if (!MP_NEGP(x)) - return (mp_testbit(x, n)); - x = mp_not2c(MP_NEW, x); - r = !mp_testbit(x, n); - MP_DROP(x); - return (r); -} - -/* --- @mp_setbit@, @mp_clearbit@ --- * - * - * Arguments: @mp *d@ = a destination - * @mp *x@ = a large integer - * @unsigned long n@ = which bit to modify - * - * Returns: The argument @x@, with the appropriate bit set or cleared. - */ - -mp *mp_setbit(mp *d, mp *x, unsigned long n) -{ - size_t rq; - - rq = n + MPW_BITS; rq -= rq % MPW_BITS; - if (d != x) { - if (d) MP_DROP(d); - d = MP_COPY(x); - } - MP_DEST(d, rq, x->f & (MP_NEG | MP_BURN)); - d->v[n/MPW_BITS] |= 1 << n%MPW_BITS; - return (d); -} - -mp *mp_clearbit(mp *d, mp *x, unsigned long n) -{ - size_t rq; - - rq = n + MPW_BITS; rq -= rq % MPW_BITS; - if (d != x) { - if (d) MP_DROP(d); - d = MP_COPY(x); - } - MP_DEST(d, rq, x->f & (MP_NEG | MP_BURN)); - d->v[n/MPW_BITS] &= ~(1 << n%MPW_BITS); - return (d); -} - -/* --- @mp_setbit2c@, @mp_clearbit2c@ --- * - * - * Arguments: @mp *d@ = a destination - * @mp *x@ = a large integer - * @unsigned long n@ = which bit to modify - * - * Returns: The argument @x@, with the appropriate bit set or cleared. - * Fakes up two's complement representation. - */ - -mp *mp_setbit2c(mp *d, mp *x, unsigned long n) -{ - if (!MP_NEGP(x)) - return mp_setbit(d, x, n); - d = mp_not2c(d, x); - d = mp_clearbit(d, d, n); - d = mp_not2c(d, d); - return (d); -} - -mp *mp_clearbit2c(mp *d, mp *x, unsigned long n) -{ - if (!MP_NEGP(x)) - return mp_clearbit(d, x, n); - d = mp_not2c(d, x); - d = mp_setbit(d, d, n); - d = mp_not2c(d, d); - return (d); -} - -/* --- @mp_eq@ --- * - * - * Arguments: @const mp *a, *b@ = two numbers - * - * Returns: Nonzero if the numbers are equal. - */ - -int mp_eq(const mp *a, const mp *b) { return (MP_EQ(a, b)); } - -/* --- @mp_cmp@ --- * - * - * Arguments: @const mp *a, *b@ = two numbers - * - * Returns: Less than, equal to or greater than zero, according to - * whether @a@ is less than, equal to or greater than @b@. - */ - -int mp_cmp(const mp *a, const mp *b) -{ - if (!((a->f ^ b->f) & MP_NEG)) { - if (a->f & MP_NEG) - return (-mpx_ucmp(a->v, a->vl, b->v, b->vl)); - else - return (mpx_ucmp(a->v, a->vl, b->v, b->vl)); - } else if (a->f & MP_NEG) - return (-1); - else - return (+1); -} - -/* --- @mp_neg@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = argument - * - * Returns: The negation of the argument. - * - * Use: Negates its argument. - */ - -mp *mp_neg(mp *d, mp *a) -{ - /* --- Surprising amounts of messing about required --- */ - - MP_SHRINK(a); - MP_COPY(a); - if (d) - MP_DROP(d); - if (a->v == a->vl) - return (a); - MP_DEST(a, MP_LEN(a), a->f); - a->f ^= MP_NEG; - return (a); -} - -/* --- @mp_bitop@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: The result of the given bitwise operation. These functions - * don't handle negative numbers at all sensibly. For that, use - * the @...2c@ variants. The functions are named after the - * truth tables they generate: - * - * a: 0011 - * b: 0101 - * @mpx_bitXXXX@ - */ - -#define MP_BITBINOP(string) \ - \ -mp *mp_bit##string(mp *d, mp *a, mp *b) \ -{ \ - MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)), (a->f | b->f) & ~MP_NEG); \ - mpx_bit##string(d->v, d->vl, a->v, a->vl, b->v, b->vl); \ - d->f = (a->f | b->f) & MP_BURN; \ - MP_SHRINK(d); \ - return (d); \ -} - -MPX_DOBIN(MP_BITBINOP) - -/* --- @mp_not@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = source - * - * Returns: The bitwise complement of the source. - */ - -mp *mp_not(mp *d, mp *a) -{ - MP_DEST(d, MP_LEN(a), a->f); - mpx_not(d->v, d->vl, a->v, a->vl); - d->f = a->f & MP_BURN; - MP_SHRINK(d); - return (d); -} - -/* --- @mp_bitop2c@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: The result of the given bitwise operation. Negative numbers - * are treated as two's complement, sign-extended infinitely to - * the left. The functions are named after the truth tables - * they generate: - * - * a: 0011 - * b: 0101 - * @mpx_bitXXXX@ - */ - -/* --- How this actually works --- * - * - * The two arguments are inverted (with a sign-swap) if they're currently - * negative. This means that we end up using a different function (one which - * reinverts as we go) for the main operation. Also, if the sign would be - * negative at the end, we preinvert the output and then invert again with a - * sign-swap. - * - * Start with: wxyz WXYZ - * If @a@ negative: yzwx or YZWX - * If @b@ negative: xwzy XWZY - * If both negative: zyxw ZYXW - */ - -#define MP_BIT2CBINOP(n, base, an, bn, abn, p_base, p_an, p_bn, p_abn) \ - \ -mp *mp_bit##n##2c(mp *d, mp *a, mp *b) \ -{ \ - if (!((a->f | b->f) & MP_NEG)) { /* Both positive */ \ - d = mp_bit##base(d, a, b); \ - p_base \ - } else if (!(b->f & MP_NEG)) { /* Only @b@ positive */ \ - MP_COPY(b); \ - d = mp_not2c(d, a); \ - d = mp_bit##an(d, d, b); \ - MP_DROP(b); \ - p_an \ - } else if (!(a->f & MP_NEG)) { /* Only @a@ positive */ \ - MP_COPY(a); \ - d = mp_not2c(d, b); \ - d = mp_bit##bn(d, a, d); \ - MP_DROP(a); \ - p_bn \ - } else { /* Both negative */ \ - mp *t = mp_not2c(MP_NEW, a); \ - d = mp_not2c(d, b); \ - d = mp_bit##abn(d, t, d); \ - MP_DROP(t); \ - p_abn \ - } \ - return (d); \ -} \ - -#define NEG d = mp_not2c(d, d); -#define POS -MP_BIT2CBINOP(0000, 0000, 0000, 0000, 0000, POS, POS, POS, POS) -MP_BIT2CBINOP(0001, 0001, 0100, 0010, 0111, POS, POS, POS, NEG) -MP_BIT2CBINOP(0010, 0010, 0111, 0001, 0100, POS, NEG, POS, POS) -MP_BIT2CBINOP(0011, 0011, 0011, 0011, 0011, POS, NEG, POS, NEG) -MP_BIT2CBINOP(0100, 0100, 0001, 0111, 0010, POS, POS, NEG, POS) -MP_BIT2CBINOP(0101, 0101, 0101, 0101, 0101, POS, POS, NEG, NEG) -MP_BIT2CBINOP(0110, 0110, 0110, 0110, 0110, POS, NEG, NEG, POS) -MP_BIT2CBINOP(0111, 0111, 0010, 0100, 0001, POS, NEG, NEG, NEG) -MP_BIT2CBINOP(1000, 0111, 0010, 0100, 0001, NEG, POS, POS, POS) -MP_BIT2CBINOP(1001, 0110, 0110, 0110, 0110, NEG, POS, POS, NEG) -MP_BIT2CBINOP(1010, 0101, 0101, 0101, 0101, NEG, NEG, POS, POS) -MP_BIT2CBINOP(1011, 0100, 0001, 0111, 0010, NEG, NEG, POS, NEG) -MP_BIT2CBINOP(1100, 0011, 0011, 0011, 0011, NEG, POS, NEG, POS) -MP_BIT2CBINOP(1101, 0010, 0111, 0001, 0100, NEG, POS, NEG, NEG) -MP_BIT2CBINOP(1110, 0001, 0100, 0010, 0111, NEG, NEG, NEG, POS) -MP_BIT2CBINOP(1111, 0000, 0000, 0000, 0000, NEG, NEG, NEG, NEG) -#undef NEG -#undef POS - -/* --- @mp_not2c@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = source - * - * Returns: The sign-extended complement of the argument. - */ - -mp *mp_not2c(mp *d, mp *a) -{ - mpw one = 1; - - MP_DEST(d, MP_LEN(a) + 1, a->f); - if (d == a) { - if (MP_NEGP(a)) - MPX_USUBN(d->v, d->vl, 1); - else - MPX_UADDN(d->v, d->vl, 1); - } else { - if (MP_NEGP(a)) - mpx_usub(d->v, d->vl, a->v, a->vl, &one, &one + 1); - else - mpx_uadd(d->v, d->vl, a->v, a->vl, &one, &one + 1); - } - d->f = (a->f & (MP_NEG | MP_BURN)) ^ MP_NEG; - MP_SHRINK(d); - return (d); -} - -/* --- @mp_add@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: Result, @a@ added to @b@. - */ - -mp *mp_add(mp *d, mp *a, mp *b) -{ - MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)) + 1, a->f | b->f); - if (!((a->f ^ b->f) & MP_NEG)) - mpx_uadd(d->v, d->vl, a->v, a->vl, b->v, b->vl); - else { - if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) { - mp *t = a; a = b; b = t; - } - mpx_usub(d->v, d->vl, a->v, a->vl, b->v, b->vl); - } - d->f = ((a->f | b->f) & MP_BURN) | (a->f & MP_NEG); - MP_SHRINK(d); - return (d); -} - -/* --- @mp_sub@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: Result, @b@ subtracted from @a@. - */ - -mp *mp_sub(mp *d, mp *a, mp *b) -{ - unsigned sgn = 0; - MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)) + 1, a->f | b->f); - if ((a->f ^ b->f) & MP_NEG) - mpx_uadd(d->v, d->vl, a->v, a->vl, b->v, b->vl); - else { - if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) { - mp *t = a; a = b; b = t; - sgn = MP_NEG; - } - mpx_usub(d->v, d->vl, a->v, a->vl, b->v, b->vl); - } - d->f = ((a->f | b->f) & MP_BURN) | ((a->f ^ sgn) & MP_NEG); - MP_SHRINK(d); - return (d); -} - -/* --- @mp_mul@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: Result, @a@ multiplied by @b@. - */ - -mp *mp_mul(mp *d, mp *a, mp *b) -{ - a = MP_COPY(a); - b = MP_COPY(b); - - if (MP_LEN(a) <= MPK_THRESH || MP_LEN(b) <= MPK_THRESH) { - MP_DEST(d, MP_LEN(a) + MP_LEN(b), a->f | b->f | MP_UNDEF); - mpx_umul(d->v, d->vl, a->v, a->vl, b->v, b->vl); - } else { - size_t m = MAX(MP_LEN(a), MP_LEN(b)); - mpw *s; - MP_DEST(d, 3 * m, a->f | b->f | MP_UNDEF); - s = mpalloc(d->a, 5 * m); - mpx_kmul(d->v, d->vl, a->v, a->vl, b->v, b->vl, s, s + 5 * m); - mpfree(d->a, s); - } - - d->f = ((a->f | b->f) & MP_BURN) | ((a->f ^ b->f) & MP_NEG); - MP_SHRINK(d); - MP_DROP(a); - MP_DROP(b); - return (d); -} - -/* --- @mp_sqr@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = source - * - * Returns: Result, @a@ squared. - */ - -mp *mp_sqr(mp *d, mp *a) -{ - size_t m = MP_LEN(a); - - a = MP_COPY(a); - if (m > MPK_THRESH) { - mpw *s; - MP_DEST(d, 3 * m, a->f | MP_UNDEF); - s = mpalloc(d->a, 5 * m); - mpx_ksqr(d->v, d->vl, a->v, a->vl, s, s + 5 * m); - mpfree(d->a, s); - } else { - MP_DEST(d, 2 * m + 2, a->f | MP_UNDEF); - mpx_usqr(d->v, d->vl, a->v, a->vl); - } - d->f = a->f & MP_BURN; - MP_SHRINK(d); - MP_DROP(a); - return (d); -} - -/* --- @mp_div@ --- * - * - * Arguments: @mp **qq, **rr@ = destination, quotient and remainder - * @mp *a, *b@ = sources - * - * Use: Calculates the quotient and remainder when @a@ is divided by - * @b@. The destinations @*qq@ and @*rr@ must be distinct. - * Either of @qq@ or @rr@ may be null to indicate that the - * result is irrelevant. (Discarding both results is silly.) - * There is a performance advantage if @a == *rr@. - * - * The behaviour when @a@ and @b@ have the same sign is - * straightforward. When the signs differ, this implementation - * chooses @r@ to have the same sign as @b@, rather than the - * more normal choice that the remainder has the same sign as - * the dividend. This makes modular arithmetic a little more - * straightforward. - */ - -void mp_div(mp **qq, mp **rr, mp *a, mp *b) - { - mp *r = rr ? *rr : MP_NEW; - mp *q = qq ? *qq : MP_NEW; - mpw *sv, *svl; - - /* --- Set the remainder up right --- * - * - * Just in case the divisor is larger, be able to cope with this. It's not - * important in @mpx_udiv@, but it is here because of the sign correction. - */ - - b = MP_COPY(b); - a = MP_COPY(a); - if (r) - MP_DROP(r); - r = a; - MP_DEST(r, MAX(MP_LEN(a), MP_LEN(b)) + 2, a->f | b->f); - - /* --- Fix up the quotient too --- */ - - r = MP_COPY(r); - MP_DEST(q, MP_LEN(r), r->f | MP_UNDEF); - MP_DROP(r); - - /* --- Set up some temporary workspace --- */ - - { - size_t rq = MP_LEN(b) + 1; - sv = mpalloc(r->a, rq); - svl = sv + rq; - } - - /* --- Perform the calculation --- */ - - mpx_udiv(q->v, q->vl, r->v, r->vl, b->v, b->vl, sv, svl); - - /* --- Sort out the sign of the results --- * - * - * If the signs of the arguments differ, and the remainder is nonzero, I - * must add one to the absolute value of the quotient and subtract the - * remainder from @b@. - */ - - q->f = ((r->f | b->f) & MP_BURN) | ((r->f ^ b->f) & MP_NEG); - if (MP_NEGP(q)) { - mpw *v; - for (v = r->v; v < r->vl; v++) { - if (*v) { - MPX_UADDN(q->v, q->vl, 1); - mpx_usub(r->v, r->vl, b->v, b->vl, r->v, r->vl); - break; - } - } - } - - r->f = ((r->f | b->f) & MP_BURN) | (b->f & MP_NEG); - - /* --- Store the return values --- */ - - mpfree(r->a, sv); - MP_DROP(b); - - if (!qq) - MP_DROP(q); - else { - MP_SHRINK(q); - *qq = q; - } - - if (!rr) - MP_DROP(r); - else { - MP_SHRINK(r); - *rr = r; - } -} - -/* --- @mp_odd@ --- * - * - * Arguments: @mp *d@ = pointer to destination integer - * @mp *m@ = pointer to source integer - * @size_t *s@ = where to store the power of 2 - * - * Returns: An odd integer integer %$t$% such that %$m = 2^s t$%. - * - * Use: Computes a power of two and an odd integer which, when - * multiplied, give a specified result. This sort of thing is - * useful in number theory quite often. - */ - -mp *mp_odd(mp *d, mp *m, size_t *s) -{ - size_t ss = 0; - const mpw *v, *vl; - - v = m->v; - vl = m->vl; - for (; !*v && v < vl; v++) - ss += MPW_BITS; - if (v >= vl) - ss = 0; - else { - mpw x = *v; - unsigned z = MPW_P2; - mpw mask = ((mpw)1 << z) - 1; - - while (z) { - if (!(x & mask)) { - x >>= z; - ss += z; - } - z >>= 1; - mask >>= z; - } - } - - *s = ss; - return (mp_lsr(d, m, ss)); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int verify(const char *op, mp *expect, mp *result, mp *a, mp *b) -{ - if (!MP_EQ(expect, result)) { - fprintf(stderr, "\n*** %s failed", op); - fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 10); - fputs("\n*** b = ", stderr); mp_writefile(b, stderr, 10); - fputs("\n*** result = ", stderr); mp_writefile(result, stderr, 10); - fputs("\n*** expect = ", stderr); mp_writefile(expect, stderr, 10); - fputc('\n', stderr); - return (0); - } - return (1); -} - -#define RIG(name, op) \ - static int t##name(dstr *v) \ - { \ - mp *a = *(mp **)v[0].buf; \ - mpw n = *(int *)v[1].buf; \ - mp b; \ - mp *r = *(mp **)v[2].buf; \ - mp *c = op(MP_NEW, a, n); \ - int ok; \ - mp_build(&b, &n, &n + 1); \ - ok = verify(#name, r, c, a, &b); \ - mp_drop(a); mp_drop(c); mp_drop(r); \ - assert(mparena_count(MPARENA_GLOBAL) == 0); \ - return (ok); \ - } - -RIG(lsl, mp_lsl) -RIG(lsr, mp_lsr) -RIG(lsl2c, mp_lsl2c) -RIG(lsr2c, mp_lsr2c) - -#undef RIG - -#define RIG(name, op) \ - static int t##name(dstr *v) \ - { \ - mp *a = *(mp **)v[0].buf; \ - mp *b = *(mp **)v[1].buf; \ - mp *r = *(mp **)v[2].buf; \ - mp *c = op(MP_NEW, a, b); \ - int ok = verify(#name, r, c, a, b); \ - mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(r); \ - assert(mparena_count(MPARENA_GLOBAL) == 0); \ - return (ok); \ - } - -RIG(add, mp_add) -RIG(sub, mp_sub) -RIG(mul, mp_mul) -RIG(exp, mp_exp) - -#undef RIG - -static int tdiv(dstr *v) -{ - mp *a = *(mp **)v[0].buf; - mp *b = *(mp **)v[1].buf; - mp *q = *(mp **)v[2].buf; - mp *r = *(mp **)v[3].buf; - mp *c = MP_NEW, *d = MP_NEW; - int ok = 1; - mp_div(&c, &d, a, b); - ok &= verify("div(quotient)", q, c, a, b); - ok &= verify("div(remainder)", r, d, a, b); - mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(d); mp_drop(r); mp_drop(q); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tbin(dstr *v) -{ - static mp *(*fn[])(mp *, mp *, mp *) = { -#define DO(string) mp_bit##string##2c, -MPX_DOBIN(DO) -#undef DO - }; - int ok = 1; - unsigned op = 0; - mp *a = *(mp **)v[1].buf; - mp *b = *(mp **)v[2].buf; - mp *r = *(mp **)v[3].buf; - mp *c; - - if (strcmp(v[0].buf, "and") == 0) op = 1; - else if (strcmp(v[0].buf, "or") == 0) op = 7; - else if (strcmp(v[0].buf, "nand") == 0) op = 14; - else if (strcmp(v[0].buf, "nor") == 0) op = 8; - else if (strcmp(v[0].buf, "xor") == 0) op = 6; - else { - char *p = v[0].buf; - while (*p) { - op <<= 1; - if (*p++ == '1') - op |= 1; - } - } - - c = fn[op](MP_NEW, a, b); - ok = verify(v[0].buf, r, c, a, b); - mp_drop(a); mp_drop(b); mp_drop(r); mp_drop(c); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tset(dstr *v) -{ - mp *a = *(mp **)v[0].buf; - unsigned long n = *(unsigned long *)v[1].buf; - mp *r = *(mp **)v[2].buf; - mp *c; - int ok = 1; - - c = mp_setbit2c(MP_NEW, a, n); - if (!MP_EQ(c, r)) { - ok = 0; - fprintf(stderr, "\n***setbit (set) failed"); - fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 16); - fprintf(stderr, "\n*** n = %lu", n); - fputs("\n*** r = ", stderr); mp_writefile(r, stderr, 16); - fputs("\n*** c = ", stderr); mp_writefile(c, stderr, 16); - fputc('\n', stderr); - } - if (!mp_testbit2c(r, n)) { - ok = 0; - fprintf(stderr, "\n***setbit (test) failed"); - fprintf(stderr, "\n*** n = %lu", n); - fputs("\n*** r = ", stderr); mp_writefile(r, stderr, 16); - fputc('\n', stderr); - } - mp_drop(a); - mp_drop(r); - mp_drop(c); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tclr(dstr *v) -{ - mp *a = *(mp **)v[0].buf; - unsigned long n = *(unsigned long *)v[1].buf; - mp *r = *(mp **)v[2].buf; - mp *c; - int ok = 1; - - c = mp_clearbit2c(MP_NEW, a, n); - if (!MP_EQ(c, r)) { - ok = 0; - fprintf(stderr, "\n***clrbit (set) failed"); - fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 16); - fprintf(stderr, "\n*** n = %lu", n); - fputs("\n*** r = ", stderr); mp_writefile(r, stderr, 16); - fputs("\n*** c = ", stderr); mp_writefile(c, stderr, 16); - fputc('\n', stderr); - } - if (mp_testbit2c(r, n)) { - ok = 0; - fprintf(stderr, "\n***clrbit (test) failed"); - fprintf(stderr, "\n*** n = %lu", n); - fputs("\n*** r = ", stderr); mp_writefile(r, stderr, 16); - fputc('\n', stderr); - } - mp_drop(a); - mp_drop(c); - mp_drop(r); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tneg(dstr *v) -{ - mp *a = *(mp **)v[0].buf; - mp *r = *(mp **)v[1].buf; - int ok = 1; - mp *n = mp_neg(MP_NEW, a); - if (!MP_EQ(r, n)) { - ok = 0; - fprintf(stderr, "\n*** neg failed\n"); - fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 10); - fputs("\n*** r = ", stderr); mp_writefile(r, stderr, 10); - fputs("\n*** n = ", stderr); mp_writefile(n, stderr, 10); - fputc('\n', stderr); - } - mp_drop(n); - n = mp_neg(a, a); - if (!MP_EQ(r, n)) { - ok = 0; - fprintf(stderr, "\n*** neg failed\n"); - fputs("\n*** a* = ", stderr); mp_writefile(a, stderr, 10); - fputs("\n*** r = ", stderr); mp_writefile(r, stderr, 10); - fputs("\n*** n = ", stderr); mp_writefile(n, stderr, 10); - fputc('\n', stderr); - } - mp_drop(a); - mp_drop(r); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int todd(dstr *v) -{ - mp *a = *(mp **)v[0].buf; - size_t rs = *(uint32 *)v[1].buf; - mp *rt = *(mp **)v[2].buf; - int ok = 1; - mp *t; - size_t s; - t = mp_odd(MP_NEW, a, &s); - if (s != rs || !MP_EQ(t, rt)) { - ok = 0; - fprintf(stderr, "\n*** odd failed"); - fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 10); - fprintf(stderr, "\n*** s = %lu", (unsigned long)s); - fputs("\n*** t = ", stderr); mp_writefile(t, stderr, 10); - fprintf(stderr, "\n*** rs = %lu", (unsigned long)rs); - fputs("\n*** rt = ", stderr); mp_writefile(rt, stderr, 10); - fputc('\n', stderr); - } - mp_drop(a); - mp_drop(rt); - mp_drop(t); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "lsl", tlsl, { &type_mp, &type_int, &type_mp, 0 } }, - { "lsr", tlsr, { &type_mp, &type_int, &type_mp, 0 } }, - { "lsl2c", tlsl2c, { &type_mp, &type_int, &type_mp, 0 } }, - { "lsr2c", tlsr2c, { &type_mp, &type_int, &type_mp, 0 } }, - { "setbit", tset, { &type_mp, &type_ulong, &type_mp, 0 } }, - { "clrbit", tclr, { &type_mp, &type_ulong, &type_mp, 0 } }, - { "add", tadd, { &type_mp, &type_mp, &type_mp, 0 } }, - { "sub", tsub, { &type_mp, &type_mp, &type_mp, 0 } }, - { "mul", tmul, { &type_mp, &type_mp, &type_mp, 0 } }, - { "div", tdiv, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, - { "exp", texp, { &type_mp, &type_mp, &type_mp, 0 } }, - { "bin2c", tbin, { &type_string, &type_mp, &type_mp, &type_mp, 0 } }, - { "odd", todd, { &type_mp, &type_uint32, &type_mp, 0 } }, - { "neg", tneg, { &type_mp, &type_mp, 0 } }, - { 0, 0, { 0 } }, -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mp"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp-const.c b/mp-const.c deleted file mode 100644 index dc31007..0000000 --- a/mp-const.c +++ /dev/null @@ -1,51 +0,0 @@ -/* -*-c-*- - * - * $Id: mp-const.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Useful multiprecision constants - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" - -/*----- Global variables --------------------------------------------------*/ - -static mpw mpw_const[] = { 1, 2, 3, 4, 5, 10, 256 }; - -mp mp_const[] = { - { &mpw_const[0], &mpw_const[0], 0, 0, MP_CONST, 0 }, - { &mpw_const[0], &mpw_const[0] + 1, 1, 0, MP_CONST, 0 }, - { &mpw_const[1], &mpw_const[1] + 1, 1, 0, MP_CONST, 0 }, - { &mpw_const[2], &mpw_const[2] + 1, 1, 0, MP_CONST, 0 }, - { &mpw_const[3], &mpw_const[3] + 1, 1, 0, MP_CONST, 0 }, - { &mpw_const[4], &mpw_const[4] + 1, 1, 0, MP_CONST, 0 }, - { &mpw_const[5], &mpw_const[5] + 1, 1, 0, MP_CONST, 0 }, - { &mpw_const[6], &mpw_const[6] + 1, 1, 0, MP_CONST, 0 }, - { &mpw_const[0], &mpw_const[0] + 1, 1, 0, MP_CONST | MP_NEG, 0 }, - { 0, mpw_const, 1, 0, MP_CONST | MP_BURN, 0 }, -}; - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp-exp.c b/mp-exp.c deleted file mode 100644 index 9cb56ee..0000000 --- a/mp-exp.c +++ /dev/null @@ -1,67 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Exponentiation for large integers - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "mp.h" -#include "mp-exp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mp_exp@ --- * - * - * Arguments: @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e$%. - */ - -mp *mp_exp(mp *d, mp *a, mp *e) -{ - mp *x = MP_ONE; - mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; - assert(!MP_NEGP(e)); - - MP_COPY(a); - if (MP_ZEROP(e)) - ; - else if (MP_LEN(e) < EXP_THRESH) - EXP_SIMPLE(x, a, e); - else - EXP_WINDOW(x, a, e); - mp_drop(d); - mp_drop(spare); - mp_drop(a); - return (x); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp-exp.h b/mp-exp.h deleted file mode 100644 index 2e5dbf2..0000000 --- a/mp-exp.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Exponentiation for large integers - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MP_EXP_H -#define CATACOMB_MP_EXP_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Exponentiation ----------------------------------------------------*/ - -#define EXP_TYPE mp * - -#define EXP_COPY(d, x) d = MP_COPY(x) -#define EXP_DROP(x) MP_DROP(x) - -#define EXP_MUL(a, x) do { \ - mp *t = mp_mul(spare, a, x); \ - spare = a; \ - a = t; \ -} while (0) - -#define EXP_SQR(a) do { \ - mp *t = mp_sqr(spare, a); \ - spare = a; \ - a = t; \ -} while (0) - -#define EXP_FIX(x) - -#define EXP_SETMUL(d, x, y) d = mp_mul(MP_NEW, x, y) -#define EXP_SETSQR(d, x) d = mp_sqr(MP_NEW, x) - -#include "exp.h" - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mp-fibonacci.c b/mp-fibonacci.c deleted file mode 100644 index e103979..0000000 --- a/mp-fibonacci.c +++ /dev/null @@ -1,271 +0,0 @@ -/* -*-c-*- - * - * Compute the %$n$%th Fibonacci number - * - * (c) 2013 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpint.h" - -/*----- About the algorithm -----------------------------------------------* - * - * Define %$F_0 = 0$% and %$F_1 = 1$%, and %$F_{k+1} = F_k + F_{k-1}$% for - * all %$k$%. (This defines %$F_k$% for negative %$k$% too, by - * %$F_{k-1} = F_{k+1} - F_k$%; in particular, %$F_{-1} = 1$% and - * %$F_{-2} = -1$%.) We say that %$F_k$% is the %$k$%th Fibonacci number. - * - * We work in the ring %$\ZZ[t]/(t^2 - t -1)$%. Every residue class in this - * ring contains a unique representative with degree at most 1. I claim that - * %$t^k = F_k t + F_{k-1}$% for all %$k$%. Certainly %$t = F_1 t + F_0$%. - * Note that %$t (F_{-1} t + F_{-2}) = t (t - 1) = t^2 - t = 1$%, so the - * claim holds for %$k = -1$%. Suppose, inductively, that it holds for - * %$k$%; then %$t^{k+1} = t \cdot t^k = F_k t^2 + F_{k-1} t = {}$% - * %$(F_k + F_{k-1}) t + F_k = F_{k+1} t + F_k$%; and %$t^{k-1} = {}$% - * %$t^{-1} t^k = (t - 1) t^k = t^{k+1} - t^k = {}$% - * %$(F_{k+1} - F_k) t + (F_k - F_{k-1}) = F_{k-1} t + F_{k-2}$%, proving the - * claim. - * - * So we can compute Fibonacci numbers by exponentiating in this ring. - * Squaring and multiplication work like this. - * - * * Square: %$(a t + b)^2 = a^2 t^2 + 2 a b t + b^2 = {}$% - * %$(a^2 + 2 a b) t + (a^2 + b^2)$% - * - * * Multiply: %$(a t + b)(c t + d) = a c t^2 + (a d + b c) t + b d = {}$% - * %$(a c + a d + b c) t + (a c + b d)$%. - */ - -/*----- Exponentiation machinery ------------------------------------------*/ - -/* --- @struct fib@ --- * - * - * A simple structure tracking polynomial coefficients. - */ - -struct fib { - int n; /* Exponent for this entry */ - mp *a, *b; /* Coefficients: %$a t + b$% */ -}; - -#define MAX 100 /* Saturation bounds for exponent */ -#define MIN -100 - -/* --- @CLAMP@ --- * - * - * Clamp @n@ within the upper and lower bounds. - */ - -#define CLAMP(n) do { \ - if (n > MAX) n = MAX; else if (n < MIN) n = MIN; \ -} while (0) - -/* --- Basic structure maintenance functions --- */ - -static void fib_init(struct fib *f) - { f->a = f->b = MP_NEW; } - -static void fib_drop(struct fib *f) - { if (f->a) MP_DROP(f->a); if (f->b) MP_DROP(f->b); } - -static void fib_copy(struct fib *d, struct fib *x) - { d->n = x->n; d->a = MP_COPY(x->a); d->b = MP_COPY(x->b); } - -/* --- @fib_sqr@ --- * - * - * Arguments: @struct fib *d@ = destination structure - * @struct fib *x@ = operand - * - * Returns: --- - * - * Use: Set @d@ to the square of @x@. - */ - -static void fib_sqr(struct fib *d, struct fib *x) -{ - mp *aa, *t; - - /* --- Special case: if @x@ is the identity then just copy --- */ - - if (!x->n) { - if (d != x) { fib_drop(d); fib_copy(d, x); } - return; - } - - /* --- Compute the result --- */ - - aa = mp_sqr(MP_NEW, x->a); /* %$a^2$% */ - - t = mp_mul(d->a, x->a, x->b); /* %$t = a b$% */ - t = mp_lsl(t, t, 1); /* %$t = 2 a b$% */ - d->a = mp_add(t, t, aa); /* %$a' = a^2 + 2 a b$% */ - - t = mp_sqr(d->b, x->b); /* %$t = b^2$% */ - d->b = mp_add(t, t, aa); /* %$b' = a^2 + b^2$% */ - - /* --- Sort out the exponent on the result --- */ - - d->n = 2*x->n; CLAMP(d->n); - - /* --- Done --- */ - - MP_DROP(aa); -} - -/* --- @fib_mul@ --- * - * - * Arguments: @struct fib *d@ = destination structure - * @struct fib *x, *y@ = operands - * - * Returns: --- - * - * Use: Set @d@ to the product of @x@ and @y@. - */ - -static void fib_mul(struct fib *d, struct fib *x, struct fib *y) -{ - mp *t, *u, *bd; - - /* --- Lots of special cases for low exponents --- */ - - if (y->n == 0) { - copy_x: - if (d != x) { fib_drop(d); fib_copy(d, x); } - return; - } else if (x->n == 0) { x = y; goto copy_x; } - else if (y->n == -1) { - dec_x: - t = mp_sub(d->a, x->a, x->b); - d->a = MP_COPY(x->b); if (d->b) MP_DROP(d->b); d->b = t; - d->n = x->n - 1; CLAMP(d->n); - return; - } else if (y->n == +1) { - inc_x: - t = mp_add(d->b, x->a, x->b); - d->b = MP_COPY(x->a); if (d->a) MP_DROP(d->a); d->a = t; - d->n = x->n + 1; CLAMP(d->n); - return; - } else if (x->n == -1) { x = y; goto dec_x; } - else if (x->n == +1) { x = y; goto inc_x; } - - /* --- Compute the result --- */ - - bd = mp_mul(MP_NEW, x->b, y->b); /* %$b d$% */ - t = mp_add(MP_NEW, x->a, x->b); /* %$t = a + b$% */ - u = mp_add(MP_NEW, y->a, y->b); /* %$u = c + d$% */ - t = mp_mul(t, t, u); /* %$t = (a + b)(c + d)$% */ - u = mp_mul(u, x->a, y->a); /* %$u = a c$% */ - - d->a = mp_sub(d->a, t, bd); /* %$a' = a c + a d + b c$% */ - d->b = mp_add(d->b, u, bd); /* %$b' = a c + b d$% */ - - /* --- Sort out the exponent on the result --- */ - - if (x->n == MIN || x->n == MAX) d->n = x->n; - else if (y->n == MIN || y->n == MAX) d->n = y->n; - else { d->n = x->n + y->n; CLAMP(d->n); } - - /* --- Done --- */ - - MP_DROP(bd); MP_DROP(t); MP_DROP(u); -} - -/* --- Exponentiation --- */ - -#define EXP_TYPE struct fib -#define EXP_COPY(d, x) fib_copy(&d, &x) -#define EXP_DROP(x) fib_drop(&x) -#define EXP_FIX(d) - -#define EXP_SQR(x) fib_sqr(&x, &x) -#define EXP_MUL(x, y) fib_mul(&x, &x, &y) -#define EXP_SETSQR(d, x) fib_init(&d); fib_sqr(&d, &x) -#define EXP_SETMUL(d, x, y) fib_init(&d); fib_mul(&d, &x, &y) - -#include "exp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mp_fibonacci@ --- * - * - * Arguments: @long n@ = index desired (may be negative) - * - * Returns: The %$n$%th Fibonacci number. - */ - -mp *mp_fibonacci(long n) -{ - struct fib d, g; - mp *nn; - - d.n = 0; d.a = MP_ZERO; d.b = MP_ONE; - if (n >= 0) { g.n = 1; g.a = MP_ONE; g.b = MP_ZERO; } - else { g.n = -1; g.a = MP_ONE; g.b = MP_MONE; n = -n; } - nn = mp_fromlong(MP_NEW, n); - - EXP_WINDOW(d, g, nn); - - MP_DROP(nn); fib_drop(&g); MP_DROP(d.b); - return (d.a); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -static int vfib(dstr *v) -{ - long x = *(long *)v[0].buf; - mp *fx = *(mp **)v[1].buf; - mp *y = mp_fibonacci(x); - int ok = 1; - if (!MP_EQ(fx, y)) { - fprintf(stderr, "fibonacci failed\n"); - MP_FPRINTF(stderr, (stderr, "fib(%ld) = ", x), fx); - MP_EPRINT("result", y); - ok = 0; - } - mp_drop(fx); - mp_drop(y); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "fibonacci", vfib, { &type_long, &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, tests, SRCDIR "/tests/mp"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp-gcd.c b/mp-gcd.c deleted file mode 100644 index 40531c7..0000000 --- a/mp-gcd.c +++ /dev/null @@ -1,347 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Extended GCD calculation - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mp_gcd@ --- * - * - * Arguments: @mp **gcd, **xx, **yy@ = where to write the results - * @mp *a, *b@ = sources (must be nonzero) - * - * Returns: --- - * - * Use: Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that - * @ax + by = gcd(a, b)@. This is useful for computing modular - * inverses. - */ - -void mp_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b) -{ - mp *x = MP_ONE, *X = MP_ZERO; - mp *y = MP_ZERO, *Y = MP_ONE; - mp *u, *v; - mp *q = MP_NEW, *t, *spare = MP_NEW; - unsigned f = 0; - -#define f_swap 1u -#define f_aneg 2u -#define f_bneg 4u -#define f_ext 8u - - /* --- Sort out some initial flags --- */ - - if (xx || yy) - f |= f_ext; - - if (MP_NEGP(a)) - f |= f_aneg; - if (MP_NEGP(b)) - f |= f_bneg; - - /* --- Ensure that @a@ is larger than @b@ --- * - * - * Use absolute values here! - */ - - if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) { - t = a; a = b; b = t; - f |= f_swap; - } - - /* --- Check for zeroness --- */ - - if (MP_ZEROP(b)) { - - /* --- Store %$|a|$% as the GCD --- */ - - if (gcd) { - if (*gcd) MP_DROP(*gcd); - a = MP_COPY(a); - if (MP_NEGP(a)) { - MP_SPLIT(a); - a->f &= ~MP_NEG; - f |= f_aneg; - } - *gcd = a; - } - - /* --- Store %$1$% and %$0$% in the appropriate bins --- */ - - if (f & f_ext) { - if (f & f_swap) { - mp **tt = xx; xx = yy; yy = tt; - } - if (xx) { - if (*xx) MP_DROP(*xx); - if (MP_EQ(a, MP_ZERO)) - *xx = MP_ZERO; - else if (f & f_aneg) - *xx = MP_MONE; - else - *xx = MP_ONE; - } - if (yy) { - if (*yy) MP_DROP(*yy); - *yy = MP_ZERO; - } - } - return; - } - - /* --- Force the signs on the arguments and take copies --- */ - - a = MP_COPY(a); - b = MP_COPY(b); - - MP_SPLIT(a); a->f &= ~MP_NEG; - MP_SPLIT(b); b->f &= ~MP_NEG; - - u = MP_COPY(a); - v = MP_COPY(b); - - /* --- Main extended Euclidean algorithm --- */ - - while (!MP_ZEROP(v)) { - mp_div(&q, &u, u, v); - if (f & f_ext) { - t = mp_mul(spare, X, q); - t = mp_sub(t, x, t); - spare = x; x = X; X = t; - t = mp_mul(spare, Y, q); - t = mp_sub(t, y, t); - spare = y; y = Y; Y = t; - } - t = u; u = v; v = t; - } - - MP_DROP(q); if (spare) MP_DROP(spare); - if (!gcd) - MP_DROP(u); - else { - if (*gcd) MP_DROP(*gcd); - u->f &= ~MP_NEG; - *gcd = u; - } - - /* --- Perform a little normalization --- * - * - * Ensure that the coefficient returned is positive, if there is only one. - * If there are two, favour @y@. Of course, if the original arguments were - * negative then I'll need to twiddle their signs as well. - */ - - if (f & f_ext) { - - /* --- If @a@ and @b@ got swapped, swap the coefficients back --- */ - - if (f & f_swap) { - t = x; x = y; y = t; - t = a; a = b; b = t; - } - - /* --- Sort out the signs --- * - * - * Note that %$ax + by = a(x - b) + b(y + a)$%. - * - * This is currently bodgy. It needs sorting out at some time. - */ - - if (yy) { - if (MP_NEGP(y)) { - do { - y = mp_add(y, y, a); - x = mp_sub(x, x, b); - } while (MP_NEGP(y)); - } else { - while (MP_CMP(y, >=, a)) { - y = mp_sub(y, y, a); - x = mp_add(x, x, b); - } - } - } else { - if (MP_NEGP(x)) { - do - x = mp_add(x, x, b); - while (MP_NEGP(x)); - } else { - while (MP_CMP(x, >=, b)) - x = mp_sub(x, x, b); - } - } - - /* --- Twiddle the signs --- */ - - if (f & f_aneg) - x->f ^= MP_NEG; - if (f & f_bneg) - y->f ^= MP_NEG; - - /* --- Store the results --- */ - - if (!xx) - MP_DROP(x); - else { - if (*xx) MP_DROP(*xx); - *xx = x; - } - - if (!yy) - MP_DROP(y); - else { - if (*yy) MP_DROP(*yy); - *yy = y; - } - } - - MP_DROP(v); - MP_DROP(X); MP_DROP(Y); - MP_DROP(a); MP_DROP(b); -} - -/* -- @mp_modinv@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *x@ = argument - * @mp *p@ = modulus - * - * Returns: The inverse %$x^{-1} \bmod p$%. - * - * Use: Computes a modular inverse. An assertion fails if %$p$% - * has no inverse. - */ - -mp *mp_modinv(mp *d, mp *x, mp *p) -{ - mp *g = MP_NEW; - mp_gcd(&g, 0, &d, p, x); - assert(MP_EQ(g, MP_ONE)); - mp_drop(g); - return (d); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int modinv(dstr *v) -{ - int ok = 1; - mp *x = *(mp **)v[0].buf; - mp *m = *(mp **)v[1].buf; - mp *r = *(mp **)v[2].buf; - - mp *y = mp_modinv(MP_NEW, x, m); - if (!MP_EQ(y, r)) { - fputs("\n*** mp_modinv failed", stderr); - fputs("\nx = ", stderr); mp_writefile(x, stderr, 10); - fputs("\nm = ", stderr); mp_writefile(m, stderr, 10); - fputs("\nexpect = ", stderr); mp_writefile(r, stderr, 10); - fputs("\nresult = ", stderr); mp_writefile(y, stderr, 10); - ok = 0; - } - MP_DROP(x); MP_DROP(m); MP_DROP(r); MP_DROP(y); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int gcd(dstr *v) -{ - int ok = 1; - mp *a = *(mp **)v[0].buf; - mp *b = *(mp **)v[1].buf; - mp *g = *(mp **)v[2].buf; - mp *x = *(mp **)v[3].buf; - mp *y = *(mp **)v[4].buf; - - mp *gg = MP_NEW, *xx = MP_NEW, *yy = MP_NEW; - mp_gcd(&gg, &xx, &yy, a, b); - if (!MP_EQ(x, xx)) { - fputs("\n*** mp_gcd(x) failed", stderr); - fputs("\na = ", stderr); mp_writefile(a, stderr, 10); - fputs("\nb = ", stderr); mp_writefile(b, stderr, 10); - fputs("\nexpect = ", stderr); mp_writefile(x, stderr, 10); - fputs("\nresult = ", stderr); mp_writefile(xx, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - if (!MP_EQ(y, yy)) { - fputs("\n*** mp_gcd(y) failed", stderr); - fputs("\na = ", stderr); mp_writefile(a, stderr, 10); - fputs("\nb = ", stderr); mp_writefile(b, stderr, 10); - fputs("\nexpect = ", stderr); mp_writefile(y, stderr, 10); - fputs("\nresult = ", stderr); mp_writefile(yy, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - if (!ok) { - mp *ax = mp_mul(MP_NEW, a, xx); - mp *by = mp_mul(MP_NEW, b, yy); - ax = mp_add(ax, ax, by); - if (MP_EQ(ax, gg)) - fputs("\n*** (Alternative result found.)\n", stderr); - MP_DROP(ax); - MP_DROP(by); - } - - if (!MP_EQ(g, gg)) { - fputs("\n*** mp_gcd(gcd) failed", stderr); - fputs("\na = ", stderr); mp_writefile(a, stderr, 10); - fputs("\nb = ", stderr); mp_writefile(b, stderr, 10); - fputs("\nexpect = ", stderr); mp_writefile(g, stderr, 10); - fputs("\nresult = ", stderr); mp_writefile(gg, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - MP_DROP(a); MP_DROP(b); MP_DROP(g); MP_DROP(x); MP_DROP(y); - MP_DROP(gg); MP_DROP(xx); MP_DROP(yy); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "gcd", gcd, { &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, - { "modinv", modinv, { &type_mp, &type_mp, &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mp"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp-io.c b/mp-io.c deleted file mode 100644 index 9639a99..0000000 --- a/mp-io.c +++ /dev/null @@ -1,281 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Loading and storing of multiprecision integers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mp_octets@ --- * - * - * Arguments: @const mp *m@ = a multiprecision integer - * - * Returns: The number of octets required to represent @m@. - * - * Use: Calculates the external storage required for a multiprecision - * integer. - */ - -size_t mp_octets(const mp *m) -{ - size_t sz; - MPX_OCTETS(sz, m->v, m->vl); - return (sz); -} - -/* --- @mp_octets2c@ --- * - * - * Arguments: @const mp *m@ = a multiprecision integer - * - * Returns: The number of octets required to represent @m@. - * - * Use: Calculates the external storage required for a multiprecision - * integer represented as two's complement. - */ - -size_t mp_octets2c(const mp *m) -{ - size_t sz; - MPX_OCTETS2C(sz, m->v, m->vl); - return (sz); -} - -/* --- @mp_bits@ --- * - * - * Arguments: @const mp *m@ = a multiprecision integer - * - * Returns: The number of bits required to represent @m@. - * - * Use: Calculates the external storage required for a multiprecision - * integer. - */ - -unsigned long mp_bits(const mp *m) -{ - unsigned long bits; - MPX_BITS(bits, m->v, m->vl); - return (bits); -} - -/* --- @mp_loadl@ --- * - * - * Arguments: @mp *d@ = destination - * @const void *pv@ = pointer to source data - * @size_t sz@ = size of the source data - * - * Returns: Resulting multiprecision number. - * - * Use: Loads a multiprecision number from an array of octets. The - * first byte in the array is the least significant. More - * formally, if the bytes are %$b_0, b_1, \ldots, b_{n-1}$% - * then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%. - */ - -mp *mp_loadl(mp *d, const void *pv, size_t sz) -{ - MP_DEST(d, MPW_RQ(sz), MP_UNDEF); - mpx_loadl(d->v, d->vl, pv, sz); - d->f &= ~(MP_UNDEF | MP_NEG); - mp_shrink(d); - return (d); -} - -/* --- @mp_storel@ --- * - * - * Arguments: @const mp *m@ = source - * @void *pv@ = pointer to output array - * @size_t sz@ = size of the output array - * - * Returns: --- - * - * Use: Stores a multiprecision number in an array of octets. The - * first byte in the array is the least significant. If the - * array is too small to represent the number, high-order bits - * are truncated; if the array is too large, high order bytes - * are filled with zeros. More formally, if the number is - * %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%, - * then the array is %$b_0, b_1, \ldots, b_{n-1}$%. - */ - -void mp_storel(const mp *m, void *pv, size_t sz) -{ - mpx_storel(m->v, m->vl, pv, sz); -} - -/* --- @mp_loadb@ --- * - * - * Arguments: @mp *d@ = destination - * @const void *pv@ = pointer to source data - * @size_t sz@ = size of the source data - * - * Returns: Resulting multiprecision number. - * - * Use: Loads a multiprecision number from an array of octets. The - * last byte in the array is the least significant. More - * formally, if the bytes are %$b_{n-1}, b_{n-2}, \ldots, b_0$% - * then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%. - */ - -mp *mp_loadb(mp *d, const void *pv, size_t sz) -{ - MP_DEST(d, MPW_RQ(sz), MP_UNDEF); - mpx_loadb(d->v, d->vl, pv, sz); - d->f &= ~(MP_UNDEF | MP_NEG); - mp_shrink(d); - return (d); -} - -/* --- @mp_storeb@ --- * - * - * Arguments: @const mp *m@ = source - * @void *pv@ = pointer to output array - * @size_t sz@ = size of the output array - * - * Returns: --- - * - * Use: Stores a multiprecision number in an array of octets. The - * last byte in the array is the least significant. If the - * array is too small to represent the number, high-order bits - * are truncated; if the array is too large, high order bytes - * are filled with zeros. More formally, if the number is - * %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%, - * then the array is %$b_{n-1}, b_{n-2}, \ldots, b_0$%. - */ - -void mp_storeb(const mp *m, void *pv, size_t sz) -{ - mpx_storeb(m->v, m->vl, pv, sz); -} - -/* --- @mp_loadl2c@ --- * - * - * Arguments: @mp *d@ = destination - * @const void *pv@ = pointer to source data - * @size_t sz@ = size of the source data - * - * Returns: Resulting multiprecision number. - * - * Use: Loads a multiprecision number from an array of octets as - * two's complement. The first byte in the array is the least - * significant. - */ - -mp *mp_loadl2c(mp *d, const void *pv, size_t sz) -{ - const octet *ov = pv; - MP_DEST(d, MPW_RQ(sz), MP_UNDEF); - if (!sz || !(ov[sz - 1] & 0x80)) { - mpx_loadl(d->v, d->vl, pv, sz); - d->f &= ~MP_NEG; - } else { - mpx_loadl2cn(d->v, d->vl, pv, sz); - d->f |= MP_NEG; - } - d->f &= ~MP_UNDEF; - mp_shrink(d); - return (d); -} - -/* --- @mp_storel2c@ --- * - * - * Arguments: @const mp *m@ = source - * @void *pv@ = pointer to output array - * @size_t sz@ = size of the output array - * - * Returns: --- - * - * Use: Stores a multiprecision number in an array of octets as two's - * complement. The first byte in the array is the least - * significant. If the array is too small to represent the - * number, high-order bits are truncated; if the array is too - * large, high order bytes are sign-extended. - */ - -void mp_storel2c(const mp *m, void *pv, size_t sz) -{ - if (MP_NEGP(m)) - mpx_storel2cn(m->v, m->vl, pv, sz); - else - mpx_storel(m->v, m->vl, pv, sz); -} - -/* --- @mp_loadb2c@ --- * - * - * Arguments: @mp *d@ = destination - * @const void *pv@ = pointer to source data - * @size_t sz@ = size of the source data - * - * Returns: Resulting multiprecision number. - * - * Use: Loads a multiprecision number from an array of octets as - * two's complement. The last byte in the array is the least - * significant. - */ - -mp *mp_loadb2c(mp *d, const void *pv, size_t sz) -{ - const octet *ov = pv; - MP_DEST(d, MPW_RQ(sz), MP_UNDEF); - if (!sz || !(ov[0] & 0x80)) { - mpx_loadb(d->v, d->vl, pv, sz); - d->f &= ~MP_NEG; - } else { - mpx_loadb2cn(d->v, d->vl, pv, sz); - d->f |= MP_NEG; - } - d->f &= ~MP_UNDEF; - mp_shrink(d); - return (d); -} - -/* --- @mp_storeb2c@ --- * - * - * Arguments: @const mp *m@ = source - * @void *pv@ = pointer to output array - * @size_t sz@ = size of the output array - * - * Returns: --- - * - * Use: Stores a multiprecision number in an array of octets, as - * two's complement. The last byte in the array is the least - * significant. If the array is too small to represent the - * number, high-order bits are truncated; if the array is too - * large, high order bytes are sign-extended. - */ - -void mp_storeb2c(const mp *m, void *pv, size_t sz) -{ - if (MP_NEGP(m)) - mpx_storeb2cn(m->v, m->vl, pv, sz); - else - mpx_storeb(m->v, m->vl, pv, sz); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp-jacobi.c b/mp-jacobi.c deleted file mode 100644 index 3674f22..0000000 --- a/mp-jacobi.c +++ /dev/null @@ -1,203 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Compute Jacobi symbol - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mp_jacobi@ --- * - * - * Arguments: @mp *a@ = an integer - * @mp *n@ = another integer - * - * Returns: @-1@, @0@ or @1@ -- the Jacobi symbol %$J(a, n)$%. - * - * Use: Computes the Kronecker symbol %$\jacobi{a}{n}$%. If @n@ is - * prime, this is the Legendre symbol and is equal to 1 if and - * only if @a@ is a quadratic residue mod @n@. The result is - * zero if and only if @a@ and @n@ have a common factor greater - * than one. - * - * If @n@ is composite, then this computes the Kronecker symbol - * - * %$\jacobi{a}{n}=\jacobi{a}{u}\prod_i\jacobi{a}{p_i}^{e_i}$% - * - * where %$n = u p_0^{e_0} \ldots p_{n-1}^{e_{n-1}}$% is the - * prime factorization of %$n$%. The missing bits are: - * - * * %$\jacobi{a}{1} = 1$%; - * * %$\jacobi{a}{-1} = 1$% if @a@ is negative, or 1 if - * positive; - * * %$\jacobi{a}{0} = 0$%; - * * %$\jacobi{a}{2}$ is 0 if @a@ is even, 1 if @a@ is - * congruent to 1 or 7 (mod 8), or %$-1$% otherwise. - * - * If %$n$% is positive and odd, then this is the Jacobi - * symbol. (The Kronecker symbol is a consistant domain - * extension; the Jacobi symbol was implemented first, and the - * name stuck.) - */ - -int mp_jacobi(mp *a, mp *n) -{ - int s = 1; - size_t p2; - - /* --- Handle zero specially --- * - * - * I can't find any specific statement for what to do when %$n = 0$%; PARI - * opts to set %$\jacobi{\pm1}{0} = \pm 1$% and %$\jacobi{a}{0} = 0$% for - * other %$a$%. - */ - - if (MP_ZEROP(n)) { - if (MP_EQ(a, MP_ONE)) return (+1); - else if (MP_EQ(a, MP_MONE)) return (-1); - else return (0); - } - - /* --- Deal with powers of two --- * - * - * This implicitly takes a copy of %$n$%. Copy %$a$% at the same time to - * make cleanup easier. - */ - - MP_COPY(a); - n = mp_odd(MP_NEW, n, &p2); - if (p2) { - if (MP_EVENP(a)) { - s = 0; - goto done; - } else if ((p2 & 1) && ((a->v[0] & 7) == 3 || (a->v[0] & 7) == 5)) - s = -s; - } - - /* --- Deal with negative %$n$% --- */ - - if (MP_NEGP(n)) { - n = mp_neg(n, n); - if (MP_NEGP(a)) - s = -s; - } - - /* --- Check for unit %$n$% --- */ - - if (MP_EQ(n, MP_ONE)) - goto done; - - /* --- Reduce %$a$% modulo %$n$% --- */ - - if (MP_NEGP(a) || MP_CMP(a, >=, n)) - mp_div(0, &a, a, n); - - /* --- Main recursive mess, flattened out into something nice --- */ - - for (;;) { - mpw nn; - size_t e; - - /* --- Some simple special cases --- */ - - MP_SHRINK(a); - if (MP_ZEROP(a)) { - s = 0; - goto done; - } - - /* --- Main case with powers of two --- */ - - a = mp_odd(a, a, &e); - nn = n->v[0] & 7; - if ((e & 1) && (nn == 3 || nn == 5)) - s = -s; - if (MP_LEN(a) == 1 && a->v[0] == 1) - goto done; - if ((nn & 3) == 3 && (a->v[0] & 3) == 3) - s = -s; - - /* --- Reduce and swap --- */ - - mp_div(0, &n, n, a); - { mp *t = n; n = a; a = t; } - } - - /* --- Wrap everything up --- */ - -done: - MP_DROP(a); - MP_DROP(n); - return (s); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -static int verify(dstr *v) -{ - mp *a = *(mp **)v[0].buf; - mp *n = *(mp **)v[1].buf; - int s = *(int *)v[2].buf; - int j = mp_jacobi(a, n); - int ok = 1; - - if (s != j) { - fputs("\n*** fail", stderr); - fputs("a = ", stderr); mp_writefile(a, stderr, 10); fputc('\n', stderr); - fputs("n = ", stderr); mp_writefile(n, stderr, 10); fputc('\n', stderr); - fprintf(stderr, "s = %i\n", s); - fprintf(stderr, "j = %i\n", j); - ok = 0; - } - - mp_drop(a); - mp_drop(n); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "jacobi", verify, { &type_mp, &type_mp, &type_int, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mp"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp-mem.c b/mp-mem.c deleted file mode 100644 index fcb6c4d..0000000 --- a/mp-mem.c +++ /dev/null @@ -1,336 +0,0 @@ -/* -*-c-*- - * - * $Id: mp-mem.c,v 1.8 2004/04/08 16:17:32 mdw Exp $ - * - * Memory management for multiprecision numbers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - - -#include "mp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mp_new@ --- * - * - * Arguments: @size_t sz@ = size of vector required - * @unsigned f@ = flags to set - * - * Returns: Pointer to a new MP structure. - * - * Use: Allocates a new multiprecision integer. The data space is - * allocated from either the standard global or secret arena, - * depending on the initial flags requested. - */ - -mp *mp_new(size_t sz, unsigned f) -{ - mp *m = CREATE(mp); - m->a = (f & MP_BURN) ? MPARENA_SECURE : MPARENA_GLOBAL; - m->v = mpalloc(m->a, sz); - m->vl = m->v + sz; - m->sz = sz; - m->f = f & ~(MP_CONST | MP_DESTROYED); - m->ref = 1; - return (m); -} - -/* --- @mp_create@ --- * - * - * Arguments: @size_t sz@ = size of vector required - * - * Returns: Pointer to pristine new MP structure with enough memory - * bolted onto it. - * - * Use: Creates a new multiprecision integer, initially zero. The - * integer has a single reference. - */ - -mp *mp_create(size_t sz) -{ - mp *m = CREATE(mp); - m->v = mpalloc(MPARENA_GLOBAL, sz); - m->vl = m->v + sz; - m->sz = sz; - m->a = MPARENA_GLOBAL; - m->f = MP_UNDEF; - m->ref = 1; - return (m); -} - -/* --- @mp_createsecure@ --- * - * - * Arguments: @size_t sz@ = size of vector required - * - * Returns: Pointer to pristine new MP structure with enough memory - * bolted onto it. - * - * Use: Creates a new multiprecision integer with indeterminate - * contents. The integer has a single reference. The integer's - * data space is allocated from the secure arena. Its burn flag - * is set. - */ - -mp *mp_createsecure(size_t sz) -{ - mp *m = CREATE(mp); - m->v = mpalloc(MPARENA_SECURE, sz); - m->vl = m->v + sz; - m->sz = sz; - m->a = MPARENA_SECURE; - m->f = MP_UNDEF | MP_BURN; - m->ref = 1; - return (m); -} - -/* --- @mp_build@ --- * - * - * Arguments: @mp *m@ = pointer to an MP block to fill in - * @mpw *v@ = pointer to a word array - * @mpw *vl@ = pointer just past end of array - * - * Returns: --- - * - * Use: Creates a multiprecision integer representing some smallish - * number. You must provide storage for the number and dispose - * of it when you've finished with it. The number is marked as - * constant while it exists. - */ - -void mp_build(mp *m, mpw *v, mpw *vl) -{ - m->v = v; - m->vl = vl; - m->sz = vl - v; - m->a = MPARENA_GLOBAL; - m->f = MP_CONST; - m->ref = 1; -} - -/* --- @mp_destroy@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * - * Returns: --- - * - * Use: Destroys a multiprecision integer. The reference count isn't - * checked. Don't use this function if you don't know what - * you're doing: use @mp_drop@ instead. - */ - -void mp_destroy(mp *m) -{ - assert(((void)"Destroying a free integer", !(m->f & MP_DESTROYED))); - assert(((void)"Attempted to destroy a constant", !(m->f & MP_CONST))); - if (m->f & MP_BURN) - memset(m->v, 0, MPWS(m->sz)); - mpfree(m->a, m->v); - m->f |= MP_DESTROYED; - DESTROY(m); -} - -/* --- @mp_copy@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * - * Returns: A copy of the given multiprecision integer. - * - * Use: Copies the given integer. In fact you just get another - * reference to the same old one again. - */ - -mp *mp_copy(mp *m) { return MP_COPY(m); } - -/* --- @mp_drop@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * - * Returns: --- - * - * Use: Drops a reference to an integer which isn't wanted any more. - * If there are no more references, the integer is destroyed. - */ - -void mp_drop(mp *m) { if (m) MP_DROP(m); } - -/* --- @mp_split@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * - * Returns: A reference to the same integer, possibly with a different - * address. - * - * Use: Splits off a modifiable version of the integer referred to. - */ - -mp *mp_split(mp *m) { MP_SPLIT(m); return (m); } - -/* --- @mp_resize@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * @size_t sz@ = new size - * - * Returns: --- - * - * Use: Changes an integer's size. The length and value are not - * changed. It is an error to - */ - -void mp_resize(mp *m, size_t sz) { MP_RESIZE(m, sz); } - -/* --- @mp_ensure@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * @size_t sz@ = required length - * - * Returns: --- - * - * Use: Changes an integer's length. If there is not enough space - * allocated for the new length then the size is increased. It - */ - -void mp_ensure(mp *m, size_t sz) { MP_ENSURE(m, sz); } - -/* --- @mp_dest@ --- * - * - * Arguments: @mp *m@ = a suggested destination integer - * @size_t sz@ = size required for result, in digits - * @unsigned f@ = various flags - * - * Returns: A pointer to an appropriate destination. - * - * Use: Converts a suggested destination into a real destination with - * the required properties. If the real destination is @d@, - * then the following properties will hold: - * - * * @d@ will have exactly one reference. - * - * * If @m@ is not @MP_NEW@, then the contents of @m@ will not - * change, unless @f@ has the @MP_UNDEF@ flag set. - * - * * If @m@ is not @MP_NEW@, then he reference count of @m@ on - * entry is equal to the sum of the counts of @d@ and @m@ on - * exit. - * - * * The size of @d@ will be at least @sz@. - * - * * If @f@ has the @MP_BURN@ flag set, then @d@ will be - * allocated from @MPARENA_SECURE@. - * - * Understanding this function is crucial to using Catacomb's - * multiprecision integer library effectively. - */ - -mp *mp_dest(mp *m, size_t sz, unsigned f) -{ - /* --- If no destination, make one --- */ - - if (m == MP_NEWSEC) - m = mp_new(sz, f | MP_UNDEF | MP_BURN); - else if (m == MP_NEW) - m = mp_new(sz, f | MP_UNDEF); - else { - size_t len = MP_LEN(m); - unsigned undef = (m->f | f) & MP_UNDEF; - - /* --- If the value must be preserved, the block can't shrink --- */ - - if (!undef && sz < len) - sz = len; - - /* --- Otherwise check whether the destination is suitable --- */ - - if (m->ref > 1 || (m->f & MP_CONST) || - sz > m->sz || ((f & ~m->f) & MP_BURN)) { - - /* --- No -- allocate a new buffer --- * - * - * The buffer must be secure if (a) the caller requested a secure - * buffer, or (b) the old buffer is secure and I'm not allowed to - * discard the old contents. - */ - - mparena *a; - mpw *v; - - if ((f & MP_BURN) || (!undef && (m->f & MP_BURN))) - a = MPARENA_SECURE; - else - a = MPARENA_GLOBAL; - v = mpalloc(a, sz); - - /* --- Copy the data over --- */ - - if (!undef) { - memcpy(v, m->v, MPWS(len)); - if (sz - len > 0) - memset(v + len, 0, MPWS(sz - len)); - } - - /* --- If @m@ has other references, make a new node --- * - * - * Otherwise dispose of the old buffer. - */ - - if (!(m->f & MP_CONST) && m->ref == 1) { - if (m->f & MP_BURN) - memset(m->v, 0, MPWS(m->sz)); - mpfree(m->a, m->v); - } else { - mp *mm = CREATE(mp); - mm->ref = 1; - mm->f = m->f; - m->ref--; - m = mm; - } - - /* --- Fix up the node --- */ - - m->v = v; - m->vl = v + sz; - m->sz = sz; - m->f = ((m->f & ~(MP_CONST | MP_BURN)) | - (f & (MP_BURN | MP_UNDEF))); - m->a = a; - } - - /* --- If the number is growing in its buffer, fix it up --- */ - - else if (sz > len) { - if (!undef) - memset(m->vl, 0, MPWS(sz - len)); - m->vl = m->v + sz; - } - } - - /* --- Done --- */ - - return (m); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp-misc.c b/mp-misc.c deleted file mode 100644 index 90bdc37..0000000 --- a/mp-misc.c +++ /dev/null @@ -1,96 +0,0 @@ -/* -*-c-*- - * - * $Id: mp-misc.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Miscellaneous multiprecision support functions - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" - -/*----- Basic manipulation ------------------------------------------------*/ - -/* --- @mp_shrink@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * - * Returns: --- - * - * Use: Reduces the recorded length of an integer. This doesn't - * reduce the amount of memory used, although it can improve - * performance a bit. To reduce memory, use @mp_minimize@ - * instead. This can't change the value of an integer, and is - * therefore safe to use even when there are multiple - * references. - */ - -void mp_shrink(mp *m) { MP_SHRINK(m); } - -/* --- @mp_minimize@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * - * Returns: --- - * - * Use: Reduces the amount of memory an integer uses. It's best to - * do this to numbers which aren't going to change in the - * future. - */ - -void mp_minimize(mp *m) -{ - MP_SHRINK(m); - MP_RESIZE(m, MP_LEN(m)); -} - -/*----- Bit scanning ------------------------------------------------------*/ - -/* --- @mp_scan@ --- * - * - * Arguments: @mpscan *sc@ = pointer to bitscanner block - * @const mp *m@ = pointer to a multiprecision integer - * - * Returns: --- - * - * Use: Initializes a bitscanner on a multiprecision integer. - */ - -void mp_scan(mpscan *sc, const mp *m) { MP_SCAN(sc, m); } - -/* --- @mp_scan@ --- * - * - * Arguments: @mpscan *sc@ = pointer to bitscanner block - * @const mp *m@ = pointer to a multiprecision integer - * - * Returns: --- - * - * Use: Initializes a reverse bitscanner on a multiprecision - * integer. - */ - -void mp_rscan(mpscan *sc, const mp *m) { MP_RSCAN(sc, m); } - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp-modexp.c b/mp-modexp.c deleted file mode 100644 index ff2cbe0..0000000 --- a/mp-modexp.c +++ /dev/null @@ -1,113 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * General-purpose modular exponentiation - * - * (c) 2006 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpbarrett.h" -#include "mpmont.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mp_modexp@ --- * - * - * Arguments: @mp *d@ = fake destination - * @mp *x@ = base of exponentiation - * @mp *e@ = exponent - * @mp *n@ = modulus (must be positive) - * - * Returns: The value %$x^e \bmod n$%. - */ - -mp *mp_modexp(mp *d, mp *x, mp *e, mp *n) -{ - if (MP_ODDP(n)) { - mpmont mm; - mpmont_create(&mm, n); - d = mpmont_exp(&mm, d, x, e); - mpmont_destroy(&mm); - } else { - mpbarrett mb; - mpbarrett_create(&mb, n); - d = mpbarrett_exp(&mb, d, x, e); - mpbarrett_destroy(&mb); - } - return (d); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int tmodexp(dstr *v) -{ - mp *a = *(mp **)v[0].buf; - mp *b = *(mp **)v[1].buf; - mp *m = *(mp **)v[2].buf; - mp *r = *(mp **)v[3].buf; - mp *mr; - int ok = 1; - - mr = mp_modexp(MP_NEW, a, b, m); - - if (!MP_EQ(mr, r)) { - fputs("\n*** modexp failed", stderr); - fputs("\n a = ", stderr); mp_writefile(a, stderr, 10); - fputs("\n e = ", stderr); mp_writefile(b, stderr, 10); - fputs("\n m = ", stderr); mp_writefile(m, stderr, 10); - fputs("\n r = ", stderr); mp_writefile(r, stderr, 10); - fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - MP_DROP(m); - MP_DROP(a); - MP_DROP(b); - MP_DROP(r); - MP_DROP(mr); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return ok; -} - -static test_chunk tests[] = { - { "modexp", tmodexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mp"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp-modsqrt.c b/mp-modsqrt.c deleted file mode 100644 index 1791185..0000000 --- a/mp-modsqrt.c +++ /dev/null @@ -1,209 +0,0 @@ -/* -*-c-*- - * - * $Id: mp-modsqrt.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Compute square roots modulo a prime - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "fibrand.h" -#include "grand.h" -#include "mp.h" -#include "mpmont.h" -#include "mprand.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mp_modsqrt@ --- * - * - * Arguments: @mp *d@ = destination integer - * @mp *a@ = source integer - * @mp *p@ = modulus (must be prime) - * - * Returns: If %$a$% is a quadratic residue, a square root of %$a$%; else - * a null pointer. - * - * Use: Returns an integer %$x$% such that %$x^2 \equiv a \pmod{p}$%, - * if one exists; else a null pointer. This function will not - * work if %$p$% is composite: you must factor the modulus, take - * a square root mod each factor, and recombine the results - * using the Chinese Remainder Theorem. - * - * We guarantee that the square root returned is the smallest - * one (i.e., the `positive' square root). - */ - -mp *mp_modsqrt(mp *d, mp *a, mp *p) -{ - mpmont mm; - mp *t; - size_t s; - mp *b; - mp *ainv; - mp *c, *r; - size_t i, j; - mp *dd, *mone; - - /* --- Cope if %$a \not\in Q_p$% --- */ - - if (mp_jacobi(a, p) != 1) { - mp_drop(d); - return (0); - } - - /* --- Choose some quadratic non-residue --- */ - - { - grand *g = fibrand_create(0); - - b = MP_NEW; - do - b = mprand_range(b, p, g, 0); - while (mp_jacobi(b, p) != -1); - g->ops->destroy(g); - } - - /* --- Find the inverse of %$a$% --- */ - - ainv = mp_modinv(MP_NEW, a, p); - - /* --- Split %$p - 1$% into a power of two and an odd number --- */ - - t = mp_sub(MP_NEW, p, MP_ONE); - t = mp_odd(t, t, &s); - - /* --- Now to really get going --- */ - - mpmont_create(&mm, p); - b = mpmont_mul(&mm, b, b, mm.r2); - c = mpmont_expr(&mm, b, b, t); - t = mp_add(t, t, MP_ONE); - t = mp_lsr(t, t, 1); - dd = mpmont_mul(&mm, MP_NEW, a, mm.r2); - r = mpmont_expr(&mm, t, dd, t); - mp_drop(dd); - ainv = mpmont_mul(&mm, ainv, ainv, mm.r2); - - mone = mp_sub(MP_NEW, p, mm.r); - - dd = MP_NEW; - - for (i = 1; i < s; i++) { - - /* --- Compute %$d_0 = r^2a^{-1}$% --- */ - - dd = mp_sqr(dd, r); - dd = mpmont_reduce(&mm, dd, dd); - dd = mpmont_mul(&mm, dd, dd, ainv); - - /* --- Now %$d = d_0^{2^{s - i - 1}}$% --- */ - - for (j = i; j < s - 1; j++) { - dd = mp_sqr(dd, dd); - dd = mpmont_reduce(&mm, dd, dd); - } - - /* --- Fiddle at the end --- */ - - if (MP_EQ(dd, mone)) - r = mpmont_mul(&mm, r, r, c); - c = mp_sqr(c, c); - c = mpmont_reduce(&mm, c, c); - } - - /* --- Done, so tidy up --- * - * - * Canonify the answer. - */ - - d = mpmont_reduce(&mm, d, r); - r = mp_sub(r, p, d); - if (MP_CMP(r, <, d)) { mp *tt = r; r = d; d = tt; } - mp_drop(ainv); - mp_drop(r); mp_drop(c); - mp_drop(dd); - mp_drop(mone); - mpmont_destroy(&mm); - - return (d); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -static int verify(dstr *v) -{ - mp *a = *(mp **)v[0].buf; - mp *p = *(mp **)v[1].buf; - mp *rr = *(mp **)v[2].buf; - mp *r = mp_modsqrt(MP_NEW, a, p); - int ok = 0; - - if (!r) - ok = 0; - else if (MP_EQ(r, rr)) - ok = 1; - - if (!ok) { - fputs("\n*** fail\n", stderr); - fputs("a = ", stderr); mp_writefile(a, stderr, 10); fputc('\n', stderr); - fputs("p = ", stderr); mp_writefile(p, stderr, 10); fputc('\n', stderr); - if (r) { - fputs("r = ", stderr); - mp_writefile(r, stderr, 10); - fputc('\n', stderr); - } else - fputs("r = \n", stderr); - fputs("rr = ", stderr); mp_writefile(rr, stderr, 10); fputc('\n', stderr); - ok = 0; - } - - mp_drop(a); - mp_drop(p); - mp_drop(r); - mp_drop(rr); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "modsqrt", verify, { &type_mp, &type_mp, &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mp"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp-sqrt.c b/mp-sqrt.c deleted file mode 100644 index 1491021..0000000 --- a/mp-sqrt.c +++ /dev/null @@ -1,155 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Compute integer square roots - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mp_sqrt@ --- * - * - * Arguments: @mp *d@ = pointer to destination integer - * @mp *a@ = (nonnegative) integer to take square root of - * - * Returns: The largest integer %$x$% such that %$x^2 \le a$%. - * - * Use: Computes integer square roots. - * - * The current implementation isn't very good: it uses the - * Newton-Raphson method to find an approximation to %$a$%. If - * there's any demand for a better version, I'll write one. - */ - -mp *mp_sqrt(mp *d, mp *a) -{ - unsigned long z; - mp *q = MP_NEW, *r = MP_NEW; - - /* --- Sanity preservation --- */ - - assert(!MP_NEGP(a)); - - /* --- Deal with trivial cases --- */ - - MP_SHRINK(a); - if (MP_ZEROP(a)) { - mp_drop(d); - return (MP_ZERO); - } - - /* --- Find an initial guess of about the right size --- */ - - z = mp_bits(a); - z >>= 1; - mp_copy(a); - d = mp_lsr(d, a, z); - - /* --- Main approximation --- * - * - * We use the Newton-Raphson recurrence relation - * - * %$x_{i+1} = x_i - \frac{x_i^2 - a}{2 x_i}$% - * - * We inspect the term %$q = x^2 - a$% to see when to stop. Increasing - * %$x$% is pointless when %$-q < 2 x + 1$%. - */ - - for (;;) { - q = mp_sqr(q, d); - q = mp_sub(q, q, a); - if (MP_ZEROP(q)) - break; - if (MP_NEGP(q)) { - r = mp_lsl(r, d, 1); - r->f |= MP_NEG; - if (MP_CMP(q, >=, r)) - break; - } - mp_div(&r, &q, q, d); - r = mp_lsr(r, r, 1); - if (r->v == r->vl) - d = mp_sub(d, d, MP_ONE); - else - d = mp_sub(d, d, r); - } - - /* --- Finished, at last --- */ - - mp_drop(a); - mp_drop(q); - mp_drop(r); - return (d); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -static int verify(dstr *v) -{ - mp *a = *(mp **)v[0].buf; - mp *qq = *(mp **)v[1].buf; - mp *q = mp_sqrt(MP_NEW, a); - int ok = 1; - - if (!MP_EQ(q, qq)) { - ok = 0; - fputs("\n*** sqrt failed", stderr); - fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 10); - fputs("\n*** result = ", stderr); mp_writefile(q, stderr, 10); - fputs("\n*** expect = ", stderr); mp_writefile(qq, stderr, 10); - fputc('\n', stderr); - } - - mp_drop(a); - mp_drop(q); - mp_drop(qq); - assert(mparena_count(MPARENA_GLOBAL) == 0); - - return (ok); -} - -static test_chunk tests[] = { - { "sqrt", verify, { &type_mp, &type_mp, 0 } }, - { 0, 0, { 0 } }, -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mp"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp-test.c b/mp-test.c deleted file mode 100644 index 55c9ae9..0000000 --- a/mp-test.c +++ /dev/null @@ -1,64 +0,0 @@ -/* -*-c-*- - * - * $Id: mp-test.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Testing functionality for multiprecision integers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include -#include -#include -#include - -#include "mp.h" -#include "mptext.h" - -/*----- The `MP' testrig data type ----------------------------------------*/ - -static void mp_cvt(const char *buf, dstr *d) -{ - mp *m; - DENSURE(d, sizeof(mp *)); - m = mp_readstring(MP_NEW, (char *)buf, 0, 0); - if (!m) - die(1, "bad integer `%s'", buf); - *(mp **)d->buf = m; -} - -static void mp_dump(dstr *d, FILE *fp) -{ - mp *m = *(mp **)d->buf; - mp_writefile(m, fp, 10); -} - -const test_type type_mp = { mp_cvt, mp_dump }; - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mp.h b/mp.h deleted file mode 100644 index 13f97d1..0000000 --- a/mp.h +++ /dev/null @@ -1,1026 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Simple multiprecision arithmetic - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MP_H -#define CATACOMB_MP_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -#ifndef CATACOMB_MPW_H -# include "mpw.h" -#endif - -#ifndef CATACOMB_ARENA_H -# include "arena.h" -#endif - -#ifndef CATACOMB_MPARENA_H -# include "mparena.h" -#endif - -#ifndef CATACOMB_MPX_H -# include "mpx.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- A multiprecision integer --- */ - -typedef struct mp { - mpw *v, *vl; /* Vector of digits, current limit */ - size_t sz; /* Size of digit buffer in words */ - mparena *a; /* Arena for buffer allocation */ - unsigned f; /* Flags (see below) */ - unsigned ref; /* Reference counter */ -} mp; - -#define MP_NEG 1u /* Negative (signed magnitude) */ -#define MP_BURN 2u /* Secret (viral flag) */ -#define MP_CONST 4u /* Uses strange memory allocation */ -#define MP_UNDEF 8u /* Contains nothing interesting */ -#define MP_DESTROYED 16u /* Has been destroyed */ - -/* --- A factor for simultaneous exponentation --- * - * - * Used by the Montgomery and Barrett exponentiators. - */ - -typedef struct mp_expfactor { - mp *base; - mp *exp; -} mp_expfactor; - -/*----- Useful constants --------------------------------------------------*/ - -extern mp mp_const[]; - -#define MP_ZERO (&mp_const[0]) -#define MP_ONE (&mp_const[1]) -#define MP_TWO (&mp_const[2]) -#define MP_THREE (&mp_const[3]) -#define MP_FOUR (&mp_const[4]) -#define MP_FIVE (&mp_const[5]) -#define MP_TEN (&mp_const[6]) -#define MP_256 (&mp_const[7]) -#define MP_MONE (&mp_const[8]) - -#define MP_NEW ((mp *)0) -#define MP_NEWSEC (&mp_const[9]) - -/*----- Trivial macros ----------------------------------------------------*/ - -/* --- @MP_LEN@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * - * Returns: Length of the integer, in words. - */ - -#define MP_LEN(m) ((m)->vl - ((m)->v)) - -/*----- Memory management and reference counting --------------------------*/ - -/* --- @mp_new@ --- * - * - * Arguments: @size_t sz@ = size of vector required - * @unsigned f@ = flags to set - * - * Returns: Pointer to a new MP structure. - * - * Use: Allocates a new multiprecision integer. The data space is - * allocated from either the standard global or secret arena, - * depending on the initial flags requested. - */ - -extern mp *mp_new(size_t /*sz*/, unsigned /*f*/); - -/* --- @mp_create@ --- * - * - * Arguments: @size_t sz@ = size of vector required - * - * Returns: Pointer to pristine new MP structure with enough memory - * bolted onto it. - * - * Use: Creates a new multiprecision integer with indeterminate - * contents. The integer has a single reference. - */ - -extern mp *mp_create(size_t /*sz*/); - -/* --- @mp_createsecure@ --- * - * - * Arguments: @size_t sz@ = size of vector required - * - * Returns: Pointer to pristine new MP structure with enough memory - * bolted onto it. - * - * Use: Creates a new multiprecision integer with indeterminate - * contents. The integer has a single reference. The integer's - * data space is allocated from the secure arena. Its burn flag - * is set. - */ - -extern mp *mp_createsecure(size_t /*sz*/); - -/* --- @mp_build@ --- * - * - * Arguments: @mp *m@ = pointer to an MP block to fill in - * @mpw *v@ = pointer to a word array - * @mpw *vl@ = pointer just past end of array - * - * Returns: --- - * - * Use: Creates a multiprecision integer representing some smallish - * number. You must provide storage for the number and dispose - * of it when you've finished with it. The number is marked as - * constant while it exists. - */ - -extern void mp_build(mp */*m*/, mpw */*v*/, mpw */*vl*/); - -/* --- @mp_destroy@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * - * Returns: --- - * - * Use: Destroys a multiprecision integer. The reference count isn't - * checked. Don't use this function if you don't know what - * you're doing: use @mp_drop@ instead. - */ - -extern void mp_destroy(mp */*m*/); - -/* --- @mp_copy@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * - * Returns: A copy of the given multiprecision integer. - * - * Use: Copies the given integer. In fact you just get another - * reference to the same old one again. - */ - -extern mp *mp_copy(mp */*m*/); - -#define MP_COPY(m) ((m)->ref++, (m)) - -/* --- @mp_drop@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * - * Returns: --- - * - * Use: Drops a reference to an integer which isn't wanted any more. - * If there are no more references, the integer is destroyed. - */ - -extern void mp_drop(mp */*m*/); - -#define MP_DROP(m) do { \ - mp *_mm = (m); \ - _mm->ref--; \ - if (_mm->ref == 0 && !(_mm->f & MP_CONST)) \ - mp_destroy(_mm); \ -} while (0) - -/* --- @mp_split@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * - * Returns: A reference to the same integer, possibly with a different - * address. - * - * Use: Splits off a modifiable version of the integer referred to. - */ - -extern mp *mp_split(mp */*m*/); - -#define MP_SPLIT(m) do { \ - mp *_m = (m); \ - if ((_m->f & MP_CONST) || _m->ref > 1) { \ - size_t _len = MP_LEN(_m); \ - mp *_mm = mp_new(_len, _m->f); \ - if (!(_m->f & MP_UNDEF)) \ - memcpy(_mm->v, _m->v, MPWS(_len)); \ - _m->ref--; \ - _m = _mm; \ - } \ - (m) = _m; \ -} while (0) - -/* --- @mp_resize@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * @size_t sz@ = new size - * - * Returns: --- - * - * Use: Resizes the vector containing the integer's digits. The new - * size must be at least as large as the current integer's - * length. This isn't really intended for client use. - */ - -extern void mp_resize(mp */*m*/, size_t /*sz*/); - -#define MP_RESIZE(m, ssz) do { \ - mp *_m = (m); \ - size_t _sz = (ssz); \ - mparena *_a = (_m->f & MP_BURN) ? MPARENA_SECURE : MPARENA_GLOBAL; \ - mpw *_v; \ - size_t _len = MP_LEN(_m); \ - assert(((void)"can't make size less than length", _sz >= _len)); \ - _v = mpalloc(_a, _sz); \ - if (!(_m->f & MP_UNDEF)) \ - memcpy(_v, _m->v, MPWS(_len)); \ - if (_m->f & MP_BURN) \ - memset(_m->v, 0, MPWS(_m->sz)); \ - mpfree(_m->a, _m->v); \ - _m->a = _a; \ - _m->v = _v; \ - _m->vl = _v + _len; \ -} while (0) - -/* --- @mp_ensure@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * @size_t sz@ = required size - * - * Returns: --- - * - * Use: Ensures that the integer has enough space for @sz@ digits. - * The value is not changed. - */ - -extern void mp_ensure(mp */*m*/, size_t /*sz*/); - -#define MP_ENSURE(m, ssz) do { \ - mp *_m = (m); \ - size_t _ssz = (ssz); \ - size_t _len = MP_LEN(_m); \ - if (_ssz >= _len) { \ - if (_ssz > _m->sz) \ - mp_resize(_m, _ssz); \ - if (!(_m->f & MP_UNDEF) && _ssz > _len) \ - memset(_m->vl, 0, MPWS(_ssz - _len)); \ - _m->vl = _m->v + _ssz; \ - } \ -} while (0) - -/* --- @mp_dest@ --- * - * - * Arguments: @mp *m@ = a suggested destination integer - * @size_t sz@ = size required for result, in digits - * @unsigned f@ = various flags - * - * Returns: A pointer to an appropriate destination. - * - * Use: Converts a suggested destination into a real destination with - * the required properties. If the real destination is @d@, - * then the following properties will hold: - * - * * @d@ will have exactly one reference. - * - * * If @m@ is not @MP_NEW@, then the contents of @m@ will not - * change, unless @f@ has the @MP_UNDEF@ flag set. - * - * * If @m@ is not @MP_NEW@, then he reference count of @m@ on - * entry is equal to the sum of the counts of @d@ and @m@ on - * exit. - * - * * The size of @d@ will be at least @sz@. - * - * * If @f@ has the @MP_BURN@ flag set, then @d@ will be - * allocated from @MPARENA_SECURE@. - * - * Understanding this function is crucial to using Catacomb's - * multiprecision integer library effectively. - */ - -extern mp *mp_dest(mp */*m*/, size_t /*sz*/, unsigned /*f*/); - -#define MP_DEST(m, ssz, f) do { \ - mp *_m = (m); \ - size_t _ssz = (ssz); \ - unsigned _f = (f); \ - _m = mp_dest(_m, _ssz, _f); \ - (m) = _m; \ -} while (0) - -/*----- Size manipulation -------------------------------------------------*/ - -/* --- @mp_shrink@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * - * Returns: --- - * - * Use: Reduces the recorded length of an integer. This doesn't - * reduce the amount of memory used, although it can improve - * performance a bit. To reduce memory, use @mp_minimize@ - * instead. This can't change the value of an integer, and is - * therefore safe to use even when there are multiple - * references. - */ - -extern void mp_shrink(mp */*m*/); - -#define MP_SHRINK(m) do { \ - mp *_mm = (m); \ - MPX_SHRINK(_mm->v, _mm->vl); \ - if (MP_ZEROP(_mm)) \ - _mm->f &= ~MP_NEG; \ -} while (0) - -/* --- @mp_minimize@ --- * - * - * Arguments: @mp *m@ = pointer to a multiprecision integer - * - * Returns: --- - * - * Use: Reduces the amount of memory an integer uses. It's best to - * do this to numbers which aren't going to change in the - * future. - */ - -extern void mp_minimize(mp */*m*/); - -/*----- Bit scanning ------------------------------------------------------*/ - -#ifndef CATACOMB_MPSCAN_H -# include "mpscan.h" -#endif - -/* --- @mp_scan@ --- * - * - * Arguments: @mpscan *sc@ = pointer to bitscanner block - * @const mp *m@ = pointer to a multiprecision integer - * - * Returns: --- - * - * Use: Initializes a bitscanner on a multiprecision integer. - */ - -extern void mp_scan(mpscan */*sc*/, const mp */*m*/); - -#define MP_SCAN(sc, m) do { \ - const mp *_mm = (m); \ - mpscan *_sc = (sc); \ - MPSCAN_INITX(_sc, _mm->v, _mm->vl); \ -} while (0) - -/* --- @mp_rscan@ --- * - * - * Arguments: @mpscan *sc@ = pointer to bitscanner block - * @const mp *m@ = pointer to a multiprecision integer - * - * Returns: --- - * - * Use: Initializes a reverse bitscanner on a multiprecision - * integer. - */ - -extern void mp_rscan(mpscan */*sc*/, const mp */*m*/); - -#define MP_RSCAN(sc, m) do { \ - const mp *_mm = (m); \ - mpscan *_sc = (sc); \ - MPSCAN_RINITX(_sc, _mm->v, _mm->vl); \ -} while (0) - -/* --- Other bitscanning aliases --- */ - -#define mp_step mpscan_step -#define mp_bit mpscan_bit -#define mp_rstep mpscan_rstep -#define mp_rbit mpscan_rbit - -#define MP_STEP MPSCAN_STEP -#define MP_BIT MPSCAN_BIT -#define MP_RSTEP MPSCAN_RSTEP -#define MP_RBIT MPSCAN_RBIT - -/*----- Loading and storing -----------------------------------------------*/ - -/* --- @mp_octets@ --- * - * - * Arguments: @const mp *m@ = a multiprecision integer - * - * Returns: The number of octets required to represent @m@. - * - * Use: Calculates the external storage required for a multiprecision - * integer. - */ - -extern size_t mp_octets(const mp */*m*/); - -/* --- @mp_octets2c@ --- * - * - * Arguments: @const mp *m@ = a multiprecision integer - * - * Returns: The number of octets required to represent @m@. - * - * Use: Calculates the external storage required for a multiprecision - * integer represented as two's complement. - */ - -extern size_t mp_octets2c(const mp */*m*/); - -/* --- @mp_bits@ --- * - * - * Arguments: @const mp *m@ = a multiprecision integer - * - * Returns: The number of bits required to represent @m@. - * - * Use: Calculates the external storage required for a multiprecision - * integer. - */ - -extern unsigned long mp_bits(const mp */*m*/); - -/* --- @mp_loadl@ --- * - * - * Arguments: @mp *d@ = destination - * @const void *pv@ = pointer to source data - * @size_t sz@ = size of the source data - * - * Returns: Resulting multiprecision number. - * - * Use: Loads a multiprecision number from an array of octets. The - * first byte in the array is the least significant. More - * formally, if the bytes are %$b_0, b_1, \ldots, b_{n-1}$% - * then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%. - */ - -extern mp *mp_loadl(mp */*d*/, const void */*pv*/, size_t /*sz*/); - -/* --- @mp_storel@ --- * - * - * Arguments: @const mp *m@ = source - * @void *pv@ = pointer to output array - * @size_t sz@ = size of the output array - * - * Returns: --- - * - * Use: Stores a multiprecision number in an array of octets. The - * first byte in the array is the least significant. If the - * array is too small to represent the number, high-order bits - * are truncated; if the array is too large, high order bytes - * are filled with zeros. More formally, if the number is - * %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%, - * then the array is %$b_0, b_1, \ldots, b_{n-1}$%. - */ - -extern void mp_storel(const mp */*m*/, void */*pv*/, size_t /*sz*/); - -/* --- @mp_loadb@ --- * - * - * Arguments: @mp *d@ = destination - * @const void *pv@ = pointer to source data - * @size_t sz@ = size of the source data - * - * Returns: Resulting multiprecision number. - * - * Use: Loads a multiprecision number from an array of octets. The - * last byte in the array is the least significant. More - * formally, if the bytes are %$b_{n-1}, b_{n-2}, \ldots, b_0$% - * then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%. - */ - -extern mp *mp_loadb(mp */*d*/, const void */*pv*/, size_t /*sz*/); - -/* --- @mp_storeb@ --- * - * - * Arguments: @const mp *m@ = source - * @void *pv@ = pointer to output array - * @size_t sz@ = size of the output array - * - * Returns: --- - * - * Use: Stores a multiprecision number in an array of octets. The - * last byte in the array is the least significant. If the - * array is too small to represent the number, high-order bits - * are truncated; if the array is too large, high order bytes - * are filled with zeros. More formally, if the number is - * %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%, - * then the array is %$b_{n-1}, b_{n-2}, \ldots, b_0$%. - */ - -extern void mp_storeb(const mp */*m*/, void */*pv*/, size_t /*sz*/); - -/* --- @mp_loadl2c@ --- * - * - * Arguments: @mp *d@ = destination - * @const void *pv@ = pointer to source data - * @size_t sz@ = size of the source data - * - * Returns: Resulting multiprecision number. - * - * Use: Loads a multiprecision number from an array of octets as - * two's complement. The first byte in the array is the least - * significant. - */ - -extern mp *mp_loadl2c(mp */*d*/, const void */*pv*/, size_t /*sz*/); - -/* --- @mp_storel2c@ --- * - * - * Arguments: @const mp *m@ = source - * @void *pv@ = pointer to output array - * @size_t sz@ = size of the output array - * - * Returns: --- - * - * Use: Stores a multiprecision number in an array of octets as two's - * complement. The first byte in the array is the least - * significant. If the array is too small to represent the - * number, high-order bits are truncated; if the array is too - * large, high order bytes are sign-extended. - */ - -extern void mp_storel2c(const mp */*m*/, void */*pv*/, size_t /*sz*/); - -/* --- @mp_loadb2c@ --- * - * - * Arguments: @mp *d@ = destination - * @const void *pv@ = pointer to source data - * @size_t sz@ = size of the source data - * - * Returns: Resulting multiprecision number. - * - * Use: Loads a multiprecision number from an array of octets as - * two's complement. The last byte in the array is the least - * significant. - */ - -extern mp *mp_loadb2c(mp */*d*/, const void */*pv*/, size_t /*sz*/); - -/* --- @mp_storeb2c@ --- * - * - * Arguments: @const mp *m@ = source - * @void *pv@ = pointer to output array - * @size_t sz@ = size of the output array - * - * Returns: --- - * - * Use: Stores a multiprecision number in an array of octets, as - * two's complement. The last byte in the array is the least - * significant. If the array is too small to represent the - * number, high-order bits are truncated; if the array is too - * large, high order bytes are sign-extended. - */ - -extern void mp_storeb2c(const mp */*m*/, void */*pv*/, size_t /*sz*/); - -/*----- Bit operations ----------------------------------------------------*/ - -/* --- @mp_not@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = source - * - * Returns: The bitwise complement of the source. - */ - -extern mp *mp_not(mp */*d*/, mp */*a*/); - -/* --- @mp_bitop@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: The result of the given bitwise operation. These functions - * don't handle negative numbers at all sensibly. For that, use - * the @...2c@ variants. The functions are named after the - * truth tables they generate: - * - * a: 0011 - * b: 0101 - * @mpx_bitXXXX@ - */ - -#define MP_BITDECL(string) \ - extern mp *mp_bit##string(mp */*d*/, mp */*a*/, mp */*b*/); -MPX_DOBIN(MP_BITDECL) - -/* --- @mp_[n]and@, @mp_[n]or@, @mp_[n]xor@, @mp_not@ --- * - * - * Synonyms for the commonly-used functions. - */ - -#define mp_and mp_bit0001 -#define mp_or mp_bit0111 -#define mp_nand mp_bit1110 -#define mp_nor mp_bit1000 -#define mp_xor mp_bit0110 - -/* --- @mp_testbit@ --- * - * - * Arguments: @mp *x@ = a large integer - * @unsigned long n@ = which bit to test - * - * Returns: Nonzero if the bit is set, zero if not. - */ - -extern int mp_testbit(mp */*x*/, unsigned long /*n*/); - -/* --- @mp_setbit@, @mp_clearbit@ --- * - * - * Arguments: @mp *d@ = a destination - * @mp *x@ = a large integer - * @unsigned long n@ = which bit to modify - * - * Returns: The argument @x@, with the appropriate bit set or cleared. - */ - -extern mp *mp_setbit(mp */*d*/, mp */*x*/, unsigned long /*n*/); -extern mp *mp_clearbit(mp */*d*/, mp */*x*/, unsigned long /*n*/); - -/* --- @mp_lsl@, @mp_lslc@, @mp_lsr@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = source - * @size_t n@ = number of bits to move - * - * Returns: Result, @a@ shifted left or right by @n@. - * - * Use: Bitwise shift operators. @mp_lslc@ fills the bits introduced - * on the right with ones instead of zeroes: it's used - * internally by @mp_lsl2c@, though it may be useful on its - * own. - */ - -extern mp *mp_lsl(mp */*d*/, mp */*a*/, size_t /*n*/); -extern mp *mp_lslc(mp */*d*/, mp */*a*/, size_t /*n*/); -extern mp *mp_lsr(mp */*d*/, mp */*a*/, size_t /*n*/); - -/* --- @mp_not2c@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = source - * - * Returns: The sign-extended complement of the argument. - */ - -extern mp *mp_not2c(mp */*d*/, mp */*a*/); - -/* --- @mp_bitop2c@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: The result of the given bitwise operation. Negative numbers - * are treated as two's complement, sign-extended infinitely to - * the left. The functions are named after the truth tables - * they generate: - * - * a: 0011 - * b: 0101 - * @mpx_bitXXXX@ - */ - -#define MP_BIT2CDECL(string) \ - extern mp *mp_bit##string##2c(mp */*d*/, mp */*a*/, mp */*b*/); -MPX_DOBIN(MP_BIT2CDECL) - -/* --- @mp_[n]and@, @mp_[n]or@, @mp_[n]xor@, @mp_not@ --- * - * - * Synonyms for the commonly-used functions. - */ - -#define mp_and2c mp_bit00012c -#define mp_or2c mp_bit01112c -#define mp_nand2c mp_bit11102c -#define mp_nor2c mp_bit10002c -#define mp_xor2c mp_bit01102c - -/* --- @mp_lsl2c@, @mp_lsr2c@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = source - * @size_t n@ = number of bits to move - * - * Returns: Result, @a@ shifted left or right by @n@. Handles the - * pretence of sign-extension for negative numbers. - */ - -extern mp *mp_lsl2c(mp */*d*/, mp */*a*/, size_t /*n*/); -extern mp *mp_lsr2c(mp */*d*/, mp */*a*/, size_t /*n*/); - -/* --- @mp_testbit2c@ --- * - * - * Arguments: @mp *x@ = a large integer - * @unsigned long n@ = which bit to test - * - * Returns: Nonzero if the bit is set, zero if not. Fakes up two's - * complement representation. - */ - -extern int mp_testbit2c(mp */*x*/, unsigned long /*n*/); - -/* --- @mp_setbit2c@, @mp_clearbit2c@ --- * - * - * Arguments: @mp *d@ = a destination - * @mp *x@ = a large integer - * @unsigned long n@ = which bit to modify - * - * Returns: The argument @x@, with the appropriate bit set or cleared. - * Fakes up two's complement representation. - */ - -extern mp *mp_setbit2c(mp */*d*/, mp */*x*/, unsigned long /*n*/); -extern mp *mp_clearbit2c(mp */*d*/, mp */*x*/, unsigned long /*n*/); - -/*----- Comparisons -------------------------------------------------------*/ - -/* --- @mp_eq@ --- * - * - * Arguments: @const mp *a, *b@ = two numbers - * - * Returns: Nonzero if the numbers are equal. - */ - -extern int mp_eq(const mp */*a*/, const mp */*b*/); - -#define MP_EQ(a, b) \ - ((((a)->f ^ (b)->f) & MP_NEG) == 0 && \ - mpx_ueq((a)->v, (a)->vl, (b)->v, (b)->vl)) - -/* --- @mp_cmp@ --- * - * - * Arguments: @const mp *a, *b@ = two numbers - * - * Returns: Less than, equal to or greater than zero, according to - * whether @a@ is less than, equal to or greater than @b@. - */ - -extern int mp_cmp(const mp */*a*/, const mp */*b*/); - -#define MP_CMP(a, op, b) (mp_cmp((a), (b)) op 0) - -/* --- Other handy macros --- */ - -#define MP_NEGP(x) ((x)->f & MP_NEG) -#define MP_ZEROP(x) (!MP_LEN(x)) -#define MP_POSP(x) (!MP_NEGP(x) && !MP_ZEROP(x)) -#define MP_ODDP(x) (!MP_ZEROP(x) && ((x)->v[0] & 1u)) -#define MP_EVENP(x) (!MP_ODDP(x)) - -/*----- Arithmetic operations ---------------------------------------------*/ - -/* --- @mp_neg@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = argument - * - * Returns: The negation of the argument. - * - * Use: Negates its argument. - */ - -extern mp *mp_neg(mp */*d*/, mp */*a*/); - -/* --- @mp_add@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: Result, @a@ added to @b@. - */ - -extern mp *mp_add(mp */*d*/, mp */*a*/, mp */*b*/); - -/* --- @mp_sub@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: Result, @b@ subtracted from @a@. - */ - -extern mp *mp_sub(mp */*d*/, mp */*a*/, mp */*b*/); - -/* --- @mp_mul@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a, *b@ = sources - * - * Returns: Result, @a@ multiplied by @b@. - */ - -extern mp *mp_mul(mp */*d*/, mp */*a*/, mp */*b*/); - -/* --- @mp_sqr@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *a@ = source - * - * Returns: Result, @a@ squared. - */ - -extern mp *mp_sqr(mp */*d*/, mp */*a*/); - -/* --- @mp_div@ --- * - * - * Arguments: @mp **qq, **rr@ = destination, quotient and remainder - * @mp *a, *b@ = sources - * - * Use: Calculates the quotient and remainder when @a@ is divided by - * @b@. - */ - -extern void mp_div(mp **/*qq*/, mp **/*rr*/, mp */*a*/, mp */*b*/); - -/* --- @mp_exp@ --- * - * - * Arguments: @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e$%. - */ - -extern mp *mp_exp(mp */*d*/, mp */*a*/, mp */*e*/); - -/* --- @mp_odd@ --- * - * - * Arguments: @mp *d@ = pointer to destination integer - * @mp *m@ = pointer to source integer - * @size_t *s@ = where to store the power of 2 - * - * Returns: An odd integer integer %$t$% such that %$m = 2^s t$%. - * - * Use: Computes a power of two and an odd integer which, when - * multiplied, give a specified result. This sort of thing is - * useful in number theory quite often. - */ - -extern mp *mp_odd(mp */*d*/, mp */*m*/, size_t */*s*/); - -/*----- More advanced algorithms ------------------------------------------*/ - -/* --- @mp_sqrt@ --- * - * - * Arguments: @mp *d@ = pointer to destination integer - * @mp *a@ = (nonnegative) integer to take square root of - * - * Returns: The largest integer %$x$% such that %$x^2 \le a$%. - * - * Use: Computes integer square roots. - * - * The current implementation isn't very good: it uses the - * Newton-Raphson method to find an approximation to %$a$%. If - * there's any demand for a better version, I'll write one. - */ - -extern mp *mp_sqrt(mp */*d*/, mp */*a*/); - -/* --- @mp_gcd@ --- * - * - * Arguments: @mp **gcd, **xx, **yy@ = where to write the results - * @mp *a, *b@ = sources (must be nonzero) - * - * Returns: --- - * - * Use: Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that - * @ax + by = gcd(a, b)@. This is useful for computing modular - * inverses. Neither @a@ nor @b@ may be zero. - */ - -extern void mp_gcd(mp **/*gcd*/, mp **/*xx*/, mp **/*yy*/, - mp */*a*/, mp */*b*/); - -/* -- @mp_modinv@ --- * - * - * Arguments: @mp *d@ = destination - * @mp *x@ = argument - * @mp *p@ = modulus - * - * Returns: The inverse %$x^{-1} \bmod p$%. - * - * Use: Computes a modular inverse. An assertion fails if %$p$% - * has no inverse. - */ - -extern mp *mp_modinv(mp */*d*/, mp */*x*/, mp */*p*/); - -/* --- @mp_jacobi@ --- * - * - * Arguments: @mp *a@ = an integer - * @mp *n@ = another integer - * - * Returns: @-1@, @0@ or @1@ -- the Jacobi symbol %$J(a, n)$%. - * - * Use: Computes the Kronecker symbol %$\jacobi{a}{n}$%. If @n@ is - * prime, this is the Legendre symbol and is equal to 1 if and - * only if @a@ is a quadratic residue mod @n@. The result is - * zero if and only if @a@ and @n@ have a common factor greater - * than one. - * - * If @n@ is composite, then this computes the Kronecker symbol - * - * %$\jacobi{a}{n}=\jacobi{a}{u}\prod_i\jacobi{a}{p_i}^{e_i}$% - * - * where %$n = u p_0^{e_0} \ldots p_{n-1}^{e_{n-1}}$% is the - * prime factorization of %$n$%. The missing bits are: - * - * * %$\jacobi{a}{1} = 1$%; - * * %$\jacobi{a}{-1} = 1$% if @a@ is negative, or 1 if - * positive; - * * %$\jacobi{a}{0} = 0$%; - * * %$\jacobi{a}{2}$ is 0 if @a@ is even, 1 if @a@ is - * congruent to 1 or 7 (mod 8), or %$-1$% otherwise. - * - * If %$n$% is positive and odd, then this is the Jacobi - * symbol. (The Kronecker symbol is a consistant domain - * extension; the Jacobi symbol was implemented first, and the - * name stuck.) - */ - -extern int mp_jacobi(mp */*a*/, mp */*n*/); - -/* --- @mp_modsqrt@ --- * - * - * Arguments: @mp *d@ = destination integer - * @mp *a@ = source integer - * @mp *p@ = modulus (must be prime) - * - * Returns: If %$a$% is a quadratic residue, a square root of %$a$%; else - * a null pointer. - * - * Use: Returns an integer %$x$% such that %$x^2 \equiv a \pmod{p}$%, - * if one exists; else a null pointer. This function will not - * work if %$p$% is composite: you must factor the modulus, take - * a square root mod each factor, and recombine the results - * using the Chinese Remainder Theorem. - * - * We guarantee that the square root returned is the smallest - * one (i.e., the `positive' square root). - */ - -extern mp *mp_modsqrt(mp */*d*/, mp */*a*/, mp */*p*/); - -/* --- @mp_modexp@ --- * - * - * Arguments: @mp *d@ = fake destination - * @mp *x@ = base of exponentiation - * @mp *e@ = exponent - * @mp *n@ = modulus (must be positive) - * - * Returns: The value %$x^e \bmod n$%. - */ - -extern mp *mp_modexp(mp */*d*/, mp */*x*/, mp */*e*/, mp */*n*/); - -/*----- Test harness support ----------------------------------------------*/ - -#include - -#ifndef CATACOMB_MPTEXT_H -# include "mptext.h" -#endif - -extern const test_type type_mp; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mparena.c b/mparena.c deleted file mode 100644 index c726912..0000000 --- a/mparena.c +++ /dev/null @@ -1,340 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Allocation and freeing of MP buffers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include -#include -#include - -#include "mparena.h" - -/*----- Tweakables --------------------------------------------------------*/ - -/* --- @MPARENA_TRIVIAL@ --- * - * - * Make the allocator a passthrough. It immediately calls the underlying - * allocation functions rather than attempting to keep track of blocks - * itself. - */ - -#define MPARENA_TRIVIAL - -/* --- @MPARENA_DEBUG@ --- * - * - * The name of an output trace file to which logging information about the - * state of arena trees should be written. If unset, no logging is done. - */ - -/* #define MPARENA_DEBUG "mparena.out" */ - -/*----- Static variables --------------------------------------------------*/ - -#ifdef MPARENA_DEBUG - static FILE *debugfp = 0; - -# define MPARENA_OPENFILE do { \ - if (!debugfp) { \ - if ((debugfp = fopen(MPARENA_DEBUG, "w")) == 0) { \ - fprintf(stderr, "couldn't open debug output file\n"); \ - exit(EXIT_FAILURE); \ - } \ - } \ - } while (0) - -#endif - -/*----- Standard arenas ---------------------------------------------------*/ - -mparena mparena_global = MPARENA_INIT; -mparena mparena_secure = MPARENA_INIT; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @tdump@ --- * - * - * Arguments: @mparena_node *n@ = pointer to tree node to dump - * - * Returns: --- - * - * Use: Recursively dumps out the allocation tree. - */ - -#ifdef MPARENA_DEBUG - -static void tdump(mparena_node *n) -{ - if (!n) - putc('*', debugfp); - else { - putc('(', debugfp); - tdump(n->left); - fprintf(debugfp, ", %u, ", n->v[0]); - tdump(n->right); - putc(')', debugfp); - } -} - -#endif - -/* --- @mparena_create@ --- * - * - * Arguments: @mparena *a@ = pointer to arena block - * - * Returns: --- - * - * Use: Initializes an MP arena so that blocks can be allocated from - * it. - */ - -void mparena_create(mparena *a) -{ - a->root = 0; - a->n = 0; - a->a = &arena_stdlib; -} - -/* --- @mparena_setarena@ --- * - * - * Arguments: @mparena *a@ = pointer to MP arena block - * @arena *aa@ = pointer to arena - * - * Returns: --- - * - * Use: Sets the underlying arena for an MP arena. - */ - -extern void mparena_setarena(mparena *a, arena *aa) { a->a = aa; } - -/* --- @mparena_destroy@ --- * - * - * Arguments: @mparena *a@ = pointer to arena block - * - * Returns: --- - * - * Use: Frees an MP arena, and all the vectors held within it. The - * blocks which are currently allocated can be freed into some - * other arena. - */ - -static void tfree(mparena *a, mparena_node *n) -{ - A_FREE(a->a, n->v); - if (n->left) - tfree(a, n->left); - if (n->right) - tfree(a, n->right); - DESTROY(n); -} - -void mparena_destroy(mparena *a) -{ - tfree(a, a->root); - a->root = 0; -} - -/* --- @mparena_count@ --- * - * - * Arguments: @mparena *a@ = pointer to arena block - * - * Returns: Number of allocated blocks from this arena. - * - * Use: Reports the number of blocks allocated from the arena and not - * yet freed. - */ - -unsigned mparena_count(mparena *a) -{ - return (a->n); -} - -/* --- @mpalloc@ --- * - * - * Arguments: @mparena *a@ = pointer to arena block - * @size_t sz@ = number of digits required - * - * Returns: Pointer to a suitably sized block. - * - * Use: Allocates a lump of data suitable for use as an array of MP - * digits. - */ - -#ifdef MPARENA_TRIVIAL - -mpw *mpalloc(mparena *a, size_t sz) -{ - mpw *v; - if (!sz) return (0); - a->n++; - v = A_ALLOC(a->a, MPWS(sz)); - if (!v) - THROW(EXC_NOMEM); - return (v); -} - -#else - -mpw *mpalloc(mparena *a, size_t sz) -{ - mparena_node **nn, *n; - mpw *v; - - nn = &a->root; - -#ifdef MPARENA_DEBUG - MPARENA_OPENFILE; - fprintf(debugfp, "alloc %u\n before: ", sz); - tdump(a->root); putc('\n', debugfp); -#endif - - /* --- First, find a block which is big enough --- */ - -again: - n = *nn; - if (!n) { -#ifdef MPARENA_DEBUG - fputs(" failed\n", debugfp); -#endif - if ((v = A_ALLOC(a->a, MPWS(sz + 1))) == 0) - THROW(EXC_NOMEM); - v[0] = sz; - a->n++; - return (v + 1); - } - if (n->v[0] < sz) { - nn = &n->right; - goto again; - } - - /* --- Now try to find a smaller block which is suitable --- */ - - while (n->left && n->left->v[0] >= sz) { - nn = &n->left; - n = *nn; - } - - /* --- If the block we've got is still too large, start digging --- */ - - if (n->v[0] > sz * 2) { - nn = &n->left; - goto again; - } - - /* --- I've now found a suitable block --- */ - - v = n->v; - - /* --- Remove this node from the tree --- */ - - if (!n->left) - *nn = n->right; - else if (!n->right) - *nn = n->left; - else { - mparena_node *left = n->left; - mparena_node *p = *nn = n->right; - while (p->left) - p = p->left; - p->left = left; - } - -#ifdef MPARENA_DEBUG - fputs(" after: ", debugfp); - tdump(a->root); putc('\n', debugfp); -#endif - - /* --- Get rid of this node now --- */ - - DESTROY(n); - a->n++; - return (v + 1); -} - -#endif - -/* --- @mpfree@ --- * - * - * Arguments: @mparena *a@ = pointer to arena block - * @mpw *v@ = pointer to allocated vector - * - * Returns: --- - * - * Use: Returns an MP vector to an arena. - */ - -#ifdef MPARENA_TRIVIAL - -void mpfree(mparena *a, mpw *v) -{ - if (!v) return; - a->n--; - A_FREE(a->a, v); -} - -#else - -void mpfree(mparena *a, mpw *v) -{ - mparena_node **nn, *n; - size_t sz = *--v; - -#ifdef MPARENA_DEBUG - MPARENA_OPENFILE; - fprintf(debugfp, "free %u\n before: ", sz); - tdump(a->root); putc('\n', debugfp); -#endif - - nn = &a->root; - while (*nn) { - n = *nn; - if (n->v[0] > sz) - nn = &n->left; - else - nn = &n->right; - } - - n = CREATE(mparena_node); - n->left = n->right = 0; - n->v = v; - *nn = n; - a->n--; - -#ifdef MPARENA_DEBUG - fputs(" after: ", debugfp); - tdump(a->root); putc('\n', debugfp); -#endif -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mparena.h b/mparena.h deleted file mode 100644 index 94b69ad..0000000 --- a/mparena.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -*-c-*- - * - * $Id: mparena.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Allocation and freeing of MP buffers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPARENA_H -#define CATACOMB_MPARENA_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_MPW_H -# include "mpw.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- @mparena_node@ --- * - * - * For internal use by the MP arena manager. The free blocks are held in a - * binary tree by size, held in the first digit of each vector. - */ - -typedef struct mparena_node { - struct mparena_node *left, *right; - mpw *v; -} mparena_node; - -/* --- @mparena@ --- * - * - * The actual arena. - */ - -typedef struct mparena { - mparena_node *root; - unsigned n; - arena *a; -} mparena; - -/*----- Standard arenas ---------------------------------------------------*/ - -extern mparena mparena_global; -#define MPARENA_GLOBAL (&mparena_global) - -extern mparena mparena_secure; -#define MPARENA_SECURE (&mparena_secure) - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @mparena_create@ --- * - * - * Arguments: @mparena *a@ = pointer to arena block - * - * Returns: --- - * - * Use: Initializes an MP arena so that blocks can be allocated from - * it. - */ - -extern void mparena_create(mparena */*a*/); - -#define MPARENA_INIT { 0, 0, &arena_stdlib } - -/* --- @mparena_setarena@ --- * - * - * Arguments: @mparena *a@ = pointer to MP arena block - * @arena *aa@ = pointer to arena - * - * Returns: --- - * - * Use: Sets the underlying arena for an MP arena. - */ - -extern void mparena_setarena(mparena */*a*/, arena */*aa*/); - -/* --- @mparena_destroy@ --- * - * - * Arguments: @mparena *a@ = pointer to arena block - * - * Returns: --- - * - * Use: Frees an MP arena, and all the vectors held within it. The - * blocks which are currently allocated can be freed into some - * other MP arena, as long as the underlying arenas are the - * same. - */ - -extern void mparena_destroy(mparena */*a*/); - -/* --- @mparena_count@ --- * - * - * Arguments: @mparena *a@ = pointer to arena block - * - * Returns: Number of allocated blocks from this arena. - * - * Use: Reports the number of blocks allocated from the arena and not - * yet freed. - */ - -extern unsigned mparena_count(mparena */*a*/); - -/* --- @mpalloc@ --- * - * - * Arguments: @mparena *a@ = pointer to arena block - * @size_t sz@ = number of digits required - * - * Returns: Pointer to a suitably sized block. - * - * Use: Allocates a lump of data suitable for use as an array of MP - * digits. - */ - -extern mpw *mpalloc(mparena */*a*/, size_t /*sz*/); - -/* --- @mpfree@ --- * - * - * Arguments: @mparena *a@ = pointer to arena block - * @mpw *v@ = pointer to allocated vector - * - * Returns: --- - * - * Use: Returns an MP vector to an arena. - */ - -extern void mpfree(mparena */*a*/, mpw */*v*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mpbarrett-exp.c b/mpbarrett-exp.c deleted file mode 100644 index ef8fa59..0000000 --- a/mpbarrett-exp.c +++ /dev/null @@ -1,124 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Modular exponentiation using Barrett reduction - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpbarrett.h" -#include "mpbarrett-exp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mpbarrett_exp@ --- * - * - * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context - * @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e \bmod m$%. - */ - -mp *mpbarrett_exp(mpbarrett *mb, mp *d, mp *a, mp *e) -{ - mp *x = MP_ONE; - mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; - - MP_COPY(a); - MP_SHRINK(e); - if (MP_ZEROP(e)) - ; - else { - if (MP_NEGP(e)) - a = mp_modinv(a, a, mb->m); - if (MP_LEN(e) < EXP_THRESH) - EXP_SIMPLE(x, a, e); - else - EXP_WINDOW(x, a, e); - } - mp_drop(d); - mp_drop(spare); - mp_drop(a); - return (x); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int vexp(dstr *v) -{ - mp *m = *(mp **)v[0].buf; - mp *a = *(mp **)v[1].buf; - mp *b = *(mp **)v[2].buf; - mp *r = *(mp **)v[3].buf; - mp *mr; - int ok = 1; - - mpbarrett mb; - mpbarrett_create(&mb, m); - - mr = mpbarrett_exp(&mb, MP_NEW, a, b); - - if (!MP_EQ(mr, r)) { - fputs("\n*** barrett modexp failed", stderr); - fputs("\n m = ", stderr); mp_writefile(m, stderr, 10); - fputs("\n a = ", stderr); mp_writefile(a, stderr, 10); - fputs("\n e = ", stderr); mp_writefile(b, stderr, 10); - fputs("\n r = ", stderr); mp_writefile(r, stderr, 10); - fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - mp_drop(m); - mp_drop(a); - mp_drop(b); - mp_drop(r); - mp_drop(mr); - mpbarrett_destroy(&mb); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return ok; -} - -static test_chunk tests[] = { - { "mpbarrett-exp", vexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mpbarrett"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpbarrett-exp.h b/mpbarrett-exp.h deleted file mode 100644 index ee5043d..0000000 --- a/mpbarrett-exp.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*-c-*- - * - * $Id: mpbarrett-exp.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Exponentiation operations for Barrett reduction - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPBARRETT_EXP_H -#define CATACOMB_MPBARRETT_EXP_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Exponentation definitions -----------------------------------------*/ - -#define EXP_TYPE mp * - -#define EXP_COPY(d, x) d = MP_COPY(x) -#define EXP_DROP(x) MP_DROP(x) - -#define EXP_MUL(a, x) do { \ - mp *t = mp_mul(spare, a, x); \ - spare = a; \ - a = mpbarrett_reduce(mb, t, t); \ -} while (0) - -#define EXP_SQR(a) do { \ - mp *t = mp_sqr(spare, a); \ - spare = a; \ - a = mpbarrett_reduce(mb, t, t); \ -} while (0) - -#define EXP_FIX(x) - -#define EXP_SETMUL(d, x, y) do { \ - d = mp_mul(MP_NEW, x, y); \ - d = mpbarrett_reduce(mb, d, d); \ -} while (0) - -#define EXP_SETSQR(d, x) do { \ - d = mp_sqr(MP_NEW, x); \ - d = mpbarrett_reduce(mb, d, d); \ -} while (0) - -#include "exp.h" - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mpbarrett-mexp.c b/mpbarrett-mexp.c deleted file mode 100644 index 2cfda96..0000000 --- a/mpbarrett-mexp.c +++ /dev/null @@ -1,177 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Multiple simultaneous exponentiations - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpbarrett.h" - -#define EXP_WINSZ 3 -#include "mpbarrett-exp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mpbarrett_mexp@ --- * - * - * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context - * @mp *d@ = fake destination - * @const mp_expfactor *f@ = pointer to array of factors - * @size_t n@ = number of factors supplied - * - * Returns: If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the - * exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result - * is: - * - * %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$% - */ - -mp *mpbarrett_mexp(mpbarrett *mb, mp *d, const mp_expfactor *f, size_t n) -{ - mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor)); - mp *a = MP_ONE; - mp *spare; - mp *g = MP_NEW; - size_t i; - - spare = MP_NEW; - for (i = 0; i < n; i++) { - if (f[i].exp->f & MP_BURN) - spare = MP_NEWSEC; - if (MP_NEGP(f[i].exp)) - ff[i].base = mp_modinv(MP_NEW, f[i].base, mb->m); - else - ff[i].base = MP_COPY(f[i].base); - ff[i].exp = f[i].exp; - } - mp_drop(g); - EXP_SIMUL(a, ff, n); - mp_drop(d); - mp_drop(spare); - for (i = 0; i < n; i++) - mp_drop(ff[i].base); - xfree(ff); - return (a); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -static int verify(size_t n, dstr *v) -{ - mp *m = *(mp **)v[0].buf; - mp_expfactor *f = xmalloc(n * sizeof(*f)); - mp *r, *rr; - size_t i, j; - mpbarrett mb; - int ok = 1; - - j = 1; - for (i = 0; i < n; i++) { - f[i].base = *(mp **)v[j++].buf; - f[i].exp = *(mp **)v[j++].buf; - } - - rr = *(mp **)v[j].buf; - mpbarrett_create(&mb, m); - r = mpbarrett_mexp(&mb, MP_NEW, f, n); - if (!MP_EQ(r, rr)) { - fputs("\n*** mexp failed\n", stderr); - fputs("m = ", stderr); mp_writefile(m, stderr, 10); - for (i = 0; i < n; i++) { - fprintf(stderr, "\ng_%u = ", i); - mp_writefile(f[i].base, stderr, 10); - fprintf(stderr, "\ne_%u = ", i); - mp_writefile(f[i].exp, stderr, 10); - } - fputs("\nr = ", stderr); mp_writefile(r, stderr, 10); - fputs("\nR = ", stderr); mp_writefile(rr, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - for (i = 0; i < n; i++) { - MP_DROP(f[i].base); - MP_DROP(f[i].exp); - } - MP_DROP(m); - MP_DROP(r); - MP_DROP(rr); - mpbarrett_destroy(&mb); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int t1(dstr *v) { return verify(1, v); } -static int t2(dstr *v) { return verify(2, v); } -static int t3(dstr *v) { return verify(3, v); } -static int t4(dstr *v) { return verify(4, v); } -static int t5(dstr *v) { return verify(5, v); } - -static test_chunk tests[] = { - { "mexp-1", t1, { &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { "mexp-2", t2, { &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { "mexp-3", t3, { &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { "mexp-4", t4, { &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { "mexp-5", t5, { &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mpbarrett"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpbarrett.c b/mpbarrett.c deleted file mode 100644 index 13210b3..0000000 --- a/mpbarrett.c +++ /dev/null @@ -1,213 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Barrett modular reduction - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpbarrett.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mpbarrett_create@ --- * - * - * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context - * @mp *m@ = modulus to work to - * - * - * Returns: Zero on success, nonzero on error. - * - * Use: Initializes a Barrett reduction context ready for use. - */ - -int mpbarrett_create(mpbarrett *mb, mp *m) -{ - mp *b; - - /* --- Validate the arguments --- */ - - if (!MP_POSP(m)) - return (-1); - - /* --- Compute %$\mu$% --- */ - - mp_shrink(m); - mb->k = MP_LEN(m); - mb->m = MP_COPY(m); - b = mp_new(2 * mb->k + 1, 0); - MPX_ZERO(b->v, b->vl - 1); - b->vl[-1] = 1; - mp_div(&b, 0, b, m); - mb->mu = b; - return (0); -} - -/* --- @mpbarrett_destroy@ --- * - * - * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context - * - * Returns: --- - * - * Use: Destroys a Barrett reduction context releasing any resources - * claimed. - */ - -void mpbarrett_destroy(mpbarrett *mb) -{ - mp_drop(mb->m); - mp_drop(mb->mu); -} - -/* --- @mpbarrett_reduce@ --- * - * - * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context - * @mp *d@ = destination for result - * @mp *m@ = number to reduce - * - * Returns: The residue of @m@ modulo the number in the reduction - * context. - * - * Use: Performs an efficient modular reduction. - */ - -mp *mpbarrett_reduce(mpbarrett *mb, mp *d, mp *m) -{ - mp *q; - size_t k = mb->k; - - /* --- Special case if @m@ is too small --- */ - - if (MP_LEN(m) < k) { - m = MP_COPY(m); - if (d) - MP_DROP(d); - return (m); - } - - /* --- First stage --- */ - - { - mp qq; - mp_build(&qq, m->v + (k - 1), m->vl); - q = mp_mul(MP_NEW, &qq, mb->mu); - if (MP_LEN(q) <= k) { - m = MP_COPY(m); - if (d) - MP_DROP(d); - MP_DROP(q); - return (m); - } - } - - /* --- Second stage --- */ - - { - mp *r; - mpw *mvl; - - MP_COPY(m); - if (MP_LEN(m) <= k + 1) - mvl = m->vl; - else - mvl = m->v + k + 1; - r = mp_new(k + 1, (q->f | mb->m->f) & MP_BURN); - mpx_umul(r->v, r->vl, q->v + k + 1, q->vl, mb->m->v, mb->m->vl); - MP_DEST(d, k + 1, r->f | MP_UNDEF); - mpx_usub(d->v, d->vl, m->v, mvl, r->v, r->vl); - d->f = (m->f | r->f) & (MP_BURN | MP_NEG); - MP_DROP(r); - MP_DROP(q); - MP_DROP(m); - } - - /* --- Final stage --- */ - - MP_SHRINK(d); - while (MPX_UCMP(d->v, d->vl, >=, mb->m->v, mb->m->vl)) - mpx_usub(d->v, d->vl, d->v, d->vl, mb->m->v, mb->m->vl); - - /* --- Fix up the sign --- */ - - if (d->f & MP_NEG) { - mpx_usub(d->v, d->vl, mb->m->v, mb->m->vl, d->v, d->vl); - d->f &= ~MP_NEG; - } - - MP_SHRINK(d); - return (d); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int vmod(dstr *v) -{ - mp *x = *(mp **)v[0].buf; - mp *n = *(mp **)v[1].buf; - mp *r = *(mp **)v[2].buf; - mp *s; - mpbarrett mb; - int ok = 1; - - mpbarrett_create(&mb, n); - s = mpbarrett_reduce(&mb, MP_NEW, x); - - if (!MP_EQ(s, r)) { - fputs("\n*** barrett reduction failure\n", stderr); - fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr); - fputs("n = ", stderr); mp_writefile(n, stderr, 10); fputc('\n', stderr); - fputs("r = ", stderr); mp_writefile(r, stderr, 10); fputc('\n', stderr); - fputs("s = ", stderr); mp_writefile(s, stderr, 10); fputc('\n', stderr); - ok = 0; - } - - mpbarrett_destroy(&mb); - mp_drop(x); - mp_drop(n); - mp_drop(r); - mp_drop(s); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "mpbarrett-reduce", vmod, { &type_mp, &type_mp, &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mpbarrett"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpbarrett.h b/mpbarrett.h deleted file mode 100644 index 71d9ba7..0000000 --- a/mpbarrett.h +++ /dev/null @@ -1,143 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Barrett modular reduction - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on Barrett reduction ----------------------------------------* - * - * Barrett reduction is a technique for computing modular residues. Unlike - * Montgomery reduction, it doesn't have restrictions on the modulus (except - * that it be positive) and doesn't confuse matters by putting an extra - * factor all the way through your computation. - * - * It's useful for slightly less heavy-duty work than Montgomery reduction - * because the precomputation phase is rather simpler, involving a single - * division operation. - * - * Sometimes it's useful to exponentiate modulo an even number, so there's a - * modexp routine provided which uses Barrett reduction rather than - * Montgomery reduction. This is handy when you're working on indices in an - * even-order cyclic group or something. - */ - -#ifndef CATACOMB_MPBARRETT_H -#define CATACOMB_MPBARRETT_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct mpbarrett { - mp *m; - mp *mu; - size_t k; -} mpbarrett; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @mpbarrett_create@ --- * - * - * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context - * @mp *m@ = modulus to work to - * - * Returns: Zero on success, nonzero on error. - * - * Use: Initializes a Barrett reduction context ready for use. - */ - -extern int mpbarrett_create(mpbarrett */*mb*/, mp */*m*/); - -/* --- @mpbarrett_destroy@ --- * - * - * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context - * - * Returns: --- - * - * Use: Destroys a Barrett reduction context releasing any resources - * claimed. - */ - -extern void mpbarrett_destroy(mpbarrett */*mb*/); - -/* --- @mpbarrett_reduce@ --- * - * - * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context - * @mp *d@ = destination for result - * @mp *m@ = number to reduce - * - * Returns: The residue of @m@ modulo the number in the reduction - * context. - * - * Use: Performs an efficient modular reduction. - */ - -extern mp *mpbarrett_reduce(mpbarrett */*mb*/, mp */*d*/, mp */*m*/); - -/* --- @mpbarrett_exp@ --- * - * - * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context - * @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e \bmod m$%. - */ - -extern mp *mpbarrett_exp(mpbarrett */*mb*/, mp */*d*/, mp */*a*/, mp */*e*/); - -/* --- @mpbarrett_mexp@ --- * - * - * Arguments: @mpbarrett *mb@ = pointer to Barrett reduction context - * @mp *d@ = fake destination - * @const mp_expfactor *f@ = pointer to array of factors - * @size_t n@ = number of factors supplied - * - * Returns: If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the - * exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result - * is: - * - * %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$% - */ - -extern mp *mpbarrett_mexp(mpbarrett */*mb*/, mp */*d*/, - const mp_expfactor */*f*/, size_t /*n*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mpcrt.c b/mpcrt.c deleted file mode 100644 index bf6459f..0000000 --- a/mpcrt.c +++ /dev/null @@ -1,293 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Chinese Remainder Theorem computations (Gauss's algorithm) - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpcrt.h" -#include "mpmul.h" -#include "mpbarrett.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mpcrt_create@ --- * - * - * Arguments: @mpcrt *c@ = pointer to CRT context - * @mpcrt_mod *v@ = pointer to vector of moduli - * @size_t k@ = number of moduli - * @mp *n@ = product of all moduli (@MP_NEW@ if unknown) - * - * Returns: --- - * - * Use: Initializes a context for solving Chinese Remainder Theorem - * problems. The vector of moduli can be incomplete. Omitted - * items must be left as null pointers. Not all combinations of - * missing things can be coped with, even if there is - * technically enough information to cope. For example, if @n@ - * is unspecified, all the @m@ values must be present, even if - * there is one modulus with both @m@ and @n@ (from which the - * product of all moduli could clearly be calculated). - */ - -void mpcrt_create(mpcrt *c, mpcrt_mod *v, size_t k, mp *n) -{ - size_t i; - - /* --- Simple initialization things --- */ - - c->k = k; - c->v = v; - - /* --- Work out @n@ if I don't have it already --- */ - - if (n != MP_NEW) - n = MP_COPY(n); - else { - mpmul mm; - mpmul_init(&mm); - for (i = 0; i < k; i++) - mpmul_add(&mm, v[i].m); - n = mpmul_done(&mm); - } - - /* --- A quick hack if %$k = 2$% --- */ - - if (k == 2) { - - /* --- The %$n / n_i$% values are trivial in this case --- */ - - if (!v[0].n) - v[0].n = MP_COPY(v[1].m); - if (!v[1].n) - v[1].n = MP_COPY(v[0].m); - - /* --- Now sort out the inverses --- * - * - * @mp_gcd@ will ensure that the first argument is negative. - */ - - if (!v[0].ni && !v[1].ni) { - mp *g = MP_NEW; - mp_gcd(&g, &v[0].ni, &v[1].ni, v[0].n, v[1].n); - assert(MP_EQ(g, MP_ONE)); - mp_drop(g); - v[0].ni = mp_add(v[0].ni, v[0].ni, v[1].n); - } else { - int i, j; - mp *x; - - if (!v[0].ni) - i = 0, j = 1; - else - i = 1, j = 0; - - x = mp_mul(MP_NEW, v[j].n, v[j].ni); - x = mp_sub(x, x, MP_ONE); - mp_div(&x, 0, x, v[i].n); - v[i].ni = x; - } - } - - /* --- Set up the Barrett context --- */ - - mpbarrett_create(&c->mb, n); - - /* --- Walk through filling in @n@, @ni@ and @nnir@ --- */ - - for (i = 0; i < k; i++) { - if (!v[i].n) - mp_div(&v[i].n, 0, n, v[i].m); - if (!v[i].ni) - v[i].ni = mp_modinv(MP_NEW, v[i].n, v[i].m); - if (!v[i].nni) - v[i].nni = mp_mul(MP_NEW, v[i].n, v[i].ni); - } - - /* --- Done --- */ - - mp_drop(n); -} - -/* --- @mpcrt_destroy@ --- * - * - * Arguments: @mpcrt *c@ - pointer to CRT context - * - * Returns: --- - * - * Use: Destroys a CRT context, releasing all the resources it holds. - */ - -void mpcrt_destroy(mpcrt *c) -{ - size_t i; - - for (i = 0; i < c->k; i++) { - if (c->v[i].m) mp_drop(c->v[i].m); - if (c->v[i].n) mp_drop(c->v[i].n); - if (c->v[i].ni) mp_drop(c->v[i].ni); - if (c->v[i].nni) mp_drop(c->v[i].nni); - } - mpbarrett_destroy(&c->mb); -} - -/* --- @mpcrt_solve@ --- * - * - * Arguments: @mpcrt *c@ = pointer to CRT context - * @mp *d@ = fake destination - * @mp **v@ = array of residues - * - * Returns: The unique solution modulo the product of the individual - * moduli, which leaves the given residues. - * - * Use: Constructs a result given its residue modulo an array of - * coprime integers. This can be used to improve performance of - * RSA encryption or Blum-Blum-Shub generation if the factors - * of the modulus are known, since results can be computed mod - * each of the individual factors and then combined at the end. - * This is rather faster than doing the full-scale modular - * exponentiation. - */ - -mp *mpcrt_solve(mpcrt *c, mp *d, mp **v) -{ - mp *a = MP_ZERO; - mp *x = MP_NEW; - size_t i; - - for (i = 0; i < c->k; i++) { - x = mp_mul(x, c->v[i].nni, v[i]); - x = mpbarrett_reduce(&c->mb, x, x); - a = mp_add(a, a, x); - } - if (x) - MP_DROP(x); - a = mpbarrett_reduce(&c->mb, a, a); - if (d != MP_NEW) - MP_DROP(d); - return (a); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int verify(size_t n, dstr *v) -{ - mpcrt_mod *m = xmalloc(n * sizeof(mpcrt_mod)); - mp **r = xmalloc(n * sizeof(mp *)); - mpcrt c; - mp *a, *b; - size_t i; - int ok = 1; - - for (i = 0; i < n; i++) { - r[i] = *(mp **)v[2 * i].buf; - m[i].m = *(mp **)v[2 * i + 1].buf; - m[i].n = 0; - m[i].ni = 0; - m[i].nni = 0; - } - a = *(mp **)v[2 * n].buf; - - mpcrt_create(&c, m, n, 0); - b = mpcrt_solve(&c, MP_NEW, r); - - if (!MP_EQ(a, b)) { - fputs("\n*** failed\n", stderr); - fputs("n = ", stderr); - mp_writefile(c.mb.m, stderr, 10); - for (i = 0; i < n; i++) { - fprintf(stderr, "\nr[%u] = ", i); - mp_writefile(r[i], stderr, 10); - fprintf(stderr, "\nm[%u] = ", i); - mp_writefile(m[i].m, stderr, 10); - fprintf(stderr, "\nN[%u] = ", i); - mp_writefile(m[i].n, stderr, 10); - fprintf(stderr, "\nM[%u] = ", i); - mp_writefile(m[i].ni, stderr, 10); - } - fputs("\nresult = ", stderr); - mp_writefile(b, stderr, 10); - fputs("\nexpect = ", stderr); - mp_writefile(a, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - for (i = 0; i < n; i++) - mp_drop(r[i]); - mp_drop(a); - mp_drop(b); - mpcrt_destroy(&c); - xfree(m); - xfree(r); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int crt1(dstr *v) { return verify(1, v); } -static int crt2(dstr *v) { return verify(2, v); } -static int crt3(dstr *v) { return verify(3, v); } -static int crt4(dstr *v) { return verify(4, v); } -static int crt5(dstr *v) { return verify(5, v); } - -static test_chunk tests[] = { - { "crt-1", crt1, { &type_mp, &type_mp, - &type_mp, 0 } }, - { "crt-2", crt2, { &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { "crt-3", crt3, { &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { "crt-4", crt4, { &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { "crt-5", crt5, { &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mpcrt"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpcrt.h b/mpcrt.h deleted file mode 100644 index c108916..0000000 --- a/mpcrt.h +++ /dev/null @@ -1,125 +0,0 @@ -/* -*-c-*- - * - * $Id: mpcrt.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Chinese Remainder Theorem computations (Gauss's algorithm) - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPCRT_H -#define CATACOMB_MPCRT_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_MPBARRETT_H -# include "mpbarrett.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct mpcrt_mod { - mp *m; /* %$n_i$% -- the modulus */ - mp *n; /* %$N_i = n / n_i$% */ - mp *ni; /* %$M_i = N_i^{-1} \bmod n_i$% */ - mp *nni; /* %$N_i M_i \bmod m$% */ -} mpcrt_mod; - -typedef struct mpcrt { - size_t k; /* Number of distinct moduli */ - mpbarrett mb; /* Barrett context for product */ - mpcrt_mod *v; /* Vector of information for each */ -} mpcrt; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @mpcrt_create@ --- * - * - * Arguments: @mpcrt *c@ = pointer to CRT context - * @mpcrt_mod *v@ = pointer to vector of moduli - * @size_t k@ = number of moduli - * @mp *n@ = product of all moduli (@MP_NEW@ if unknown) - * - * Returns: --- - * - * Use: Initializes a context for solving Chinese Remainder Theorem - * problems. The vector of moduli can be incomplete. Omitted - * items must be left as null pointers. Not all combinations of - * missing things can be coped with, even if there is - * technically enough information to cope. For example, if @n@ - * is unspecified, all the @m@ values must be present, even if - * there is one modulus with both @m@ and @n@ (from which the - * product of all moduli could clearly be calculated). - */ - -extern void mpcrt_create(mpcrt */*c*/, mpcrt_mod */*v*/, - size_t /*k*/, mp */*n*/); - -/* --- @mpcrt_destroy@ --- * - * - * Arguments: @mpcrt *c@ - pointer to CRT context - * - * Returns: --- - * - * Use: Destroys a CRT context, releasing all the resources it holds. - */ - -extern void mpcrt_destroy(mpcrt */*c*/); - -/* --- @mpcrt_solve@ --- * - * - * Arguments: @mpcrt *c@ = pointer to CRT context - * @mp *d@ = fake destination - * @mp **v@ = array of residues - * - * Returns: The unique solution modulo the product of the individual - * moduli, which leaves the given residues. - * - * Use: Constructs a result given its residue modulo an array of - * coprime integers. This can be used to improve performance of - * RSA encryption or Blum-Blum-Shub generation if the factors - * of the modulus are known, since results can be computed mod - * each of the individual factors and then combined at the end. - * This is rather faster than doing the full-scale modular - * exponentiation. - */ - -extern mp *mpcrt_solve(mpcrt */*c*/, mp */*d*/, mp **/*v*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mpdump.c b/mpdump.c deleted file mode 100644 index 1d80f40..0000000 --- a/mpdump.c +++ /dev/null @@ -1,74 +0,0 @@ -/* -*-c-*- - * - * $Id: mpdump.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Dump a multiprecision integer as C data - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include "mp.h" - -/*----- Main code ---------------------------------------------------------*/ - -int main(int argc, char *argv[]) -{ - mp *x; - int i; - int w, n; - - if (argc != 2) { - fprintf(stderr, "%s: missing argument\n", argv[0]); - return (1); - } - if ((x = mp_readstring(0, argv[1], 0, 0)) == 0) { - fprintf(stderr, "%s: bad integer `%s'", argv[0], argv[1]); - return (1); - } - fputs(" ", stdout); - w = (MPW_BITS + 3)/4; - n = 1; - while (2 + 2 * n * (4 + w) < 72) n <<= 1; - i = 0; - for (;;) { - printf("0x%0*x", w, x->v[i]); - i++; - if (i >= MP_LEN(x)) break; - fputs(",", stdout); - if (i % n) fputs(" ", stdout); else fputs("\n ", stdout); - } - if (fflush(stdout) || ferror(stdout)) { - fprintf(stderr, "%s: error writing data: %s", argv[0], strerror(errno)); - return (1); - } - fputs("\n", stdout); - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpint.c b/mpint.c deleted file mode 100644 index 7c1b8cc..0000000 --- a/mpint.c +++ /dev/null @@ -1,179 +0,0 @@ -/* -*-c-*- - * - * $Id: mpint.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Conversion between MPs and standard C integers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mpint.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Conversion from C integers --- */ - -#define FROM(name, type) \ - mp *mp_from##name(mp *d, type i) { \ - MP_FROMINT(d, type, i); \ - return (d); \ - } - -FROM(short, short) -FROM(ushort, unsigned short) -FROM(int, int) -FROM(uint, unsigned) -FROM(uint32, uint32) -FROM(long, long) -FROM(ulong, unsigned long) - -#undef FROM - -/* --- Conversion to C integers --- */ - -#define TO(name, type, max) \ - type mp_to##name(const mp *m) \ - { \ - type i; \ - MP_TOINT(m, type, max, i); \ - return (i); \ - } - -TO(short, short, SHRT_MAX) -TO(ushort, unsigned short, USHRT_MAX) -TO(int, int, INT_MAX) -TO(uint, unsigned, UINT_MAX) -TO(uint32, uint32, 0xffffffff) -TO(long, long, LONG_MAX) -TO(ulong, unsigned long, ULONG_MAX) - -#undef TO - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -static int fromuint(dstr *v) -{ - unsigned long i = *(unsigned long *)v[0].buf; - mp *m = *(mp **)v[1].buf; - mp *d = mp_fromuint(MP_NEW, i); - int ok = 1; - - if (!MP_EQ(d, m)) { - fputs("\n*** fromint failed.\n", stderr); - fprintf(stderr, "i = %lu", i); - fputs("\nexpect = ", stderr); mp_writefile(m, stderr, 10); - fputs("\nresult = ", stderr); mp_writefile(d, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - mp_drop(m); - mp_drop(d); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int fromint(dstr *v) -{ - long i = *(long *)v[0].buf; - mp *m = *(mp **)v[1].buf; - mp *d = mp_fromint(MP_NEW, i); - int ok = 1; - - if (!MP_EQ(d, m)) { - fputs("\n*** fromint failed.\n", stderr); - fprintf(stderr, "i = %li", i); - fputs("\nexpect = ", stderr); mp_writefile(m, stderr, 10); - fputs("\nresult = ", stderr); mp_writefile(d, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - mp_drop(m); - mp_drop(d); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int touint(dstr *v) -{ - mp *m = *(mp **)v[0].buf; - unsigned long i = *(unsigned long *)v[1].buf; - unsigned j = mp_touint(m); - int ok = 1; - - if ((unsigned)i != j) { - fputs("\n*** touint failed.\n", stderr); - fputs("m = ", stderr); mp_writefile(m, stderr, 10); - fprintf(stderr, "\nexpect = %lu; result = %u\n", i, j); - ok = 0; - } - - mp_drop(m); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int toint(dstr *v) -{ - mp *m = *(mp **)v[0].buf; - long i = *(long *)v[1].buf; - int j = mp_toint(m); - int ok = 1; - - if (i != j) { - fputs("\n*** toint failed.\n", stderr); - fputs("m = ", stderr); mp_writefile(m, stderr, 10); - fprintf(stderr, "\nexpect = %li; result = %i\n", i, j); - ok = 0; - } - - mp_drop(m); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "fromuint", fromuint, { &type_ulong, &type_mp, 0 } }, - { "fromint", fromint, { &type_long, &type_mp, 0 } }, - { "touint", touint, { &type_mp, &type_ulong, 0 } }, - { "toint", toint, { &type_mp, &type_long, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mpint"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpint.h b/mpint.h deleted file mode 100644 index dbf9065..0000000 --- a/mpint.h +++ /dev/null @@ -1,192 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Conversion between MPs and standard C integers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPINT_H -#define CATACOMB_MPINT_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -/*----- Generic translation macros ----------------------------------------*/ - -/* --- @MP_FROMINT@ --- * - * - * Arguments: @d@ = destination multiprecision integer - * @type@ = type of integer which @i@ is - * @i@ = a standard C integer - * - * Use: Stores the value of @i@ in @d@. This macro is actually - * rather subtle in places. Be careful what you change. - */ - -#define MP_FROMINT(d, type, i) do { \ - type _i = (i); \ - size_t _o = 0; \ - mp *_d = (d); \ - size_t _sz = 4; \ - \ - MP_DEST(_d, _sz, 0); \ - _d->f &= ~(MP_NEG | MP_UNDEF); \ - \ - if (_i >= 0) { \ - while (_i) { \ - if (_o == _sz) { \ - _sz <<= 1; \ - MP_ENSURE(_d, _sz); \ - } \ - _d->v[_o++] = MPW(_i); \ - if (_i <= MPW_MAX) \ - break; \ - else \ - _i /= (type)MPW_MAX + 1; \ - } \ - } else { \ - _d->f |= MP_NEG; \ - while (_i) { \ - if (_o == _sz) { \ - _sz <<= 1; \ - MP_ENSURE(_d, _sz); \ - } \ - _d->v[_o++] = MPW(-_i); \ - if (_i >= -MPW_MAX) \ - break; \ - else \ - _i /= (type)MPW_MAX + 1; \ - } \ - } \ - \ - _d->vl = _d->v + _o; \ - (d) = _d; \ -} while (0) - -/* --- @MP_TOINT@ --- * - * - * Arguments: @m@ = a multiprecision integer - * @type@ = the type of @i@ - * @max@ = the largest value @i@ can represent - * @i@ = an integer variable - * - * Use: Stores the value of a multiprecision integer in a standard C - * integer. If the value won't fit, the behaviour is determined - * by the type of @i@: if @i@ is unsigned, the value of the - * multiprecision integer modulo @max + 1@ is stored; if @i@ is - * signed, the behaviour is undefined. - * - * If you don't want to be bitten by these sorts of things, keep - * copies of @INT_MAX@ or whatever is appropriate in - * multiprecision form and compare before conversion. - */ - -#define MP_TOINT(m, type, max, i) do { \ - type _i = 0; \ - type _max = (max); \ - unsigned _s = 0; \ - const mp *_m = (m); \ - const mpw *_v = _m->v, *_vl = _m->vl; \ - \ - /* --- Do all the arithmetic in negative numbers --- */ \ - \ - while (_v < _vl && _max > 0) { \ - _i -= *_v << _s; \ - _s += MPW_BITS; \ - _v++; \ - _max /= (mpd)MPW_MAX + 1; \ - } \ - if (!MP_NEGP(_m)) \ - _i = -_i; \ - (i) = _i; \ -} while (0) - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @mp_fromINT@ --- * - * - * Arguments: @mp *d@ = pointer to destination multiprecision integer - * @INT i@ = standard C integer to convert - * - * Returns: The resulting multiprecision integer. - * - * Use: Converts a standard C integer to a multiprecision integer. - */ - -#define mp_fromINT(name, type) \ - extern mp *mp_from##name(mp */*d*/, type /*i*/) - -mp_fromINT(short, short); -mp_fromINT(ushort, unsigned short); -mp_fromINT(int, int); -mp_fromINT(uint, unsigned); -mp_fromINT(uint32, uint32); -mp_fromINT(long, long); -mp_fromINT(ulong, unsigned long); - -#undef mp_fromINT - -/* --- @mp_toINT@ --- * - * - * Arguments: @const mp *m@ = pointer to a multiprecision integer - * - * Returns: The value of the integer @m@ as a C integer. - * - * Use: Converts a multiprecision integer to a standard C integer. - * If the value of the multiprecision integer cannot be - * represented in the return type, and the return type is - * unsigned, it is reduced modulo @TYPE_MAX + 1@; if the return - * type is signed, the behaviour is undefined. - */ - -#define mp_toINT(name, type) \ - extern type mp_to##name(const mp */*m*/) - -mp_toINT(short, short); -mp_toINT(ushort, unsigned short); -mp_toINT(int, int); -mp_toINT(uint, unsigned); -mp_toINT(uint32, uint32); -mp_toINT(long, long); -mp_toINT(ulong, unsigned long); - -#undef mp_toINT - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mpmont-exp.c b/mpmont-exp.c deleted file mode 100644 index 6959baf..0000000 --- a/mpmont-exp.c +++ /dev/null @@ -1,147 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Modular exponentiation with Montgomery reduction - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpmont.h" -#include "mpmont-exp.h" - -/*----- Exponentiation ----------------------------------------------------*/ - -/* --- @mpmont_expr@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$(a R^{-1})^e R \bmod m$%. - */ - -mp *mpmont_expr(mpmont *mm, mp *d, mp *a, mp *e) -{ - mp *x = MP_COPY(mm->r); - mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; - - MP_COPY(a); - MP_SHRINK(e); - if (MP_ZEROP(e)) - ; - else { - if (MP_NEGP(e)) { - a = mpmont_reduce(mm, a, a); - a = mp_modinv(a, a, mm->m); - a = mpmont_mul(mm, a, a, mm->r2); - } - if (MP_LEN(e) < EXP_THRESH) - EXP_SIMPLE(x, a, e); - else - EXP_WINDOW(x, a, e); - } - mp_drop(d); - mp_drop(spare); - mp_drop(a); - return (x); -} - -/* --- @mpmont_exp@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e \bmod m$%. - */ - -mp *mpmont_exp(mpmont *mm, mp *d, mp *a, mp *e) -{ - e = MP_COPY(e); - d = mpmont_mul(mm, d, a, mm->r2); - d = mpmont_expr(mm, d, d, e); - d = mpmont_reduce(mm, d, d); - MP_DROP(e); - return (d); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int texp(dstr *v) -{ - mp *m = *(mp **)v[0].buf; - mp *a = *(mp **)v[1].buf; - mp *b = *(mp **)v[2].buf; - mp *r = *(mp **)v[3].buf; - mp *mr; - int ok = 1; - - mpmont mm; - mpmont_create(&mm, m); - - mr = mpmont_exp(&mm, MP_NEW, a, b); - - if (!MP_EQ(mr, r)) { - fputs("\n*** montgomery modexp failed", stderr); - fputs("\n m = ", stderr); mp_writefile(m, stderr, 10); - fputs("\n a = ", stderr); mp_writefile(a, stderr, 10); - fputs("\n e = ", stderr); mp_writefile(b, stderr, 10); - fputs("\n r = ", stderr); mp_writefile(r, stderr, 10); - fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - MP_DROP(m); - MP_DROP(a); - MP_DROP(b); - MP_DROP(r); - MP_DROP(mr); - mpmont_destroy(&mm); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return ok; -} - -static test_chunk tests[] = { - { "exp", texp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, - { 0, 0, { 0 } }, -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mpmont"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpmont-exp.h b/mpmont-exp.h deleted file mode 100644 index 7730524..0000000 --- a/mpmont-exp.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*-c-*- - * - * $Id: mpmont-exp.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Exponentiation operations for Montgomery reduction - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPMONT_EXP_H -#define CATACOMB_MPMONT_EXP_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Exponentation definitions -----------------------------------------*/ - -#define EXP_TYPE mp * - -#define EXP_COPY(d, x) d = MP_COPY(x) -#define EXP_DROP(x) MP_DROP(x) - -#define EXP_MUL(a, x) do { \ - mp *t = mpmont_mul(mm, spare, a, x); \ - spare = a; \ - a = t; \ -} while (0) - -#define EXP_SQR(a) do { \ - mp *t = mp_sqr(spare, a); \ - spare = a; \ - a = mpmont_reduce(mm, t, t); \ -} while (0) - -#define EXP_FIX(x) - -#define EXP_SETMUL(d, x, y) d = mpmont_mul(mm, MP_NEW, x, y) - -#define EXP_SETSQR(d, x) do { \ - d = mp_sqr(MP_NEW, x); \ - d = mpmont_reduce(mm, d, d); \ -} while (0) - -#include "exp.h" - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mpmont-mexp.c b/mpmont-mexp.c deleted file mode 100644 index 92f40c3..0000000 --- a/mpmont-mexp.c +++ /dev/null @@ -1,213 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Multiple simultaneous exponentiations - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpmont.h" - -#define EXP_WINSZ 3 -#include "mpmont-exp.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mpmont_mexpr@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *d@ = fake destination - * @const mp_expfactor *f@ = pointer to array of factors - * @size_t n@ = number of factors supplied - * - * Returns: If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the - * exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result - * is: - * - * %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$% - * - * except that the %$g_i$% and result are in Montgomery form. - */ - -static mp *mexpr(mpmont *mm, mp *d, mp_expfactor *f, size_t n) -{ - mp *a = MP_COPY(mm->r); - mp *spare = MP_NEW; - size_t i; - - for (i = 0; i < n; i++) { - mp *t; - if (f[i].exp->f & MP_BURN) - spare = MP_NEWSEC; - if (MP_NEGP(f[i].exp)) { - t = mpmont_reduce(mm, f[i].base, f[i].base); - t = mp_modinv(t, t, mm->m); - f[i].base = mpmont_mul(mm, t, t, mm->r2); - } - } - EXP_SIMUL(a, f, n); - mp_drop(d); - mp_drop(spare); - for (i = 0; i < n; i++) - MP_DROP(f[i].base); - xfree(f); - return (a); -} - -mp *mpmont_mexpr(mpmont *mm, mp *d, const mp_expfactor *f, size_t n) -{ - mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor)); - size_t i; - - for (i = 0; i < n; i++) { - ff[i].base = MP_COPY(f[i].base); - ff[i].exp = f[i].exp; - } - return (mexpr(mm, d, ff, n)); -} - -/* --- @mpmont_mexp@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *d@ = fake destination - * @const mp_expfactor *f@ = pointer to array of factors - * @size_t n@ = number of factors supplied - * - * Returns: Product of bases raised to exponents, all mod @m@. - * - * Use: Convenient interface over @mpmont_mexpr@. - */ - -mp *mpmont_mexp(mpmont *mm, mp *d, const mp_expfactor *f, size_t n) -{ - mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor)); - size_t i; - - for (i = 0; i < n; i++) { - ff[i].base = mpmont_mul(mm, MP_NEW, f[i].base, mm->r2); - ff[i].exp = f[i].exp; - } - d = mexpr(mm, d, ff, n); - return (mpmont_reduce(mm, d, d)); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -static int verify(size_t n, dstr *v) -{ - mp *m = *(mp **)v[0].buf; - mp_expfactor *f = xmalloc(n * sizeof(*f)); - mp *r, *rr; - size_t i, j; - mpmont mm; - int ok = 1; - - j = 1; - for (i = 0; i < n; i++) { - f[i].base = *(mp **)v[j++].buf; - f[i].exp = *(mp **)v[j++].buf; - } - - rr = *(mp **)v[j].buf; - mpmont_create(&mm, m); - r = mpmont_mexp(&mm, MP_NEW, f, n); - if (!MP_EQ(r, rr)) { - fputs("\n*** mexp failed\n", stderr); - fputs("m = ", stderr); mp_writefile(m, stderr, 10); - for (i = 0; i < n; i++) { - fprintf(stderr, "\ng_%u = ", i); - mp_writefile(f[i].base, stderr, 10); - fprintf(stderr, "\ne_%u = ", i); - mp_writefile(f[i].exp, stderr, 10); - } - fputs("\nr = ", stderr); mp_writefile(r, stderr, 10); - fputs("\nR = ", stderr); mp_writefile(rr, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - for (i = 0; i < n; i++) { - MP_DROP(f[i].base); - MP_DROP(f[i].exp); - } - MP_DROP(m); - MP_DROP(r); - MP_DROP(rr); - mpmont_destroy(&mm); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int t1(dstr *v) { return verify(1, v); } -static int t2(dstr *v) { return verify(2, v); } -static int t3(dstr *v) { return verify(3, v); } -static int t4(dstr *v) { return verify(4, v); } -static int t5(dstr *v) { return verify(5, v); } - -static test_chunk tests[] = { - { "mexp-1", t1, { &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { "mexp-2", t2, { &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { "mexp-3", t3, { &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { "mexp-4", t4, { &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { "mexp-5", t5, { &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, &type_mp, - &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mpmont"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpmont.c b/mpmont.c deleted file mode 100644 index 65b3fcc..0000000 --- a/mpmont.c +++ /dev/null @@ -1,429 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Montgomery reduction - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpmont.h" - -/*----- Tweakables --------------------------------------------------------*/ - -/* --- @MPMONT_DISABLE@ --- * - * - * Replace all the clever Montgomery reduction with good old-fashioned long - * division. - */ - -/* #define MPMONT_DISABLE */ - -/*----- Reduction and multiplication --------------------------------------*/ - -/* --- @mpmont_create@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *m@ = modulus to use - * - * Returns: Zero on success, nonzero on error. - * - * Use: Initializes a Montgomery reduction context ready for use. - * The argument @m@ must be a positive odd integer. - */ - -#ifdef MPMONT_DISABLE - -int mpmont_create(mpmont *mm, mp *m) -{ - mp_shrink(m); - mm->m = MP_COPY(m); - mm->r = MP_ONE; - mm->r2 = MP_ONE; - mm->mi = MP_ONE; - return (0); -} - -#else - -int mpmont_create(mpmont *mm, mp *m) -{ - size_t n = MP_LEN(m); - mp *r2 = mp_new(2 * n + 1, 0); - mp r; - - /* --- Take a copy of the modulus --- */ - - if (!MP_POSP(m) || !MP_ODDP(m)) - return (-1); - mm->m = MP_COPY(m); - - /* --- Determine %$R^2$% --- */ - - mm->n = n; - MPX_ZERO(r2->v, r2->vl - 1); - r2->vl[-1] = 1; - - /* --- Find the magic value @mi@ --- */ - - mp_build(&r, r2->v + n, r2->vl); - mm->mi = mp_modinv(MP_NEW, m, &r); - mm->mi = mp_sub(mm->mi, &r, mm->mi); - - /* --- Discover the values %$R \bmod m$% and %$R^2 \bmod m$% --- */ - - mm->r2 = MP_NEW; - mp_div(0, &mm->r2, r2, m); - mm->r = mpmont_reduce(mm, MP_NEW, mm->r2); - MP_DROP(r2); - return (0); -} - -#endif - -/* --- @mpmont_destroy@ --- * - * - * Arguments: @mpmont *mm@ = pointer to a Montgomery reduction context - * - * Returns: --- - * - * Use: Disposes of a context when it's no longer of any use to - * anyone. - */ - -void mpmont_destroy(mpmont *mm) -{ - MP_DROP(mm->m); - MP_DROP(mm->r); - MP_DROP(mm->r2); - MP_DROP(mm->mi); -} - -/* --- @mpmont_reduce@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *d@ = destination - * @mp *a@ = source, assumed positive - * - * Returns: Result, %$a R^{-1} \bmod m$%. - */ - -#ifdef MPMONT_DISABLE - -mp *mpmont_reduce(mpmont *mm, mp *d, mp *a) -{ - mp_div(0, &d, a, mm->m); - return (d); -} - -#else - -mp *mpmont_reduce(mpmont *mm, mp *d, mp *a) -{ - size_t n = mm->n; - - /* --- Check for serious Karatsuba reduction --- */ - - if (n > MPK_THRESH * 3) { - mp al; - mpw *vl; - mp *u; - - if (MP_LEN(a) >= n) - vl = a->v + n; - else - vl = a->vl; - mp_build(&al, a->v, vl); - u = mp_mul(MP_NEW, &al, mm->mi); - if (MP_LEN(u) > n) - u->vl = u->v + n; - u = mp_mul(u, u, mm->m); - d = mp_add(d, a, u); - mp_drop(u); - } - - /* --- Otherwise do it the hard way --- */ - - else { - mpw *dv, *dvl; - mpw *mv, *mvl; - mpw mi; - size_t k = n; - - /* --- Initial conditioning of the arguments --- */ - - a = MP_COPY(a); - if (d) - MP_DROP(d); - d = a; - MP_DEST(d, 2 * n + 1, a->f); - - dv = d->v; dvl = d->vl; - mv = mm->m->v; mvl = mm->m->vl; - - /* --- Let's go to work --- */ - - mi = mm->mi->v[0]; - while (k--) { - mpw u = MPW(*dv * mi); - MPX_UMLAN(dv, dvl, mv, mvl, u); - dv++; - } - } - - /* --- Wrap everything up --- */ - - memmove(d->v, d->v + n, MPWS(MP_LEN(d) - n)); - d->vl -= n; - if (MPX_UCMP(d->v, d->vl, >=, mm->m->v, mm->m->vl)) - mpx_usub(d->v, d->vl, d->v, d->vl, mm->m->v, mm->m->vl); - if (d->f & MP_NEG) { - mpx_usub(d->v, d->vl, mm->m->v, mm->m->vl, d->v, d->vl); - d->f &= ~MP_NEG; - } - MP_SHRINK(d); - return (d); -} - -#endif - -/* --- @mpmont_mul@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *d@ = destination - * @mp *a, *b@ = sources, assumed positive - * - * Returns: Result, %$a b R^{-1} \bmod m$%. - */ - -#ifdef MPMONT_DISABLE - -mp *mpmont_mul(mpmont *mm, mp *d, mp *a, mp *b) -{ - d = mp_mul(d, a, b); - mp_div(0, &d, d, mm->m); - return (d); -} - -#else - -mp *mpmont_mul(mpmont *mm, mp *d, mp *a, mp *b) -{ - if (mm->n > MPK_THRESH * 3) { - d = mp_mul(d, a, b); - d = mpmont_reduce(mm, d, d); - } else { - mpw *dv, *dvl; - mpw *av, *avl; - mpw *bv, *bvl; - mpw *mv, *mvl; - mpw y; - size_t n, i; - mpw mi; - - /* --- Initial conditioning of the arguments --- */ - - if (MP_LEN(a) > MP_LEN(b)) { - mp *t = a; a = b; b = t; - } - n = MP_LEN(mm->m); - - a = MP_COPY(a); - b = MP_COPY(b); - MP_DEST(d, 2 * n + 1, a->f | b->f | MP_UNDEF); - dv = d->v; dvl = d->vl; - MPX_ZERO(dv, dvl); - av = a->v; avl = a->vl; - bv = b->v; bvl = b->vl; - mv = mm->m->v; mvl = mm->m->vl; - y = *bv; - - /* --- Montgomery multiplication phase --- */ - - i = 0; - mi = mm->mi->v[0]; - while (i < n && av < avl) { - mpw x = *av++; - mpw u = MPW((*dv + x * y) * mi); - MPX_UMLAN(dv, dvl, bv, bvl, x); - MPX_UMLAN(dv, dvl, mv, mvl, u); - dv++; - i++; - } - - /* --- Simpler Montgomery reduction phase --- */ - - while (i < n) { - mpw u = MPW(*dv * mi); - MPX_UMLAN(dv, dvl, mv, mvl, u); - dv++; - i++; - } - - /* --- Done --- */ - - memmove(d->v, dv, MPWS(dvl - dv)); - d->vl -= dv - d->v; - if (MPX_UCMP(d->v, d->vl, >=, mm->m->v, mm->m->vl)) - mpx_usub(d->v, d->vl, d->v, d->vl, mm->m->v, mm->m->vl); - if ((a->f ^ b->f) & MP_NEG) - mpx_usub(d->v, d->vl, mm->m->v, mm->m->vl, d->v, d->vl); - MP_SHRINK(d); - d->f = (a->f | b->f) & MP_BURN; - MP_DROP(a); - MP_DROP(b); - } - - return (d); -} - -#endif - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -static int tcreate(dstr *v) -{ - mp *m = *(mp **)v[0].buf; - mp *mi = *(mp **)v[1].buf; - mp *r = *(mp **)v[2].buf; - mp *r2 = *(mp **)v[3].buf; - - mpmont mm; - int ok = 1; - - mpmont_create(&mm, m); - - if (mm.mi->v[0] != mi->v[0]) { - fprintf(stderr, "\n*** bad mi: found %lu, expected %lu", - (unsigned long)mm.mi->v[0], (unsigned long)mi->v[0]); - fputs("\nm = ", stderr); mp_writefile(m, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - if (!MP_EQ(mm.r, r)) { - fputs("\n*** bad r", stderr); - fputs("\nm = ", stderr); mp_writefile(m, stderr, 10); - fputs("\nexpected ", stderr); mp_writefile(r, stderr, 10); - fputs("\n found ", stderr); mp_writefile(mm.r, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - if (!MP_EQ(mm.r2, r2)) { - fputs("\n*** bad r2", stderr); - fputs("\nm = ", stderr); mp_writefile(m, stderr, 10); - fputs("\nexpected ", stderr); mp_writefile(r2, stderr, 10); - fputs("\n found ", stderr); mp_writefile(mm.r2, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - MP_DROP(m); - MP_DROP(mi); - MP_DROP(r); - MP_DROP(r2); - mpmont_destroy(&mm); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tmul(dstr *v) -{ - mp *m = *(mp **)v[0].buf; - mp *a = *(mp **)v[1].buf; - mp *b = *(mp **)v[2].buf; - mp *r = *(mp **)v[3].buf; - int ok = 1; - - mpmont mm; - mpmont_create(&mm, m); - - { - mp *qr = mp_mul(MP_NEW, a, b); - mp_div(0, &qr, qr, m); - - if (!MP_EQ(qr, r)) { - fputs("\n*** classical modmul failed", stderr); - fputs("\n m = ", stderr); mp_writefile(m, stderr, 10); - fputs("\n a = ", stderr); mp_writefile(a, stderr, 10); - fputs("\n b = ", stderr); mp_writefile(b, stderr, 10); - fputs("\n r = ", stderr); mp_writefile(r, stderr, 10); - fputs("\nqr = ", stderr); mp_writefile(qr, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - mp_drop(qr); - } - - { - mp *ar = mpmont_mul(&mm, MP_NEW, a, mm.r2); - mp *br = mpmont_mul(&mm, MP_NEW, b, mm.r2); - mp *mr = mpmont_mul(&mm, MP_NEW, ar, br); - mr = mpmont_reduce(&mm, mr, mr); - if (!MP_EQ(mr, r)) { - fputs("\n*** montgomery modmul failed", stderr); - fputs("\n m = ", stderr); mp_writefile(m, stderr, 10); - fputs("\n a = ", stderr); mp_writefile(a, stderr, 10); - fputs("\n b = ", stderr); mp_writefile(b, stderr, 10); - fputs("\n r = ", stderr); mp_writefile(r, stderr, 10); - fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - MP_DROP(ar); MP_DROP(br); - mp_drop(mr); - } - - - MP_DROP(m); - MP_DROP(a); - MP_DROP(b); - MP_DROP(r); - mpmont_destroy(&mm); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return ok; -} - -static test_chunk tests[] = { - { "create", tcreate, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, - { "mul", tmul, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, - { 0, 0, { 0 } }, -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mpmont"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpmont.h b/mpmont.h deleted file mode 100644 index 745cf5a..0000000 --- a/mpmont.h +++ /dev/null @@ -1,203 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Montgomery reduction - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPMONT_H -#define CATACOMB_MPMONT_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -/*----- Notes on Montgomery reduction -------------------------------------* - * - * Given a little bit of precomputation, Montgomery reduction enables modular - * reductions of products to be calculated rather rapidly, without recourse - * to annoying things like division. - * - * Before starting, you need to do a little work. In particular, the - * following things need to be worked out: - * - * * %$m$%, which is the modulus you'll be working with. This must be odd, - * otherwise the whole thing doesn't work. You're better off using - * Barrett reduction if your modulus might be even. - * - * * %$b$%, the radix of the number system you're in (here, it's - * @MPW_MAX + 1@). - * - * * %$-m^{-1} \bmod b$%, a useful number for the reduction step. (This - * means that the modulus mustn't be even. This shouldn't be a problem.) - * - * * %$R = b^n > m > b^{n - 1}$%, or at least %$\log_2 R$%. - * - * * %$R \bmod m$% and %$R^2 \bmod m$%, which are useful when doing - * calculations such as exponentiation. - * - * The result of a Montgomery reduction of %$x$% is %$x R^{-1} \bmod m$%, - * which doesn't look ever-so useful. The trick is to initially apply a - * factor of %$R$% to all of your numbers so that when you multiply and - * perform a Montgomery reduction you get %$(x R \cdot y R) R^{-1} \bmod m$%, - * which is just %$x y R \bmod m$%. Thanks to distributivity, even additions - * and subtractions can be performed on numbers in this form -- the extra - * factor of %$R$% just runs through all the calculations until it's finally - * stripped out by a final reduction operation. - */ - -/*----- Data structures ---------------------------------------------------*/ - -/* --- A Montgomery reduction context --- */ - -typedef struct mpmont { - mp *m; /* Modulus */ - mp *mi; /* %$-m^{-1} \bmod R$% */ - size_t n; /* %$\log_b R$% */ - mp *r, *r2; /* %$R \bmod m$%, %$R^2 \bmod m$% */ -} mpmont; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @mpmont_create@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *m@ = modulus to use - * - * Returns: Zero on success, nonzero on error. - * - * Use: Initializes a Montgomery reduction context ready for use. - * The argument @m@ must be a positive odd integer. - */ - -extern int mpmont_create(mpmont */*mm*/, mp */*m*/); - -/* --- @mpmont_destroy@ --- * - * - * Arguments: @mpmont *mm@ = pointer to a Montgomery reduction context - * - * Returns: --- - * - * Use: Disposes of a context when it's no longer of any use to - * anyone. - */ - -extern void mpmont_destroy(mpmont */*mm*/); - -/* --- @mpmont_reduce@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *d@ = destination - * @mp *a@ = source, assumed positive - * - * Returns: Result, %$a R^{-1} \bmod m$%. - */ - -extern mp *mpmont_reduce(mpmont */*mm*/, mp */*d*/, mp */*a*/); - -/* --- @mpmont_mul@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *d@ = destination - * @mp *a, *b@ = sources, assumed positive - * - * Returns: Result, %$a b R^{-1} \bmod m$%. - */ - -extern mp *mpmont_mul(mpmont */*mm*/, mp */*d*/, mp */*a*/, mp */*b*/); - -/* --- @mpmont_expr@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$(a R^{-1})^e R \bmod m$%. This is useful if - * further modular arithmetic is to be performed on the result. - */ - -extern mp *mpmont_expr(mpmont */*mm*/, mp */*d*/, mp */*a*/, mp */*e*/); - -/* --- @mpmont_exp@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e \bmod m$%. - */ - -extern mp *mpmont_exp(mpmont */*mm*/, mp */*d*/, mp */*a*/, mp */*e*/); - -/* --- @mpmont_mexpr@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *d@ = fake destination - * @const mp_expfactor *f@ = pointer to array of factors - * @size_t n@ = number of factors supplied - * - * Returns: If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the - * exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result - * is: - * - * %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$% - * - * - * except that the %$g_i$% and result are in Montgomery form. - */ - -extern mp *mpmont_mexpr(mpmont */*mm*/, mp */*d*/, - const mp_expfactor */*f*/, size_t /*n*/); - -/* --- @mpmont_mexp@ --- * - * - * Arguments: @mpmont *mm@ = pointer to Montgomery reduction context - * @mp *d@ = fake destination - * @const mp_expfactor *f@ = pointer to array of factors - * @size_t n@ = number of factors supplied - * - * Returns: Product of bases raised to exponents, all mod @m@. - * - * Use: Convenient interface over @mpmont_mexpr@. - */ - -extern mp *mpmont_mexp(mpmont */*mm*/, mp */*d*/, - const mp_expfactor */*f*/, size_t /*n*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mpmul.c b/mpmul.c deleted file mode 100644 index 1f932b0..0000000 --- a/mpmul.c +++ /dev/null @@ -1,181 +0,0 @@ -/* -*-c-*- - * - * $Id: mpmul.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Multiply many small numbers together - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpint.h" -#include "mpmul.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mpmul_init@ --- * - * - * Arguments: @mpmul *b@ = pointer to multiplier context to initialize - * - * Returns: --- - * - * Use: Initializes a big multiplier context for use. - */ - -void mpmul_init(mpmul *b) -{ - b->i = 0; -} - -/* --- @mpmul_add@ --- * - * - * Arguments: @mpmul *b@ = pointer to multiplier context - * @mp *x@ = the next factor to multiply in - * - * Returns: --- - * - * Use: Contributes another factor to the mix. It's important that - * the integer lasts at least as long as the multiplication - * context; this sort of rules out @mp_build@ integers. - */ - -#define HWM (MPMUL_DEPTH - 20) -#define LWM (MPMUL_DEPTH / 2) - -void mpmul_add(mpmul *b, mp *x) -{ - size_t i = b->i; - - /* --- Now do the reduction step --- */ - - x = MP_COPY(x); - - while (i > 0) { - if (MP_LEN(b->v[i - 1]) > MP_LEN(x)) - break; - i--; - x = mp_mul(x, x, b->v[i]); - MP_DROP(b->v[i]); - } - - if (i > HWM) { - while (i > LWM || (i > 0 && MP_LEN(b->v[i - 1]) <= MP_LEN(x))) { - i--; - x = mp_mul(x, x, b->v[i]); - MP_DROP(b->v[i]); - } - } - - b->v[i++] = x; - b->i = i; -} - -/* --- @mpmul_done@ --- * - * - * Arguments: @mpmul *b@ = pointer to big multiplication context - * - * Returns: The product of all the numbers contributed. - * - * Use: Returns a (large) product of numbers. The context is - * deallocated. - */ - -mp *mpmul_done(mpmul *b) -{ - size_t i = b->i; - mp *x; - - if (!i) - return (MP_ONE); - i--; - x = b->v[i]; - while (i > 0) { - i--; - x = mp_mul(x, x, b->v[i]); - MP_DROP(b->v[i]); - } - return (x); -} - -/* --- @mp_factorial@ --- * - * - * Arguments: @unsigned long i@ = number whose factorial should be - * computed. - * - * Returns: The requested factorial. - */ - -mp *mp_factorial(unsigned long i) -{ - unsigned long j; - mp *x = MP_NEW; - mpmul b = MPMUL_INIT; - - for (j = 1; j <= i; j++) { - x = mp_fromulong(x, j); - mpmul_add(&b, x); - } - mp_drop(x); - return (mpmul_done(&b)); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -static int vfact(dstr *v) -{ - unsigned long x = *(unsigned long *)v[0].buf; - mp *fx = *(mp **)v[1].buf; - mp *y = mp_factorial(x); - int ok = 1; - if (!MP_EQ(fx, y)) { - fprintf(stderr, "factorial failed\n"); - MP_FPRINTF(stderr, (stderr, "%lu! = ", x), fx); - MP_EPRINT("result", y); - ok = 0; - } - mp_drop(fx); - mp_drop(y); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "factorial", vfact, { &type_ulong, &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, tests, SRCDIR "/tests/mp"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpmul.h b/mpmul.h deleted file mode 100644 index bd1f156..0000000 --- a/mpmul.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -*-c-*- - * - * $Id: mpmul.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Multiply many small numbers together - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPMUL_H -#define CATACOMB_MPMUL_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -/* --- How the algorithm works --- * - * - * Multiplication on large integers is least wasteful when the numbers - * multiplied are approximately the same size. When a new multiplier is - * added to the system, we push it onto a stack. Then we `reduce' the stack: - * while the value on the top of the stack is not shorter than the value - * below it, replace the top two elements by their product. - * - * Let %$b$% be the radix of our multiprecision integers, and let %$Z$% be - * the maximum number of digits. Then the largest integer we can represent - * is %$M - 1 = b^Z - 1$%. We could assume that all of the integers we're - * given are about the same size. This would give us the same upper bound as - * that derived in `mptext.c'. - * - * However, we're in less control over our inputs. In particular, if a - * sequence of integers with strictly decreasing lengths is input then we're - * sunk. Suppose that the stack contains, from top to bottom, %$b^i$%, - * %$b^{i+1}$%, ..., %$b^n$%. The final product will therefore be - * %$p = b^{(n+i)(n-i+1)/2}$%. We must now find the maximum stack depth - * %$d = n - i$% such that %$p > M$%. - * - * Taking logs of both sides gives that %$(d + 2 i)(d + 1) > 2 Z$%. We can - * maximize %$d$% by taking %$i = 0$%, which gives that %$d^2 + d > 2 Z$%, so - * %$d$% must be approximately %$(\sqrt{8 Z + 1} - 1)/2$%, which is - * uncomfortably large. - * - * We compromise by choosing double the `mptext' bound and imposing high- and - * low-water marks for forced reduction. - */ - -#define MPMUL_DEPTH (2 * (CHAR_BIT * sizeof(size_t) + 10)) - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct mpmul { - size_t i; - mp *v[MPMUL_DEPTH]; -} mpmul; - -#define MPMUL_INIT { 0 } - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @mpmul_init@ --- * - * - * Arguments: @mpmul *b@ = pointer to multiplier context to initialize - * - * Returns: --- - * - * Use: Initializes a big multiplier context for use. - */ - -extern void mpmul_init(mpmul */*b*/); - -/* --- @mpmul_add@ --- * - * - * Arguments: @mpmul *b@ = pointer to multiplier context - * @mp *x@ = the next factor to multiply in - * - * Returns: --- - * - * Use: Contributes another factor to the mix. It's important that - * the integer lasts at least as long as the multiplication - * context; this sort of rules out @mp_build@ integers. - */ - -extern void mpmul_add(mpmul */*b*/, mp */*x*/); - -/* --- @mpmul_done@ --- * - * - * Arguments: @mpmul *b@ = pointer to big multiplication context - * - * Returns: The product of all the numbers contributed. - * - * Use: Returns a (large) product of numbers. The context is - * deallocated. - */ - -extern mp *mpmul_done(mpmul */*b*/); - -/* --- @mp_factorial@ --- * - * - * Arguments: @unsigned long i@ = number whose factorial should be - * computed. - * - * Returns: The requested factorial. - */ - -extern mp *mp_factorial(unsigned long /*i*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mprand.c b/mprand.c deleted file mode 100644 index c0f9675..0000000 --- a/mprand.c +++ /dev/null @@ -1,140 +0,0 @@ -/* -*-c-*- - * - * $Id: mprand.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Generate a random multiprecision integer - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "grand.h" -#include "mp.h" -#include "mprand.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mprand@ --- * - * - * Arguments: @mp *d@ = destination integer - * @unsigned b@ = number of bits - * @grand *r@ = pointer to random number source - * @mpw or@ = mask to OR with low-order bits - * - * Returns: A random integer with the requested number of bits. - * - * Use: Constructs an arbitrarily large pseudorandom integer. - * Assuming that the generator @r@ is good, the result is - * uniformly distributed in the interval %$[2^{b - 1}, 2^b)$%. - * The result is then ORred with the given @or@ value. This - * will often be 1, to make the result odd. - */ - -mp *mprand(mp *d, unsigned b, grand *r, mpw or) -{ - size_t sz = (b + 7) >> 3; - arena *a = (d && (d->f & MP_BURN)) ? arena_secure : arena_global; - octet *v = x_alloc(a, sz); - unsigned m; - - /* --- Fill buffer with random data --- */ - - r->ops->fill(r, v, sz); - - /* --- Force into the correct range --- * - * - * This is slightly tricky. Oh, well. - */ - - b = (b - 1) & 7; - m = (1 << b); - v[0] = (v[0] & (m - 1)) | m; - - /* --- Mask, load and return --- */ - - d = mp_loadb(d, v, sz); - d->v[0] |= or; - memset(v, 0, sz); - x_free(a, v); - return (d); -} - -/* --- @mprand_range@ --- * - * - * Arguments: @mp *d@ = destination integer - * @mp *l@ = limit for random number - * @grand *r@ = random number source - * @mpw or@ = mask for low-order bits - * - * Returns: A pseudorandom integer, unformly distributed over the - * interval %$[0, l)$%. - * - * Use: Generates a uniformly-distributed pseudorandom number in the - * appropriate range. - */ - -mp *mprand_range(mp *d, mp *l, grand *r, mpw or) -{ - size_t b = mp_bits(l); - size_t sz = (b + 7) >> 3; - arena *a = (d && (d->f & MP_BURN)) ? arena_secure : arena_global; - octet *v = x_alloc(a, sz); - unsigned m; - - /* --- The algorithm --- * - * - * Rather simpler than most. Find the number of bits in the number %$l$% - * (i.e., the integer %$b$% such that %$2^{b - 1} \le l < 2^b$%), and - * generate pseudorandom integers with %$n$% bits (but not, unlike in the - * function above, with the top bit forced to 1). If the integer is - * greater than or equal to %$l$%, try again. - * - * This is similar to the algorithms used in @lcrand_range@ and friends, - * except that I've forced the `raw' range of the random numbers such that - * %$l$% itself is the largest multiple of %$l$% in the range (since, by - * the inequality above, %$2^b \le 2l$%). This removes the need for costly - * division and remainder operations. - * - * As usual, the number of iterations expected is two. - */ - - b = ((b - 1) & 7) + 1; - m = (1 << b) - 1; - do { - r->ops->fill(r, v, sz); - v[0] &= m; - d = mp_loadb(d, v, sz); - d->v[0] |= or; - } while (MP_CMP(d, >=, l)); - - /* --- Done --- */ - - memset(v, 0, sz); - x_free(a, v); - return (d); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mprand.h b/mprand.h deleted file mode 100644 index cb51e1c..0000000 --- a/mprand.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -*-c-*- - * - * $Id: mprand.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Generate a random multiprecision integer - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPRAND_H -#define CATACOMB_MPRAND_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @mprand@ --- * - * - * Arguments: @mp *d@ = destination integer - * @unsigned b@ = number of bits - * @grand *r@ = pointer to random number source - * @mpw or@ = mask to OR with low-order bits - * - * Returns: A random integer with the requested number of bits - * - * Use: Constructs an arbitrarily large pseudorandom integer. - * Assuming that the generator @r@ is good, the result is - * uniformly distributed in the interval %$[2^{b - 1}, 2^b)$%. - * The result is then ORred with the given @or@ value. This - * will often be 1, to make the result odd. - */ - -extern mp *mprand(mp */*d*/, unsigned /*b*/, grand */*r*/, mpw /*or*/); - -/* --- @mprand_range@ --- * - * - * Arguments: @mp *d@ = destination integer - * @mp *l@ = limit for random number - * @grand *r@ = random number source - * @mpw or@ = mask for low-order bits - * - * Returns: A pseudorandom integer, unformly distributed over the - * interval %$[0, l)$%. - * - * Use: Generates a uniformly-distributed pseudorandom number in the - * appropriate range. - */ - -extern mp *mprand_range(mp */*d*/, mp */*l*/, grand */*r*/, mpw /*or*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mpreduce-exp.h b/mpreduce-exp.h deleted file mode 100644 index c22fd47..0000000 --- a/mpreduce-exp.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*-c-*- - * - * $Id: mpreduce-exp.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Exponentiation operations for binary field reduction - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPREDUCE_EXP_H -#define CATACOMB_MPREDUCE_EXP_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Exponentiation definitions ----------------------------------------*/ - -#define EXP_TYPE mp * - -#define EXP_COPY(d, x) d = MP_COPY(x) -#define EXP_DROP(x) MP_DROP(x) - -#define EXP_MUL(a, x) do { \ - mp *t = mp_mul(spare, a, x); \ - spare = a; \ - a = mpreduce_do(mr, t, t); \ -} while (0) - -#define EXP_SQR(a) do { \ - mp *t = mp_sqr(spare, a); \ - spare = a; \ - a = mpreduce_do(mr, t, t); \ -} while (0) - -#define EXP_FIX(x) - -#define EXP_SETMUL(d, x, y) do { \ - d = mp_mul(MP_NEW, x, y); \ - d = mpreduce_do(mr, d, d); \ -} while (0) - -#define EXP_SETSQR(d, x) do { \ - d = mp_sqr(MP_NEW, x); \ - d = mpreduce_do(mr, d, d); \ -} while (0) - -#include "exp.h" - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mpreduce.c b/mpreduce.c deleted file mode 100644 index 5016f29..0000000 --- a/mpreduce.c +++ /dev/null @@ -1,440 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Efficient reduction modulo nice primes - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include "mp.h" -#include "mpreduce.h" -#include "mpreduce-exp.h" - -/*----- Data structures ---------------------------------------------------*/ - -DA_DECL(instr_v, mpreduce_instr); - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mpreduce_create@ --- * - * - * Arguments: @gfreduce *r@ = structure to fill in - * @mp *x@ = an integer - * - * Returns: Zero if successful; nonzero on failure. - * - * Use: Initializes a context structure for reduction. - */ - -int mpreduce_create(mpreduce *r, mp *p) -{ - mpscan sc; - enum { Z = 0, Z1 = 2, X = 4, X0 = 6 }; - unsigned st = Z; - instr_v iv = DA_INIT; - unsigned long d, i; - unsigned op; - size_t w, b, bb; - - /* --- Fill in the easy stuff --- */ - - if (!MP_POSP(p)) - return (-1); - d = mp_bits(p); - r->lim = d/MPW_BITS; - r->s = d%MPW_BITS; - if (r->s) - r->lim++; - r->p = mp_copy(p); - - /* --- Stash a new instruction --- */ - -#define INSTR(op_, argx_, argy_) do { \ - DA_ENSURE(&iv, 1); \ - DA(&iv)[DA_LEN(&iv)].op = (op_); \ - DA(&iv)[DA_LEN(&iv)].argx = (argx_); \ - DA(&iv)[DA_LEN(&iv)].argy = (argy_); \ - DA_EXTEND(&iv, 1); \ -} while (0) - - /* --- Main loop --- * - * - * A simple state machine decomposes @p@ conveniently into positive and - * negative powers of 2. The pure form of the state machine is left below - * for reference (and in case I need inspiration for a NAF exponentiator). - */ - -#ifdef DEBUG - for (i = 0, mp_scan(&sc, p); mp_step(&sc); i++) { - switch (st | mp_bit(&sc)) { - case Z | 1: st = Z1; break; - case Z1 | 0: st = Z; printf("+ %lu\n", i - 1); break; - case Z1 | 1: st = X; printf("- %lu\n", i - 1); break; - case X | 0: st = X0; break; - case X0 | 1: st = X; printf("- %lu\n", i - 1); break; - case X0 | 0: st = Z; printf("+ %lu\n", i - 1); break; - } - } - if (st >= X) printf("+ %lu\n", i - 1); - st = Z; -#endif - - bb = MPW_BITS - (d + 1)%MPW_BITS; - for (i = 0, mp_scan(&sc, p); i < d && mp_step(&sc); i++) { - switch (st | mp_bit(&sc)) { - case Z | 1: st = Z1; break; - case Z1 | 0: st = Z; op = MPRI_SUB; goto instr; - case Z1 | 1: st = X; op = MPRI_ADD; goto instr; - case X | 0: st = X0; break; - case X0 | 1: st = X; op = MPRI_ADD; goto instr; - case X0 | 0: st = Z; op = MPRI_SUB; goto instr; - instr: - w = (d - i)/MPW_BITS + 1; - b = (bb + i)%MPW_BITS; - INSTR(op | !!b, w, b); - } - } - if (DA_LEN(&iv) && (DA(&iv)[DA_LEN(&iv) - 1].op & ~1u) == MPRI_SUB) { - mp_drop(r->p); - DA_DESTROY(&iv); - return (-1); - } - -#undef INSTR - - /* --- Wrap up --- */ - - r->in = DA_LEN(&iv); - if (!r->in) - r->iv = 0; - else if (!r->s) { - r->iv = xmalloc(r->in * sizeof(mpreduce_instr)); - memcpy(r->iv, DA(&iv), r->in * sizeof(mpreduce_instr)); - } else { - r->iv = xmalloc(r->in * 2 * sizeof(mpreduce_instr)); - for (i = 0; i < r->in; i++) { - r->iv[i] = DA(&iv)[i]; - op = r->iv[i].op & ~1u; - w = r->iv[i].argx; - b = r->iv[i].argy; - b += r->s; - if (b >= MPW_BITS) { - b -= MPW_BITS; - w--; - } - if (b) op |= 1; - r->iv[i + r->in].op = op; - r->iv[i + r->in].argx = w; - r->iv[i + r->in].argy = b; - } - } - DA_DESTROY(&iv); - -#ifdef DEBUG - mpreduce_dump(r, stdout); -#endif - return (0); -} - -/* --- @mpreduce_destroy@ --- * - * - * Arguments: @mpreduce *r@ = structure to free - * - * Returns: --- - * - * Use: Reclaims the resources from a reduction context. - */ - -void mpreduce_destroy(mpreduce *r) -{ - mp_drop(r->p); - if (r->iv) xfree(r->iv); -} - -/* --- @mpreduce_dump@ --- * - * - * Arguments: @mpreduce *r@ = structure to dump - * @FILE *fp@ = file to dump on - * - * Returns: --- - * - * Use: Dumps a reduction context. - */ - -void mpreduce_dump(mpreduce *r, FILE *fp) -{ - size_t i; - static const char *opname[] = { "add", "addshift", "sub", "subshift" }; - - fprintf(fp, "mod = "); mp_writefile(r->p, fp, 16); - fprintf(fp, "\n lim = %lu; s = %d\n", (unsigned long)r->lim, r->s); - for (i = 0; i < r->in; i++) { - assert(r->iv[i].op < N(opname)); - fprintf(fp, " %s %lu %lu\n", - opname[r->iv[i].op], - (unsigned long)r->iv[i].argx, - (unsigned long)r->iv[i].argy); - } - if (r->s) { - fprintf(fp, "tail end charlie\n"); - for (i = r->in; i < 2 * r->in; i++) { - assert(r->iv[i].op < N(opname)); - fprintf(fp, " %s %lu %lu\n", - opname[r->iv[i].op], - (unsigned long)r->iv[i].argx, - (unsigned long)r->iv[i].argy); - } - } -} - -/* --- @mpreduce_do@ --- * - * - * Arguments: @mpreduce *r@ = reduction context - * @mp *d@ = destination - * @mp *x@ = source - * - * Returns: Destination, @x@ reduced modulo the reduction poly. - */ - -static void run(const mpreduce_instr *i, const mpreduce_instr *il, - mpw *v, mpw z) -{ - for (; i < il; i++) { -#ifdef DEBUG - mp vv; - mp_build(&vv, v - i->argx, v + 1); - printf(" 0x"); mp_writefile(&vv, stdout, 16); - printf(" %c (0x%lx << %u) == 0x", - (i->op & ~1u) == MPRI_ADD ? '+' : '-', - (unsigned long)z, - i->argy); -#endif - switch (i->op) { - case MPRI_ADD: MPX_UADDN(v - i->argx, v + 1, z); break; - case MPRI_ADDLSL: mpx_uaddnlsl(v - i->argx, v + 1, z, i->argy); break; - case MPRI_SUB: MPX_USUBN(v - i->argx, v + 1, z); break; - case MPRI_SUBLSL: mpx_usubnlsl(v - i->argx, v + 1, z, i->argy); break; - default: - abort(); - } -#ifdef DEBUG - mp_build(&vv, v - i->argx, v + 1); - mp_writefile(&vv, stdout, 16); - printf("\n"); -#endif - } -} - -mp *mpreduce_do(mpreduce *r, mp *d, mp *x) -{ - mpw *v, *vl; - const mpreduce_instr *il; - mpw z; - -#ifdef DEBUG - mp *_r = 0, *_rr = 0; -#endif - - /* --- If source is negative, divide --- */ - - if (MP_NEGP(x)) { - mp_div(0, &d, x, r->p); - return (d); - } - - /* --- Try to reuse the source's space --- */ - - MP_COPY(x); - if (d) MP_DROP(d); - MP_DEST(x, MP_LEN(x), x->f); - - /* --- Do the reduction --- */ - -#ifdef DEBUG - _r = MP_NEW; - mp_div(0, &_r, x, r->p); - MP_PRINTX("x", x); - _rr = 0; -#endif - - il = r->iv + r->in; - if (MP_LEN(x) >= r->lim) { - v = x->v + r->lim; - vl = x->vl; - while (vl-- > v) { - while (*vl) { - z = *vl; - *vl = 0; - run(r->iv, il, vl, z); -#ifdef DEBUG - MP_PRINTX("x", x); - mp_div(0, &_rr, x, r->p); - assert(MP_EQ(_r, _rr)); -#endif - } - } - if (r->s) { - while (*vl >> r->s) { - z = *vl >> r->s; - *vl &= ((1 << r->s) - 1); - run(r->iv + r->in, il + r->in, vl, z); -#ifdef DEBUG - MP_PRINTX("x", x); - mp_div(0, &_rr, x, r->p); - assert(MP_EQ(_r, _rr)); -#endif - } - } - } - - /* --- Finishing touches --- */ - - MP_SHRINK(x); - if (MP_CMP(x, >=, r->p)) - x = mp_sub(x, x, r->p); - - /* --- Done --- */ - -#ifdef DEBUG - assert(MP_EQ(_r, x)); - mp_drop(_r); - mp_drop(_rr); -#endif - return (x); -} - -/* --- @mpreduce_exp@ --- * - * - * Arguments: @mpreduce *mr@ = pointer to reduction context - * @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e \bmod m$%. - */ - -mp *mpreduce_exp(mpreduce *mr, mp *d, mp *a, mp *e) -{ - mp *x = MP_ONE; - mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW; - - MP_SHRINK(e); - MP_COPY(a); - if (MP_ZEROP(e)) - ; - else { - if (MP_NEGP(e)) - a = mp_modinv(a, a, mr->p); - if (MP_LEN(e) < EXP_THRESH) - EXP_SIMPLE(x, a, e); - else - EXP_WINDOW(x, a, e); - } - mp_drop(a); - mp_drop(d); - mp_drop(spare); - return (x); -} - -/*----- Test rig ----------------------------------------------------------*/ - - -#ifdef TEST_RIG - -#define MP(x) mp_readstring(MP_NEW, #x, 0, 0) - -static int vreduce(dstr *v) -{ - mp *d = *(mp **)v[0].buf; - mp *n = *(mp **)v[1].buf; - mp *r = *(mp **)v[2].buf; - mp *c; - int ok = 1; - mpreduce rr; - - mpreduce_create(&rr, d); - c = mpreduce_do(&rr, MP_NEW, n); - if (!MP_EQ(c, r)) { - fprintf(stderr, "\n*** reduction failed\n*** "); - mpreduce_dump(&rr, stderr); - fprintf(stderr, "\n*** n = "); mp_writefile(n, stderr, 10); - fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 10); - fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 10); - fprintf(stderr, "\n"); - ok = 0; - } - mpreduce_destroy(&rr); - mp_drop(n); mp_drop(d); mp_drop(r); mp_drop(c); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int vmodexp(dstr *v) -{ - mp *p = *(mp **)v[0].buf; - mp *g = *(mp **)v[1].buf; - mp *x = *(mp **)v[2].buf; - mp *r = *(mp **)v[3].buf; - mp *c; - int ok = 1; - mpreduce rr; - - mpreduce_create(&rr, p); - c = mpreduce_exp(&rr, MP_NEW, g, x); - if (!MP_EQ(c, r)) { - fprintf(stderr, "\n*** modexp failed\n*** "); - fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 10); - fprintf(stderr, "\n*** g = "); mp_writefile(g, stderr, 10); - fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 10); - fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 10); - fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 10); - fprintf(stderr, "\n"); - ok = 0; - } - mpreduce_destroy(&rr); - mp_drop(p); mp_drop(g); mp_drop(r); mp_drop(x); mp_drop(c); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk defs[] = { - { "reduce", vreduce, { &type_mp, &type_mp, &type_mp, 0 } }, - { "modexp", vmodexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, defs, SRCDIR"/tests/mpreduce"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpreduce.h b/mpreduce.h deleted file mode 100644 index 80037d1..0000000 --- a/mpreduce.h +++ /dev/null @@ -1,128 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Efficient reduction modulo nice primes - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPREDUCE_H -#define CATACOMB_MPREDUCE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct mpreduce_instr { - unsigned op; /* Instruction opcode */ - size_t argx, argy; /* Immediate arguments */ -} mpreduce_instr; - -enum { - MPRI_ADD, /* Add @p@ offset by @x@ words */ - MPRI_ADDLSL, /* Add @p << y@ offset by @x@ */ - MPRI_SUB, /* Sub @p@ offset by @x@ words */ - MPRI_SUBLSL, /* Sub @p << y@ offset by @x@ */ - MPRI_MAX -}; - -typedef struct mpreduce { - size_t lim; /* Word containing top bit */ - unsigned s; /* Shift for top word */ - mp *p; /* Copy of the modulus */ - size_t in; /* Number of instruction words */ - mpreduce_instr *iv; /* Vector of instructions */ -} mpreduce; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @mpreduce_create@ --- * - * - * Arguments: @gfreduce *r@ = structure to fill in - * @mp *x@ = an integer - * - * Returns: Zero for success, nonzero on error. - * - * Use: Initializes a context structure for reduction. - */ - -extern int mpreduce_create(mpreduce */*r*/, mp */*p*/); - -/* --- @mpreduce_destroy@ --- * - * - * Arguments: @mpreduce *r@ = structure to free - * - * Returns: --- - * - * Use: Reclaims the resources from a reduction context. - */ - -extern void mpreduce_destroy(mpreduce */*r*/); - -/* --- @mpreduce_dump@ --- * - * - * Arguments: @mpreduce *r@ = structure to dump - * @FILE *fp@ = file to dump on - * - * Returns: --- - * - * Use: Dumps a reduction context. - */ - -extern void mpreduce_dump(mpreduce */*r*/, FILE */*fp*/); - -/* --- @mpreduce_do@ --- * - * - * Arguments: @mpreduce *r@ = reduction context - * @mp *d@ = destination - * @mp *x@ = source - * - * Returns: Destination, @x@ reduced modulo the reduction poly. - */ - -extern mp *mpreduce_do(mpreduce */*r*/, mp */*d*/, mp */*x*/); - -/* --- @mpreduce_exp@ --- * - * - * Arguments: @mpreduce *mr@ = pointer to reduction context - * @mp *d@ = fake destination - * @mp *a@ = base - * @mp *e@ = exponent - * - * Returns: Result, %$a^e \bmod m$%. - */ - -extern mp *mpreduce_exp(mpreduce */*mr*/, mp */*d*/, mp */*a*/, mp */*e*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mpscan.c b/mpscan.c deleted file mode 100644 index a939333..0000000 --- a/mpscan.c +++ /dev/null @@ -1,122 +0,0 @@ -/* -*-c-*- - * - * $Id: mpscan.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Sequential bit scan of multiprecision integers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mpscan.h" - -/*----- Right-to-left scanning --------------------------------------------*/ - -/* --- @mpscan_initx@ --- * - * - * Arguments: @mpscan *m@ = pointer to bitscanner structure - * @const mpw *v, *vl@ = vector of words to scan - * - * Returns: --- - * - * Use: Initializes a bitscanner from a low-level vector-and-length - * representation of an integer. Initially no bit is ready; you - * must call @mpscan_step@ before anything useful will come - * out. - */ - -void mpscan_initx(mpscan *m, const mpw *v, const mpw *vl) -{ - MPSCAN_INITX(m, v, vl); -} - -/* --- @mpscan_step@ --- * - * - * Arguments: @mpscan *m@ = pointer to bitscanner - * - * Returns: Nonzero if there is another bit to read. - * - * Use: Steps on to the next bit in the integer. The macro version - * evaluates its argument multiple times. - */ - -int mpscan_step(mpscan *m) { return (MPSCAN_STEP(m)); } - -/* --- @mpscan_bit@ --- * - * - * Arguments: @const mpscan *m@ = pointer to bitscanner - * - * Returns: The value of the current bit. - * - * Use: Reads the value of the current bit looked at by a - * bitscanner. - */ - -int mpscan_bit(const mpscan *m) { return (MPSCAN_BIT(m)); } - -/*----- Left-to right-scanning --------------------------------------------*/ - -/* --- @mpscan_rinitx@ --- * - * - * Arguments: @mpscan *m@ = pointer to bitscanner structure - * @const mpw *v, *vl@ = vector of words to scan - * - * Returns: --- - * - * Use: Initializes a reverse bitscanner from a low-level - * vector-and-length representation of an integer. Initially no - * bit is ready; you must call @mpscan_rstep@ before anything - * useful will come out. - */ - -void mpscan_rinitx(mpscan *m, const mpw *v, const mpw *vl) -{ - MPSCAN_RINITX(m, v, vl); -} - -/* --- @mpscan_rstep@ --- * - * - * Arguments: @mpscan *m@ = pointer to bitscanner - * - * Returns: Nonzero if there is another bit to read. - * - * Use: Steps on to the next bit in the integer. The macro version - * evaluates its argument multiple times. - */ - -int mpscan_rstep(mpscan *m) { return (MPSCAN_RSTEP(m)); } - -/* --- @mpscan_rbit@ --- * - * - * Arguments: @const mpscan *m@ = pointer to bitscanner - * - * Returns: The value of the current bit. - * - * Use: Reads the value of the current bit looked at by a - * reverse bitscanner. - */ - -int mpscan_rbit(const mpscan *m) { return (MPSCAN_RBIT(m)); } - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpscan.h b/mpscan.h deleted file mode 100644 index 0d02519..0000000 --- a/mpscan.h +++ /dev/null @@ -1,172 +0,0 @@ -/* -*-c-*- - * - * $Id: mpscan.h,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Sequential bit scan of multiprecision integers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPSCAN_H -#define CATACOMB_MPSCAN_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MPW_H -# include "mpw.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct mpscan { - const mpw *v, *vl; /* Vector of words to scan */ - mpw w; /* Current word to scan */ - int bits; /* Number of bits left in @w@ */ -} mpscan; - -/*----- Right-to-left scanning --------------------------------------------*/ - -/* --- @mpscan_initx@ --- * - * - * Arguments: @mpscan *m@ = pointer to bitscanner structure - * @const mpw *v, *vl@ = vector of words to scan - * - * Returns: --- - * - * Use: Initializes a bitscanner from a low-level base-and-limit - * representation of an integer. Initially no bit is ready; you - * must call @mpscan_step@ before anything useful will come - * out. - */ - -#define MPSCAN_INITX(m_, v_, vl_) do { \ - mpscan *_m = (m_); \ - _m->v = (v_); \ - _m->vl = (vl_); \ - _m->bits = 0; \ -} while (0) - -extern void mpscan_initx(mpscan */*m*/, const mpw */*v*/, const mpw */*vl*/); - -/* --- @mpscan_step@ --- * - * - * Arguments: @mpscan *m@ = pointer to bitscanner - * - * Returns: Nonzero if there is another bit to read. - * - * Use: Steps on to the next bit in the integer. The macro version - * evaluates its argument multiple times. - */ - -#define MPSCAN_STEP(m) \ - ((m)->bits ? ((m)->w >>= 1, (m)->bits--, 1) : \ - (m)->v < (m)->vl ? ((m)->w = *(m)->v++, \ - (m)->bits = MPW_BITS - 1, 1) : \ - 0) - -extern int mpscan_step(mpscan */*m*/); - -/* --- @mpscan_bit@ --- * - * - * Arguments: @const mpscan *m@ = pointer to bitscanner - * - * Returns: The value of the current bit. - * - * Use: Reads the value of the current bit looked at by a - * bitscanner. - */ - -#define MPSCAN_BIT(m) ((m)->w & 1) - -extern int mpscan_bit(const mpscan */*m*/); - -/*----- Left-to right-scanning --------------------------------------------*/ - -/* --- @mpscan_rinitx@ --- * - * - * Arguments: @mpscan *m@ = pointer to bitscanner structure - * @const mpw *v, *vl@ = vector of words to scan - * - * Returns: --- - * - * Use: Initializes a reverse bitscanner from a low-level - * vector-and-length representation of an integer. Initially no - * bit is ready; you must call @mpscan_rstep@ before anything - * useful will come out. - */ - -#define MPSCAN_RINITX(m_, v_, vl_) do { \ - mpscan *_m = (m_); \ - _m->v = (v_); \ - _m->vl = (vl_); \ - while (_m->vl > _m->v && !_m->vl[-1]) \ - _m->vl--; \ - _m->bits = 0; \ -} while (0) - -extern void mpscan_rinitx(mpscan */*m*/, - const mpw */*v*/, const mpw */*vl*/); - -/* --- @mpscan_rstep@ --- * - * - * Arguments: @mpscan *m@ = pointer to bitscanner - * - * Returns: Nonzero if there is another bit to read. - * - * Use: Steps on to the next bit in the integer. The macro version - * evaluates its argument multiple times. - */ - -#define MPSCAN_RSTEP(m) \ - ((m)->bits ? ((m)->w <<= 1, (m)->bits--, 1) : \ - (m)->vl > (m)->v ? ((m)->w = *--(m)->vl, \ - (m)->bits = MPW_BITS - 1, 1) : \ - 0) - -extern int mpscan_rstep(mpscan */*m*/); - -/* --- @mpscan_rbit@ --- * - * - * Arguments: @const mpscan *m@ = pointer to bitscanner - * - * Returns: The value of the current bit. - * - * Use: Reads the value of the current bit looked at by a - * reverse bitscanner. - */ - -#define MPSCAN_RBIT(m) (((m)->w >> (MPW_BITS - 1)) & 1) - -extern int mpscan_rbit(const mpscan */*m*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mptext-dstr.c b/mptext-dstr.c deleted file mode 100644 index 6a9ad68..0000000 --- a/mptext-dstr.c +++ /dev/null @@ -1,88 +0,0 @@ -/* -*-c-*- - * - * $Id: mptext-dstr.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Reading and writing large integers on strings - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "mptext.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Operations table --- */ - -static int get(void *p) -{ - mptext_dstrctx *c = p; - if (c->i >= c->d->len) - return (EOF); - return ((unsigned char)c->d->buf[c->i++]); -} - -static void unget(int ch, void *p) -{ - mptext_dstrctx *c = p; - if (ch == EOF || c->i == 0) - return; - c->i--; -} - -static int put(const char *s, size_t sz, void *p) -{ - mptext_dstrctx *c = p; - DPUTM(c->d, s, sz); - return (0); -} - -const mptext_ops mptext_dstrops = { get, unget, put }; - -/* --- Convenience functions --- */ - -mp *mp_readdstr(mp *m, dstr *d, size_t *off, int radix) -{ - mptext_dstrctx c; - c.d = d; - c.i = off ? *off : 0; - m = mp_read(m, radix, &mptext_dstrops, &c); - if (off) - *off = c.i; - return (m); -} - -int mp_writedstr(mp *m, dstr *d, int radix) -{ - mptext_dstrctx c; - int rc; - c.d = d; - rc = mp_write(m, radix, &mptext_dstrops, &c); - DPUTZ(d); - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mptext-file.c b/mptext-file.c deleted file mode 100644 index 1eb273a..0000000 --- a/mptext-file.c +++ /dev/null @@ -1,64 +0,0 @@ -/* -*-c-*- - * - * $Id: mptext-file.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Reading and writing large integers on files - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "mptext.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Operations table --- */ - -static int get(void *p) { FILE *fp = p; return getc(fp); } - -static void unget(int ch, void *p) { FILE *fp = p; ungetc(ch, fp); } - -static int put(const char *s, size_t sz, void *p) -{ - FILE *fp = p; - return (fwrite(s, 1, sz, fp) != sz); -} - -const mptext_ops mptext_fileops = { get, unget, put }; - -/* --- Convenience functions --- */ - -mp *mp_readfile(mp *m, FILE *fp, int radix) -{ - return mp_read(m, radix, &mptext_fileops, fp); -} - -int mp_writefile(mp *m, FILE *fp, int radix) -{ - return mp_write(m, radix, &mptext_fileops, fp); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mptext-len.c b/mptext-len.c deleted file mode 100644 index e8142fb..0000000 --- a/mptext-len.c +++ /dev/null @@ -1,99 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Work out length of a number's string representation - * - * (c) 2002 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mptext.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mptext_len@ --- * - * - * Arguments: @mp *x@ = number to work on - * @int r@ = radix the number will be expressed in - * - * Returns: The number of digits needed to represent the number in the - * given base. This will not include space for a leading sign - * (use @MP_NEGP@ to check that, or just add one on for luck); - * neither will it add space for a terminating null. In general - * the answer will be an overestimate. - */ - -size_t mptext_len(mp *x, int r) -{ - unsigned long b = mp_bits(x); - int s, ss = 2; - size_t n; - unsigned d = 0; - - /* --- Huh? --- * - * - * The number of digits is at most %$\lceil b \log 2/\log r \rceil$%. We - * produce an underestimate of %$\log_2 r = \log r/\log 2$% and divide by - * that. How? By linear interpolation between known points on the curve. - * The known points are precisely the powers of 2, so we can find a pair - * efficiently by doubling up. The log curve is convex, so linear - * interpolation between points on the curve is always an underestimate. - * - * The integer maths here is a bit weird, so here's how it works. If - * %$s = 2^d$% is the power of 2 below %$r$% then we want to compute - * %$\lceil b/(d + (r - s)/s) \rceil = \lceil (b s)/(s(d - 1) + r \rceil$% - * which is %$\lfloor (r + s (b + d - 1) - 1)/(r + s(d - 1)) \rfloor$%. - * Gluing the whole computation together like this makes the code hard to - * read, but means that there are fewer possibilities for rounding errors - * and thus we get a tighter bound. - */ - - /* --- Find the right pair of points --- */ - - if (r < 0) r = -r; - do { - s = ss; - d++; - if (r == s) { - n = (b + (d - 1))/d; - goto done; - } - ss = s << 1; - } while (ss <= r); - - /* --- Do the interpolation --- */ - - n = (r + s*(b + d - 1) - 1)/(r + s*(d - 1)); - - /* --- Fixups --- */ - -done: - if (!n) - n = 1; - return (n); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mptext-string.c b/mptext-string.c deleted file mode 100644 index ecb8f18..0000000 --- a/mptext-string.c +++ /dev/null @@ -1,98 +0,0 @@ -/* -*-c-*- - * - * $Id: mptext-string.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Reading and writing large integers on strings - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "mptext.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Operations table --- */ - -static int get(void *p) -{ - mptext_stringctx *c = p; - if (c->buf >= c->lim) - return (EOF); - return ((unsigned char)*c->buf++); -} - -static void unget(int ch, void *p) -{ - mptext_stringctx *c = p; - if (ch != EOF) - c->buf--; -} - -static int put(const char *s, size_t sz, void *p) -{ - mptext_stringctx *c = p; - int rc = 0; - if (sz > c->lim - c->buf) { - sz = c->lim - c->buf; - rc = EOF; - } - if (sz) { - memcpy(c->buf, s, sz); - c->buf += sz; - } - return (rc); -} - -const mptext_ops mptext_stringops = { get, unget, put }; - -/* --- Convenience functions --- */ - -mp *mp_readstring(mp *m, const char *p, char **end, int radix) -{ - mptext_stringctx c; - c.buf = (/*unconst */ char *)p; - c.lim = c.buf + strlen(p); - m = mp_read(m, radix, &mptext_stringops, &c); - if (end) - *end = c.buf; - return (m); -} - -int mp_writestring(mp *m, char *p, size_t sz, int radix) -{ - mptext_stringctx c; - int rc; - if (!sz) - return (0); - c.buf = p; - c.lim = p + sz - 1; - rc = mp_write(m, radix, &mptext_stringops, &c); - *c.buf = 0; - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mptext.c b/mptext.c deleted file mode 100644 index 8c00e34..0000000 --- a/mptext.c +++ /dev/null @@ -1,851 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Textual representation of multiprecision numbers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include "mp.h" -#include "mptext.h" -#include "paranoia.h" - -/*----- Magical numbers ---------------------------------------------------*/ - -/* --- Maximum recursion depth --- * - * - * This is the number of bits in a @size_t@ object. Why? - * - * To see this, let %$b = \textit{MPW\_MAX} + 1$% and let %$Z$% be the - * largest @size_t@ value. Then the largest possible @mp@ is %$M - 1$% where - * %$M = b^Z$%. Let %$r$% be a radix to read or write. Since the recursion - * squares the radix at each step, the highest number reached by the - * recursion is %$d$%, where: - * - * %$r^{2^d} = b^Z$%. - * - * Solving gives that %$d = \lg \log_r b^Z$%. If %$r = 2$%, this is maximum, - * so choosing %$d = \lg \lg b^Z = \lg (Z \lg b) = \lg Z + \lg \lg b$%. - * - * Expressing %$\lg Z$% as @CHAR_BIT * sizeof(size_t)@ yields an - * overestimate, since a @size_t@ representation may contain `holes'. - * Choosing to represent %$\lg \lg b$% by 10 is almost certainly sufficient - * for `some time to come'. - */ - -#define DEPTH (CHAR_BIT * sizeof(size_t) + 10) - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mp_read@ --- * - * - * Arguments: @mp *m@ = destination multiprecision number - * @int radix@ = base to assume for data (or zero to guess) - * @const mptext_ops *ops@ = pointer to operations block - * @void *p@ = data for the operations block - * - * Returns: The integer read, or zero if it didn't work. - * - * Use: Reads an integer from some source. If the @radix@ is - * specified, the number is assumed to be given in that radix, - * with the letters `a' (either upper- or lower-case) upwards - * standing for digits greater than 9. Otherwise, base 10 is - * assumed unless the number starts with `0' (octal), `0x' (hex) - * or `nnn_' (base `nnn'). An arbitrary amount of whitespace - * before the number is ignored. - */ - -/* --- About the algorithm --- * - * - * The algorithm here is rather aggressive. I maintain an array of - * successive squarings of the radix, and a stack of partial results, each - * with a counter attached indicating which radix square to multiply by. - * Once the item at the top of the stack reaches the same counter level as - * the next item down, they are combined together and the result is given a - * counter level one higher than either of the results. - * - * Gluing the results together at the end is slightly tricky. Pay attention - * to the code. - * - * This is more complicated because of the need to handle the slightly - * bizarre syntax. - */ - -mp *mp_read(mp *m, int radix, const mptext_ops *ops, void *p) -{ - int ch; /* Current char being considered */ - unsigned f = 0; /* Flags about the current number */ - int r; /* Radix to switch over to */ - mpw rd; /* Radix as an @mp@ digit */ - mp rr; /* The @mp@ for the radix */ - unsigned nf = m ? m->f & MP_BURN : 0; /* New @mp@ flags */ - - /* --- Stacks --- */ - - mp *pow[DEPTH]; /* List of powers */ - unsigned pows; /* Next index to fill */ - struct { unsigned i; mp *m; } s[DEPTH]; /* Main stack */ - unsigned sp; /* Current stack pointer */ - - /* --- Flags --- */ - -#define f_neg 1u -#define f_ok 2u -#define f_start 4u - - /* --- Initialize the stacks --- */ - - mp_build(&rr, &rd, &rd + 1); - pow[0] = &rr; - pows = 1; - - sp = 0; - - /* --- Initialize the destination number --- */ - - if (m) - MP_DROP(m); - - /* --- Read an initial character --- */ - - ch = ops->get(p); - if (radix >= 0) { - while (isspace(ch)) - ch = ops->get(p); - } - - /* --- Handle an initial sign --- */ - - if (radix >= 0 && (ch == '-' || ch == '+')) { - if (ch == '-') - f |= f_neg; - do ch = ops->get(p); while isspace(ch); - } - - /* --- If the radix is zero, look for leading zeros --- */ - - if (radix > 0) { - assert(((void)"ascii radix must be <= 62", radix <= 62)); - rd = radix; - r = -1; - } else if (radix < 0) { - rd = -radix; - assert(((void)"binary radix must fit in a byte", rd <= UCHAR_MAX)); - r = -1; - } else if (ch != '0') { - rd = 10; - r = 0; - } else { - ch = ops->get(p); - switch (ch) { - case 'x': - rd = 16; - goto prefix; - case 'o': - rd = 8; - goto prefix; - case 'b': - rd = 2; - goto prefix; - prefix: - ch = ops->get(p); - break; - default: - rd = 8; - f |= f_ok; - } - r = -1; - } - - /* --- Use fast algorithm for binary radix --- * - * - * This is the restart point after having parsed a radix number from the - * input. We check whether the radix is binary, and if so use a fast - * algorithm which just stacks the bits up in the right order. - */ - -restart: - switch (rd) { - unsigned bit; - - case 2: bit = 1; goto bin; - case 4: bit = 2; goto bin; - case 8: bit = 3; goto bin; - case 16: bit = 4; goto bin; - case 32: bit = 5; goto bin; - case 64: bit = 6; goto bin; - case 128: bit = 7; goto bin; - default: - break; - - /* --- The fast binary algorithm --- * - * - * We stack bits up starting at the top end of a word. When one word is - * full, we write it to the integer, and start another with the left-over - * bits. When the array in the integer is full, we resize using low-level - * calls and copy the current data to the top end. Finally, we do a single - * bit-shift when we know where the end of the number is. - */ - - bin: { - mpw a = 0; - unsigned b = MPW_BITS; - size_t len, n; - mpw *v; - - m = mp_dest(MP_NEW, 1, nf); - len = n = m->sz; - n = len; - v = m->v + n; - for (;; ch = ops->get(p)) { - unsigned x; - - if (ch < 0) - break; - - /* --- Check that the character is a digit and in range --- */ - - if (radix < 0) - x = ch % rd; - else { - if (!isalnum(ch)) - break; - if (ch >= '0' && ch <= '9') - x = ch - '0'; - else { - if (rd <= 36) - ch = tolower(ch); - if (ch >= 'a' && ch <= 'z') /* ASCII dependent! */ - x = ch - 'a' + 10; - else if (ch >= 'A' && ch <= 'Z') - x = ch - 'A' + 36; - else - break; - } - } - if (x >= rd) - break; - - /* --- Feed the digit into the accumulator --- */ - - f |= f_ok; - if (!x && !(f & f_start)) - continue; - f |= f_start; - if (b > bit) { - b -= bit; - a |= MPW(x) << b; - } else { - a |= MPW(x) >> (bit - b); - b += MPW_BITS - bit; - *--v = MPW(a); - n--; - if (!n) { - n = len; - len <<= 1; - v = mpalloc(m->a, len); - memcpy(v + n, m->v, MPWS(n)); - mpfree(m->a, m->v); - m->v = v; - v = m->v + n; - } - a = (b < MPW_BITS) ? MPW(x) << b : 0; - } - } - - /* --- Finish up --- */ - - if (!(f & f_ok)) { - mp_drop(m); - m = 0; - } else { - *--v = MPW(a); - n--; - m->sz = len; - m->vl = m->v + len; - m->f &= ~MP_UNDEF; - m = mp_lsr(m, m, (unsigned long)n * MPW_BITS + b); - } - ops->unget(ch, p); - goto done; - }} - - /* --- Time to start --- */ - - for (;; ch = ops->get(p)) { - unsigned x; - - if (ch < 0) - break; - - /* --- An underscore indicates a numbered base --- */ - - if (ch == '_' && r > 0 && r <= 62) { - unsigned i; - - /* --- Clear out the stacks --- */ - - for (i = 1; i < pows; i++) - MP_DROP(pow[i]); - pows = 1; - for (i = 0; i < sp; i++) - MP_DROP(s[i].m); - sp = 0; - - /* --- Restart the search --- */ - - rd = r; - r = -1; - f &= ~f_ok; - ch = ops->get(p); - goto restart; - } - - /* --- Check that the character is a digit and in range --- */ - - if (radix < 0) - x = ch % rd; - else { - if (!isalnum(ch)) - break; - if (ch >= '0' && ch <= '9') - x = ch - '0'; - else { - if (rd <= 36) - ch = tolower(ch); - if (ch >= 'a' && ch <= 'z') /* ASCII dependent! */ - x = ch - 'a' + 10; - else if (ch >= 'A' && ch <= 'Z') - x = ch - 'A' + 36; - else - break; - } - } - - /* --- Sort out what to do with the character --- */ - - if (x >= 10 && r >= 0) - r = -1; - if (x >= rd) - break; - - if (r >= 0) - r = r * 10 + x; - - /* --- Stick the character on the end of my integer --- */ - - assert(((void)"Number is too unimaginably huge", sp < DEPTH)); - s[sp].m = m = mp_new(1, nf); - m->v[0] = x; - s[sp].i = 0; - - /* --- Now grind through the stack --- */ - - while (sp > 0 && s[sp - 1].i == s[sp].i) { - - /* --- Combine the top two items --- */ - - sp--; - m = s[sp].m; - m = mp_mul(m, m, pow[s[sp].i]); - m = mp_add(m, m, s[sp + 1].m); - s[sp].m = m; - MP_DROP(s[sp + 1].m); - s[sp].i++; - - /* --- Make a new radix power if necessary --- */ - - if (s[sp].i >= pows) { - assert(((void)"Number is too unimaginably huge", pows < DEPTH)); - pow[pows] = mp_sqr(MP_NEW, pow[pows - 1]); - pows++; - } - } - f |= f_ok; - sp++; - } - - ops->unget(ch, p); - - /* --- If we're done, compute the rest of the number --- */ - - if (f & f_ok) { - if (!sp) - return (MP_ZERO); - else { - mp *z = MP_ONE; - sp--; - - while (sp > 0) { - - /* --- Combine the top two items --- */ - - sp--; - m = s[sp].m; - z = mp_mul(z, z, pow[s[sp + 1].i]); - m = mp_mul(m, m, z); - m = mp_add(m, m, s[sp + 1].m); - s[sp].m = m; - MP_DROP(s[sp + 1].m); - - /* --- Make a new radix power if necessary --- */ - - if (s[sp].i >= pows) { - assert(((void)"Number is too unimaginably huge", pows < DEPTH)); - pow[pows] = mp_sqr(MP_NEW, pow[pows - 1]); - pows++; - } - } - MP_DROP(z); - m = s[0].m; - } - } else { - unsigned i; - for (i = 0; i < sp; i++) - MP_DROP(s[i].m); - } - - /* --- Clear the radix power list --- */ - - { - unsigned i; - for (i = 1; i < pows; i++) - MP_DROP(pow[i]); - } - - /* --- Bail out if the number was bad --- */ - -done: - if (!(f & f_ok)) - return (0); - - /* --- Set the sign and return --- */ - - if (f & f_neg) - m->f |= MP_NEG; - MP_SHRINK(m); - return (m); - -#undef f_start -#undef f_neg -#undef f_ok -} - -/* --- @mp_write@ --- * - * - * Arguments: @mp *m@ = pointer to a multi-precision integer - * @int radix@ = radix to use when writing the number out - * @const mptext_ops *ops@ = pointer to an operations block - * @void *p@ = data for the operations block - * - * Returns: Zero if it worked, nonzero otherwise. - * - * Use: Writes a large integer in textual form. - */ - -/* --- Simple case --- * - * - * Use a fixed-sized buffer and single-precision arithmetic to pick off - * low-order digits. Put each digit in a buffer, working backwards from the - * end. If the buffer becomes full, recurse to get another one. Ensure that - * there are at least @z@ digits by writing leading zeroes if there aren't - * enough real digits. - */ - -static int simple(mpw n, int radix, unsigned z, - const mptext_ops *ops, void *p) -{ - int rc = 0; - char buf[64]; - unsigned i = sizeof(buf); - int rd = radix > 0 ? radix : -radix; - - do { - int ch; - mpw x; - - x = n % rd; - n /= rd; - if (radix < 0) - ch = x; - else if (x < 10) - ch = '0' + x; - else if (x < 36) /* Ascii specific */ - ch = 'a' + x - 10; - else - ch = 'A' + x - 36; - buf[--i] = ch; - if (z) - z--; - } while (i && n); - - if (n) - rc = simple(n, radix, z, ops, p); - else { - char zbuf[32]; - memset(zbuf, (radix < 0) ? 0 : '0', sizeof(zbuf)); - while (!rc && z >= sizeof(zbuf)) { - rc = ops->put(zbuf, sizeof(zbuf), p); - z -= sizeof(zbuf); - } - if (!rc && z) - rc = ops->put(zbuf, z, p); - } - if (!rc) - rc = ops->put(buf + i, sizeof(buf) - i, p); - BURN(buf); - return (rc); -} - -/* --- Complicated case --- * - * - * If the number is small, fall back to the simple case above. Otherwise - * divide and take remainder by current large power of the radix, and emit - * each separately. Don't emit a zero quotient. Be very careful about - * leading zeroes on the remainder part, because they're deeply significant. - */ - -static int complicated(mp *m, int radix, mp **pr, unsigned i, unsigned z, - const mptext_ops *ops, void *p) -{ - int rc = 0; - mp *q = MP_NEW; - unsigned d = 1 << i; - - if (MP_LEN(m) < 2) - return (simple(MP_LEN(m) ? m->v[0] : 0, radix, z, ops, p)); - - assert(i); - mp_div(&q, &m, m, pr[i]); - if (MP_ZEROP(q)) - d = z; - else { - if (z > d) - z -= d; - else - z = 0; - rc = complicated(q, radix, pr, i - 1, z, ops, p); - } - if (!rc) - rc = complicated(m, radix, pr, i - 1, d, ops, p); - mp_drop(q); - return (rc); -} - -/* --- Binary case --- * - * - * Special case for binary output. Goes much faster. - */ - -static int binary(mp *m, int bit, int radix, const mptext_ops *ops, void *p) -{ - mpw *v; - mpw a; - int rc = 0; - unsigned b; - unsigned mask; - unsigned long n; - unsigned f = 0; - char buf[8], *q; - unsigned x; - int ch; - -#define f_out 1u - - /* --- Work out where to start --- */ - - n = mp_bits(m); - if (n % bit) - n += bit - (n % bit); - b = n % MPW_BITS; - n /= MPW_BITS; - - if (n >= MP_LEN(m)) { - n--; - b += MPW_BITS; - } - - v = m->v + n; - a = *v; - mask = (1 << bit) - 1; - q = buf; - - /* --- Main code --- */ - - for (;;) { - if (b > bit) { - b -= bit; - x = a >> b; - } else { - x = a << (bit - b); - b += MPW_BITS - bit; - if (v == m->v) - break; - a = *--v; - if (b < MPW_BITS) - x |= a >> b; - } - x &= mask; - if (!x && !(f & f_out)) - continue; - - if (radix < 0) - ch = x; - else if (x < 10) - ch = '0' + x; - else if (x < 36) - ch = 'a' + x - 10; /* Ascii specific */ - else - ch = 'A' + x - 36; - *q++ = ch; - if (q >= buf + sizeof(buf)) { - if ((rc = ops->put(buf, sizeof(buf), p)) != 0) - goto done; - q = buf; - } - f |= f_out; - } - - x &= mask; - if (radix < 0) - ch = x; - else if (x < 10) - ch = '0' + x; - else if (x < 36) - ch = 'a' + x - 10; /* Ascii specific */ - else - ch = 'A' + x - 36; - *q++ = ch; - rc = ops->put(buf, q - buf, p); - -done: - mp_drop(m); - return (rc); - -#undef f_out -} - -/* --- Main driver code --- */ - -int mp_write(mp *m, int radix, const mptext_ops *ops, void *p) -{ - int rc; - - if (MP_EQ(m, MP_ZERO)) - return (ops->put(radix > 0 ? "0" : "\0", 1, p)); - - /* --- Set various things up --- */ - - m = MP_COPY(m); - MP_SPLIT(m); - - /* --- Check the radix for sensibleness --- */ - - if (radix > 0) - assert(((void)"ascii radix must be <= 62", radix <= 62)); - else if (radix < 0) - assert(((void)"binary radix must fit in a byte", -radix <= UCHAR_MAX)); - else - assert(((void)"radix can't be zero in mp_write", 0)); - - /* --- If the number is negative, sort that out --- */ - - if (MP_NEGP(m)) { - assert(radix > 0); - if (ops->put("-", 1, p)) - return (EOF); - m->f &= ~MP_NEG; - } - - /* --- Handle binary radix --- */ - - switch (radix) { - case 2: case -2: return (binary(m, 1, radix, ops, p)); - case 4: case -4: return (binary(m, 2, radix, ops, p)); - case 8: case -8: return (binary(m, 3, radix, ops, p)); - case 16: case -16: return (binary(m, 4, radix, ops, p)); - case 32: case -32: return (binary(m, 5, radix, ops, p)); - case -64: return (binary(m, 6, radix, ops, p)); - case -128: return (binary(m, 7, radix, ops, p)); - } - - /* --- If the number is small, do it the easy way --- */ - - if (MP_LEN(m) < 2) - rc = simple(MP_LEN(m) ? m->v[0] : 0, radix, 0, ops, p); - - /* --- Use a clever algorithm --- * - * - * Square the radix repeatedly, remembering old results, until I get - * something more than half the size of the number @m@. Use this to divide - * the number: the quotient and remainder will be approximately the same - * size, and I'll have split them on a digit boundary, so I can just emit - * the quotient and remainder recursively, in order. - */ - - else { - mp *pr[DEPTH]; - size_t target = (MP_LEN(m) + 1) / 2; - unsigned i = 0; - mp *z = mp_new(1, 0); - - /* --- Set up the exponent table --- */ - - z->v[0] = (radix > 0 ? radix : -radix); - z->f = 0; - for (;;) { - assert(((void)"Number is too unimaginably huge", i < DEPTH)); - pr[i++] = z; - if (MP_LEN(z) > target) - break; - z = mp_sqr(MP_NEW, z); - } - - /* --- Write out the answer --- */ - - rc = complicated(m, radix, pr, i - 1, 0, ops, p); - - /* --- Tidy away the array --- */ - - while (i > 0) - mp_drop(pr[--i]); - } - - /* --- Tidying up code --- */ - - MP_DROP(m); - return (rc); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -static int verify(dstr *v) -{ - int ok = 1; - int ib = *(int *)v[0].buf, ob = *(int *)v[2].buf; - dstr d = DSTR_INIT; - size_t off = 0; - mp *m = mp_readdstr(MP_NEW, &v[1], &off, ib); - if (m) { - if (!ob) { - fprintf(stderr, "*** unexpected successful parse\n" - "*** input [%2i] = ", ib); - if (ib < 0) - type_hex.dump(&v[1], stderr); - else - fputs(v[1].buf, stderr); - mp_writedstr(m, &d, 10); - fprintf(stderr, "\n*** (value = %s)\n", d.buf); - ok = 0; - } else { - mp_writedstr(m, &d, ob); - if (d.len != v[3].len || memcmp(d.buf, v[3].buf, d.len) != 0) { - fprintf(stderr, "*** failed read or write\n" - "*** input [%2i] = ", ib); - if (ib < 0) - type_hex.dump(&v[1], stderr); - else - fputs(v[1].buf, stderr); - fprintf(stderr, "\n*** output [%2i] = ", ob); - if (ob < 0) - type_hex.dump(&d, stderr); - else - fputs(d.buf, stderr); - fprintf(stderr, "\n*** expected [%2i] = ", ob); - if (ob < 0) - type_hex.dump(&v[3], stderr); - else - fputs(v[3].buf, stderr); - fputc('\n', stderr); - ok = 0; - } - } - mp_drop(m); - } else { - if (ob) { - fprintf(stderr, "*** unexpected parse failure\n" - "*** input [%2i] = ", ib); - if (ib < 0) - type_hex.dump(&v[1], stderr); - else - fputs(v[1].buf, stderr); - fprintf(stderr, "\n*** expected [%2i] = ", ob); - if (ob < 0) - type_hex.dump(&v[3], stderr); - else - fputs(v[3].buf, stderr); - fputc('\n', stderr); - ok = 0; - } - } - - if (v[1].len - off != v[4].len || - memcmp(v[1].buf + off, v[4].buf, v[4].len) != 0) { - fprintf(stderr, "*** leftovers incorrect\n" - "*** input [%2i] = ", ib); - if (ib < 0) - type_hex.dump(&v[1], stderr); - else - fputs(v[1].buf, stderr); - fprintf(stderr, "\n*** expected `%s'\n" - "*** found `%s'\n", - v[4].buf, v[1].buf + off); - ok = 0; - } - - dstr_destroy(&d); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "mptext-ascii", verify, - { &type_int, &type_string, &type_int, &type_string, &type_string, 0 } }, - { "mptext-bin-in", verify, - { &type_int, &type_hex, &type_int, &type_string, &type_string, 0 } }, - { "mptext-bin-out", verify, - { &type_int, &type_string, &type_int, &type_hex, &type_string, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/mptext"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mptext.h b/mptext.h deleted file mode 100644 index dade3cf..0000000 --- a/mptext.h +++ /dev/null @@ -1,186 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Textual representation of multiprecision numbers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPTEXT_H -#define CATACOMB_MPTEXT_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct mptext_ops { - int (*get)(void */*p*/); - void (*unget)(int /*ch*/, void */*p*/); - int (*put)(const char */*s*/, size_t /*len*/, void */*p*/); -} mptext_ops; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @mp_read@ --- * - * - * Arguments: @mp *m@ = destination multiprecision number - * @int radix@ = base to assume for data (or zero to guess) - * @const mptext_ops *ops@ = pointer to operations block - * @void *p@ = data for the operations block - * - * Returns: The integer read, or zero if it didn't work. - * - * Use: Reads an integer from some source. If the @radix@ is - * specified, the number is assumed to be given in that radix, - * with the letters `a' (either upper- or lower-case) upwards - * standing for digits greater than 9. Otherwise, base 10 is - * assumed unless the number starts with `0' (octal), `0x' (hex) - * or `nnn_' (base `nnn'). An arbitrary amount of whitespace - * before the number is ignored. - */ - -extern mp *mp_read(mp */*m*/, int /*radix*/, - const mptext_ops */*ops*/, void */*p*/); - -/* --- @mp_write@ --- * - * - * Arguments: @mp *m@ = pointer to a multi-precision integer - * @int radix@ = radix to use when writing the number out - * @const mptext_ops *ops@ = pointer to an operations block - * @void *p@ = data for the operations block - * - * Returns: Zero if it worked, nonzero otherwise. - * - * Use: Writes a large integer in textual form. - */ - -extern int mp_write(mp */*m*/, int /*radix*/, - const mptext_ops */*ops*/, void */*p*/); - -/* --- @mptext_len@ --- * - * - * Arguments: @mp *x@ = number to work on - * @int r@ = radix the number will be expressed in - * - * Returns: The number of digits needed to represent the number in the - * given base. This will not include space for a leading sign - * (use @MP_NEGP@ to check that, or just add one on for luck); - * neither will it add space for a terminating null. In general - * the answer will be an overestimate. - */ - -extern size_t mptext_len(mp */*x*/, int /*r*/); - -/*----- File I/O ----------------------------------------------------------*/ - -#include - -/* --- Operations table --- * - * - * The @mptext_fileops@ expect the pointer argument to be a @FILE *@. - */ - -extern const mptext_ops mptext_fileops; - -/* --- Convenience functions --- */ - -extern mp *mp_readfile(mp */*m*/, FILE */*fp*/, int /*radix*/); -extern int mp_writefile(mp */*m*/, FILE */*fp*/, int /*radix*/); - -#define MP_DOFPRINTFR(fp, args, m, r) do { \ - fprintf args; \ - if (m) \ - mp_writefile(m, fp, r); \ - else \ - fputs("", fp); \ - fputc('\n', fp); \ -} while (0) - -#define MP_DOFPRINTR(fp, name, m, r) \ - MP_DOFPRINTFR(fp, (fp, "%s = ", name), m, r) - -#define MP_PRINT(name, m) MP_DOFPRINTR(stdout, name, m, 10) -#define MP_EPRINT(name, m) MP_DOFPRINTR(stderr, name, m, 10) -#define MP_PRINTX(name, m) MP_DOFPRINTR(stdout, name, m, 16) -#define MP_EPRINTX(name, m) MP_DOFPRINTR(stderr, name, m, 16) - -#define MP_FPRINTF(fp, args, m) MP_DOFPRINTFR(fp, args, m, 10) -#define MP_FPRINTFX(fp, args, m) MP_DOFPRINTFR(fp, args, m, 16) - -/*----- String I/O --------------------------------------------------------*/ - -/* --- Context format --- */ - -typedef struct mptext_stringctx { - char *buf; - char *lim; -} mptext_stringctx; - -/* --- Operations table --- */ - -extern const mptext_ops mptext_stringops; - -/* --- Convenience functions --- */ - -extern mp *mp_readstring(mp */*m*/, const char */*p*/, char **/*end*/, - int /*radix*/); -extern int mp_writestring(mp */*m*/, char */*p*/, size_t /*sz*/, - int /*radix*/); - -/*----- Dynamic string I/O ------------------------------------------------*/ - -#include - -/* --- Context format --- */ - -typedef struct mptext_dstrctx { - dstr *d; - size_t i; -} mptext_dstrctx; - -/* --- Operations table --- */ - -extern const mptext_ops mptext_dstrops; - -/* --- Convenience functions --- */ - -extern mp *mp_readdstr(mp */*m*/, dstr */*d*/, size_t */*off*/, - int /*radix*/); -extern int mp_writedstr(mp */*m*/, dstr */*d*/, int /*radix*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mptypes.c b/mptypes.c deleted file mode 100644 index eb8b975..0000000 --- a/mptypes.c +++ /dev/null @@ -1,214 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Generate `mptypes.h' header file for current architecture - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _GNU_SOURCE -#include "config.h" - -#include -#include -#if __STDC_VERSION__ >= 199900l -# include -# include -#endif - -/*----- Data types --------------------------------------------------------*/ - -/* --- Hack for GCC --- * - * - * WG14 in their infinite wisdom decided not to use the GCC constant name. - */ - -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91) -# define EXT __extension__ -#else -# define EXT -#endif - -#if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX) -# define ULLONG_MAX ULONG_LONG_MAX -#endif - -/* --- Choose the largest integer type --- */ - -#if defined(UINTMAX_MAX) && defined(PRIuMAX) - typedef uintmax_t umax; -# define P_UMAX PRIuMAX -#elif defined(ULLONG_MAX) - EXT typedef unsigned long long umax; -# define P_UMAX "llu" -#else - typedef unsigned long umax; -# define P_UMAX "lu" -#endif - -/* --- Table of interesting types --- * - * - * These are in preference order. - */ - -enum { - f_stdint = 1u, - f_ext = 2u -}; - -struct itype { - const char *name; - const char *suff; - umax max; - unsigned flags; - unsigned bits; -} tytab[] = { - { "unsigned int", "u", UINT_MAX, 0 }, - { "unsigned short", "u", USHRT_MAX, 0 }, - { "unsigned long", "ul", ULONG_MAX, 0 }, -#ifdef ULLONG_MAX - { "unsigned long long", "ull", EXT ULLONG_MAX, f_ext }, -#endif -#ifdef UINTMAX_MAX - { "uintmax_t", "u", UINTMAX_MAX, f_stdint }, -#endif - { 0, 0 }, -}; - -typedef struct itype itype; - -/*----- Main code ---------------------------------------------------------*/ - -int main(int argc, char *argv[]) -{ - itype *i; - itype *largest, *mpw, *mpd; - const static char *extstr = "CATACOMB_MPTYPES_EXTENSION "; - unsigned p2; - - /* --- Find the bitcounts --- */ - - for (i = tytab; i->name; i++) { - unsigned bits; - umax u = i->max; - for (bits = 0; u; bits++) - u >>= 1; - i->bits = bits; - } - - /* --- Now try to find the interesting types --- * - * - * The first thing to do is to find the largest type. Then I find the - * `best' type which is less than half that size, and then the `best' type - * which is twice as big as that one. - */ - -#if defined(FORCE_MPW_CUSSID) - largest = mpd = &tytab[3]; - mpw = &tytab[2]; - mpw->bits = 19; mpw->max = 0x7ffff; - mpd->bits = 38; mpd->max = 0x3fffffffffll; -#elif defined(FORCE_MPW_SHORT) - largest = mpd = &tytab[2]; - mpw = &tytab[1]; - mpw->bits = 16; mpw->max = 0xffff; - mpd->bits = 32; mpd->max = 0xffffffff; -#else - largest = tytab; - for (i = tytab; i->name; i++) { - if (i->bits > largest->bits) - largest = i; - } - for (mpw = 0, i = tytab; i->name; i++) { - if (i->bits * 2 <= largest->bits && (!mpw || i->bits > mpw->bits)) - mpw = i; - } - if (!mpw) - mpw = tytab; - for (mpd = 0, i = tytab; i->name; i++) { - if (i->bits >= mpw->bits * 2 && (!mpd || i->bits < mpd->bits)) - mpd = i; - } - if (!mpd) { - static itype w, d; - d = w = *mpw; - w.bits /= 2; w.max = ~(~((umax)0) << w.bits); - d.bits = w.bits * 2; d.max = ~(~((umax)0) << d.bits); - mpw = &w; mpd = &d; - } -#endif - for (p2 = 1; (p2 << 1) < mpw->bits; p2 <<= 1); - - /* --- Output time --- */ - - puts("\ -/* -*-c-*-\n\ - *\n\ - * mptypes.h [generated]\n\ - */\n\ -\n\ -#ifndef CATACOMB_MPTYPES_H\n\ -#define CATACOMB_MPTYPES_H\n\ -"); - if ((mpd->flags | mpw->flags) & f_stdint) { - puts("\ -#if __STDC_VERSION__ >= 199900l\n\ -# include \n\ -#endif\n\ -"); - } - if ((mpd->flags | mpw->flags) & f_ext) { - printf("\ -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91)\n\ -# define %s __extension__\n\ -#else\n\ -# define %s\n\ -#endif\n\ -", extstr, extstr); - } - printf("\ -%stypedef %s mpw;\n\ -#define MPW_BITS %u\n\ -#define MPW_P2 %u\n\ -#define MPW_MAX %s%" P_UMAX "%s\n\ -\n\ -%stypedef %s mpd;\n\ -#define MPD_BITS %u\n\ -#define MPD_MAX %s%" P_UMAX "%s\n\ -\n\ -#endif\n\ -", - mpw->flags & f_ext ? extstr : "", mpw->name, - mpw->bits, p2, - mpw->flags & f_ext ? extstr : "", mpw->max, mpw->suff, - mpd->flags & f_ext ? extstr : "", mpd->name, - mpd->bits, - mpd->flags & f_ext ? extstr : "", mpd->max, mpd->suff); - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpw.h b/mpw.h deleted file mode 100644 index e37ea16..0000000 --- a/mpw.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -*-c-*- - * - * $Id: mpw.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Very low-level multiprecision definitions - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPW_H -#define CATACOMB_MPW_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_BITS_H -# include -#endif - -#ifndef CATACOMB_MPTYPES_H -# include "mptypes.h" -#endif - -/*----- Useful macros -----------------------------------------------------*/ - -/* --- @MPW@ --- * - * - * Arguments: @x@ = an unsigned value - * - * Use: Expands to the value of @x@ masked and typecast to a - * multiprecision integer word. - */ - -#define MPW(x) ((mpw)((x) & MPW_MAX)) - -/* --- @MPWS@ --- * - * - * Arguments: @n@ = number of words - * - * Use: Expands to the number of bytes occupied by a given number of - * words. - */ - -#define MPWS(n) ((n) * sizeof(mpw)) - -/* --- @MPW_RQ@ --- * - * - * Arguments: @sz@ = size of an octet array, in octets - * - * Use: Expands to the number of @mpw@ words required to represent - * the number held in the octet array. - */ - -#define MPW_RQ(sz) (((sz) * 8 + MPW_BITS - 1) / MPW_BITS) - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/mpx-kmul.c b/mpx-kmul.c deleted file mode 100644 index 081de88..0000000 --- a/mpx-kmul.c +++ /dev/null @@ -1,249 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Karatsuba's multiplication algorithm - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include "mpx.h" -#include "karatsuba.h" - -/*----- Tweakables --------------------------------------------------------*/ - -#ifdef TEST_RIG -# undef MPK_THRESH -# define MPK_THRESH 4 /* Smallest possible correct value */ -#endif - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mpx_kmul@ --- * - * - * Arguments: @mpw *dv, *dvl@ = pointer to destination buffer - * @const mpw *av, *avl@ = pointer to first argument - * @const mpw *bv, *bvl@ = pointer to second argument - * @mpw *sv, *svl@ = pointer to scratch workspace - * - * Returns: --- - * - * Use: Multiplies two multiprecision integers using Karatsuba's - * algorithm. This is rather faster than traditional long - * multiplication (e.g., @mpx_umul@) on large numbers, although - * more expensive on small ones. - * - * The destination must be three times as large as the larger - * argument. The scratch space must be five times as large as - * the larger argument. - */ - -void mpx_kmul(mpw *dv, mpw *dvl, - const mpw *av, const mpw *avl, - const mpw *bv, const mpw *bvl, - mpw *sv, mpw *svl) -{ - const mpw *avm, *bvm; - size_t m; - - /* --- Dispose of easy cases to @mpx_umul@ --- * - * - * Karatsuba is only a win on large numbers, because of all the - * recursiveness and bookkeeping. The recursive calls make a quick check - * to see whether to bottom out to @mpx_umul@ which should help quite a - * lot, but sometimes the only way to know is to make sure... - */ - - MPX_SHRINK(av, avl); - MPX_SHRINK(bv, bvl); - - if (avl - av <= MPK_THRESH || bvl - bv <= MPK_THRESH) { - mpx_umul(dv, dvl, av, avl, bv, bvl); - return; - } - - /* --- How the algorithm works --- * - * - * Let %$A = xb + y$% and %$B = ub + v$%. Then, simply by expanding, - * %$AB = x u b^2 + b(x v + y u) + y v$%. That's not helped any, because - * I've got four multiplications, each four times easier than the one I - * started with. However, note that I can rewrite the coefficient of %$b$% - * as %$xv + yu = (x + y)(u + v) - xu - yv$%. The terms %$xu$% and %$yv$% - * I've already calculated, and that leaves only one more multiplication to - * do. So now I have three multiplications, each four times easier, and - * that's a win. - */ - - /* --- First things --- * - * - * Sort out where to break the factors in half. I'll choose the midpoint - * of the larger one, since this minimizes the amount of work I have to do - * most effectively. - */ - - if (avl - av > bvl - bv) { - m = (avl - av + 1) >> 1; - avm = av + m; - if (bvl - bv > m) - bvm = bv + m; - else - bvm = bvl; - } else { - m = (bvl - bv + 1) >> 1; - bvm = bv + m; - if (avl - av > m) - avm = av + m; - else - avm = avl; - } - - /* --- Sort out the middle term --- */ - - { - mpw *bsv = sv + m + 1, *ssv = bsv + m + 1; - mpw *rdv = dv + m, *rdvl = rdv + 2 * (m + 2); - - assert(rdvl <= dvl); - assert(ssv <= svl); - UADD2(sv, bsv, av, avm, avm, avl); - UADD2(bsv, ssv, bv, bvm, bvm, bvl); - if (m > MPK_THRESH) - mpx_kmul(rdv, rdvl, sv, bsv, bsv, ssv, ssv, svl); - else - mpx_umul(rdv, rdvl, sv, bsv, bsv, ssv); - } - - /* --- Sort out the other two terms --- */ - - { - mpw *svm = sv + m, *svn = svm + m, *ssv = svn + 4; - mpw *tdv = dv + m; - mpw *rdv = tdv + m; - - if (avl == avm || bvl == bvm) - MPX_ZERO(rdv + m + 1, dvl); - else { - if (m > MPK_THRESH) - mpx_kmul(sv, ssv, avm, avl, bvm, bvl, ssv, svl); - else - mpx_umul(sv, ssv, avm, avl, bvm, bvl); - MPX_COPY(rdv + m + 1, dvl, svm + 1, svn); - UADD(rdv, sv, svm + 1); - USUB(tdv, sv, svn); - } - - if (m > MPK_THRESH) - mpx_kmul(sv, ssv, av, avm, bv, bvm, ssv, svl); - else - mpx_umul(sv, ssv, av, avm, bv, bvm); - MPX_COPY(dv, tdv, sv, svm); - USUB(tdv, sv, svn); - UADD(tdv, svm, svn); - } -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include -#include - -#define ALLOC(v, vl, sz) do { \ - size_t _sz = (sz); \ - mpw *_vv = xmalloc(MPWS(_sz)); \ - mpw *_vvl = _vv + _sz; \ - (v) = _vv; \ - (vl) = _vvl; \ -} while (0) - -#define LOAD(v, vl, d) do { \ - const dstr *_d = (d); \ - mpw *_v, *_vl; \ - ALLOC(_v, _vl, MPW_RQ(_d->len)); \ - mpx_loadb(_v, _vl, _d->buf, _d->len); \ - (v) = _v; \ - (vl) = _vl; \ -} while (0) - -#define MAX(x, y) ((x) > (y) ? (x) : (y)) - -static void dumpmp(const char *msg, const mpw *v, const mpw *vl) -{ - fputs(msg, stderr); - MPX_SHRINK(v, vl); - while (v < vl) - fprintf(stderr, " %08lx", (unsigned long)*--vl); - fputc('\n', stderr); -} - -static int umul(dstr *v) -{ - mpw *a, *al; - mpw *b, *bl; - mpw *c, *cl; - mpw *d, *dl; - mpw *s, *sl; - size_t m; - int ok = 1; - - LOAD(a, al, &v[0]); - LOAD(b, bl, &v[1]); - LOAD(c, cl, &v[2]); - m = MAX(al - a, bl - b) + 1; - ALLOC(d, dl, 3 * m); - ALLOC(s, sl, 5 * m); - - mpx_kmul(d, dl, a, al, b, bl, s, sl); - if (!mpx_ueq(d, dl, c, cl)) { - fprintf(stderr, "\n*** umul failed\n"); - dumpmp(" a", a, al); - dumpmp(" b", b, bl); - dumpmp("expected", c, cl); - dumpmp(" result", d, dl); - ok = 0; - } - - xfree(a); xfree(b); xfree(c); xfree(d); xfree(s); - return (ok); -} - -static test_chunk defs[] = { - { "umul", umul, { &type_hex, &type_hex, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, defs, SRCDIR"/tests/mpx"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpx-ksqr.c b/mpx-ksqr.c deleted file mode 100644 index ba7aa18..0000000 --- a/mpx-ksqr.c +++ /dev/null @@ -1,213 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Karatsuba-based squaring algorithm - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include "mpx.h" -#include "karatsuba.h" - -/*----- Tweakables --------------------------------------------------------*/ - -#ifdef TEST_RIG -# undef MPK_THRESH -# define MPK_THRESH 4 -#endif - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mpx_ksqr@ --- * - * - * Arguments: @mpw *dv, *dvl@ = pointer to destination buffer - * @const mpw *av, *avl@ = pointer to first argument - * @mpw *sv, *svl@ = pointer to scratch workspace - * - * Returns: --- - * - * Use: Squares a multiprecision integers using something similar to - * Karatsuba's multiplication algorithm. This is rather faster - * than traditional long multiplication (e.g., @mpx_umul@) on - * large numbers, although more expensive on small ones, and - * rather simpler than full-blown Karatsuba multiplication. - * - * The destination must be three times as large as the larger - * argument. The scratch space must be five times as large as - * the larger argument. - */ - -void mpx_ksqr(mpw *dv, mpw *dvl, - const mpw *av, const mpw *avl, - mpw *sv, mpw *svl) -{ - const mpw *avm; - size_t m; - - /* --- Dispose of easy cases to @mpx_usqr@ --- * - * - * Karatsuba is only a win on large numbers, because of all the - * recursiveness and bookkeeping. The recursive calls make a quick check - * to see whether to bottom out to @mpx_usqr@ which should help quite a - * lot, but sometimes the only way to know is to make sure... - */ - - MPX_SHRINK(av, avl); - - if (avl - av <= MPK_THRESH) { - mpx_usqr(dv, dvl, av, avl); - return; - } - - /* --- How the algorithm works --- * - * - * The identity for squaring is known to all schoolchildren. - * Let %$A = xb + y$%. Then %$A^2 = x^2 b^2 + 2 x y b + y^2$%. Now, - * %$(x + y)^2 - x^2 - y^2 = 2 x y$%, which means I only need to do three - * squarings. - */ - - /* --- First things --- * - * - * Sort out where to break the factor in half. - */ - - m = (avl - av + 1) >> 1; - avm = av + m; - - /* --- Sort out everything --- */ - - { - mpw *svm = sv + m, *svn = svm + m, *ssv = svn + 4; - mpw *tdv = dv + m; - mpw *rdv = tdv + m; - - assert(rdv + m + 4 < dvl); - assert(ssv < svl); - UADD2(sv, svm, av, avm, avm, avl); - if (m > MPK_THRESH) - mpx_ksqr(tdv, rdv + m + 4, sv, svm + 1, ssv, svl); - else - mpx_usqr(tdv, rdv + m + 4, sv, svm + 1); - - if (m > MPK_THRESH) - mpx_ksqr(sv, ssv, avm, avl, ssv, svl); - else - mpx_usqr(sv, ssv, avm, avl); - MPX_COPY(rdv + m + 1, dvl, svm + 1, svn); - UADD(rdv, sv, svm + 1); - USUB(tdv, sv, svn); - - if (m > MPK_THRESH) - mpx_ksqr(sv, ssv, av, avm, ssv, svl); - else - mpx_usqr(sv, ssv, av, avm); - MPX_COPY(dv, tdv, sv, svm); - UADD(tdv, svm, svn); - USUB(tdv, sv, svn); - } -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include -#include - -#define ALLOC(v, vl, sz) do { \ - size_t _sz = (sz); \ - mpw *_vv = xmalloc(MPWS(_sz)); \ - mpw *_vvl = _vv + _sz; \ - (v) = _vv; \ - (vl) = _vvl; \ -} while (0) - -#define LOAD(v, vl, d) do { \ - const dstr *_d = (d); \ - mpw *_v, *_vl; \ - ALLOC(_v, _vl, MPW_RQ(_d->len)); \ - mpx_loadb(_v, _vl, _d->buf, _d->len); \ - (v) = _v; \ - (vl) = _vl; \ -} while (0) - -#define MAX(x, y) ((x) > (y) ? (x) : (y)) - -static void dumpmp(const char *msg, const mpw *v, const mpw *vl) -{ - fputs(msg, stderr); - MPX_SHRINK(v, vl); - while (v < vl) - fprintf(stderr, " %08lx", (unsigned long)*--vl); - fputc('\n', stderr); -} - -static int usqr(dstr *v) -{ - mpw *a, *al; - mpw *c, *cl; - mpw *d, *dl; - mpw *s, *sl; - size_t m; - int ok = 1; - - LOAD(a, al, &v[0]); - LOAD(c, cl, &v[1]); - m = al - a + 1; - ALLOC(d, dl, 3 * m); - ALLOC(s, sl, 5 * m); - - mpx_ksqr(d, dl, a, al, s, sl); - if (!mpx_ueq(d, dl, c, cl)) { - fprintf(stderr, "\n*** usqr failed\n"); - dumpmp(" a", a, al); - dumpmp("expected", c, cl); - dumpmp(" result", d, dl); - ok = 0; - } - - xfree(a); xfree(c); xfree(d); xfree(s); - return (ok); -} - -static test_chunk defs[] = { - { "usqr", usqr, { &type_hex, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, defs, SRCDIR"/tests/mpx"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpx.c b/mpx.c deleted file mode 100644 index 29e1ded..0000000 --- a/mpx.c +++ /dev/null @@ -1,1739 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Low-level multiprecision arithmetic - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include - -#include "mptypes.h" -#include "mpx.h" -#include "bitops.h" - -/*----- Loading and storing -----------------------------------------------*/ - -/* --- @mpx_storel@ --- * - * - * Arguments: @const mpw *v, *vl@ = base and limit of source vector - * @void *pp@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Stores an MP in an octet array, least significant octet - * first. High-end octets are silently discarded if there - * isn't enough space for them. - */ - -void mpx_storel(const mpw *v, const mpw *vl, void *pp, size_t sz) -{ - mpw n, w = 0; - octet *p = pp, *q = p + sz; - unsigned bits = 0; - - while (p < q) { - if (bits < 8) { - if (v >= vl) { - *p++ = U8(w); - break; - } - n = *v++; - *p++ = U8(w | n << bits); - w = n >> (8 - bits); - bits += MPW_BITS - 8; - } else { - *p++ = U8(w); - w >>= 8; - bits -= 8; - } - } - memset(p, 0, q - p); -} - -/* --- @mpx_loadl@ --- * - * - * Arguments: @mpw *v, *vl@ = base and limit of destination vector - * @const void *pp@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Loads an MP in an octet array, least significant octet - * first. High-end octets are ignored if there isn't enough - * space for them. - */ - -void mpx_loadl(mpw *v, mpw *vl, const void *pp, size_t sz) -{ - unsigned n; - mpw w = 0; - const octet *p = pp, *q = p + sz; - unsigned bits = 0; - - if (v >= vl) - return; - while (p < q) { - n = U8(*p++); - w |= n << bits; - bits += 8; - if (bits >= MPW_BITS) { - *v++ = MPW(w); - w = n >> (MPW_BITS - bits + 8); - bits -= MPW_BITS; - if (v >= vl) - return; - } - } - *v++ = w; - MPX_ZERO(v, vl); -} - -/* --- @mpx_storeb@ --- * - * - * Arguments: @const mpw *v, *vl@ = base and limit of source vector - * @void *pp@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Stores an MP in an octet array, most significant octet - * first. High-end octets are silently discarded if there - * isn't enough space for them. - */ - -void mpx_storeb(const mpw *v, const mpw *vl, void *pp, size_t sz) -{ - mpw n, w = 0; - octet *p = pp, *q = p + sz; - unsigned bits = 0; - - while (q > p) { - if (bits < 8) { - if (v >= vl) { - *--q = U8(w); - break; - } - n = *v++; - *--q = U8(w | n << bits); - w = n >> (8 - bits); - bits += MPW_BITS - 8; - } else { - *--q = U8(w); - w >>= 8; - bits -= 8; - } - } - memset(p, 0, q - p); -} - -/* --- @mpx_loadb@ --- * - * - * Arguments: @mpw *v, *vl@ = base and limit of destination vector - * @const void *pp@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Loads an MP in an octet array, most significant octet - * first. High-end octets are ignored if there isn't enough - * space for them. - */ - -void mpx_loadb(mpw *v, mpw *vl, const void *pp, size_t sz) -{ - unsigned n; - mpw w = 0; - const octet *p = pp, *q = p + sz; - unsigned bits = 0; - - if (v >= vl) - return; - while (q > p) { - n = U8(*--q); - w |= n << bits; - bits += 8; - if (bits >= MPW_BITS) { - *v++ = MPW(w); - w = n >> (MPW_BITS - bits + 8); - bits -= MPW_BITS; - if (v >= vl) - return; - } - } - *v++ = w; - MPX_ZERO(v, vl); -} - -/* --- @mpx_storel2cn@ --- * - * - * Arguments: @const mpw *v, *vl@ = base and limit of source vector - * @void *pp@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Stores a negative MP in an octet array, least significant - * octet first, as two's complement. High-end octets are - * silently discarded if there isn't enough space for them. - * This obviously makes the output bad. - */ - -void mpx_storel2cn(const mpw *v, const mpw *vl, void *pp, size_t sz) -{ - unsigned c = 1; - unsigned b = 0; - mpw n, w = 0; - octet *p = pp, *q = p + sz; - unsigned bits = 0; - - while (p < q) { - if (bits < 8) { - if (v >= vl) { - b = w; - break; - } - n = *v++; - b = w | n << bits; - w = n >> (8 - bits); - bits += MPW_BITS - 8; - } else { - b = w; - w >>= 8; - bits -= 8; - } - b = U8(~b + c); - c = c && !b; - *p++ = b; - } - while (p < q) { - b = U8(~b + c); - c = c && !b; - *p++ = b; - b = 0; - } -} - -/* --- @mpx_loadl2cn@ --- * - * - * Arguments: @mpw *v, *vl@ = base and limit of destination vector - * @const void *pp@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Loads a negative MP in an octet array, least significant - * octet first, as two's complement. High-end octets are - * ignored if there isn't enough space for them. This probably - * means you made the wrong choice coming here. - */ - -void mpx_loadl2cn(mpw *v, mpw *vl, const void *pp, size_t sz) -{ - unsigned n; - unsigned c = 1; - mpw w = 0; - const octet *p = pp, *q = p + sz; - unsigned bits = 0; - - if (v >= vl) - return; - while (p < q) { - n = U8(~(*p++) + c); - c = c && !n; - w |= n << bits; - bits += 8; - if (bits >= MPW_BITS) { - *v++ = MPW(w); - w = n >> (MPW_BITS - bits + 8); - bits -= MPW_BITS; - if (v >= vl) - return; - } - } - *v++ = w; - MPX_ZERO(v, vl); -} - -/* --- @mpx_storeb2cn@ --- * - * - * Arguments: @const mpw *v, *vl@ = base and limit of source vector - * @void *pp@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Stores a negative MP in an octet array, most significant - * octet first, as two's complement. High-end octets are - * silently discarded if there isn't enough space for them, - * which probably isn't what you meant. - */ - -void mpx_storeb2cn(const mpw *v, const mpw *vl, void *pp, size_t sz) -{ - mpw n, w = 0; - unsigned b = 0; - unsigned c = 1; - octet *p = pp, *q = p + sz; - unsigned bits = 0; - - while (q > p) { - if (bits < 8) { - if (v >= vl) { - b = w; - break; - } - n = *v++; - b = w | n << bits; - w = n >> (8 - bits); - bits += MPW_BITS - 8; - } else { - b = w; - w >>= 8; - bits -= 8; - } - b = U8(~b + c); - c = c && !b; - *--q = b; - } - while (q > p) { - b = ~b + c; - c = c && !(b & 0xff); - *--q = b; - b = 0; - } -} - -/* --- @mpx_loadb2cn@ --- * - * - * Arguments: @mpw *v, *vl@ = base and limit of destination vector - * @const void *pp@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Loads a negative MP in an octet array, most significant octet - * first as two's complement. High-end octets are ignored if - * there isn't enough space for them. This probably means you - * chose this function wrongly. - */ - -void mpx_loadb2cn(mpw *v, mpw *vl, const void *pp, size_t sz) -{ - unsigned n; - unsigned c = 1; - mpw w = 0; - const octet *p = pp, *q = p + sz; - unsigned bits = 0; - - if (v >= vl) - return; - while (q > p) { - n = U8(~(*--q) + c); - c = c && !n; - w |= n << bits; - bits += 8; - if (bits >= MPW_BITS) { - *v++ = MPW(w); - w = n >> (MPW_BITS - bits + 8); - bits -= MPW_BITS; - if (v >= vl) - return; - } - } - *v++ = w; - MPX_ZERO(v, vl); -} - -/*----- Logical shifting --------------------------------------------------*/ - -/* --- @mpx_lsl@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = source vector base and limit - * @size_t n@ = number of bit positions to shift by - * - * Returns: --- - * - * Use: Performs a logical shift left operation on an integer. - */ - -void mpx_lsl(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n) -{ - size_t nw; - unsigned nb; - - /* --- Trivial special case --- */ - - if (n == 0) - MPX_COPY(dv, dvl, av, avl); - - /* --- Single bit shifting --- */ - - else if (n == 1) { - mpw w = 0; - while (av < avl) { - mpw t; - if (dv >= dvl) - goto done; - t = *av++; - *dv++ = MPW((t << 1) | w); - w = t >> (MPW_BITS - 1); - } - if (dv >= dvl) - goto done; - *dv++ = MPW(w); - MPX_ZERO(dv, dvl); - goto done; - } - - /* --- Break out word and bit shifts for more sophisticated work --- */ - - nw = n / MPW_BITS; - nb = n % MPW_BITS; - - /* --- Handle a shift by a multiple of the word size --- */ - - if (nb == 0) { - if (nw >= dvl - dv) - MPX_ZERO(dv, dvl); - else { - MPX_COPY(dv + nw, dvl, av, avl); - memset(dv, 0, MPWS(nw)); - } - } - - /* --- And finally the difficult case --- * - * - * This is a little convoluted, because I have to start from the end and - * work backwards to avoid overwriting the source, if they're both the same - * block of memory. - */ - - else { - mpw w; - size_t nr = MPW_BITS - nb; - size_t dvn = dvl - dv; - size_t avn = avl - av; - - if (dvn <= nw) { - MPX_ZERO(dv, dvl); - goto done; - } - - if (dvn > avn + nw) { - size_t off = avn + nw + 1; - MPX_ZERO(dv + off, dvl); - dvl = dv + off; - w = 0; - } else { - avl = av + dvn - nw; - w = *--avl << nb; - } - - while (avl > av) { - mpw t = *--avl; - *--dvl = MPW((t >> nr) | w); - w = t << nb; - } - - *--dvl = MPW(w); - MPX_ZERO(dv, dvl); - } - -done:; -} - -/* --- @mpx_lslc@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = source vector base and limit - * @size_t n@ = number of bit positions to shift by - * - * Returns: --- - * - * Use: Performs a logical shift left operation on an integer, only - * it fills in the bits with ones instead of zeroes. - */ - -void mpx_lslc(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n) -{ - size_t nw; - unsigned nb; - - /* --- Trivial special case --- */ - - if (n == 0) - MPX_COPY(dv, dvl, av, avl); - - /* --- Single bit shifting --- */ - - else if (n == 1) { - mpw w = 1; - while (av < avl) { - mpw t; - if (dv >= dvl) - goto done; - t = *av++; - *dv++ = MPW((t << 1) | w); - w = t >> (MPW_BITS - 1); - } - if (dv >= dvl) - goto done; - *dv++ = MPW(w); - MPX_ZERO(dv, dvl); - goto done; - } - - /* --- Break out word and bit shifts for more sophisticated work --- */ - - nw = n / MPW_BITS; - nb = n % MPW_BITS; - - /* --- Handle a shift by a multiple of the word size --- */ - - if (nb == 0) { - if (nw >= dvl - dv) - MPX_ONE(dv, dvl); - else { - MPX_COPY(dv + nw, dvl, av, avl); - MPX_ONE(dv, dv + nw); - } - } - - /* --- And finally the difficult case --- * - * - * This is a little convoluted, because I have to start from the end and - * work backwards to avoid overwriting the source, if they're both the same - * block of memory. - */ - - else { - mpw w; - size_t nr = MPW_BITS - nb; - size_t dvn = dvl - dv; - size_t avn = avl - av; - - if (dvn <= nw) { - MPX_ONE(dv, dvl); - goto done; - } - - if (dvn > avn + nw) { - size_t off = avn + nw + 1; - MPX_ZERO(dv + off, dvl); - dvl = dv + off; - w = 0; - } else { - avl = av + dvn - nw; - w = *--avl << nb; - } - - while (avl > av) { - mpw t = *--avl; - *--dvl = MPW((t >> nr) | w); - w = t << nb; - } - - *--dvl = MPW((MPW_MAX >> nr) | w); - MPX_ONE(dv, dvl); - } - -done:; -} - -/* --- @mpx_lsr@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = source vector base and limit - * @size_t n@ = number of bit positions to shift by - * - * Returns: --- - * - * Use: Performs a logical shift right operation on an integer. - */ - -void mpx_lsr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n) -{ - size_t nw; - unsigned nb; - - /* --- Trivial special case --- */ - - if (n == 0) - MPX_COPY(dv, dvl, av, avl); - - /* --- Single bit shifting --- */ - - else if (n == 1) { - mpw w = av < avl ? *av++ >> 1 : 0; - while (av < avl) { - mpw t; - if (dv >= dvl) - goto done; - t = *av++; - *dv++ = MPW((t << (MPW_BITS - 1)) | w); - w = t >> 1; - } - if (dv >= dvl) - goto done; - *dv++ = MPW(w); - MPX_ZERO(dv, dvl); - goto done; - } - - /* --- Break out word and bit shifts for more sophisticated work --- */ - - nw = n / MPW_BITS; - nb = n % MPW_BITS; - - /* --- Handle a shift by a multiple of the word size --- */ - - if (nb == 0) { - if (nw >= avl - av) - MPX_ZERO(dv, dvl); - else - MPX_COPY(dv, dvl, av + nw, avl); - } - - /* --- And finally the difficult case --- */ - - else { - mpw w; - size_t nr = MPW_BITS - nb; - - av += nw; - w = av < avl ? *av++ : 0; - while (av < avl) { - mpw t; - if (dv >= dvl) - goto done; - t = *av++; - *dv++ = MPW((w >> nb) | (t << nr)); - w = t; - } - if (dv < dvl) { - *dv++ = MPW(w >> nb); - MPX_ZERO(dv, dvl); - } - } - -done:; -} - -/*----- Bitwise operations ------------------------------------------------*/ - -/* --- @mpx_bitop@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector - * @const mpw *av, *avl@ = first source vector - * @const mpw *bv, *bvl@ = second source vector - * - * Returns: --- - * - * Use; Provides the dyadic boolean functions. - */ - -#define MPX_BITBINOP(string) \ - \ -void mpx_bit##string(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, \ - const mpw *bv, const mpw *bvl) \ -{ \ - MPX_SHRINK(av, avl); \ - MPX_SHRINK(bv, bvl); \ - \ - while (dv < dvl) { \ - mpw a, b; \ - a = (av < avl) ? *av++ : 0; \ - b = (bv < bvl) ? *bv++ : 0; \ - *dv++ = B##string(a, b); \ - } \ -} - -MPX_DOBIN(MPX_BITBINOP) - -void mpx_not(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl) -{ - MPX_SHRINK(av, avl); - - while (dv < dvl) { - mpw a; - a = (av < avl) ? *av++ : 0; - *dv++ = ~a; - } -} - -/*----- Unsigned arithmetic -----------------------------------------------*/ - -/* --- @mpx_2c@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector - * @const mpw *v, *vl@ = source vector - * - * Returns: --- - * - * Use: Calculates the two's complement of @v@. - */ - -void mpx_2c(mpw *dv, mpw *dvl, const mpw *v, const mpw *vl) -{ - mpw c = 0; - while (dv < dvl && v < vl) - *dv++ = c = MPW(~*v++); - if (dv < dvl) { - if (c > MPW_MAX / 2) - c = MPW(~0); - while (dv < dvl) - *dv++ = c; - } - MPX_UADDN(dv, dvl, 1); -} - -/* --- @mpx_ueq@ --- * - * - * Arguments: @const mpw *av, *avl@ = first argument vector base and limit - * @const mpw *bv, *bvl@ = second argument vector base and limit - * - * Returns: Nonzero if the two vectors are equal. - * - * Use: Performs an unsigned integer test for equality. - */ - -int mpx_ueq(const mpw *av, const mpw *avl, const mpw *bv, const mpw *bvl) -{ - MPX_SHRINK(av, avl); - MPX_SHRINK(bv, bvl); - if (avl - av != bvl - bv) - return (0); - while (av < avl) { - if (*av++ != *bv++) - return (0); - } - return (1); -} - -/* --- @mpx_ucmp@ --- * - * - * Arguments: @const mpw *av, *avl@ = first argument vector base and limit - * @const mpw *bv, *bvl@ = second argument vector base and limit - * - * Returns: Less than, equal to, or greater than zero depending on - * whether @a@ is less than, equal to or greater than @b@, - * respectively. - * - * Use: Performs an unsigned integer comparison. - */ - -int mpx_ucmp(const mpw *av, const mpw *avl, const mpw *bv, const mpw *bvl) -{ - MPX_SHRINK(av, avl); - MPX_SHRINK(bv, bvl); - - if (avl - av > bvl - bv) - return (+1); - else if (avl - av < bvl - bv) - return (-1); - else while (avl > av) { - mpw a = *--avl, b = *--bvl; - if (a > b) - return (+1); - else if (a < b) - return (-1); - } - return (0); -} - -/* --- @mpx_uadd@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = first addend vector base and limit - * @const mpw *bv, *bvl@ = second addend vector base and limit - * - * Returns: --- - * - * Use: Performs unsigned integer addition. If the result overflows - * the destination vector, high-order bits are discarded. This - * means that two's complement addition happens more or less for - * free, although that's more a side-effect than anything else. - * The result vector may be equal to either or both source - * vectors, but may not otherwise overlap them. - */ - -void mpx_uadd(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, - const mpw *bv, const mpw *bvl) -{ - mpw c = 0; - - while (av < avl || bv < bvl) { - mpw a, b; - mpd x; - if (dv >= dvl) - return; - a = (av < avl) ? *av++ : 0; - b = (bv < bvl) ? *bv++ : 0; - x = (mpd)a + (mpd)b + c; - *dv++ = MPW(x); - c = x >> MPW_BITS; - } - if (dv < dvl) { - *dv++ = c; - MPX_ZERO(dv, dvl); - } -} - -/* --- @mpx_uaddn@ --- * - * - * Arguments: @mpw *dv, *dvl@ = source and destination base and limit - * @mpw n@ = other addend - * - * Returns: --- - * - * Use: Adds a small integer to a multiprecision number. - */ - -void mpx_uaddn(mpw *dv, mpw *dvl, mpw n) { MPX_UADDN(dv, dvl, n); } - -/* --- @mpx_uaddnlsl@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination and first argument vector - * @mpw a@ = second argument - * @unsigned o@ = offset in bits - * - * Returns: --- - * - * Use: Computes %$d + 2^o a$%. If the result overflows then - * high-order bits are discarded, as usual. We must have - * @0 < o < MPW_BITS@. - */ - -void mpx_uaddnlsl(mpw *dv, mpw *dvl, mpw a, unsigned o) -{ - mpd x = (mpd)a << o; - - while (x && dv < dvl) { - x += *dv; - *dv++ = MPW(x); - x >>= MPW_BITS; - } -} - -/* --- @mpx_usub@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = first argument vector base and limit - * @const mpw *bv, *bvl@ = second argument vector base and limit - * - * Returns: --- - * - * Use: Performs unsigned integer subtraction. If the result - * overflows the destination vector, high-order bits are - * discarded. This means that two's complement subtraction - * happens more or less for free, althuogh that's more a side- - * effect than anything else. The result vector may be equal to - * either or both source vectors, but may not otherwise overlap - * them. - */ - -void mpx_usub(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, - const mpw *bv, const mpw *bvl) -{ - mpw c = 0; - - while (av < avl || bv < bvl) { - mpw a, b; - mpd x; - if (dv >= dvl) - return; - a = (av < avl) ? *av++ : 0; - b = (bv < bvl) ? *bv++ : 0; - x = (mpd)a - (mpd)b - c; - *dv++ = MPW(x); - if (x >> MPW_BITS) - c = 1; - else - c = 0; - } - if (c) - c = MPW_MAX; - while (dv < dvl) - *dv++ = c; -} - -/* --- @mpx_usubn@ --- * - * - * Arguments: @mpw *dv, *dvl@ = source and destination base and limit - * @n@ = subtrahend - * - * Returns: --- - * - * Use: Subtracts a small integer from a multiprecision number. - */ - -void mpx_usubn(mpw *dv, mpw *dvl, mpw n) { MPX_USUBN(dv, dvl, n); } - -/* --- @mpx_uaddnlsl@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination and first argument vector - * @mpw a@ = second argument - * @unsigned o@ = offset in bits - * - * Returns: --- - * - * Use: Computes %$d + 2^o a$%. If the result overflows then - * high-order bits are discarded, as usual. We must have - * @0 < o < MPW_BITS@. - */ - -void mpx_usubnlsl(mpw *dv, mpw *dvl, mpw a, unsigned o) -{ - mpw b = a >> (MPW_BITS - o); - a <<= o; - - if (dv < dvl) { - mpd x = (mpd)*dv - MPW(a); - *dv++ = MPW(x); - if (x >> MPW_BITS) - b++; - MPX_USUBN(dv, dvl, b); - } -} - -/* --- @mpx_umul@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = multiplicand vector base and limit - * @const mpw *bv, *bvl@ = multiplier vector base and limit - * - * Returns: --- - * - * Use: Performs unsigned integer multiplication. If the result - * overflows the desination vector, high-order bits are - * discarded. The result vector may not overlap the argument - * vectors in any way. - */ - -void mpx_umul(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, - const mpw *bv, const mpw *bvl) -{ - /* --- This is probably worthwhile on a multiply --- */ - - MPX_SHRINK(av, avl); - MPX_SHRINK(bv, bvl); - - /* --- Deal with a multiply by zero --- */ - - if (bv == bvl) { - MPX_ZERO(dv, dvl); - return; - } - - /* --- Do the initial multiply and initialize the accumulator --- */ - - MPX_UMULN(dv, dvl, av, avl, *bv++); - - /* --- Do the remaining multiply/accumulates --- */ - - while (dv < dvl && bv < bvl) { - mpw m = *bv++; - mpw c = 0; - const mpw *avv = av; - mpw *dvv = ++dv; - - while (avv < avl) { - mpd x; - if (dvv >= dvl) - goto next; - x = (mpd)*dvv + (mpd)m * (mpd)*avv++ + c; - *dvv++ = MPW(x); - c = x >> MPW_BITS; - } - MPX_UADDN(dvv, dvl, c); - next:; - } -} - -/* --- @mpx_umuln@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = multiplicand vector base and limit - * @mpw m@ = multiplier - * - * Returns: --- - * - * Use: Multiplies a multiprecision integer by a single-word value. - * The destination and source may be equal. The destination - * is completely cleared after use. - */ - -void mpx_umuln(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, mpw m) - { MPX_UMULN(dv, dvl, av, avl, m); } - -/* --- @mpx_umlan@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination/accumulator base and limit - * @const mpw *av, *avl@ = multiplicand vector base and limit - * @mpw m@ = multiplier - * - * Returns: --- - * - * Use: Multiplies a multiprecision integer by a single-word value - * and adds the result to an accumulator. - */ - -void mpx_umlan(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, mpw m) - { MPX_UMLAN(dv, dvl, av, avl, m); } - -/* --- @mpx_usqr@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *av@ = source vector base and limit - * - * Returns: --- - * - * Use: Performs unsigned integer squaring. The result vector must - * not overlap the source vector in any way. - */ - -void mpx_usqr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl) -{ - MPX_ZERO(dv, dvl); - - /* --- Main loop --- */ - - while (av < avl) { - const mpw *avv = av; - mpw *dvv = dv; - mpw a = *av; - mpd c; - - /* --- Stop if I've run out of destination --- */ - - if (dvv >= dvl) - break; - - /* --- Work out the square at this point in the proceedings --- */ - - { - mpd x = (mpd)a * (mpd)a + *dvv; - *dvv++ = MPW(x); - c = MPW(x >> MPW_BITS); - } - - /* --- Now fix up the rest of the vector upwards --- */ - - avv++; - while (dvv < dvl && avv < avl) { - mpd x = (mpd)a * (mpd)*avv++; - mpd y = ((x << 1) & MPW_MAX) + c + *dvv; - c = (x >> (MPW_BITS - 1)) + (y >> MPW_BITS); - *dvv++ = MPW(y); - } - while (dvv < dvl && c) { - mpd x = c + *dvv; - *dvv++ = MPW(x); - c = x >> MPW_BITS; - } - - /* --- Get ready for the next round --- */ - - av++; - dv += 2; - } -} - -/* --- @mpx_udiv@ --- * - * - * Arguments: @mpw *qv, *qvl@ = quotient vector base and limit - * @mpw *rv, *rvl@ = dividend/remainder vector base and limit - * @const mpw *dv, *dvl@ = divisor vector base and limit - * @mpw *sv, *svl@ = scratch workspace - * - * Returns: --- - * - * Use: Performs unsigned integer division. If the result overflows - * the quotient vector, high-order bits are discarded. (Clearly - * the remainder vector can't overflow.) The various vectors - * may not overlap in any way. Yes, I know it's a bit odd - * requiring the dividend to be in the result position but it - * does make some sense really. The remainder must have - * headroom for at least two extra words. The scratch space - * must be at least one word larger than the divisor. - */ - -void mpx_udiv(mpw *qv, mpw *qvl, mpw *rv, mpw *rvl, - const mpw *dv, const mpw *dvl, - mpw *sv, mpw *svl) -{ - unsigned norm = 0; - size_t scale; - mpw d, dd; - - /* --- Initialize the quotient --- */ - - MPX_ZERO(qv, qvl); - - /* --- Perform some sanity checks --- */ - - MPX_SHRINK(dv, dvl); - assert(((void)"division by zero in mpx_udiv", dv < dvl)); - - /* --- Normalize the divisor --- * - * - * The algorithm requires that the divisor be at least two digits long. - * This is easy to fix. - */ - - { - unsigned b; - - d = dvl[-1]; - for (b = MPW_P2; b; b >>= 1) { - if (d <= (MPW_MAX >> b)) { - d <<= b; - norm += b; - } - } - if (dv + 1 == dvl) - norm += MPW_BITS; - } - - /* --- Normalize the dividend/remainder to match --- */ - - if (norm) { - mpx_lsl(rv, rvl, rv, rvl, norm); - mpx_lsl(sv, svl, dv, dvl, norm); - dv = sv; - dvl = svl; - MPX_SHRINK(dv, dvl); - } - - MPX_SHRINK(rv, rvl); - d = dvl[-1]; - dd = dvl[-2]; - - /* --- Work out the relative scales --- */ - - { - size_t rvn = rvl - rv; - size_t dvn = dvl - dv; - - /* --- If the divisor is clearly larger, notice this --- */ - - if (dvn > rvn) { - mpx_lsr(rv, rvl, rv, rvl, norm); - return; - } - - scale = rvn - dvn; - } - - /* --- Calculate the most significant quotient digit --- * - * - * Because the divisor has its top bit set, this can only happen once. The - * pointer arithmetic is a little contorted, to make sure that the - * behaviour is defined. - */ - - if (MPX_UCMP(rv + scale, rvl, >=, dv, dvl)) { - mpx_usub(rv + scale, rvl, rv + scale, rvl, dv, dvl); - if (qvl - qv > scale) - qv[scale] = 1; - } - - /* --- Now for the main loop --- */ - - { - mpw *rvv = rvl - 2; - - while (scale) { - mpw q; - mpd rh; - - /* --- Get an estimate for the next quotient digit --- */ - - mpw r = rvv[1]; - mpw rr = rvv[0]; - mpw rrr = *--rvv; - - scale--; - rh = ((mpd)r << MPW_BITS) | rr; - if (r == d) - q = MPW_MAX; - else - q = MPW(rh / d); - - /* --- Refine the estimate --- */ - - { - mpd yh = (mpd)d * q; - mpd yy = (mpd)dd * q; - mpw yl; - - if (yy > MPW_MAX) - yh += yy >> MPW_BITS; - yl = MPW(yy); - - while (yh > rh || (yh == rh && yl > rrr)) { - q--; - yh -= d; - if (yl < dd) - yh--; - yl = MPW(yl - dd); - } - } - - /* --- Remove a chunk from the dividend --- */ - - { - mpw *svv; - const mpw *dvv; - mpw mc = 0, sc = 0; - - /* --- Calculate the size of the chunk --- * - * - * This does the whole job of calculating @r >> scale - qd@. - */ - - for (svv = rv + scale, dvv = dv; - dvv < dvl && svv < rvl; - svv++, dvv++) { - mpd x = (mpd)*dvv * (mpd)q + mc; - mc = x >> MPW_BITS; - x = (mpd)*svv - MPW(x) - sc; - *svv = MPW(x); - if (x >> MPW_BITS) - sc = 1; - else - sc = 0; - } - - if (svv < rvl) { - mpd x = (mpd)*svv - mc - sc; - *svv++ = MPW(x); - if (x >> MPW_BITS) - sc = MPW_MAX; - else - sc = 0; - while (svv < rvl) - *svv++ = sc; - } - - /* --- Fix if the quotient was too large --- * - * - * This doesn't seem to happen very often. - */ - - if (rvl[-1] > MPW_MAX / 2) { - mpx_uadd(rv + scale, rvl, rv + scale, rvl, dv, dvl); - q--; - } - } - - /* --- Done for another iteration --- */ - - if (qvl - qv > scale) - qv[scale] = q; - r = rr; - rr = rrr; - } - } - - /* --- Now fiddle with unnormalizing and things --- */ - - mpx_lsr(rv, rvl, rv, rvl, norm); -} - -/* --- @mpx_udivn@ --- * - * - * Arguments: @mpw *qv, *qvl@ = storage for the quotient (may overlap - * dividend) - * @const mpw *rv, *rvl@ = dividend - * @mpw d@ = single-precision divisor - * - * Returns: Remainder after divison. - * - * Use: Performs a single-precision division operation. - */ - -mpw mpx_udivn(mpw *qv, mpw *qvl, const mpw *rv, const mpw *rvl, mpw d) -{ - size_t i; - size_t ql = qvl - qv; - mpd r = 0; - - i = rvl - rv; - while (i > 0) { - i--; - r = (r << MPW_BITS) | rv[i]; - if (i < ql) - qv[i] = r / d; - r %= d; - } - return (MPW(r)); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include -#include -#include -#include - -#include "mpscan.h" - -#define ALLOC(v, vl, sz) do { \ - size_t _sz = (sz); \ - mpw *_vv = xmalloc(MPWS(_sz)); \ - mpw *_vvl = _vv + _sz; \ - (v) = _vv; \ - (vl) = _vvl; \ -} while (0) - -#define LOAD(v, vl, d) do { \ - const dstr *_d = (d); \ - mpw *_v, *_vl; \ - ALLOC(_v, _vl, MPW_RQ(_d->len)); \ - mpx_loadb(_v, _vl, _d->buf, _d->len); \ - (v) = _v; \ - (vl) = _vl; \ -} while (0) - -#define MAX(x, y) ((x) > (y) ? (x) : (y)) - -static void dumpbits(const char *msg, const void *pp, size_t sz) -{ - const octet *p = pp; - fputs(msg, stderr); - for (; sz; sz--) - fprintf(stderr, " %02x", *p++); - fputc('\n', stderr); -} - -static void dumpmp(const char *msg, const mpw *v, const mpw *vl) -{ - fputs(msg, stderr); - MPX_SHRINK(v, vl); - while (v < vl) - fprintf(stderr, " %08lx", (unsigned long)*--vl); - fputc('\n', stderr); -} - -static int chkscan(const mpw *v, const mpw *vl, - const void *pp, size_t sz, int step) -{ - mpscan mps; - const octet *p = pp; - unsigned bit = 0; - int ok = 1; - - mpscan_initx(&mps, v, vl); - while (sz) { - unsigned x = *p; - int i; - p += step; - for (i = 0; i < 8 && MPSCAN_STEP(&mps); i++) { - if (MPSCAN_BIT(&mps) != (x & 1)) { - fprintf(stderr, - "\n*** error, step %i, bit %u, expected %u, found %u\n", - step, bit, x & 1, MPSCAN_BIT(&mps)); - ok = 0; - } - x >>= 1; - bit++; - } - sz--; - } - - return (ok); -} - -static int loadstore(dstr *v) -{ - dstr d = DSTR_INIT; - size_t sz = MPW_RQ(v->len) * 2, diff; - mpw *m, *ml; - int ok = 1; - - dstr_ensure(&d, v->len); - m = xmalloc(MPWS(sz)); - - for (diff = 0; diff < sz; diff += 5) { - size_t oct; - - ml = m + sz - diff; - - mpx_loadl(m, ml, v->buf, v->len); - if (!chkscan(m, ml, v->buf, v->len, +1)) - ok = 0; - MPX_OCTETS(oct, m, ml); - mpx_storel(m, ml, d.buf, d.sz); - if (memcmp(d.buf, v->buf, oct) != 0) { - dumpbits("\n*** storel failed", d.buf, d.sz); - ok = 0; - } - - mpx_loadb(m, ml, v->buf, v->len); - if (!chkscan(m, ml, v->buf + v->len - 1, v->len, -1)) - ok = 0; - MPX_OCTETS(oct, m, ml); - mpx_storeb(m, ml, d.buf, d.sz); - if (memcmp(d.buf + d.sz - oct, v->buf + v->len - oct, oct) != 0) { - dumpbits("\n*** storeb failed", d.buf, d.sz); - ok = 0; - } - } - - if (!ok) - dumpbits("input data", v->buf, v->len); - - xfree(m); - dstr_destroy(&d); - return (ok); -} - -static int twocl(dstr *v) -{ - dstr d = DSTR_INIT; - mpw *m, *ml; - size_t sz; - int ok = 1; - - sz = v[0].len; if (v[1].len > sz) sz = v[1].len; - dstr_ensure(&d, sz); - - sz = MPW_RQ(sz); - m = xmalloc(MPWS(sz)); - ml = m + sz; - - mpx_loadl(m, ml, v[0].buf, v[0].len); - mpx_storel2cn(m, ml, d.buf, v[1].len); - if (memcmp(d.buf, v[1].buf, v[1].len)) { - dumpbits("\n*** storel2cn failed", d.buf, v[1].len); - ok = 0; - } - - mpx_loadl2cn(m, ml, v[1].buf, v[1].len); - mpx_storel(m, ml, d.buf, v[0].len); - if (memcmp(d.buf, v[0].buf, v[0].len)) { - dumpbits("\n*** loadl2cn failed", d.buf, v[0].len); - ok = 0; - } - - if (!ok) { - dumpbits("pos", v[0].buf, v[0].len); - dumpbits("neg", v[1].buf, v[1].len); - } - - xfree(m); - dstr_destroy(&d); - - return (ok); -} - -static int twocb(dstr *v) -{ - dstr d = DSTR_INIT; - mpw *m, *ml; - size_t sz; - int ok = 1; - - sz = v[0].len; if (v[1].len > sz) sz = v[1].len; - dstr_ensure(&d, sz); - - sz = MPW_RQ(sz); - m = xmalloc(MPWS(sz)); - ml = m + sz; - - mpx_loadb(m, ml, v[0].buf, v[0].len); - mpx_storeb2cn(m, ml, d.buf, v[1].len); - if (memcmp(d.buf, v[1].buf, v[1].len)) { - dumpbits("\n*** storeb2cn failed", d.buf, v[1].len); - ok = 0; - } - - mpx_loadb2cn(m, ml, v[1].buf, v[1].len); - mpx_storeb(m, ml, d.buf, v[0].len); - if (memcmp(d.buf, v[0].buf, v[0].len)) { - dumpbits("\n*** loadb2cn failed", d.buf, v[0].len); - ok = 0; - } - - if (!ok) { - dumpbits("pos", v[0].buf, v[0].len); - dumpbits("neg", v[1].buf, v[1].len); - } - - xfree(m); - dstr_destroy(&d); - - return (ok); -} - -static int lsl(dstr *v) -{ - mpw *a, *al; - int n = *(int *)v[1].buf; - mpw *c, *cl; - mpw *d, *dl; - int ok = 1; - - LOAD(a, al, &v[0]); - LOAD(c, cl, &v[2]); - ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS); - - mpx_lsl(d, dl, a, al, n); - if (!mpx_ueq(d, dl, c, cl)) { - fprintf(stderr, "\n*** lsl(%i) failed\n", n); - dumpmp(" a", a, al); - dumpmp("expected", c, cl); - dumpmp(" result", d, dl); - ok = 0; - } - - xfree(a); xfree(c); xfree(d); - return (ok); -} - -static int lslc(dstr *v) -{ - mpw *a, *al; - int n = *(int *)v[1].buf; - mpw *c, *cl; - mpw *d, *dl; - int ok = 1; - - LOAD(a, al, &v[0]); - LOAD(c, cl, &v[2]); - ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS); - - mpx_lslc(d, dl, a, al, n); - if (!mpx_ueq(d, dl, c, cl)) { - fprintf(stderr, "\n*** lslc(%i) failed\n", n); - dumpmp(" a", a, al); - dumpmp("expected", c, cl); - dumpmp(" result", d, dl); - ok = 0; - } - - xfree(a); xfree(c); xfree(d); - return (ok); -} - -static int lsr(dstr *v) -{ - mpw *a, *al; - int n = *(int *)v[1].buf; - mpw *c, *cl; - mpw *d, *dl; - int ok = 1; - - LOAD(a, al, &v[0]); - LOAD(c, cl, &v[2]); - ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS + 1); - - mpx_lsr(d, dl, a, al, n); - if (!mpx_ueq(d, dl, c, cl)) { - fprintf(stderr, "\n*** lsr(%i) failed\n", n); - dumpmp(" a", a, al); - dumpmp("expected", c, cl); - dumpmp(" result", d, dl); - ok = 0; - } - - xfree(a); xfree(c); xfree(d); - return (ok); -} - -static int uadd(dstr *v) -{ - mpw *a, *al; - mpw *b, *bl; - mpw *c, *cl; - mpw *d, *dl; - int ok = 1; - - LOAD(a, al, &v[0]); - LOAD(b, bl, &v[1]); - LOAD(c, cl, &v[2]); - ALLOC(d, dl, MAX(al - a, bl - b) + 1); - - mpx_uadd(d, dl, a, al, b, bl); - if (!mpx_ueq(d, dl, c, cl)) { - fprintf(stderr, "\n*** uadd failed\n"); - dumpmp(" a", a, al); - dumpmp(" b", b, bl); - dumpmp("expected", c, cl); - dumpmp(" result", d, dl); - ok = 0; - } - - xfree(a); xfree(b); xfree(c); xfree(d); - return (ok); -} - -static int usub(dstr *v) -{ - mpw *a, *al; - mpw *b, *bl; - mpw *c, *cl; - mpw *d, *dl; - int ok = 1; - - LOAD(a, al, &v[0]); - LOAD(b, bl, &v[1]); - LOAD(c, cl, &v[2]); - ALLOC(d, dl, al - a); - - mpx_usub(d, dl, a, al, b, bl); - if (!mpx_ueq(d, dl, c, cl)) { - fprintf(stderr, "\n*** usub failed\n"); - dumpmp(" a", a, al); - dumpmp(" b", b, bl); - dumpmp("expected", c, cl); - dumpmp(" result", d, dl); - ok = 0; - } - - xfree(a); xfree(b); xfree(c); xfree(d); - return (ok); -} - -static int umul(dstr *v) -{ - mpw *a, *al; - mpw *b, *bl; - mpw *c, *cl; - mpw *d, *dl; - int ok = 1; - - LOAD(a, al, &v[0]); - LOAD(b, bl, &v[1]); - LOAD(c, cl, &v[2]); - ALLOC(d, dl, (al - a) + (bl - b)); - - mpx_umul(d, dl, a, al, b, bl); - if (!mpx_ueq(d, dl, c, cl)) { - fprintf(stderr, "\n*** umul failed\n"); - dumpmp(" a", a, al); - dumpmp(" b", b, bl); - dumpmp("expected", c, cl); - dumpmp(" result", d, dl); - ok = 0; - } - - xfree(a); xfree(b); xfree(c); xfree(d); - return (ok); -} - -static int usqr(dstr *v) -{ - mpw *a, *al; - mpw *c, *cl; - mpw *d, *dl; - int ok = 1; - - LOAD(a, al, &v[0]); - LOAD(c, cl, &v[1]); - ALLOC(d, dl, 2 * (al - a)); - - mpx_usqr(d, dl, a, al); - if (!mpx_ueq(d, dl, c, cl)) { - fprintf(stderr, "\n*** usqr failed\n"); - dumpmp(" a", a, al); - dumpmp("expected", c, cl); - dumpmp(" result", d, dl); - ok = 0; - } - - xfree(a); xfree(c); xfree(d); - return (ok); -} - -static int udiv(dstr *v) -{ - mpw *a, *al; - mpw *b, *bl; - mpw *q, *ql; - mpw *r, *rl; - mpw *qq, *qql; - mpw *s, *sl; - int ok = 1; - - ALLOC(a, al, MPW_RQ(v[0].len) + 2); mpx_loadb(a, al, v[0].buf, v[0].len); - LOAD(b, bl, &v[1]); - LOAD(q, ql, &v[2]); - LOAD(r, rl, &v[3]); - ALLOC(qq, qql, al - a); - ALLOC(s, sl, (bl - b) + 1); - - mpx_udiv(qq, qql, a, al, b, bl, s, sl); - if (!mpx_ueq(qq, qql, q, ql) || - !mpx_ueq(a, al, r, rl)) { - fprintf(stderr, "\n*** udiv failed\n"); - dumpmp(" divisor", b, bl); - dumpmp("expect r", r, rl); - dumpmp("result r", a, al); - dumpmp("expect q", q, ql); - dumpmp("result q", qq, qql); - ok = 0; - } - - xfree(a); xfree(b); xfree(r); xfree(q); xfree(s); xfree(qq); - return (ok); -} - -static test_chunk defs[] = { - { "load-store", loadstore, { &type_hex, 0 } }, - { "2cl", twocl, { &type_hex, &type_hex, } }, - { "2cb", twocb, { &type_hex, &type_hex, } }, - { "lsl", lsl, { &type_hex, &type_int, &type_hex, 0 } }, - { "lslc", lslc, { &type_hex, &type_int, &type_hex, 0 } }, - { "lsr", lsr, { &type_hex, &type_int, &type_hex, 0 } }, - { "uadd", uadd, { &type_hex, &type_hex, &type_hex, 0 } }, - { "usub", usub, { &type_hex, &type_hex, &type_hex, 0 } }, - { "umul", umul, { &type_hex, &type_hex, &type_hex, 0 } }, - { "usqr", usqr, { &type_hex, &type_hex, 0 } }, - { "udiv", udiv, { &type_hex, &type_hex, &type_hex, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, defs, SRCDIR"/tests/mpx"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/mpx.h b/mpx.h deleted file mode 100644 index 19f5cc7..0000000 --- a/mpx.h +++ /dev/null @@ -1,791 +0,0 @@ -/* -*-c-*- - * - * $Id: mpx.h,v 1.18 2004/04/08 01:36:15 mdw Exp $ - * - * Low level multiprecision arithmetic - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_MPX_H -#define CATACOMB_MPX_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- The idea ----------------------------------------------------------* - * - * This file provides functions and macros which work on vectors of words as - * unsigned multiprecision integers. The interface works in terms of base - * and limit pointers (i.e., a pointer to the start of a vector, and a - * pointer just past its end) rather than base pointer and length, because - * that requires more arithmetic and state to work on. - * - * The interfaces are slightly bizarre in other ways. Try to use the - * higher-level functions where you can: they're rather better designed to - * actually be friendly and useful. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_MPW_H -# include "mpw.h" -#endif - -/*----- General manipulation ----------------------------------------------*/ - -/* --- @MPX_SHRINK@ --- * - * - * Arguments: @const mpw *v@ = pointer to vector of words - * @const mpw *vl@ = (updated) current limit of vector - * - * Use: Shrinks down the limit of a multiprecision integer vector. - */ - -#define MPX_SHRINK(v, vl) do { \ - const mpw *_vv = (v), *_vvl = (vl); \ - while (_vvl > _vv && !_vvl[-1]) \ - _vvl--; \ - (vl) = (mpw *)_vvl; \ -} while (0) - -/* --- @MPX_BITS@ --- * - * - * Arguments: @unsigned long b@ = result variable - * @const mpw *v@ = pointer to array of words - * @const mpw *vl@ = limit of vector (from @MPX_SHRINK@) - * - * Use: Calculates the number of bits in a multiprecision value. - */ - -#define MPX_BITS(b, v, vl) do { \ - const mpw *_v = (v), *_vl = (vl); \ - MPX_SHRINK(_v, _vl); \ - if (_v == _vl) \ - (b) = 0; \ - else { \ - unsigned long _b = MPW_BITS * (_vl - _v - 1) + 1; \ - mpw _w = _vl[-1]; \ - unsigned _k = MPW_P2; \ - while (_k) { \ - if (_w >> _k) { \ - _w >>= _k; \ - _b += _k; \ - } \ - _k >>= 1; \ - } \ - (b) = _b; \ - } \ -} while (0) - -/* --- @MPX_OCTETS@ --- * - * - * Arguments: @size_t o@ = result variable - * @const mpw *v, *vl@ = pointer to array of words - * - * Use: Calculates the number of octets in a multiprecision value. - */ - -#define MPX_OCTETS(o, v, vl) do { \ - unsigned long _bb; \ - MPX_BITS(_bb, (v), (vl)); \ - (o) = (_bb + 7) >> 3; \ -} while (0) - -/* --- @MPX_OCTETS2C@ --- * - * - * Arguments: @size_t o@ = result variable - * @const mpw *v, *vl@ = pointer to array of words - * - * Use: Calculates the number of octets in a multiprecision value, if - * you represent it as two's complement. - */ - -#define MPX_OCTETS2C(o, v, vl) do { \ - unsigned long _bb; \ - MPX_BITS(_bb, (v), (vl)); \ - (o) = (_bb >> 3) + 1; \ -} while (0) - -/* --- @MPX_COPY@ --- * - * - * Arguments: @dv, dvl@ = destination vector base and limit - * @av, avl@ = source vector base and limit - * - * Use: Copies a multiprecision integer. - */ - -#define MPX_COPY(dv, dvl, av, avl) do { \ - mpw *_dv = (dv), *_dvl = (dvl); \ - size_t _dn = _dvl - _dv; \ - const mpw *_av = (av), *_avl = (avl); \ - size_t _an = _avl - _av; \ - if (_av == _dv) { \ - if (_dvl > _avl) \ - memset(_dv, 0, MPWS(_dn - _an)); \ - } else if (_an >= _dn) \ - memmove(_dv, _av, MPWS(_dn)); \ - else { \ - memmove(_dv, _av, MPWS(_an)); \ - memset(_dv + _an, 0, MPWS(_dn - _an)); \ - } \ -} while (0) - -/* --- @MPX_ZERO@ --- * - * - * Arguments: @v, vl@ = base and limit of vector to clear - * - * Use: Zeroes the area between the two vector pointers. - */ - -#define MPX_ZERO(v, vl) do { \ - mpw *_v = (v), *_vl = (vl); \ - if (_v < _vl) \ - memset(_v, 0, MPWS(_vl - _v)); \ -} while (0) - -/* --- @MPX_ONE@ --- * - * - * Arguments: @v, vl@ = base and limit of vector to clear - * - * Use: Fills the area between the two vector pointers with ones. - */ - -#define MPX_ONE(v, vl) do { \ - mpw * _v = (v); \ - const mpw *_vl = (vl); \ - while (_v < _vl) \ - *_v++ = MPW_MAX; \ -} while (0) - -/*----- Loading and storing -----------------------------------------------*/ - -/* --- @mpx_storel@ --- * - * - * Arguments: @const mpw *v, *vl@ = base and limit of source vector - * @void *p@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Stores an MP in an octet array, least significant octet - * first. High-end octets are silently discarded if there - * isn't enough space for them. - */ - -extern void mpx_storel(const mpw */*v*/, const mpw */*vl*/, - void */*p*/, size_t /*sz*/); - -/* --- @mpx_loadl@ --- * - * - * Arguments: @mpw *v, *vl@ = base and limit of destination vector - * @const void *p@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Loads an MP in an octet array, least significant octet - * first. High-end octets are ignored if there isn't enough - * space for them. - */ - -extern void mpx_loadl(mpw */*v*/, mpw */*vl*/, - const void */*p*/, size_t /*sz*/); - -/* --- @mpx_storeb@ --- * - * - * Arguments: @const mpw *v, *vl@ = base and limit of source vector - * @void *p@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Stores an MP in an octet array, most significant octet - * first. High-end octets are silently discarded if there - * isn't enough space for them. - */ - -extern void mpx_storeb(const mpw */*v*/, const mpw */*vl*/, - void */*p*/, size_t /*sz*/); - -/* --- @mpx_loadb@ --- * - * - * Arguments: @mpw *v, *vl@ = base and limit of destination vector - * @const void *p@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Loads an MP in an octet array, most significant octet - * first. High-end octets are ignored if there isn't enough - * space for them. - */ - -extern void mpx_loadb(mpw */*v*/, mpw */*vl*/, - const void */*p*/, size_t /*sz*/); - -/* --- @mpx_storel2cn@ --- * - * - * Arguments: @const mpw *v, *vl@ = base and limit of source vector - * @void *pp@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Stores a negative MP in an octet array, least significant - * octet first, as two's complement. High-end octets are - * silently discarded if there isn't enough space for them. - * This obviously makes the output bad. - */ - -extern void mpx_storel2cn(const mpw */*v*/, const mpw */*vl*/, - void */*p*/, size_t /*sz*/); - -/* --- @mpx_loadl2cn@ --- * - * - * Arguments: @mpw *v, *vl@ = base and limit of destination vector - * @const void *pp@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Loads a negative MP in an octet array, least significant - * octet first, as two's complement. High-end octets are - * ignored if there isn't enough space for them. This probably - * means you made the wrong choice coming here. - */ - -extern void mpx_loadl2cn(mpw */*v*/, mpw */*vl*/, - const void */*p*/, size_t /*sz*/); - -/* --- @mpx_storeb2cn@ --- * - * - * Arguments: @const mpw *v, *vl@ = base and limit of source vector - * @void *pp@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Stores a negative MP in an octet array, most significant - * octet first, as two's complement. High-end octets are - * silently discarded if there isn't enough space for them, - * which probably isn't what you meant. - */ - -extern void mpx_storeb2cn(const mpw */*v*/, const mpw */*vl*/, - void */*p*/, size_t /*sz*/); - -/* --- @mpx_loadb2cn@ --- * - * - * Arguments: @mpw *v, *vl@ = base and limit of destination vector - * @const void *pp@ = pointer to octet array - * @size_t sz@ = size of octet array - * - * Returns: --- - * - * Use: Loads a negative MP in an octet array, most significant octet - * first as two's complement. High-end octets are ignored if - * there isn't enough space for them. This probably means you - * chose this function wrongly. - */ - -extern void mpx_loadb2cn(mpw */*v*/, mpw */*vl*/, - const void */*p*/, size_t /*sz*/); - - -/*----- Logical shifting --------------------------------------------------*/ - -/* --- @mpx_lsl@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = source vector base and limit - * @size_t n@ = number of bit positions to shift by - * - * Returns: --- - * - * Use: Performs a logical shift left operation on an integer. - */ - -extern void mpx_lsl(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, - size_t /*n*/); - -/* --- @mpx_lslc@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = source vector base and limit - * @size_t n@ = number of bit positions to shift by - * - * Returns: --- - * - * Use: Performs a logical shift left operation on an integer, only - * it fills in the bits with ones instead of zeroes. - */ - -extern void mpx_lslc(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, - size_t /*n*/); - -/* --- @mpx_lsr@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = source vector base and limit - * @size_t n@ = number of bit positions to shift by - * - * Returns: --- - * - * Use: Performs a logical shift right operation on an integer. - */ - -extern void mpx_lsr(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, - size_t /*n*/); - -/*----- Bitwise operations ------------------------------------------------*/ - -/* --- @mpx_bitop@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector - * @const mpw *av, *avl@ = first source vector - * @const mpw *bv, *bvl@ = second source vector - * - * Returns: --- - * - * Use: Provide the dyadic boolean functions. The functions are - * named after the truth table they generate: - * - * a: 0011 - * b: 0101 - * @mpx_bitXXXX@ - */ - -#define MPX_DOBIN(what) \ - what(0000) what(0001) what(0010) what(0011) \ - what(0100) what(0101) what(0110) what(0111) \ - what(1000) what(1001) what(1010) what(1011) \ - what(1100) what(1101) what(1110) what(1111) - -#define MPX_BITDECL(string) \ - extern void mpx_bit##string(mpw */*dv*/, mpw */*dvl*/, \ - const mpw */*av*/, const mpw */*avl*/, \ - const mpw */*bv*/, const mpw */*bvl*/); -MPX_DOBIN(MPX_BITDECL) - -/* --- @mpx_[n]and@, @mpx_[n]or@, @mpx_xor@ --- * - * - * Synonyms for the commonly-used functions above. - */ - -#define mpx_and mpx_bit0001 -#define mpx_or mpx_bit0111 -#define mpx_nand mpx_bit1110 -#define mpx_nor mpx_bit1000 -#define mpx_xor mpx_bit0110 - -/* --- @mpx_not@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector - * @const mpw *av, *avl@ = first source vector - * - * Returns: --- - * - * Use; Bitwise NOT. - */ - -extern void mpx_not(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/); - -/*----- Unsigned arithmetic -----------------------------------------------*/ - -/* --- @mpx_2c@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector - * @const mpw *v, *vl@ = source vector - * - * Returns: --- - * - * Use: Calculates the two's complement of @v@. - */ - -extern void mpx_2c(mpw */*dv*/, mpw */*dvl*/, - const mpw */*v*/, const mpw */*vl*/); - -/* --- @mpx_ueq@ --- * - * - * Arguments: @const mpw *av, *avl@ = first argument vector base and limit - * @const mpw *bv, *bvl@ = second argument vector base and limit - * - * Returns: Nonzero if the two vectors are equal. - * - * Use: Performs an unsigned integer test for equality. - */ - -extern int mpx_ueq(const mpw */*av*/, const mpw */*avl*/, - const mpw */*bv*/, const mpw */*bvl*/); - -/* --- @mpx_ucmp@ --- * - * - * Arguments: @const mpw *av, *avl@ = first argument vector base and limit - * @const mpw *bv, *bvl@ = second argument vector base and limit - * - * Returns: Less than, equal to, or greater than zero depending on - * whether @a@ is less than, equal to or greater than @b@, - * respectively. - * - * Use: Performs an unsigned integer comparison. - */ - -#define MPX_UCMP(av, avl, op, dv, dvl) \ - (mpx_ucmp((av), (avl), (dv), (dvl)) op 0) - -extern int mpx_ucmp(const mpw */*av*/, const mpw */*avl*/, - const mpw */*bv*/, const mpw */*bvl*/); - -/* --- @mpx_uadd@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = first addend vector base and limit - * @const mpw *bv, *bvl@ = second addend vector base and limit - * - * Returns: --- - * - * Use: Performs unsigned integer addition. If the result overflows - * the destination vector, high-order bits are discarded. This - * means that two's complement addition happens more or less for - * free, although that's more a side-effect than anything else. - * The result vector may be equal to either or both source - * vectors, but may not otherwise overlap them. - */ - -extern void mpx_uadd(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, - const mpw */*bv*/, const mpw */*bvl*/); - -/* --- @mpx_uaddn@ --- * - * - * Arguments: @mpw *dv, *dvl@ = source and destination base and limit - * @mpw n@ = other addend - * - * Returns: --- - * - * Use: Adds a small integer to a multiprecision number. - */ - -#define MPX_UADDN(dv, dvl, n) do { \ - mpw *_ddv = (dv), *_ddvl = (dvl); \ - mpw _c = (n); \ - \ - while (_c && _ddv < _ddvl) { \ - mpd _x = (mpd)*_ddv + (mpd)_c; \ - *_ddv++ = MPW(_x); \ - _c = _x >> MPW_BITS; \ - } \ -} while (0) - -extern void mpx_uaddn(mpw */*dv*/, mpw */*dvl*/, mpw /*n*/); - -/* --- @mpx_uaddnlsl@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination and first argument vector - * @mpw a@ = second argument - * @unsigned o@ = offset in bits - * - * Returns: --- - * - * Use: Computes %$d + 2^o a$%. If the result overflows then - * high-order bits are discarded, as usual. We must have - * @0 < o < MPW_BITS@. - */ - -extern void mpx_uaddnlsl(mpw */*dv*/, mpw */*dvl*/, - mpw /*a*/, unsigned /*o*/); - -/* --- @mpx_usub@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = first argument vector base and limit - * @const mpw *bv, *bvl@ = second argument vector base and limit - * - * Returns: --- - * - * Use: Performs unsigned integer subtraction. If the result - * overflows the destination vector, high-order bits are - * discarded. This means that two's complement subtraction - * happens more or less for free, although that's more a side- - * effect than anything else. The result vector may be equal to - * either or both source vectors, but may not otherwise overlap - * them. - */ - -extern void mpx_usub(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, - const mpw */*bv*/, const mpw */*bvl*/); - -/* --- @mpx_usubn@ --- * - * - * Arguments: @mpw *dv, *dvl@ = source and destination base and limit - * @n@ = subtrahend - * - * Returns: --- - * - * Use: Subtracts a small integer from a multiprecision number. - */ - -#define MPX_USUBN(dv, dvl, n) do { \ - mpw *_ddv = (dv), *_ddvl = (dvl); \ - mpw _c = (n); \ - \ - while (_ddv < _ddvl) { \ - mpd _x = (mpd)*_ddv - (mpd)_c; \ - *_ddv++ = MPW(_x); \ - if (_x >> MPW_BITS) \ - _c = 1; \ - else \ - break; \ - } \ -} while (0) - -extern void mpx_usubn(mpw */*dv*/, mpw */*dvl*/, mpw /*n*/); - -/* --- @mpx_usubnlsl@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination and first argument vector - * @mpw a@ = second argument - * @unsigned o@ = offset in bits - * - * Returns: --- - * - * Use: Computes %$d - 2^o a$%. If the result overflows then - * high-order bits are discarded, as usual, so you get two's - * complement. Which might be what you wanted... We must have - * @0 < o < MPW_BITS@. - */ - -extern void mpx_usubnlsl(mpw */*dv*/, mpw */*dvl*/, - mpw /*a*/, unsigned /*o*/); - -/* --- @mpx_umul@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = multiplicand vector base and limit - * @const mpw *bv, *bvl@ = multiplier vector base and limit - * - * Returns: --- - * - * Use: Performs unsigned integer multiplication. If the result - * overflows the desination vector, high-order bits are - * discarded. The result vector may not overlap the argument - * vectors in any way. - */ - -extern void mpx_umul(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, - const mpw */*bv*/, const mpw */*bvl*/); - -/* --- @mpx_umuln@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *avl@ = multiplicand vector base and limit - * @mpw m@ = multiplier - * - * Returns: --- - * - * Use: Multiplies a multiprecision integer by a single-word value. - * The destination and source may be equal. The destination - * is completely cleared after use. - */ - -#define MPX_UMULN(dv, dvl, av, avl, m) do { \ - mpw *_dv = (dv), *_dvl = (dvl); \ - const mpw *_av = (av), *_avl = (avl); \ - mpw _c = 0; \ - mpd _m = (m); \ - \ - while (_av < _avl) { \ - mpd _x; \ - if (_dv >= _dvl) \ - break; \ - _x = (mpd)_m * (mpd)*_av++ + _c; \ - *_dv++ = MPW(_x); \ - _c = _x >> MPW_BITS; \ - } \ - if (_dv < _dvl) { \ - *_dv++ = MPW(_c); \ - MPX_ZERO(_dv, _dvl); \ - } \ -} while (0) - -extern void mpx_umuln(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, mpw m); - -/* --- @mpx_umlan@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination/accumulator base and limit - * @const mpw *av, *avl@ = multiplicand vector base and limit - * @mpw m@ = multiplier - * - * Returns: --- - * - * Use: Multiplies a multiprecision integer by a single-word value - * and adds the result to an accumulator. - */ - -#define MPX_UMLAN(dv, dvl, av, avl, m) do { \ - mpw *_dv = (dv), *_dvl = (dvl); \ - const mpw *_av = (av), *_avl = (avl); \ - mpw _cc = 0; \ - mpd _m = (m); \ - \ - while (_dv < _dvl && _av < _avl) { \ - mpd _x; \ - _x = (mpd)*_dv + (mpd)_m * (mpd)*_av++ + _cc; \ - *_dv++ = MPW(_x); \ - _cc = _x >> MPW_BITS; \ - } \ - MPX_UADDN(_dv, _dvl, _cc); \ -} while (0) - -extern void mpx_umlan(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, mpw m); - -/* --- @mpx_usqr@ --- * - * - * Arguments: @mpw *dv, *dvl@ = destination vector base and limit - * @const mpw *av, *av@ = source vector base and limit - * - * Returns: --- - * - * Use: Performs unsigned integer squaring. The result vector must - * not overlap the source vector in any way. - */ - -extern void mpx_usqr(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/); - -/* --- @mpx_udiv@ --- * - * - * Arguments: @mpw *qv, *qvl@ = quotient vector base and limit - * @mpw *rv, *rvl@ = dividend/remainder vector base and limit - * @const mpw *dv, *dvl@ = divisor vector base and limit - * @mpw *sv, *svl@ = scratch workspace - * - * Returns: --- - * - * Use: Performs unsigned integer division. If the result overflows - * the quotient vector, high-order bits are discarded. (Clearly - * the remainder vector can't overflow.) The various vectors - * may not overlap in any way. Yes, I know it's a bit odd - * requiring the dividend to be in the result position but it - * does make some sense really. The remainder must have - * headroom for at least two extra words. The scratch space - * must be at least one word larger than the divisor. - */ - -extern void mpx_udiv(mpw */*qv*/, mpw */*qvl*/, mpw */*rv*/, mpw */*rvl*/, - const mpw */*dv*/, const mpw */*dvl*/, - mpw */*sv*/, mpw */*svl*/); - -/* --- @mpx_udivn@ --- * - * - * Arguments: @mpw *qv, *qvl@ = storage for the quotient (may overlap - * dividend) - * @const mpw *rv, *rvl@ = dividend - * @mpw d@ = single-precision divisor - * - * Returns: Remainder after divison. - * - * Use: Performs a single-precision division operation. - */ - -extern mpw mpx_udivn(mpw */*qv*/, mpw */*qvl*/, - const mpw */*rv*/, const mpw */*rvl*/, mpw /*d*/); - -/*----- Karatsuba multiplication algorithms -------------------------------*/ - -/* --- @MPK_THRESH@ --- * - * - * This is the limiting length for using Karatsuba algorithms. It's best to - * use the simpler classical multiplication method on numbers smaller than - * this. It is unsafe to make this constant less than four (i.e., the - * algorithms will fail). - */ - -#define MPK_THRESH 16 - -/* --- @mpx_kmul@ --- * - * - * Arguments: @mpw *dv, *dvl@ = pointer to destination buffer - * @const mpw *av, *avl@ = pointer to first argument - * @const mpw *bv, *bvl@ = pointer to second argument - * @mpw *sv, *svl@ = pointer to scratch workspace - * - * Returns: --- - * - * Use: Multiplies two multiprecision integers using Karatsuba's - * algorithm. This is rather faster than traditional long - * multiplication (e.g., @mpx_umul@) on large numbers, although - * more expensive on small ones. - * - * The destination must be three times as large as the larger - * argument. The scratch space must be five times as large as - * the larger argument. - */ - -extern void mpx_kmul(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, - const mpw */*bv*/, const mpw */*bvl*/, - mpw */*sv*/, mpw */*svl*/); - -/* --- @mpx_ksqr@ --- * - * - * Arguments: @mpw *dv, *dvl@ = pointer to destination buffer - * @const mpw *av, *avl@ = pointer to first argument - * @mpw *sv, *svl@ = pointer to scratch workspace - * - * Returns: --- - * - * Use: Squares a multiprecision integers using something similar to - * Karatsuba's multiplication algorithm. This is rather faster - * than traditional long multiplication (e.g., @mpx_umul@) on - * large numbers, although more expensive on small ones, and - * rather simpler than full-blown Karatsuba multiplication. - * - * The destination must be three times as large as the larger - * argument. The scratch space must be five times as large as - * the larger argument. - */ - -extern void mpx_ksqr(mpw */*dv*/, mpw */*dvl*/, - const mpw */*av*/, const mpw */*avl*/, - mpw */*sv*/, mpw */*svl*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/noekeon.c b/noekeon.c deleted file mode 100644 index 9e0f295..0000000 --- a/noekeon.c +++ /dev/null @@ -1,195 +0,0 @@ -/* -*-c-*- - * - * $Id: noekeon.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The Noekeon block cipher - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "noekeon.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet noekeon_keysz[] = { KSZ_SET, NOEKEON_KEYSZ, 0 }; - -/*----- Magic constants ---------------------------------------------------*/ - -/* --- To generate the magic --- * - * - * perl -e'@@r=();$x=0x80;for(0..16){push(@@r,$x);$x<<=1;$x^=0x11b - * if$x&0x100;};print join(", ",map{sprintf"0x%02x",$_}@@r),"\n";' - */ - -static const octet rcon[17] = { - 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, - 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, - 0xd4 -}; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @noekeon_init@--- * - * - * Arguments: @noekeon_ctx *k@ = pointer to key block to fill in - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a Noekeon key buffer. Noekeon accepts a 128-bit - * key. - */ - -void noekeon_init(noekeon_ctx *k, const void *buf, size_t sz) -{ - const octet *p = buf; - static const noekeon_ctx nullkey = { { 0, 0, 0, 0 } }; - - KSZ_ASSERT(noekeon, sz); - k->k[0] = LOAD32(p + 0); - k->k[1] = LOAD32(p + 4); - k->k[2] = LOAD32(p + 8); - k->k[3] = LOAD32(p + 12); - noekeon_eblk(&nullkey, k->k, k->k); -} - -/* --- @noekeon_eblk@, @noekeon_dblk@ --- * - * - * Arguments: @const noekeon_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -#define GAMMA(a, b, c, d) do { \ - uint32 _x; \ - b ^= ~(c | d); a ^= b & c; \ - _x = d; d = a; a = _x; \ - c ^= a ^ b ^ d; \ - b ^= ~(c | d); a ^= b & c; \ -} while (0) - -#define THETA(ka, kb, kc, kd, a, b, c, d) do { \ - uint32 _x; \ - _x = a ^ c; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); b ^= _x; d ^= _x; \ - a ^= ka; b ^= kb; c ^= kc; d ^= kd; \ - _x = b ^ d; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); a ^= _x; c ^= _x; \ -} while (0) - -#define ITHETA(ka, kb, kc, kd, a, b, c, d) do { \ - uint32 _x; \ - _x = b ^ d; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); a ^= _x; c ^= _x; \ - a ^= ka; b ^= kb; c ^= kc; d ^= kd; \ - _x = a ^ c; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); b ^= _x; d ^= _x; \ -} while (0) - -#define PI1(a, b, c, d) do { \ - b = ROL32(b, 1); c = ROL32(c, 5); d = ROL32(d, 2); \ -} while (0) - -#define PI2(a, b, c, d) do { \ - b = ROR32(b, 1); c = ROR32(c, 5); d = ROR32(d, 2); \ -} while (0) - -#define ROUND(r, ka, kb, kc, kd, a, b, c, d) do { \ - a ^= *r++; THETA(ka, kb, kc, kd, a, b, c, d); \ - PI1(a, b, c, d); GAMMA(a, b, c, d); PI2(a, b, c, d); \ -} while (0) - -#define IROUND(r, ka, kb, kc, kd, a, b, c, d) do { \ - ITHETA(ka, kb, kc, kd, a, b, c, d); a ^= *--r; \ - PI1(a, b, c, d); GAMMA(a, b, c, d); PI2(a, b, c, d); \ -} while (0) - -void noekeon_eblk(const noekeon_ctx *k, const uint32 *src, uint32 *dst) -{ - uint32 ka = k->k[0], kb = k->k[1], kc = k->k[2], kd = k->k[3]; - uint32 a = src[0], b = src[1], c = src[2], d = src[3]; - const octet *r = rcon; - - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - ROUND(r, ka, kb, kc, kd, a, b, c, d); - - a ^= *r++; THETA(ka, kb, kc, kd, a, b, c, d); - - dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; -} - -void noekeon_dblk(const noekeon_ctx *k, const uint32 *src, uint32 *dst) -{ - uint32 ka = k->k[0], kb = k->k[1], kc = k->k[2], kd = k->k[3]; - uint32 a = src[0], b = src[1], c = src[2], d = src[3]; - const octet *r = rcon + sizeof(rcon); - - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - IROUND(r, ka, kb, kc, kd, a, b, c, d); - - ITHETA(ka, kb, kc, kd, a, b, c, d); a ^= *--r; - - dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; -} - -BLKC_TEST(NOEKEON, noekeon) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/noekeon.h b/noekeon.h deleted file mode 100644 index e849708..0000000 --- a/noekeon.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -*-c-*- - * - * $Id: noekeon.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The Noekeon block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the Noekeon block cipher --------------------------------* - * - * A Nessie entry, by Joan Daemen, Michael Peeters, Gilles Van Assche and - * Vincent Rijmen, two of whom were the designers of the AES winner - * Rijndael. It's a simple cipher, based on Serpent-style bit-slicing. - * Speed is about middle-of-the-road -- about as fast as SAFER, faster than - * MARS. - */ - -#ifndef CATACOMB_NOEKEON_H -#define CATACOMB_NOEKEON_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magical numbers ---------------------------------------------------*/ - -#define NOEKEON_BLKSZ 16 -#define NOEKEON_KEYSZ 16 -#define NOEKEON_CLASS (N, B, 128) - -extern const octet noekeon_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct noekeon_ctx { - uint32 k[4]; -} noekeon_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @noekeon_init@ --- * - * - * Arguments: @noekeon_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Initializes a Noekeon context with a particular key. This - * uses indirect keying. The key must be 128 bits long. - */ - -extern void noekeon_init(noekeon_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @noekeon_eblk@, @noekeon_dblk@ --- * - * - * Arguments: @const noekeon_ctx *k@ = pointer to Noekeon context - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void noekeon_eblk(const noekeon_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); -extern void noekeon_dblk(const noekeon_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/noise.c b/noise.c deleted file mode 100644 index e339317..0000000 --- a/noise.c +++ /dev/null @@ -1,461 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Acquisition of environmental noise (Unix-specific) - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "config.h" - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#ifdef HAVE_SETGROUPS -# include -#endif - -#include -#include - -#include "noise.h" -#include "paranoia.h" -#include "rand.h" - -/*----- Magical numbers ---------------------------------------------------*/ - -#define NOISE_KIDLIFE 100000 /* @noise_filter@ child lifetime */ -#define MILLION 1000000 /* One million */ - -/*----- Noise source definition -------------------------------------------*/ - -const rand_source noise_source = { noise_acquire, noise_timer }; - -/*----- Static variables --------------------------------------------------*/ - -/* --- Timer differences --- */ - -static unsigned long noise_last; /* Last time recorded */ -static unsigned long noise_diff; /* Last first order difference */ - -/* --- Setuid program handling --- */ - -static uid_t noise_uid = NOISE_NOSETUID; /* Uid to set to spawn processes */ -static gid_t noise_gid = NOISE_NOSETGID; /* Gid to set to spawn processes */ - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @bitcount@ --- * - * - * Arguments: @unsigned long x@ = a word containing bits - * - * Returns: The number of bits set in the word. - */ - -static int bitcount(unsigned long x) -{ - char ctab[] = { 0, 1, 1, 2, 1, 2, 2, 3, - 1, 2, 2, 3, 2, 3, 3, 4 }; - int count = 0; - while (x) { - count += ctab[x & 0xfu]; - x >>= 4; - } - return (count); -} - -/* --- @timer@ --- * - * - * Arguments: @rand_pool *r@ = pointer to randomness pool - * @struct timeval *tv@ = pointer to time block - * - * Returns: Nonzero if some randomness was contributed. - * - * Use: Low-level timer contributor. - */ - -static int timer(rand_pool *r, struct timeval *tv) -{ - unsigned long x, d, dd; - int de, dde; - int ret; - - x = tv->tv_usec + MILLION * tv->tv_sec; - d = x ^ noise_last; - dd = d ^ noise_diff; - noise_diff = d; - de = bitcount(d); - dde = bitcount(dd); - rand_add(r, tv, sizeof(*tv), de <= dde ? de : dde); - ret = (de || dde); - BURN(tv); x = d = dd = de = dde = 0; - return (ret); -} - -/* --- @noise_timer@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: Nonzero if some randomness was contributed. - * - * Use: Contributes the current time to the randomness pool. - * A guess at the number of useful bits contributed is made, - * based on first and second order bit differences. This isn't - * ever-so reliable, but it's better than nothing. - */ - -int noise_timer(rand_pool *r) -{ - struct timeval tv; - gettimeofday(&tv, 0); - return (timer(r, &tv)); -} - -/* --- @noise_devrandom@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: Nonzero if some randomness was contributed. - * - * Use: Attempts to obtain some randomness from the system entropy - * pool. All bits from the device are assumed to be good. - */ - -int noise_devrandom(rand_pool *r) -{ - int fd; - octet buf[RAND_POOLSZ]; - ssize_t len; - int ret = 0; - - /* --- Be nice to other clients of the random device --- * - * - * Attempt to open the device nonblockingly. If that works, take up to - * one bufferful and then close again. If there's no data to be read, - * then that's tough and we go away again, on the grounds that the device - * needs to get some more entropy from somewhere. - */ - - if ((fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK)) >= 0 || - (fd = open("/dev/arandom", O_RDONLY | O_NONBLOCK)) >= 0 || - (fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) >= 0) { - if ((len = read(fd, buf, sizeof(buf))) > 0) { - rand_add(r, buf, len, len * 8); - BURN(buf); - ret = 1; - } - close(fd); - } - noise_timer(r); - return (ret); -} - -/* --- @noise_setid@ --- * - * - * Arguments: @uid_t uid@ = uid to set - * @gid_t gid@ = gid to set - * - * Returns: --- - * - * Use: Sets the user and group ids to be used by @noise_filter@ - * when running child processes. This is useful to avoid - * giving shell commands (even carefully written ones) undue - * privileges. This interface is Unix-specific - */ - -void noise_setid(uid_t uid, gid_t gid) -{ - noise_uid = uid; - noise_gid = gid; -} - -/* --- @noise_filter@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @int good@ = number of good bits per 1024 bits - * @const char *c@ = shell command to run - * - * Returns: Nonzero if some randomness was contributed. - * - * Use: Attempts to execute a shell command, and dump it into the - * randomness pool. A very rough estimate of the number of - * good bits is made, based on the size of the command's output. - * This function calls @waitpid@, so be careful. Before execing - * the command, the process uid and gid are set to the values - * given to @noise_setid@, and an attempt is made to reset the - * list of supplementary groups. The environment passed to - * the command has been severly lobotimized. If the command - * fails to complete within a short time period, it is killed. - * Paranoid use of close-on-exec flags for file descriptors is - * recommended. - * - * This interface is Unix-specific. - */ - -int noise_filter(rand_pool *r, int good, const char *c) -{ - char buf[4096]; - pid_t kid; - int fd[2]; - struct timeval dead; - int ret = 0; - const char *env[] = { - "PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc", - 0 - }; - - /* --- Remember when this business started --- */ - - gettimeofday(&dead, 0); - timer(r, &dead); - - /* --- Create a pipe --- */ - - if (pipe(fd)) - return (ret); - - /* --- Fork a child off --- */ - - fflush(0); - kid = fork(); - if (kid < 0) { - close(fd[0]); - close(fd[1]); - return (ret); - } - - /* --- Handle the child end of the deal --- */ - - if (kid == 0) { - int f; - - /* --- Set the pipe as standard output, close standard input --- */ - - close(0); close(1); close(2); - - if (fd[1] != 1) { - if (dup2(fd[1], 1) < 0) _exit(127); - close(fd[1]); - } - - if ((f = open("/dev/null", O_RDONLY)) != 0 || - (f = open("/dev/null", O_WRONLY)) != 2) - _exit(127); - - /* --- Play games with uids --- */ - - if (noise_gid != NOISE_NOSETGID) { - setgid(noise_gid); - setegid(noise_gid); -#ifdef HAVE_SETGROUPS - setgroups(1, &noise_gid); -#endif - } - - if (noise_uid != NOISE_NOSETUID) { - setuid(noise_uid); - seteuid(noise_uid); - } - - /* --- Start the process up --- */ - - execle("/bin/sh", "-c", c, (char *)0, env); - _exit(127); - } - - /* --- Sort out my end of the deal --- */ - - close(fd[1]); - - /* --- Decide on the deadline --- */ - - TV_ADDL(&dead, &dead, 0, NOISE_KIDLIFE); - - /* --- Now read, and think --- */ - - for (;;) { - struct timeval now, diff; - fd_set rd; - - gettimeofday(&now, 0); - timer(r, &now); - if (TV_CMP(&now, >, &dead)) - break; - TV_SUB(&diff, &dead, &now); - - FD_ZERO(&rd); - FD_SET(fd[0], &rd); - - if (select(fd[0] + 1, &rd, 0, 0, &diff) < 0) - break; - if (FD_ISSET(fd[0], &rd)) { - ssize_t sz; - int goodbits; - - if ((sz = read(fd[0], buf, sizeof(buf))) <= 0) - break; - goodbits = (sz * good) / 128; - rand_add(r, buf, sz, goodbits); - ret = 1; - } - } - - /* --- We've finished with it: kill the child process --- * - * - * This is morally questionable. On the other hand, I don't want to be - * held up in the @waitpid@ call if I can possibly help it. Maybe a - * double-fork is worth doing here. - */ - - close(fd[0]); - BURN(buf); - noise_timer(r); - kill(kid, SIGKILL); - waitpid(kid, 0, 0); - return (ret); -} - -/* --- @noise_freewheel@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: Nonzero if some randomness was contributed. - * - * Use: Runs a free counter for a short while as a desparate attempt - * to get randomness from somewhere. This is actually quite - * effective. - */ - -#ifdef USE_FREEWHEEL - -static jmp_buf fwjmp; - -static void fwalarm(int sig) -{ - siglongjmp(fwjmp, 1); -} - -int noise_freewheel(rand_pool *r) -{ - void (*sigal)(int) = 0; - struct itimerval oitv, itv = { { 0, 0 }, { 0, 5000 } }; - int rc = 0; - volatile uint32 fwcount = 0; - - if (!sigsetjmp(fwjmp, 1)) { - if ((sigal = signal(SIGALRM, fwalarm)) == SIG_ERR) - return (0); - if (setitimer(ITIMER_REAL, &itv, &oitv)) - goto done; - for (;;) - fwcount++; - } else { - octet buf[4]; - STORE32(buf, fwcount); - rand_add(r, buf, sizeof(buf), 16); - rc = 1; - } - -done: - signal(SIGALRM, sigal); - if (oitv.it_value.tv_sec || oitv.it_value.tv_usec) - TV_SUB(&oitv.it_value, &oitv.it_value, &itv.it_value); - setitimer(ITIMER_REAL, &oitv, 0); - return (rc); -} - -#else - -int noise_freewheel(rand_pool *r) -{ - return (0); -} - -#endif - -/* --- @noise_enquire@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: Nonzero if some randomness was contributed. - * - * Use: Runs some shell commands to enquire about the prevailing - * environment. This can gather quite a lot of low-quality - * entropy. - */ - -int noise_enquire(rand_pool *r) -{ - struct tab { - const char *cmd; - unsigned rate; - } tab[] = { - { "ps alxww || ps -elf", 16 }, - { "netstat -n", 6 }, - { "ifconfig -a", 8 }, - { "df", 20 }, - { "w", 6 }, - { "ls -align /tmp/.", 10 }, - { 0, 0 } - }; - int i; - - for (i = 0; tab[i].cmd; i++) - noise_filter(r, tab[i].rate, tab[i].cmd); - return (1); -} - -/* --- @noise_acquire@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: --- - * - * Use: Acquires some randomness from somewhere. - */ - -void noise_acquire(rand_pool *r) -{ - unsigned i; - for (i = 0; i < 8; i++) - noise_freewheel(r); - if (!noise_devrandom(r)) { - noise_enquire(r); - for (i = 0; i < 8; i++) - noise_freewheel(r); - } -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/noise.h b/noise.h deleted file mode 100644 index 48fe6bd..0000000 --- a/noise.h +++ /dev/null @@ -1,165 +0,0 @@ -/* -*-c-*- - * - * $Id: noise.h,v 1.6 2004/04/08 01:36:15 mdw Exp $ - * - * Acquisition of environmental noise (Unix-specific) - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_NOISE_H -#define CATACOMB_NOISE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_RAND_H -# include "rand.h" -#endif - -/*----- Noise source definition -------------------------------------------*/ - -extern const rand_source noise_source; - -/*----- Magic numbers -----------------------------------------------------*/ - -#define NOISE_NOSETUID ((uid_t)-1) -#define NOISE_NOSETGID ((gid_t)-1) - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @noise_timer@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: Nonzero if some randomness was contributed. - * - * Use: Contributes the current time to the randomness pool. - * A guess at the number of useful bits contributed is made, - * based on first and second order bit differences. This isn't - * ever-so reliable, but it's better than nothing. - */ - -extern int noise_timer(rand_pool */*r*/); - -/* --- @noise_devrandom@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: Nonzero if some randomness was contributed. - * - * Use: Attempts to obtain some randomness from the system entropy - * pool. All bits from the device are assumed to be good. - */ - -extern int noise_devrandom(rand_pool */*r*/); - -/* --- @noise_setid@ --- * - * - * Arguments: @uid_t uid@ = uid to set - * @gid_t gid@ = gid to set - * - * Returns: --- - * - * Use: Sets the user and group ids to be used by @noise_filter@ - * when running child processes. This is useful to avoid - * giving shell commands (even carefully written ones) undue - * privileges. This interface is Unix-specific. - */ - -extern void noise_setid(uid_t /*uid*/, gid_t /*gid*/); - -/* --- @noise_filter@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @int good@ = number of good bits per 1024 bits - * @const char *c@ = shell command to run - * - * Returns: Nonzero if some randomness was contributed. - * - * Use: Attempts to execute a shell command, and dump it into the - * randomness pool. A very rough estimate of the number of - * good bits is made, based on the size of the command's output. - * This function calls @waitpid@, so be careful. Before execing - * the command, the process uid and gid are set to the values - * given to @noise_setid@, and an attempt is made to reset the - * list of supplementary groups. The environment passed to - * the command has been severly lobotimized. If the command - * fails to complete within a short time period, it is killed. - * Paranoid use of close-on-exec flags for file descriptors is - * recommended. - * - * This interface is Unix-specific. - */ - -extern int noise_filter(rand_pool */*r*/, int /*good*/, const char */*c*/); - -/* --- @noise_freewheel@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: Nonzero if some randomness was contributed. - * - * Use: Runs a free counter for a short while as a desparate attempt - * to get randomness from somewhere. This is actually quite - * effective. - */ - -int noise_freewheel(rand_pool */*r*/); - -/* --- @noise_enquire@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: Nonzero if some randomness was contributed. - * - * Use: Runs some shell commands to enquire about the prevailing - * environment. This can gather quite a lot of low-quality - * entropy. - */ - -extern int noise_enquire(rand_pool */*r*/); - -/* --- @noise_acquire@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: --- - * - * Use: Acquires some randomness from somewhere. - */ - -extern void noise_acquire(rand_pool */*r*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/oaep.c b/oaep.c deleted file mode 100644 index dfcd41b..0000000 --- a/oaep.c +++ /dev/null @@ -1,184 +0,0 @@ -/* -*-c-*- - * - * $Id: oaep.c,v 1.6 2004/04/08 01:36:15 mdw Exp $ - * - * Optimal asymmetric encryption packing - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include -#include -#include - -#include "ct.h" -#include "gcipher.h" -#include "ghash.h" -#include "grand.h" -#include "rsa.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @oaep_encode@ --- * - * - * Arguments: @mp *d@ = where to put the answer - * @const void *m@ = pointer to message data - * @size_t msz@ = size of message data - * @octet *b@ = spare buffer - * @size_t sz@ = size of the buffer (big enough) - * @unsigned long nbits@ = length of bits of @n@ - * @void *p@ = pointer to OAEP parameter block - * - * Returns: The encoded plaintext, or null on failure. - * - * Use: Implements the operation @EME-OAEP-ENCODE@, as defined in - * PKCS#1 v. 2.0 (RFC2437). - */ - -mp *oaep_encode(mp *d, const void *m, size_t msz, octet *b, size_t sz, - unsigned long nbits, void *p) -{ - oaep *o = p; - size_t hsz = o->ch->hashsz; - ghash *h; - octet *q, *mq; - octet *pp; - gcipher *c; - size_t n; - - /* --- Ensure that everything is sensibly sized --- */ - - if (2 * hsz + 2 + msz > sz) - return (0); - - /* --- Make the `seed' value --- */ - - q = b; - *q++ = 0; sz--; - mq = q + hsz; - GR_FILL(o->r, q, hsz); - - /* --- Fill in the rest of the buffer --- */ - - h = GH_INIT(o->ch); - GH_HASH(h, o->ep, o->epsz); - GH_DONE(h, mq); - GH_DESTROY(h); - pp = mq + hsz; - n = sz - 2 * hsz - msz - 1; - memset(pp, 0, n); - pp += n; - *pp++ = 1; - memcpy(pp, m, msz); - - /* --- Do the packing --- */ - - n = sz - hsz; - c = GC_INIT(o->cc, q, hsz); - GC_ENCRYPT(c, mq, mq, n); - GC_DESTROY(c); - - c = GC_INIT(o->cc, mq, n); - GC_ENCRYPT(c, q, q, hsz); - GC_DESTROY(c); - - /* --- Done --- */ - - return (mp_loadb(d, b, sz + 1)); -} - -/* --- @oaep_decode@ --- * - * - * Arguments: @mp *m@ = the decrypted message - * @octet *b@ = pointer to a buffer to work in - * @size_t sz@ = the size of the buffer (big enough) - * @unsigned long nbits@ = the number of bits in @n@ - * @void *p@ = pointer to OAEP parameter block - * - * Returns: The length of the output string if successful, negative on - * failure. - * - * Use: Implements the operation @EME-OAEP-DECODE@, as defined in - * PKCS#1 v. 2.0 (RFC2437). - */ - -int oaep_decode(mp *m, octet *b, size_t sz, unsigned long nbits, void *p) -{ - oaep *o = p; - gcipher *c; - ghash *h; - octet *q, *mq, *qq; - octet *pp; - uint32 goodp = 1; - size_t n; - size_t hsz = o->ch->hashsz; - - /* --- Ensure that the block is large enough --- */ - - if (sz < 2 * hsz) /* Doesn't depend on ciphertext */ - return (-1); - - /* --- Decrypt the message --- */ - - mp_storeb(m, b, sz); - q = b; - goodp &= ct_inteq(*q, 0); - q++; sz--; - mq = q + hsz; - qq = q + sz; - n = sz - hsz; - c = GC_INIT(o->cc, mq, n); - GC_DECRYPT(c, q, q, hsz); - GC_DESTROY(c); - - c = GC_INIT(o->cc, q, hsz); - GC_DECRYPT(c, mq, mq, n); - GC_DESTROY(c); - q--; - - /* --- Check the hash on the encoding parameters --- */ - - h = GH_INIT(o->ch); - GH_HASH(h, o->ep, o->epsz); - GH_DONE(h, q); - GH_DESTROY(h); - goodp &= ct_memeq(q, mq, hsz); - - /* --- Now find the start of the actual message --- */ - - pp = mq + hsz; - while (*pp == 0 && pp < qq) - pp++; - goodp &= ~ct_intle(qq - b, pp - b); - goodp &= ct_inteq(*pp, 1); - pp++; - n = qq - pp; - memmove(q, pp, n); - return (goodp ? n : -1); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/ofb-def.h b/ofb-def.h deleted file mode 100644 index 8250395..0000000 --- a/ofb-def.h +++ /dev/null @@ -1,547 +0,0 @@ -/* -*-c-*- - * - * $Id: ofb-def.h,v 1.7 2004/04/08 01:36:15 mdw Exp $ - * - * Definitions for output feedback mode - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_OFB_DEF_H -#define CATACOMB_OFB_DEF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include -#include - -#ifndef CATACOMB_ARENA_H -# include "arena.h" -#endif - -#ifndef CATACOMB_BLKC_H -# include "blkc.h" -#endif - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -#ifndef CATACOMB_PARANOIA_H -# include "paranoia.h" -#endif - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @OFB_DEF@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher - * - * Use: Creates definitions for output feedback mode. - */ - -#define OFB_DEF(PRE, pre) \ - \ -/* --- @pre_ofbgetiv@ --- * \ - * \ - * Arguments: @const pre_ofbctx *ctx@ = pointer to OFB context block \ - * @void *iv@ = pointer to output data block \ - * \ - * Returns: --- \ - * \ - * Use: Reads the currently set IV. Reading and setting an IV \ - * is not transparent to the cipher. It will add a `step' \ - * which must be matched by a similar operation during \ - * decryption. \ - */ \ - \ -void pre##_ofbgetiv(const pre##_ofbctx *ctx, void *iv) \ -{ \ - octet *p = iv; \ - unsigned off = ctx->off; \ - unsigned rest = PRE##_BLKSZ - off; \ - memcpy(p, ctx->iv + off, rest); \ - memcpy(p + rest, ctx->iv, off); \ -} \ - \ -/* --- @pre_ofbsetiv@ --- * \ - * \ - * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ - * @cnost void *iv@ = pointer to IV to set \ - * \ - * Returns: --- \ - * \ - * Use: Sets the IV to use for subsequent encryption. \ - */ \ - \ -void pre##_ofbsetiv(pre##_ofbctx *ctx, const void *iv) \ -{ \ - memcpy(ctx->iv, iv, PRE##_BLKSZ); \ - ctx->off = PRE##_BLKSZ; \ -} \ - \ -/* --- @pre_ofbbdry@ --- * \ - * \ - * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ - * \ - * Returns: --- \ - * \ - * Use: Inserts a boundary during encryption. Successful \ - * decryption must place a similar boundary. \ - */ \ - \ -void pre##_ofbbdry(pre##_ofbctx *ctx) \ -{ \ - uint32 niv[PRE##_BLKSZ / 4]; \ - BLKC_LOAD(PRE, niv, ctx->iv); \ - pre##_eblk(&ctx->ctx, niv, niv); \ - BLKC_STORE(PRE, ctx->iv, niv); \ - ctx->off = PRE##_BLKSZ; \ - BURN(niv); \ -} \ - \ -/* --- @pre_ofbsetkey@ --- * \ - * \ - * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ - * @const pre_ctx *k@ = pointer to cipher context \ - * \ - * Returns: --- \ - * \ - * Use: Sets the OFB context to use a different cipher key. \ - */ \ - \ -void pre##_ofbsetkey(pre##_ofbctx *ctx, const pre##_ctx *k) \ -{ \ - ctx->ctx = *k; \ -} \ - \ -/* --- @pre_ofbinit@ --- * \ - * \ - * Arguments: @pre_ofbctx *ctx@ = pointer to cipher context \ - * @const void *key@ = pointer to the key buffer \ - * @size_t sz@ = size of the key \ - * @const void *iv@ = pointer to initialization vector \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a OFB context ready for use. You should \ - * ensure that the IV chosen is unique: reusing an IV will \ - * compromise the security of the entire plaintext. This \ - * is equivalent to calls to @pre_init@, @pre_ofbsetkey@ \ - * and @pre_ofbsetiv@. \ - */ \ - \ -void pre##_ofbinit(pre##_ofbctx *ctx, \ - const void *key, size_t sz, \ - const void *iv) \ -{ \ - static const octet zero[PRE##_BLKSZ] = { 0 }; \ - pre##_init(&ctx->ctx, key, sz); \ - pre##_ofbsetiv(ctx, iv ? iv : zero); \ -} \ - \ -/* --- @pre_ofbencrypt@ --- * \ - * \ - * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Encrypts or decrypts a block with a block cipher in OFB \ - * mode: encryption and decryption are the same in OFB. \ - * The destination may be null to just churn the feedback \ - * round for a bit. The source may be null to use the \ - * cipher as a random data generator. \ - */ \ - \ -void pre##_ofbencrypt(pre##_ofbctx *ctx, \ - const void *src, void *dest, \ - size_t sz) \ -{ \ - const octet *s = src; \ - octet *d = dest; \ - unsigned off = ctx->off; \ - \ - /* --- Empty blocks are trivial --- */ \ - \ - if (!sz) \ - return; \ - \ - /* --- If I can deal with the block from my buffer, do that --- */ \ - \ - if (sz < PRE##_BLKSZ - off) \ - goto small; \ - \ - /* --- Finish off what's left in my buffer --- */ \ - \ - if (!d) \ - sz -= PRE##_BLKSZ - off; \ - else { \ - while (off < PRE##_BLKSZ) { \ - register octet x = s ? *s++ : 0; \ - *d++ = ctx->iv[off++] ^ x; \ - sz--; \ - } \ - } \ - \ - /* --- Main encryption loop --- */ \ - \ - { \ - uint32 iv[PRE##_BLKSZ / 4]; \ - BLKC_LOAD(PRE, iv, ctx->iv); \ - \ - for (;;) { \ - pre##_eblk(&ctx->ctx, iv, iv); \ - if (sz < PRE##_BLKSZ) \ - break; \ - if (d) { \ - if (!s) \ - BLKC_STORE(PRE, d, iv); \ - else { \ - uint32 x[PRE##_BLKSZ / 4]; \ - BLKC_LOAD(PRE, x, s); \ - BLKC_XSTORE(PRE, d, iv, x); \ - s += PRE##_BLKSZ; \ - } \ - d += PRE##_BLKSZ; \ - } \ - sz -= PRE##_BLKSZ; \ - } \ - \ - BLKC_STORE(PRE, ctx->iv, iv); \ - off = 0; \ - } \ - \ - /* --- Tidying up the tail end --- */ \ - \ - if (sz) { \ - small: \ - if (!d) \ - off += sz; \ - else do { \ - register octet x = s ? *s++ : 0; \ - *d++ = ctx->iv[off++] ^ x; \ - sz--; \ - } while (sz); \ - } \ - \ - /* --- Done --- */ \ - \ - ctx->off = off; \ - return; \ -} \ - \ -/* --- Generic cipher interface --- */ \ - \ -static const gcipher_ops gops; \ - \ -typedef struct gctx { \ - gcipher c; \ - pre##_ofbctx k; \ -} gctx; \ - \ -static gcipher *ginit(const void *k, size_t sz) \ -{ \ - gctx *g = S_CREATE(gctx); \ - g->c.ops = &gops; \ - pre##_ofbinit(&g->k, k, sz, 0); \ - return (&g->c); \ -} \ - \ -static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_ofbencrypt(&g->k, s, t, sz); \ -} \ - \ -static void gdestroy(gcipher *c) \ -{ \ - gctx *g = (gctx *)c; \ - BURN(*g); \ - S_DESTROY(g); \ -} \ - \ -static void gsetiv(gcipher *c, const void *iv) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_ofbsetiv(&g->k, iv); \ -} \ - \ -static void gbdry(gcipher *c) \ -{ \ - gctx *g = (gctx *)c; \ - pre##_ofbbdry(&g->k); \ -} \ - \ -static const gcipher_ops gops = { \ - &pre##_ofb, \ - gencrypt, gencrypt, gdestroy, gsetiv, gbdry \ -}; \ - \ -const gccipher pre##_ofb = { \ - #pre "-ofb", pre##_keysz, PRE##_BLKSZ, \ - ginit \ -}; \ - \ -/* --- Generic random number generator interface --- */ \ - \ -typedef struct grctx { \ - grand r; \ - pre##_ofbctx k; \ -} grctx; \ - \ -static void grdestroy(grand *r) \ -{ \ - grctx *g = (grctx *)r; \ - BURN(*g); \ - S_DESTROY(g); \ -} \ - \ -static int grmisc(grand *r, unsigned op, ...) \ -{ \ - grctx *g = (grctx *)r; \ - va_list ap; \ - int rc = 0; \ - uint32 i; \ - octet buf[PRE##_BLKSZ]; \ - va_start(ap, op); \ - \ - switch (op) { \ - case GRAND_CHECK: \ - switch (va_arg(ap, unsigned)) { \ - case GRAND_CHECK: \ - case GRAND_SEEDINT: \ - case GRAND_SEEDUINT32: \ - case GRAND_SEEDBLOCK: \ - case GRAND_SEEDRAND: \ - rc = 1; \ - break; \ - default: \ - rc = 0; \ - break; \ - } \ - break; \ - case GRAND_SEEDINT: \ - memset(buf, 0, sizeof(buf)); \ - i = va_arg(ap, unsigned); \ - STORE32(buf, i); \ - pre##_ofbsetiv(&g->k, buf); \ - break; \ - case GRAND_SEEDUINT32: \ - memset(buf, 0, sizeof(buf)); \ - i = va_arg(ap, uint32); \ - STORE32(buf, i); \ - pre##_ofbsetiv(&g->k, buf); \ - break; \ - case GRAND_SEEDBLOCK: { \ - const void *p = va_arg(ap, const void *); \ - size_t sz = va_arg(ap, size_t); \ - if (sz < sizeof(buf)) { \ - memset(buf, 0, sizeof(buf)); \ - memcpy(buf, p, sz); \ - p = buf; \ - } \ - pre##_ofbsetiv(&g->k, p); \ - } break; \ - case GRAND_SEEDRAND: { \ - grand *rr = va_arg(ap, grand *); \ - rr->ops->fill(rr, buf, sizeof(buf)); \ - pre##_ofbsetiv(&g->k, buf); \ - } break; \ - default: \ - GRAND_BADOP; \ - break; \ - } \ - \ - va_end(ap); \ - return (rc); \ -} \ - \ -static octet grbyte(grand *r) \ -{ \ - grctx *g = (grctx *)r; \ - octet o; \ - pre##_ofbencrypt(&g->k, 0, &o, 1); \ - return (o); \ -} \ - \ -static uint32 grword(grand *r) \ -{ \ - grctx *g = (grctx *)r; \ - octet b[4]; \ - pre##_ofbencrypt(&g->k, 0, b, sizeof(b)); \ - return (LOAD32(b)); \ -} \ - \ -static void grfill(grand *r, void *p, size_t sz) \ -{ \ - grctx *g = (grctx *)r; \ - pre##_ofbencrypt(&g->k, 0, p, sz); \ -} \ - \ -static const grand_ops grops = { \ - #pre "-ofb", \ - GRAND_CRYPTO, 0, \ - grmisc, grdestroy, \ - grword, grbyte, grword, grand_range, grfill \ -}; \ - \ -/* --- @pre_ofbrand@ --- * \ - * \ - * Arguments: @const void *k@ = pointer to key material \ - * @size_t sz@ = size of key material \ - * \ - * Returns: Pointer to generic random number generator interface. \ - * \ - * Use: Creates a random number interface wrapper around an \ - * OFB-mode block cipher. \ - */ \ - \ -grand *pre##_ofbrand(const void *k, size_t sz) \ -{ \ - grctx *g = S_CREATE(grctx); \ - g->r.ops = &grops; \ - pre##_ofbinit(&g->k, k, sz, 0); \ - return (&g->r); \ -} \ - \ -OFB_TEST(PRE, pre) - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#include "daftstory.h" - -/* --- @OFB_TEST@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions - * - * Use: Standard test rig for OFB functions. - */ - -#define OFB_TEST(PRE, pre) \ - \ -/* --- Initial plaintext for the test --- */ \ - \ -static const octet text[] = TEXT; \ - \ -/* --- Key and IV to use --- */ \ - \ -static const octet key[] = KEY; \ -static const octet iv[] = IV; \ - \ -/* --- Buffers for encryption and decryption output --- */ \ - \ -static octet ct[sizeof(text)]; \ -static octet pt[sizeof(text)]; \ - \ -static void hexdump(const octet *p, size_t sz) \ -{ \ - const octet *q = p + sz; \ - for (sz = 0; p < q; p++, sz++) { \ - printf("%02x", *p); \ - if ((sz + 1) % PRE##_BLKSZ == 0) \ - putchar(':'); \ - } \ -} \ - \ -int main(void) \ -{ \ - size_t sz = 0, rest; \ - pre##_ofbctx ctx; \ - int status = 0; \ - int done = 0; \ - pre##_ctx k; \ - \ - size_t keysz = PRE##_KEYSZ ? \ - PRE##_KEYSZ : strlen((const char *)key); \ - \ - fputs(#pre "-ofb: ", stdout); \ - \ - pre##_init(&k, key, keysz); \ - pre##_ofbsetkey(&ctx, &k); \ - \ - while (sz <= sizeof(text)) { \ - rest = sizeof(text) - sz; \ - memcpy(ct, text, sizeof(text)); \ - pre##_ofbsetiv(&ctx, iv); \ - pre##_ofbencrypt(&ctx, ct, ct, sz); \ - pre##_ofbencrypt(&ctx, ct + sz, ct + sz, rest); \ - memcpy(pt, ct, sizeof(text)); \ - pre##_ofbsetiv(&ctx, iv); \ - pre##_ofbencrypt(&ctx, pt, pt, rest); \ - pre##_ofbencrypt(&ctx, pt + rest, pt + rest, sz); \ - if (memcmp(pt, text, sizeof(text)) == 0) { \ - done++; \ - if (sizeof(text) < 40 || done % 8 == 0) \ - fputc('.', stdout); \ - if (done % 480 == 0) \ - fputs("\n\t", stdout); \ - fflush(stdout); \ - } else { \ - printf("\nError (sz = %lu)\n", (unsigned long)sz); \ - status = 1; \ - printf("\tplaintext = "); hexdump(text, sz); \ - printf(", "); hexdump(text + sz, rest); \ - fputc('\n', stdout); \ - printf("\tciphertext = "); hexdump(ct, sz); \ - printf(", "); hexdump(ct + sz, rest); \ - fputc('\n', stdout); \ - printf("\trecovered text = "); hexdump(pt, sz); \ - printf(", "); hexdump(pt + sz, rest); \ - fputc('\n', stdout); \ - fputc('\n', stdout); \ - } \ - if (sz < 63) \ - sz++; \ - else \ - sz += 9; \ - } \ - \ - fputs(status ? " failed\n" : " ok\n", stdout); \ - return (status); \ -} - -#else -# define OFB_TEST(PRE, pre) -#endif - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/ofb.h b/ofb.h deleted file mode 100644 index 970acf7..0000000 --- a/ofb.h +++ /dev/null @@ -1,187 +0,0 @@ -/* -*-c-*- - * - * $Id: ofb.h,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Output feedback for block ciphers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_OFB_H -#define CATACOMB_OFB_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @OFB_DECL@ --- * - * - * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions - * - * Use: Makes declarations for output feedback mode. - */ - -#define OFB_DECL(PRE, pre) \ - \ -/* --- Output feedback context --- */ \ - \ -typedef struct pre##_ofbctx { \ - pre##_ctx ctx; /* Underlying cipher context */ \ - unsigned off; /* Current offset in buffer */ \ - octet iv[PRE##_BLKSZ]; /* Output buffer and IV */ \ -} pre##_ofbctx; \ - \ -/* --- @pre_ofbgetiv@ --- * \ - * \ - * Arguments: @const pre_ofbctx *ctx@ = pointer to OFB context block \ - * @void *iv@ = pointer to output data block \ - * \ - * Returns: --- \ - * \ - * Use: Reads the currently set IV. Reading and setting an IV \ - * is not transparent to the cipher. It will add a `step' \ - * which must be matched by a similar operation during \ - * decryption. \ - */ \ - \ -extern void pre##_ofbgetiv(const pre##_ofbctx */*ctx*/, \ - void */*iv*/); \ - \ -/* --- @pre_ofbsetiv@ --- * \ - * \ - * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ - * @cnost void *iv@ = pointer to IV to set \ - * \ - * Returns: --- \ - * \ - * Use: Sets the IV to use for subsequent encryption. \ - */ \ - \ -extern void pre##_ofbsetiv(pre##_ofbctx */*ctx*/, \ - const void */*iv*/); \ - \ -/* --- @pre_ofbbdry@ --- * \ - * \ - * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ - * \ - * Returns: --- \ - * \ - * Use: Inserts a boundary during encryption. Successful \ - * decryption must place a similar boundary. \ - */ \ - \ -extern void pre##_ofbbdry(pre##_ofbctx */*ctx*/); \ - \ -/* --- @pre_ofbsetkey@ --- * \ - * \ - * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ - * @const pre_ctx *k@ = pointer to cipher context \ - * \ - * Returns: --- \ - * \ - * Use: Sets the OFB context to use a different cipher key. \ - */ \ - \ -extern void pre##_ofbsetkey(pre##_ofbctx */*ctx*/, \ - const pre##_ctx */*k*/); \ - \ -/* --- @pre_ofbinit@ --- * \ - * \ - * Arguments: @pre_ofbctx *ctx@ = pointer to cipher context \ - * @const void *key@ = pointer to the key buffer \ - * @size_t sz@ = size of the key \ - * @const void *iv@ = pointer to initialization vector \ - * \ - * Returns: --- \ - * \ - * Use: Initializes a OFB context ready for use. You should \ - * ensure that the IV chosen is unique: reusing an IV will \ - * compromise the security of the entire plaintext. This \ - * is equivalent to calls to @pre_init@, @pre_ofbsetkey@ \ - * and @pre_ofbsetiv@. \ - */ \ - \ -extern void pre##_ofbinit(pre##_ofbctx */*ctx*/, \ - const void */*key*/, size_t /*sz*/, \ - const void */*iv*/); \ - \ -/* --- @pre_ofbencrypt@ --- * \ - * \ - * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ - * @const void *src@ = pointer to source data \ - * @void *dest@ = pointer to destination data \ - * @size_t sz@ = size of block to be encrypted \ - * \ - * Returns: --- \ - * \ - * Use: Encrypts or decrypts a block with a block cipher in OFB \ - * mode: encryption and decryption are the same in OFB. \ - * The destination may be null to just churn the feedback \ - * round for a bit. The source may be null to use the \ - * cipher as a random data generator. \ - */ \ - \ -extern void pre##_ofbencrypt(pre##_ofbctx */*ctx*/, \ - const void */*src*/, void */*dest*/, \ - size_t /*sz*/); \ - \ -/* --- @pre_ofbrand@ --- * \ - * \ - * Arguments: @const void *k@ = pointer to key material \ - * @size_t sz@ = size of key material \ - * \ - * Returns: Pointer to generic random number generator interface. \ - * \ - * Use: Creates a random number interface wrapper around an \ - * OFB-mode block cipher. \ - */ \ - \ -extern grand *pre##_ofbrand(const void */*k*/, size_t /*sz*/); \ - \ -/* --- Generic cipher interface --- */ \ - \ -extern const gccipher pre##_ofb; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/p-gentab.awk b/p-gentab.awk deleted file mode 100755 index 09a1c37..0000000 --- a/p-gentab.awk +++ /dev/null @@ -1,102 +0,0 @@ -#! /usr/bin/awk -f -# -# $Id$ - -function banner(name, s, i) -{ - s = "/*----- " name " "; - while (length(s) < 75) s = s "-"; - return (s "*/"); -} - -function fix(name) -{ - gsub(/[^0-9A-Za-z_]+/, "_", name); - return (name); -} - -BEGIN { - print "/* -*-c-*-"; - print " *"; - print " * Table of prime groups [generated]"; - print " */"; - print ""; - print "#include \"ptab.h\""; - print ""; - print "#define N(x) (sizeof(x)/sizeof(*x))"; - print "#define MP(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }"; - print "#define NOMP { 0, 0, 0, 0, 0 }"; - print ""; - print banner("Prime data"); - print ""; - - d_i = 0; - name = ""; -} - -function putmp(x, d) -{ - if (!(x in data)) { - print "group " name ": missing " x >"/dev/stderr"; - exit 1; - } - d = data[x]; - if (!(d in cache)) { - n = "p_" fix(name) "_" x; - print "static mpw " n "[] = {"; - system("./mpdump " d); - print "};"; - print ""; - cache[d] = n; - } - mp[x] = cache[d]; -} - -function flush() -{ - if (name == "") return; - print "/* --- Group " name " --- */"; - delete mp; - print ""; - putmp("p"); - putmp("q"); - putmp("g"); - print "static pdata p_" fix(name) " = {"; - print " MP(" mp["p"] ")," - print " MP(" mp["q"] ")," - print " MP(" mp["g"] ")" - print "};"; - print ""; - dname[d_i++] = name; - d[name] = name; - r[name] = "p_" fix(name); - name = ""; -} - -/^[ \t]*(#|$)/ { next; } - -$1 == "alias" { flush(); dname[d_i++] = $2; d[$2] = $3; next; } - -$1 == "group" { flush(); delete data; name = $2; next; } - -{ data[$1] = $2; next; } - -END { - flush(); - print banner("Main table"); - print ""; - print "const pentry ptab[] = {"; - for (i = 0; i < d_i; i++) { - name = dname[i]; - rname = d[name]; - if (!rname in r) { - print "group " rname " not found (alias from " name ")" >"/dev/stderr"; - exit 1; - } - print " { \"" name "\", &" r[rname] " },"; - } - print " { 0, 0 }"; - print "};" - print ""; - print banner("That's all, folks"); -} diff --git a/papers/rand.tex b/papers/rand.tex index 5a2014d..a82387b 100644 --- a/papers/rand.tex +++ b/papers/rand.tex @@ -1,7 +1,5 @@ %%% -*-latex-*- %%% -%%% $Id: rand.tex,v 1.4 2004/04/08 01:36:15 mdw Exp $ -%%% %%% Description of Catacomb's random number generator %%% %%% (c) 1999 Straylight/Edgeware diff --git a/paranoia.h b/paranoia.h deleted file mode 100644 index e1ad2f5..0000000 --- a/paranoia.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*-c-*- - * - * $Id: paranoia.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Macros and functions for cryptographic paranoia - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_PARANOIA_H -#define CATACOMB_PARANOIA_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -/*----- Macros ------------------------------------------------------------*/ - -#define BURN(x) (memset(&(x), 0, sizeof(x))) - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/passphrase.c b/passphrase.c deleted file mode 100644 index 8bbbb9d..0000000 --- a/passphrase.c +++ /dev/null @@ -1,166 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Reading of passphrases (Unix-specific) - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include - -#include - -#include "passphrase.h" -#include "pixie.h" - -/*----- Static variables --------------------------------------------------*/ - -static int fd = -1; -static unsigned flags = 0; - -#define f_fail 1u - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @passphrase_connect@ --- - * - * Arguments: @const char *sock@ = socket name to connect to, or null for - * default - * - * Returns: Zero if OK, nonzero if it failed - * - * Use: Attempts to connect to the passphrase pixie. - */ - -int passphrase_connect(const char *sock) -{ - if (fd != -1) - close(fd); - if ((fd = pixie_open(sock)) < 0) { - flags |= f_fail; - return (-1); - } - flags &= ~f_fail; - return (0); -} - -static int pconn(void) -{ - if (fd != -1) - return (0); - if (flags & f_fail) - return (-1); - return (passphrase_connect(0)); -} - -/* --- @passphrase_read@ --- * - * - * Arguments: @const char *tag@ = pointer to passphrase tag string - * @unsigned mode@ = reading mode - * @char *buf@ = pointer to destination buffer - * @size_t sz@ = size of destination buffer - * - * Returns: Zero if successful, nonzero on failure. - * - * Use: Reads a passphrase from the user, using some system-specific - * secure mechanism. The mechanism may keep a cache of - * passphrases, so the user may not necessarily be prompted. - */ - -int passphrase_read(const char *tag, unsigned mode, char *buf, size_t sz) -{ - dstr d = DSTR_INIT; - int rc = 1; - - /* --- Try talking to the pixie --- */ - - if (!pconn()) { - rc = pixie_read(fd, tag, mode, buf, sz); - if (rc < 0) { - close(fd); - fd = -1; - return (-1); - } - if (rc == 0) - return (0); - } - - /* --- Read from the terminal --- */ - - dstr_putf(&d, "%s %s: ", - mode == PMODE_READ ? "Passphrase" : "New passphrase", - tag); - if (pixie_getpass(d.buf, buf, sz)) - goto fail; - if (mode == PMODE_VERIFY) { - char b[1024]; - DRESET(&d); - dstr_putf(&d, "Verify passphrase %s: ", tag); - if (pixie_getpass(d.buf, b, sizeof(b)) || strcmp(b, buf) != 0) { - memset(b, 0, sizeof(b)); - goto fail; - } - } - dstr_destroy(&d); - - /* --- If the pixie is interested, tell it the new passphrase --- */ - - if (fd >= 0) - pixie_set(fd, tag, buf); - return (0); - - /* --- Tidy up after a failure --- */ - -fail: - dstr_destroy(&d); - memset(buf, 0, sz); - return (-1); -} - -/* --- @passphrase_cancel@ --- * - * - * Arguments: @const char *tag@ = pointer to passphrase tag string - * - * Returns: --- - * - * Use: Attempts to make the passphrase cache forget about a - * particular passphrase. This may be useful if the passphrase - * turns out to be wrong, or if the user is attempting to change - * the passphrase. - */ - -void passphrase_cancel(const char *tag) -{ - if (!pconn()) - pixie_cancel(fd, tag); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/passphrase.h b/passphrase.h deleted file mode 100644 index 89836c3..0000000 --- a/passphrase.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Reading passphrases - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_PASSPHRASE_H -#define CATACOMB_PASSPHRASE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -/*----- Data structures ---------------------------------------------------*/ - -/* --- Passphrase modes --- * - * - * @PMODE_VERIFY@ requests that the passphrase be repeated to make sure it's - * right. - */ - -enum { - PMODE_READ, - PMODE_VERIFY -}; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @passphrase_connect@ --- - * - * Arguments: @const char *sock@ = socket name to connect to, or null for - * default - * - * Returns: Zero if OK, nonzero if it failed - * - * Use: Attempts to connect to the passphrase pixie. - */ - -extern int passphrase_connect(const char */*sock*/); - -/* --- @passphrase_read@ --- * - * - * Arguments: @const char *tag@ = pointer to passphrase tag string - * @unsigned mode@ = reading mode - * @char *buf@ = pointer to destination buffer - * @size_t sz@ = size of destination buffer - * - * Returns: Zero if successful, nonzero on failure. - * - * Use: Reads a passphrase from the user, using some system-specific - * secure mechanism. The mechanism may keep a cache of - * passphrases, so the user may not necessarily be prompted. - */ - -extern int passphrase_read(const char */*tag*/, unsigned /*mode*/, - char */*buf*/, size_t /*sz*/); - -/* --- @passphrase_cancel@ --- * - * - * Arguments: @const char *tag@ = pointer to passphrase tag string - * - * Returns: --- - * - * Use: Attempts to make the passphrase cache forget about a - * particular passphrase. This may be useful if the passphrase - * turns out to be wrong, or if the user is attempting to change - * the passphrase. - */ - -extern void passphrase_cancel(const char */*tag*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/pcheck.pl b/pcheck.pl deleted file mode 100644 index 3b1447a..0000000 --- a/pcheck.pl +++ /dev/null @@ -1,43 +0,0 @@ -#! /usr/bin/perl - -# Reads ptab.in or similarly-formatted file; writes a calc script to check -# it. - -while (<>) { - next if /^\s*(\#[^!]|$)/; - @F = split; - if ($F[0] eq "group") { - $group = $F[1]; - $_ = <>; @F = split; $F[0] eq "p" or die $F[0]; $p = $F[1]; - $_ = <>; @F = split; $F[0] eq "q" or die $F[0]; $q = $F[1]; - $_ = <>; @F = split; $F[0] eq "g" or die $F[0]; $g = $F[1]; - print <; @F = split; $F[0] eq "#:factor" or last; $f = $F[1]; - print < -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "rand.h" -#include "mp.h" -#include "mprand.h" -#include "fibrand.h" -#include "rsa.h" -#include "mpmont.h" -#include "mpbarrett.h" -#include "dh.h" -#include "pgen.h" -#include "ec.h" -#include "group.h" - -#include "cc.h" -#include "gcipher.h" -#include "ghash.h" -#include "gmac.h" -#include "ectab.h" -#include "ptab.h" - -/*----- Options -----------------------------------------------------------*/ - -typedef struct opts { - const char *name; /* Pre-configured named thing */ - unsigned fbits; /* Field size bits */ - unsigned gbits; /* Group size bits */ - unsigned n; /* Number of factors */ - unsigned i; /* Number of intervals (or zero) */ - double t; /* Time for each interval (secs) */ - unsigned f; /* Flags */ -#define OF_NOCHECK 1u /* Don't do group checking */ -} opts; - -/*----- Job switch --------------------------------------------------------*/ - -/* --- Barrett exponentiation --- */ - -typedef struct bar_ctx { - size_t n; - mpbarrett b; - mp_expfactor *e; -} bar_ctx; - -static void *bar_init(opts *o) -{ - bar_ctx *c = CREATE(bar_ctx); - gprime_param gp; - qd_parse qd; - size_t i; - - if (o->name) { - qd.p = o->name; - if (dh_parse(&qd, &gp)) - die(1, "bad prime group: %s", qd.e); - } else { - if (!o->fbits) o->fbits = 1024; - dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0); - } - mpbarrett_create(&c->b, gp.p); - if (!o->n) o->n = 1; - c->n = o->n; - c->e = xmalloc(c->n * sizeof(group_expfactor)); - for (i = 0; i < c->n; i++) { - c->e[i].base = mprand_range(MP_NEW, gp.p, &rand_global, 0); - c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0); - } - dh_paramfree(&gp); - return (c); -} - -static void bar_run(void *cc) -{ - bar_ctx *c = cc; - mp *d = mpbarrett_exp(&c->b, MP_NEW, c->e[0].base, c->e[0].exp); - MP_DROP(d); -} - -static void barsim_run(void *cc) -{ - bar_ctx *c = cc; - mp *d = mpbarrett_mexp(&c->b, MP_NEW, c->e, c->n); - MP_DROP(d); -} - -/* --- Montgomery exponentiation --- */ - -typedef struct mont_ctx { - size_t n; - mpmont m; - mp_expfactor *e; -} mont_ctx; - -static void *mont_init(opts *o) -{ - mont_ctx *c = CREATE(mont_ctx); - gprime_param gp; - qd_parse qd; - size_t i; - - if (o->name) { - qd.p = o->name; - if (dh_parse(&qd, &gp)) - die(1, "bad prime group: %s", qd.e); - } else { - if (!o->fbits) o->fbits = 1024; - dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0); - } - mpmont_create(&c->m, gp.p); - if (!o->n) o->n = 1; - c->n = o->n; - c->e = xmalloc(c->n * sizeof(mp_expfactor)); - for (i = 0; i < c->n; i++) { - c->e[i].base = mprand_range(MP_NEW, gp.p, &rand_global, 0); - c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0); - } - dh_paramfree(&gp); - return (c); -} - -static void mont_run(void *cc) -{ - mont_ctx *c = cc; - mp *d = mpmont_expr(&c->m, MP_NEW, c->e[0].base, c->e[0].exp); - MP_DROP(d); -} - -static void montsim_run(void *cc) -{ - mont_ctx *c = cc; - mp *d = mpmont_mexpr(&c->m, MP_NEW, c->e, c->n); - MP_DROP(d); -} - -/* --- Group exponentiation --- */ - -typedef struct gr_ctx { - size_t n; - group *g; - group_expfactor *e; -} gr_ctx; - -static void *grp_init(opts *o) -{ - gr_ctx *c = CREATE(gr_ctx); - const char *e; - gprime_param gp; - qd_parse qd; - size_t i; - - if (o->name) { - qd.p = o->name; - if (dh_parse(&qd, &gp)) - die(1, "bad prime group: %s", qd.e); - } else { - if (!o->fbits) o->fbits = 1024; - dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0); - } - c->g = group_prime(&gp); - if (!(o->f & OF_NOCHECK) && (e = G_CHECK(c->g, &rand_global)) != 0) - die(1, "bad group: %s", e); - if (!o->n) o->n = 1; - c->n = o->n; - c->e = xmalloc(c->n * sizeof(group_expfactor)); - for (i = 0; i < c->n; i++) { - c->e[i].base = G_CREATE(c->g); - G_FROMINT(c->g, c->e[i].base, - mprand_range(MP_NEW, gp.p, &rand_global, 0)); - c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0); - } - dh_paramfree(&gp); - return (c); -} - -static void *grec_init(opts *o) -{ - gr_ctx *c = CREATE(gr_ctx); - const char *e; - ec_info ei; - ec p = EC_INIT; - size_t i; - - if (!o->name) - die(1, "can't generate elliptic curves"); - if ((e = ec_getinfo(&ei, o->name)) != 0) - die(1, "bad curve: %s", e); - c->g = group_ec(&ei); - if (!(o->f & OF_NOCHECK) && (e = G_CHECK(c->g, &rand_global)) != 0) - die(1, "bad group: %s", e); - if (!o->n) o->n = 1; - c->n = o->n; - c->e = xmalloc(c->n * sizeof(group_expfactor)); - for (i = 0; i < c->n; i++) { - c->e[i].base = G_CREATE(c->g); - ec_rand(ei.c, &p, &rand_global); - G_FROMEC(c->g, c->e[i].base, &p); - c->e[i].exp = mprand_range(MP_NEW, ei.r, &rand_global, 0); - } - EC_DESTROY(&p); - return (c); -} - -static void gr_run(void *cc) -{ - gr_ctx *c = cc; - ge *x = G_CREATE(c->g); - G_EXP(c->g, x, c->e[0].base, c->e[0].exp); - G_DESTROY(c->g, x); -} - -static void grsim_run(void *cc) -{ - gr_ctx *c = cc; - ge *x = G_CREATE(c->g); - G_MEXP(c->g, x, c->e, c->n); - G_DESTROY(c->g, x); -} - -/* --- RSA --- */ - -typedef struct rsapriv_ctx { - rsa_priv rp; - rsa_privctx rpc; - mp *m; -} rsapriv_ctx; - -static void *rsapriv_init(opts *o) -{ - rsapriv_ctx *c = CREATE(rsapriv_ctx); - - if (!o->fbits) o->fbits = 1024; - rsa_gen(&c->rp, o->fbits, &rand_global, 0, pgen_evspin, 0); - rsa_privcreate(&c->rpc, &c->rp, 0); - c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0); - return (c); -} - -static void *rsaprivblind_init(opts *o) -{ - rsapriv_ctx *c = CREATE(rsapriv_ctx); - - if (!o->fbits) o->fbits = 1024; - rsa_gen(&c->rp, o->fbits, &rand_global, 0, pgen_evspin, 0); - rsa_privcreate(&c->rpc, &c->rp, fibrand_create(0)); - c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0); - return (c); -} - -static void rsapriv_run(void *cc) -{ - rsapriv_ctx *c = cc; - mp *d = rsa_privop(&c->rpc, MP_NEW, c->m); - MP_DROP(d); -} - -typedef struct rsapub_ctx { - rsa_pub rp; - rsa_pubctx rpc; - mp *m; -} rsapub_ctx; - -static void *rsapub_init(opts *o) -{ - rsapub_ctx *c = CREATE(rsapub_ctx); - rsa_priv rp; - - if (!o->fbits) o->fbits = 1024; - rsa_gen(&rp, o->fbits, &rand_global, 0, pgen_evspin, 0); - c->rp.n = MP_COPY(rp.n); - c->rp.e = MP_COPY(rp.e); - rsa_privfree(&rp); - rsa_pubcreate(&c->rpc, &c->rp); - c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0); - return (c); -} - -static void rsapub_run(void *cc) -{ - rsapub_ctx *c = cc; - mp *d = rsa_pubop(&c->rpc, MP_NEW, c->m); - MP_DROP(d); -} - -/* --- Symmetric encryption --- */ - -typedef struct ksched_ctx { - const gccipher *c; - octet *k; - size_t ksz; -} ksched_ctx; - -static void *ksched_init(opts *o) -{ - ksched_ctx *c = CREATE(ksched_ctx); - if (!o->name) - die(1, "must specify encryption scheme name"); - if ((c->c = gcipher_byname(o->name)) == 0) - die(1, "encryption scheme `%s' not known", o->name); - c->ksz = keysz(o->gbits/8, c->c->keysz); - c->k = xmalloc(c->ksz); - rand_get(RAND_GLOBAL, c->k, c->ksz); - return (c); -} - -static void ksched_run(void *cc) -{ - ksched_ctx *c = cc; - gcipher *gc = GC_INIT(c->c, c->k, c->ksz); - GC_DESTROY(gc); -} - -typedef struct enc_ctx { - gcipher *c; - octet *m; - size_t sz; - size_t n; -} enc_ctx; - -static void *enc_init(opts *o) -{ - enc_ctx *c = CREATE(enc_ctx); - const gccipher *cc; - size_t ksz; - octet *k; - if (!o->name) - die(1, "must specify encryption scheme name"); - if ((cc = gcipher_byname(o->name)) == 0) - die(1, "encryption scheme `%s' not known", o->name); - ksz = keysz(0, cc->keysz); - k = xmalloc(ksz); - rand_get(RAND_GLOBAL, k, ksz); - c->c = GC_INIT(cc, k, ksz); - xfree(k); - c->sz = o->gbits ? o->gbits : 65536; - c->n = o->n ? o->n : 16; - c->m = xmalloc(c->sz); - return (c); -} - -static void enc_run(void *cc) -{ - enc_ctx *c = cc; - size_t i; - for (i = 0; i < c->n; i++) - GC_ENCRYPT(c->c, c->m, c->m, c->sz); -} - -/* --- Hashing --- */ - -typedef struct hash_ctx { - const gchash *h; - octet *m; - size_t sz; - size_t n; -} hash_ctx; - -static void *hash_init(opts *o) -{ - hash_ctx *c = CREATE(hash_ctx); - if (!o->name) - die(1, "must specify hash function name"); - if ((c->h = ghash_byname(o->name)) == 0) - die(1, "hash function `%s' not known", o->name); - c->sz = o->gbits ? o->gbits : 65536; - c->n = o->n ? o->n : 16; - c->m = xmalloc(c->sz); - return (c); -} - -static void hash_run(void *cc) -{ - hash_ctx *c = cc; - size_t i; - ghash *h = GH_INIT(c->h); - for (i = 0; i < c->n; i++) - GH_HASH(h, c->m, c->sz); - GH_DONE(h, 0); - GH_DESTROY(h); -} - -/* --- Job table --- */ - -typedef struct jobops { - const char *name; - void *(*init)(opts *); - void (*run)(void *); -} jobops; - -static const jobops jobtab[] = { - { "g-prime-exp", grp_init, gr_run }, - { "g-ec-mul", grec_init, gr_run }, - { "g-prime-exp-sim", grp_init, grsim_run }, - { "g-ec-mul-sim", grec_init, grsim_run }, - { "barrett-exp", bar_init, bar_run }, - { "barrett-exp-sim", bar_init, barsim_run }, - { "mont-exp", mont_init, mont_run }, - { "mont-exp-sim", mont_init, montsim_run }, - { "rsa-priv", rsapriv_init, rsapriv_run }, - { "rsa-priv-blind", rsaprivblind_init, rsapriv_run }, - { "rsa-pub", rsapub_init, rsapub_run }, - { "ksched", ksched_init, ksched_run }, - { "enc", enc_init, enc_run }, - { "hash", hash_init, hash_run }, - { 0, 0, 0 } -}; - -/*----- Main code ---------------------------------------------------------*/ - -void version(FILE *fp) -{ - pquis(fp, "$, Catacomb " VERSION "\n"); -} - -static void usage(FILE *fp) -{ - pquis(fp, "Usage: $ [-options] job\n"); -} - -static void help(FILE *fp) -{ - version(fp); - putc('\n', fp); - usage(fp); - pquis(fp, "\n\ -Various performance tests.\n\ -\n\ -Options:\n\ -\n\ --h, --help Show this help text.\n\ --v, --version Show program version number.\n\ --u, --usage Show terse usage message.\n\ --l, --list [ITEM...] List all the various names of things.\n\ -\n\ --C, --name=NAME Select curve/DH-group/enc/hash name.\n\ --b, --field-bits Field size for g-prime and rsa.\n\ --q, --no-check Don't check field/group for validity.\n\ --B, --group-bits Group size for g-prime; key size for ksched;\n\ - data size for enc and hash.\n\ --n, --factors=COUNT Number of factors for {exp,mul}-sim.\n\ --i, --intervals=COUNT Number of intervals to run for. [0; forever]\n\ --t, --time=TIME Length of an interval in seconds. [1]\n\ -"); -} - -#define LISTS(LI) \ - LI("Lists", list, \ - listtab[i].name, listtab[i].name) \ - LI("Jobs", job, \ - jobtab[i].name, jobtab[i].name) \ - LI("Elliptic curves", ec, \ - ectab[i].name, ectab[i].name) \ - LI("Diffie-Hellman groups", dh, \ - ptab[i].name, ptab[i].name) \ - LI("Encryption algorithms", cipher, \ - gciphertab[i], gciphertab[i]->name) \ - LI("Hash functions", hash, \ - ghashtab[i], ghashtab[i]->name) - -MAKELISTTAB(listtab, LISTS) - -static unsigned uarg(const char *what, const char *p) -{ - char *q; - unsigned long u; - errno = 0; - u = strtoul(p, &q, 0); - if (*q || u > UINT_MAX || q == p || errno) - die(1, "bad %s `%s'", what, p); - return (u); -} - -static double farg(const char *what, const char *p) -{ - char *q; - double f; - errno = 0; - f = strtod(p, &q); - if (*q || q == p || errno) - die(1, "bad %s `%s'", what, p); - return (f); -} - -int main(int argc, char *argv[]) -{ - int i; - opts o = { 0 }; - const jobops *j; - struct timeval tv_next, tv_now; - double t, ttot; - unsigned n; - unsigned long ii; - clock_t c_start, c_stop; - double itot; - void *p; - - ego(argv[0]); - o.t = 1; - for (;;) { - static const struct option opts[] = { - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'v' }, - { "usage", 0, 0, 'u' }, - { "list", 0, 0, 'l' }, - { "name", OPTF_ARGREQ, 0, 'C' }, - { "field-bits", OPTF_ARGREQ, 0, 'b' }, - { "group-bits", OPTF_ARGREQ, 0, 'B' }, - { "factors", OPTF_ARGREQ, 0, 'n' }, - { "intervals", OPTF_ARGREQ, 0, 'i' }, - { "time", OPTF_ARGREQ, 0, 't' }, - { "no-check", 0, 0, 'q' }, - { 0, 0, 0, 0 } - }; - - i = mdwopt(argc, argv, "hvulC:b:B:n:i:t:q", opts, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'h': help(stdout); exit(0); - case 'v': version(stdout); exit(0); - case 'u': usage(stdout); exit(0); - case 'l': exit(displaylists(listtab, argv + optind)); - case 'C': o.name = optarg; break; - case 'b': o.fbits = uarg("field bits", optarg); break; - case 'B': o.gbits = uarg("subgroup bits", optarg); break; - case 'n': o.n = uarg("factor count", optarg); break; - case 'i': o.i = uarg("interval count", optarg); break; - case 't': o.t = farg("interval length", optarg); break; - case 'q': o.f |= OF_NOCHECK; break; - default: usage(stderr); exit(1); - } - } - if (optind + 1 != argc) { usage(stderr); exit(1); } - - for (j = jobtab; j->name; j++) - if (strcmp(j->name, argv[optind]) == 0) break; - if (!j->name) die(1, "unknown job type `%s'", argv[optind]); - p = j->init(&o); - - n = 0; - ttot = itot = 0; - gettimeofday(&tv_now, 0); - do { - tv_addl(&tv_next, &tv_now, o.t, fmod(o.t * MILLION, MILLION)); - ii = 0; - c_start = clock(); - do { - j->run(p); - ii++; - gettimeofday(&tv_now, 0); - } while (TV_CMP(&tv_now, <, &tv_next)); - c_stop = clock(); - t = (double)(c_stop - c_start)/CLOCKS_PER_SEC; - itot += ii; - ttot += t; - printf("%5u: did = %5lu; /sec = %5f; avg /sec = %5f\n", - n, ii, ii/t, itot/ttot); - fflush(stdout); - n++; - } while (!o.i || n < o.i); - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/pfilt.c b/pfilt.c deleted file mode 100644 index ae99a9b..0000000 --- a/pfilt.c +++ /dev/null @@ -1,329 +0,0 @@ -/* -*-c-*- - * - * $Id: pfilt.c,v 1.6 2004/04/08 01:36:15 mdw Exp $ - * - * Finding and testing prime numbers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpint.h" -#include "pfilt.h" -#include "pgen.h" -#include "primetab.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @smallenough@ --- * - * - * Arguments: @mp *m@ = integer to test - * - * Returns: One of the @PGEN@ result codes. - * - * Use: Assuming that @m@ has been tested by trial division on every - * prime in the small-primes array, this function will return - * @PGEN_DONE@ if the number is less than the square of the - * largest small prime. - */ - -static int smallenough(mp *m) -{ - static mp *max = 0; - int rc = PGEN_TRY; - - if (!max) { - max = mp_fromuint(MP_NEW, MAXPRIME); - max = mp_sqr(max, max); - max->a->n--; /* Permanent allocation */ - } - if (MP_CMP(m, <=, MP_ONE)) - rc = PGEN_FAIL; - else if (MP_CMP(m, <, max)) - rc = PGEN_DONE; - return (rc); -} - -/* --- @pfilt_smallfactor@ --- * - * - * Arguments: @mp *m@ = integer to test - * - * Returns: One of the @PGEN@ result codes. - * - * Use: Tests a number by dividing by a number of small primes. This - * is a useful first step if you're testing random primes; for - * sequential searches, @pfilt_create@ works better. - */ - -int pfilt_smallfactor(mp *m) -{ - int rc = PGEN_TRY; - int i; - size_t sz = MP_LEN(m); - mparena *a = m->a ? m->a : MPARENA_GLOBAL; - mpw *v = mpalloc(a, sz); - - /* --- Fill in the residues --- */ - - for (i = 0; i < NPRIME; i++) { - if (!mpx_udivn(v, v + sz, m->v, m->vl, primetab[i])) { - if (MP_LEN(m) == 1 && m->v[0] == primetab[i]) - rc = PGEN_DONE; - else - rc = PGEN_FAIL; - break; - } - } - - /* --- Check for small primes --- */ - - if (rc == PGEN_TRY) - rc = smallenough(m); - - /* --- Done --- */ - - mpfree(a, v); - return (rc); -} - -/* --- @pfilt_create@ --- * - * - * Arguments: @pfilt *p@ = pointer to prime filtering context - * @mp *m@ = pointer to initial number to test - * - * Returns: One of the @PGEN@ result codes. - * - * Use: Tests an initial number for primality by computing its - * residue modulo various small prime numbers. This is fairly - * quick, but not particularly certain. If a @PGEN_TRY@ - * result is returned, perform Rabin-Miller tests to confirm. - */ - -int pfilt_create(pfilt *p, mp *m) -{ - int rc = PGEN_TRY; - int i; - size_t sz = MP_LEN(m); - mparena *a = m->a ? m->a : MPARENA_GLOBAL; - mpw *v = mpalloc(a, sz); - - /* --- Take a copy of the number --- */ - - mp_shrink(m); - p->m = MP_COPY(m); - - /* --- Fill in the residues --- */ - - for (i = 0; i < NPRIME; i++) { - p->r[i] = mpx_udivn(v, v + sz, m->v, m->vl, primetab[i]); - if (!p->r[i] && rc == PGEN_TRY) { - if (MP_LEN(m) == 1 && m->v[0] == primetab[i]) - rc = PGEN_DONE; - else - rc = PGEN_FAIL; - } - } - - /* --- Check for small primes --- */ - - if (rc == PGEN_TRY) - rc = smallenough(m); - - /* --- Done --- */ - - mpfree(a, v); - return (rc); -} - -/* --- @pfilt_destroy@ --- * - * - * Arguments: @pfilt *p@ = pointer to prime filtering context - * - * Returns: --- - * - * Use: Discards a context and all the resources it holds. - */ - -void pfilt_destroy(pfilt *p) -{ - mp_drop(p->m); -} - -/* --- @pfilt_step@ --- * - * - * Arguments: @pfilt *p@ = pointer to prime filtering context - * @mpw step@ = how much to step the number - * - * Returns: One of the @PGEN@ result codes. - * - * Use: Steps a number by a small amount. Stepping is much faster - * than initializing with a new number. The test performed is - * the same simple one used by @primetab_create@, so @PGEN_TRY@ - * results should be followed up by a Rabin-Miller test. - */ - -int pfilt_step(pfilt *p, mpw step) -{ - int rc = PGEN_TRY; - int i; - - /* --- Add the step on to the number --- */ - - p->m = mp_split(p->m); - mp_ensure(p->m, MP_LEN(p->m) + 1); - mpx_uaddn(p->m->v, p->m->vl, step); - mp_shrink(p->m); - - /* --- Update the residue table --- */ - - for (i = 0; i < NPRIME; i++) { - p->r[i] = (p->r[i] + step) % primetab[i]; - if (!p->r[i] && rc == PGEN_TRY) { - if (MP_LEN(p->m) == 1 && p->m->v[0] == primetab[i]) - rc = PGEN_DONE; - else - rc = PGEN_FAIL; - } - } - - /* --- Check for small primes --- */ - - if (rc == PGEN_TRY) - rc = smallenough(p->m); - - /* --- Done --- */ - - return (rc); -} - -/* --- @pfilt_muladd@ --- * - * - * Arguments: @pfilt *p@ = destination prime filtering context - * @const pfilt *q@ = source prime filtering context - * @mpw m@ = number to multiply by - * @mpw a@ = number to add - * - * Returns: One of the @PGEN@ result codes. - * - * Use: Multiplies the number in a prime filtering context by a - * small value and then adds a small value. The destination - * should either be uninitialized or the same as the source. - * - * Common things to do include multiplying by 2 and adding 0 to - * turn a prime into a jump for finding other primes with @q@ as - * a factor of @p - 1@, or multiplying by 2 and adding 1. - */ - -int pfilt_muladd(pfilt *p, const pfilt *q, mpw m, mpw a) -{ - int rc = PGEN_TRY; - int i; - - /* --- Multiply the big number --- */ - - { - mp *d = mp_new(MP_LEN(q->m) + 2, q->m->f); - mpx_umuln(d->v, d->vl, q->m->v, q->m->vl, m); - mpx_uaddn(d->v, d->vl, a); - if (p == q) - mp_drop(p->m); - mp_shrink(d); - p->m = d; - } - - /* --- Gallivant through the residue table --- */ - - for (i = 0; i < NPRIME; i++) { - p->r[i] = (q->r[i] * m + a) % primetab[i]; - if (!p->r[i] && rc == PGEN_TRY) { - if (MP_LEN(p->m) == 1 && p->m->v[0] == primetab[i]) - rc = PGEN_DONE; - else - rc = PGEN_FAIL; - } - } - - /* --- Check for small primes --- */ - - if (rc == PGEN_TRY) - rc = smallenough(p->m); - - /* --- Finished --- */ - - return (rc); -} - -/* --- @pfilt_jump@ --- * - * - * Arguments: @pfilt *p@ = pointer to prime filtering context - * @const pfilt *j@ = pointer to another filtering context - * - * Returns: One of the @PGEN@ result codes. - * - * Use: Steps a number by a large amount. Even so, jumping is much - * faster than initializing a new number. The test peformed is - * the same simple one used by @primetab_create@, so @PGEN_TRY@ - * results should be followed up by a Rabin-Miller test. - * - * Note that the number stored in the @j@ context is probably - * better off being even than prime. The important thing is - * that all of the residues for the number have already been - * computed. - */ - -int pfilt_jump(pfilt *p, const pfilt *j) -{ - int rc = PGEN_TRY; - int i; - - /* --- Add the step on --- */ - - p->m = mp_add(p->m, p->m, j->m); - - /* --- Update the residue table --- */ - - for (i = 0; i < NPRIME; i++) { - p->r[i] = p->r[i] + j->r[i]; - if (p->r[i] > primetab[i]) - p->r[i] -= primetab[i]; - if (!p->r[i] && rc == PGEN_TRY) { - if (MP_LEN(p->m) == 1 && p->m->v[0] == primetab[i]) - rc = PGEN_DONE; - else - rc = PGEN_FAIL; - } - } - - /* --- Check for small primes --- */ - - if (rc == PGEN_TRY) - rc = smallenough(p->m); - - /* --- Done --- */ - - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/pfilt.h b/pfilt.h deleted file mode 100644 index 24f94c7..0000000 --- a/pfilt.h +++ /dev/null @@ -1,157 +0,0 @@ -/* -*-c-*- - * - * $Id: pfilt.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Finding and testing prime numbers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_PFILT_H -#define CATACOMB_PFILT_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_PRIMETAB_H -# include "primetab.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct pfilt { - mp *m; - smallprime r[NPRIME]; -} pfilt; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @pfilt_smallfactor@ --- * - * - * Arguments: @mp *m@ = integer to test - * - * Returns: One of the @PGEN@ result codes. - * - * Use: Tests a number by dividing by a number of small primes. This - * is a useful first step if you're testing random primes; for - * sequential searches, @pfilt_create@ works better. - */ - -extern int pfilt_smallfactor(mp */*m*/); - -/* --- @pfilt_create@ --- * - * - * Arguments: @pfilt *p@ = pointer to prime filtering context - * @mp *m@ = pointer to initial number to test - * - * Returns: A @PGEN@ result code. - * - * Use: Tests an initial number for primality by computing its - * residue modulo various small prime numbers. This is fairly - * quick, but not particularly certain. If a @PGEN_TRY@ - * result is returned, perform Rabin-Miller tests to confirm. - */ - -extern int pfilt_create(pfilt */*p*/, mp */*m*/); - -/* --- @pfilt_destroy@ --- * - * - * Arguments: @pfilt *p@ = pointer to prime filtering context - * - * Returns: --- - * - * Use: Discards a context and all the resources it holds. - */ - -extern void pfilt_destroy(pfilt */*p*/); - -/* --- @pfilt_step@ --- * - * - * Arguments: @pfilt *p@ = pointer to prime filtering context - * @mpw step@ = how much to step the number - * - * Returns: One of the @PGEN@ result codes. - * - * Use: Steps a number by a small amount. Stepping is much faster - * than initializing with a new number. The test performed is - * the same simple one used by @primetab_create@, so @PGEN_TRY@ - * results should be followed up by a Rabin-Miller test. - */ - -extern int pfilt_step(pfilt */*p*/, mpw /*step*/); - -/* --- @pfilt_muladd@ --- * - * - * Arguments: @pfilt *p@ = destination prime filtering context - * @const pfilt *q@ = source prime filtering context - * @mpw m@ = number to multiply by - * @mpw a@ = number to add - * - * Returns: One of the @PGEN@ result codes. - * - * Use: Multiplies the number in a prime filtering context by a - * small value and then adds a small value. The destination - * should either be uninitialized or the same as the source. - * - * Common things to do include multiplying by 2 and adding 0 to - * turn a prime into a jump for finding other primes with @q@ as - * a factor of @p - 1@, or multiplying by 2 and adding 1. - */ - -extern int pfilt_muladd(pfilt */*p*/, const pfilt */*q*/, - mpw /*m*/, mpw /*a*/); - -/* --- @pfilt_jump@ --- * - * - * Arguments: @pfilt *p@ = pointer to prime filtering context - * @const pfilt *j@ = pointer to another filtering context - * - * Returns: One of the @PGEN@ result codes. - * - * Use: Steps a number by a large amount. Even so, jumping is much - * faster than initializing a new number. The test peformed is - * the same simple one used by @primetab_create@, so @PGEN_TRY@ - * results should be followed up by a Rabin-Miller test. - * - * Note that the number stored in the @j@ context is probably - * better off being even than prime. The important thing is - * that all of the residues for the number have already been - * computed. - */ - -extern int pfilt_jump(pfilt */*p*/, const pfilt */*j*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/pgen-gcd.c b/pgen-gcd.c deleted file mode 100644 index 863b151..0000000 --- a/pgen-gcd.c +++ /dev/null @@ -1,103 +0,0 @@ -/* -*-c-*- - * - * $Id: pgen-gcd.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Prime search stepper ensuring a low GCD for %$(p - 1)/2$% - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "pgen.h" - -/*----- Main code ---------------------------------------------------------*/ - -int pgen_gcdstep(int rq, pgen_event *ev, void *p) -{ - pgen_gcdstepctx *g = p; - int rc = PGEN_ABORT; - - switch (rq) { - - /* --- Set everything up --- * - * - * Call things off if @p@ and @jp@ have common factors, or if @q@, @r@ - * and @jq@ have common factors greater than @max@. - */ - - case PGEN_BEGIN: { - mp *p = ev->m; - mp_gcd(&g->g, 0, 0, p, g->jp.m); - if (MP_CMP(g->g, >, MP_ONE)) - return (PGEN_ABORT); - g->q = mp_lsr(MP_NEW, p, 1); - g->jq = mp_lsr(MP_NEW, g->jp.m, 1); - mp_gcd(&g->g, 0, 0, g->q, g->jq); - mp_gcd(&g->g, 0, 0, g->g, g->r); - if (MP_CMP(g->g, >, g->max)) { - mp_drop(g->q); - mp_drop(g->jq); - return (PGEN_ABORT); - } - rc = pfilt_create(&g->p, p); - mp_drop(p); - } break; - - /* --- Grind through another iteration --- */ - - case PGEN_TRY: - mp_drop(ev->m); - rc = pfilt_jump(&g->p, &g->jp); - g->q = mp_add(g->q, g->q, g->jq); - break; - - /* --- Finished --- */ - - case PGEN_DONE: - pfilt_destroy(&g->p); - mp_drop(g->q); - mp_drop(g->jq); - return (PGEN_DONE); - } - - /* --- Step on until everything is OK --- */ - - for (;;) { - if (rc != PGEN_FAIL) { - mp_gcd(&g->g, 0, 0, g->r, g->q); - if (MP_CMP(g->g, >, g->max)) - rc = PGEN_FAIL; - } - if (rc != PGEN_FAIL) - break; - rc = pfilt_jump(&g->p, &g->jp); - g->q = mp_add(g->q, g->q, g->jq); - } - - ev->m = MP_COPY(g->p.m); - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/pgen-simul.c b/pgen-simul.c deleted file mode 100644 index 175b009..0000000 --- a/pgen-simul.c +++ /dev/null @@ -1,170 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Simultaneous prime search - * - * (c) 2006 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#include "mprand.h" -#include "pgen.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rcmerge@ --- * - * - * Arguments: @int a, b@ = a pair of @PGEN@ return codes - * - * Returns: The overall return code capturing both. - */ - -static int rcmerge(int a, int b) -{ -#define FROB(state) \ - if (a == PGEN_##state || b == PGEN_##state) return (PGEN_##state) - FROB(FAIL); - FROB(TRY); - FROB(PASS); -#undef FROB - return (PGEN_DONE); -} - -/* --- @pgen_simulstep@ --- * - * - * Step a collection of numbers simultaneously. - */ - -int pgen_simulstep(int rq, pgen_event *ev, void *p) -{ - pgen_simulctx *ss = p; - pgen_simulprime *sp; - int rc = PGEN_ABORT, nrc; - unsigned i; - mp *q; - - assert(ss->n); - switch (rq) { - case PGEN_BEGIN: - rc = PGEN_DONE; - q = MP_NEW; - for (i = 0; i < ss->n; i++) { - sp = &ss->v[i]; - q = mp_mul(q, ss->step, sp->mul); - if (MP_LEN(q) <= 1) - sp->u.step = q->v[0]; - else { - sp->u.jump = xmalloc(sizeof(pfilt)); - pfilt_create(sp->u.jump, q); - sp->f |= PGENF_JUMP; - } - q = mp_mul(q, ev->m, sp->mul); - q = mp_add(q, q, sp->add); - nrc = pfilt_create(&sp->p, q); - rc = rcmerge(rc, nrc); - } - MP_DROP(q); - if (rc != PGEN_FAIL) - goto done; - case PGEN_TRY: - for (;;) { - rc = PGEN_DONE; - for (i = 0; i < ss->n; i++) { - sp = &ss->v[i]; - if (sp->f & PGENF_JUMP) - nrc = pfilt_jump(&sp->p, sp->u.jump); - else - nrc = pfilt_step(&sp->p, sp->u.step); - rc = rcmerge(rc, nrc); - } - if (rc != PGEN_FAIL) - goto done; - } - done: - mp_drop(ev->m); - ev->m = MP_COPY(ss->v[0].p.m); - break; - case PGEN_DONE: - for (i = 0; i < ss->n; i++) { - sp = &ss->v[i]; - if (sp->f & PGENF_JUMP) { - pfilt_destroy(sp->u.jump); - xfree(sp->u.jump); - } - if (sp->f & PGENF_KEEP) - sp->u.x = MP_COPY(sp->p.m); - pfilt_destroy(&sp->p); - } - rc = PGEN_DONE; - break; - } - return (rc); -} - -/* --- @pgen_simultest@ --- * - * - * Test a collection of numbers simultaneously. - */ - -int pgen_simultest(int rq, pgen_event *ev, void *p) -{ - pgen_simulctx *ss = p; - pgen_simulprime *sp; - int rc; - unsigned i; - mp *m; - - assert(ss->n); - switch (rq) { - case PGEN_BEGIN: - for (i = 0; i < ss->n; i++) - rabin_create(&ss->v[i].r, ss->v[i].p.m); - rc = PGEN_TRY; - break; - case PGEN_TRY: - m = MP_NEW; - for (i = 0; i < ss->n; i++) { - sp = &ss->v[i]; - m = mprand_range(m, sp->p.m, ev->r, 0); - rc = rabin_test(&sp->r, m); - if (rc != PGEN_PASS) - break; - } - mp_drop(m); - break; - case PGEN_DONE: - for (i = 0; i < ss->n; i++) - rabin_destroy(&ss->v[i].r); - rc = PGEN_DONE; - break; - } - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/pgen-stdev.c b/pgen-stdev.c deleted file mode 100644 index c917998..0000000 --- a/pgen-stdev.c +++ /dev/null @@ -1,131 +0,0 @@ -/* -*-c-*- - * - * $Id: pgen-stdev.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Standard event handlers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include "pgen.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @pgen_evspin@ --- * - * - * Displays a spinning baton to show progress. - */ - -int pgen_evspin(int rq, pgen_event *ev, void *p) -{ - static char spinner[] = "/-\\|"; - static char *q = spinner; - - switch (rq) { - case PGEN_PASS: - case PGEN_FAIL: - putchar(*q++); - putchar('\b'); - fflush(stdout); - if (!*q) - q = spinner; - break; - case PGEN_DONE: - case PGEN_ABORT: - putchar(' '); - putchar('\b'); - fflush(stdout); - break; - } - return (0); -} - -/* --- @pgen_ev@ --- * - * - * Traditional event handler, shows dots for each test. - */ - -int pgen_ev(int rq, pgen_event *ev, void *p) -{ - switch (rq) { - case PGEN_BEGIN: - printf("Searching for %s: ", ev->name); - fflush(stdout); - break; - case PGEN_FAIL: - putchar('.'); - fflush(stdout); - break; - case PGEN_PASS: - putchar('+'); - fflush(stdout); - break; - case PGEN_DONE: - puts("+ ok"); - break; - case PGEN_ABORT: - puts(" failed"); - break; - } - return (0); -} - -/* --- @pgen_subev@ --- * - * - * Subsidiary event handler, mainly for Lim-Lee searches and so on. - */ - -int pgen_subev(int rq, pgen_event *ev, void *p) -{ - switch (rq) { - case PGEN_BEGIN: - printf("[%s: ", ev->name); - fflush(stdout); - break; - case PGEN_FAIL: - putchar('.'); - fflush(stdout); - break; - case PGEN_PASS: - putchar('+'); - fflush(stdout); - break; - case PGEN_DONE: - fputs("+]", stdout); - fflush(stdout); - break; - case PGEN_ABORT: - fputs(" failed]", stdout); - fflush(stdout); - break; - } - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/pgen.c b/pgen.c deleted file mode 100644 index 1a2a8ac..0000000 --- a/pgen.c +++ /dev/null @@ -1,422 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Prime generation glue - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include - -#include "fibrand.h" -#include "grand.h" -#include "mp.h" -#include "mprand.h" -#include "pgen.h" -#include "pfilt.h" -#include "rabin.h" - -/*----- Standard prime filter ---------------------------------------------*/ - -/* --- @pgen_filter@ --- */ - -int pgen_filter(int rq, pgen_event *ev, void *p) -{ - pgen_filterctx *f = p; - int rc = PGEN_FAIL; - - switch (rq) { - case PGEN_BEGIN: - rc = pfilt_create(&f->f, ev->m); - mp_drop(ev->m); - break; - case PGEN_TRY: - mp_drop(ev->m); - break; - case PGEN_DONE: - pfilt_destroy(&f->f); - return (PGEN_DONE); - default: - rc = PGEN_ABORT; - break; - } - - if (rc == PGEN_FAIL && !((f->step | f->f.m->v[0]) & 1)) - rc = pfilt_step(&f->f, 1); - while (rc == PGEN_FAIL) - rc = pfilt_step(&f->f, f->step); - ev->m = MP_COPY(f->f.m); - return (rc); -} - -/* --- @pgen_jump@ --- * - * - * Similar to the standard @pgen_filter@, but jumps in large steps rather - * than small ones. - */ - -int pgen_jump(int rq, pgen_event *ev, void *p) -{ - pgen_jumpctx *f = p; - int rc = PGEN_ABORT; - - switch (rq) { - case PGEN_BEGIN: { - mp *g = MP_NEW; - mp_gcd(&g, 0, 0, ev->m, f->j->m); - if (MP_CMP(g, >, MP_ONE)) { - mp_drop(g); - return (PGEN_ABORT); - } - mp_drop(g); - rc = pfilt_create(&f->f, ev->m); - mp_drop(ev->m); - } break; - case PGEN_TRY: - mp_drop(ev->m); - rc = pfilt_jump(&f->f, f->j); - break; - case PGEN_DONE: - pfilt_destroy(&f->f); - return (PGEN_DONE); - } - - while (rc == PGEN_FAIL) - rc = pfilt_jump(&f->f, f->j); - ev->m = MP_COPY(f->f.m); - return (rc); -} - -/*----- Standard prime test -----------------------------------------------*/ - -/* --- @pgen_test@ --- */ - -int pgen_test(int rq, pgen_event *ev, void *p) -{ - rabin *r = p; - int rc = PGEN_ABORT; - - switch (rq) { - case PGEN_BEGIN: - rabin_create(r, ev->m); - rc = PGEN_TRY; - break; - case PGEN_TRY: - if (!ev->tests) - rc = rabin_rtest(r, MP_TWO); - else { - mp *a = mprand_range(MP_NEW, ev->m, ev->r, 0); - rc = rabin_rtest(r, a); - mp_drop(a); - } - break; - case PGEN_DONE: - rabin_destroy(r); - rc = PGEN_DONE; - break; - } - - return (rc); -} - -/*----- The main driver ---------------------------------------------------*/ - -/* --- @pgen@ --- * - * - * Arguments: @const char *name@ = name of the value being searched for - * @mp *d@ = destination for the result integer - * @mp *m@ = start value to pass to stepper - * @pgen_proc *event@ = event handler function - * @void *ectx@ = context argument for event andler - * @unsigned steps@ = number of steps to take in search - * @pgen_proc *step@ = stepper function to use - * @void *sctx@ = context argument for stepper - * @unsigned tests@ = number of tests to make - * @pgen_proc *test@ = tester function to use - * @void *tctx@ = context argument for tester - * - * Returns: Pointer to final result, or null. - * - * Use: A generalized prime-number search skeleton. Yes, that's a - * scary number of arguments. - */ - -mp *pgen(const char *name, mp *d, mp *m, pgen_proc *event, void *ectx, - unsigned steps, pgen_proc *step, void *sctx, - unsigned tests, pgen_proc *test, void *tctx) -{ - pgen_event ev; - int rq, rc; - pgen_proc *proc; - void *ctx; - int p; - - enum { P_STEP, P_TEST }; - - /* --- Set up the initial event block --- */ - - ev.name = name; - if (m) - ev.m = MP_COPY(m); - else - ev.m = 0; - ev.steps = 0; - ev.tests = 0; - ev.r = fibrand_create(0); - - /* --- Tell the event handler we're under way --- */ - - if (event && event(PGEN_BEGIN, &ev, ectx) == PGEN_ABORT) { - ev.r->ops->destroy(ev.r); - return (0); - } - - /* --- Set up for the initial call --- */ - - proc = step; ctx = sctx; p = P_STEP; rq = PGEN_BEGIN; - - /* --- Enter the great maelstrom of state transitions --- */ - - for (;;) { - unsigned act = 0; - -#define A_STEP 1u -#define A_TEST 2u -#define A_EVENT 4u -#define A_ENDTEST 8u -#define A_ENDSTEP 16u -#define A_DONE 32u - - /* --- Call the procedure and decide what to do next --- */ - - rc = proc(rq, &ev, ctx); - switch (rc) { - case PGEN_TRY: - if (p == P_TEST) - rq = PGEN_TRY; - else { - act |= A_EVENT; - proc = test; ctx = tctx; p = P_TEST; - rq = PGEN_BEGIN; - } - break; - case PGEN_PASS: - act |= A_TEST | A_EVENT; - if (p == P_TEST) - rq = PGEN_TRY; - else { - proc = test; ctx = tctx; p = P_TEST; - rq = PGEN_BEGIN; - } - break; - case PGEN_FAIL: - act |= A_STEP; - if (p == P_TEST) { - act |= A_ENDTEST | A_EVENT; - proc = step; ctx = sctx; p = P_STEP; - } - rq = PGEN_TRY; - break; - case PGEN_DONE: - act |= A_EVENT | A_DONE | A_ENDSTEP; - if (p == P_TEST) - act |= A_ENDTEST; - break; - case PGEN_ABORT: - act |= A_EVENT | A_DONE; - if (p == P_TEST || rq == PGEN_TRY) - act |= A_ENDSTEP; - if (p == P_TEST && rq != PGEN_BEGIN) - act |= A_ENDTEST; - break; - default: - assert(((void)"Invalid response from function", 0)); - break; - } - - /* --- If decrementing counters is requested, do that --- */ - - if ((act & A_STEP) && steps) { - ev.steps++; - if (ev.steps == steps) { - act |= A_EVENT | A_ENDSTEP | A_DONE; - rc = PGEN_ABORT; - } - ev.tests = 0; - } - - if ((act & A_TEST) && tests) { - ev.tests++; - if (ev.tests == tests) { - act |= A_ENDTEST | A_ENDSTEP | A_DONE; - rc = PGEN_DONE; - } - } - - /* --- Report an event if so directed --- */ - - if ((act & A_EVENT) && event && event(rc, &ev, ectx) == PGEN_ABORT) { - rc = PGEN_ABORT; - if (!(act & A_DONE)) { - act |= A_ENDSTEP | A_DONE; - if (p == P_TEST) - act |= A_ENDTEST; - } - } - - /* --- Close down tester and stepper functions --- */ - - if (act & A_ENDTEST) - test(PGEN_DONE, &ev, tctx); - if (act & A_ENDSTEP) - step(PGEN_DONE, &ev, sctx); - - /* --- Stop the entire test if necessary --- */ - - if (act & A_DONE) - break; - } - - /* --- Tidy up and return --- */ - - if (rc == PGEN_ABORT) { - mp_drop(ev.m); - ev.m = 0; - } - ev.r->ops->destroy(ev.r); - mp_drop(d); - - return (ev.m); -} - -/* --- @pgen_primep@ --- * - * - * Arguments: @mp *p@ = a number to check - * @grand *gr@ = a random number source - * - * Returns: Nonzero if @p@ is really prime. - */ - -int pgen_primep(mp *p, grand *gr) -{ - int i; - rabin r; - mp *x = MP_NEW; - - if (MP_NEGP(p)) return (0); - switch (pfilt_smallfactor(p)) { - case PGEN_DONE: return (1); - case PGEN_FAIL: return (0); - } - rabin_create(&r, p); - for (i = 32; i; i--) { - x = mprand_range(x, p, gr, 0); - if (rabin_rtest(&r, x) == PGEN_FAIL) - break; - } - MP_DROP(x); - rabin_destroy(&r); - return (!i); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -static int t_primep(dstr *v) -{ - mp *m = *(mp **)v[0].buf; - int e = *(int *)v[1].buf; - int r; - grand *rng; - int ok = 1; - - rng = fibrand_create(0); - r = pgen_primep(m, rng); - GR_DESTROY(rng); - if (e != r) { - fputs("\n*** primep failed", stderr); - fputs("\nm = ", stderr); mp_writefile(m, stderr, 10); - fprintf(stderr, "\nexpected %d", e); - fprintf(stderr, "\nreported %d", r); - fputc('\n', stderr); - ok = 0; - } - - mp_drop(m); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int verify(dstr *v) -{ - mp *m = *(mp **)v[0].buf; - mp *q = *(mp **)v[1].buf; - mp *p; - int ok = 1; - - pgen_filterctx pf; - rabin r; - - pf.step = 2; - p = pgen("p", MP_NEW, m, pgen_evspin, 0, 0, pgen_filter, &pf, - rabin_iters(mp_bits(m)), pgen_test, &r); - if (!p || !MP_EQ(p, q)) { - fputs("\n*** pgen failed", stderr); - fputs("\nm = ", stderr); mp_writefile(m, stderr, 10); - fputs("\np = ", stderr); mp_writefile(p, stderr, 10); - fputs("\nq = ", stderr); mp_writefile(q, stderr, 10); - fputc('\n', stderr); - ok = 0; - } - - mp_drop(m); - mp_drop(q); - mp_drop(p); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "pgen", verify, { &type_mp, &type_mp, 0 } }, - { "primep", t_primep, { &type_mp, &type_int, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - test_run(argc, argv, tests, SRCDIR "/tests/pgen"); - return (0); -} -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/pgen.h b/pgen.h deleted file mode 100644 index a066e28..0000000 --- a/pgen.h +++ /dev/null @@ -1,291 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Prime generation glue - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_PGEN_H -#define CATACOMB_PGEN_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_PFILT_H -# include "pfilt.h" -#endif - -#ifndef CATACOMB_RABIN_H -# include "rabin.h" -#endif - -/*----- Event handling ----------------------------------------------------* - * - * Different programs and architectures will want to show progress of prime - * searches and similar processes in different ways. Of course, for simple - * searches, it's possible to use the @pfilt@ and @rabin@ functions and - * maintain control over the general control flow throughout the search. - * - * For more complex cases, this sort of control is undesirable. It's - * possible to specify an event handler which is informed in abstract about - * the search. The event handler can also request the search be aborted. - */ - -/* --- Event code constants --- * - * - * You're allowed to rely on the values of @PGEN_DONE@ and @PGEN_ABORT@. - */ - -enum { - PGEN_BEGIN = 1, /* Search for value begins */ - PGEN_TRY, /* A new candidate has appeared */ - PGEN_FAIL, /* The candidate failed the test */ - PGEN_PASS, /* The candidate passed a test */ - PGEN_DONE = 0, /* A good value has been found */ - PGEN_ABORT = -1 /* The search has been aborted */ -}; - -/* --- Event information --- * - * - * Note that the pseudorandom number generator supplied is not - * cryptographically strong. - */ - -typedef struct pgen_event { - const char *name; /* Which quantity is being found */ - mp *m; /* Current value under test */ - unsigned steps; /* Number of candidates left */ - unsigned tests; /* Tests left before passing */ - grand *r; /* Source of random numbers */ -} pgen_event; - -/*----- Prime search parameters -------------------------------------------* - * - * The prime search is parameterized in a large number of ways, although this - * isn't so much of a surprise given the different sorts of properties - * required from prime numbers in cryptographic applications. - * - * There are two main things which need to be configured: stepping, and - * testing. (Filtering is done as part of stepping.) - * - * The functions here provide a toolkit for constructing stepping and testing - * routines. In a lot of cases, the functions can be used directly; in - * others, simple bits of glue need be written. - * - * Two types of functions are defined: steppers and testers, but their - * interfaces are substantially similar. Each is given a request code, a - * context block and an event block. It is meant to update its context and - * the event block and return an event code. - * - * A call with a request of @PGEN_BEGIN@ asks the stepper or tester to - * initialize itself using the information in its event block and context. A - * return of @PGEN_FAIL@ reports an immediate failure; @PGEN_ABORT@ reports a - * fatal problem; @PGEN_DONE@ reports immediate success. @PGEN_TRY@ reports - * successful initialization and requests test iterations. - * - * A call to a stepper with a request of @PGEN_TRY@ asks it to step to the - * next possible candidate, replacing the value @m@ in the event block with - * the new candidate. A call to a tester with a request of @PGEN_TRY@ - * runs one pass of the test. It should return @PGEN_FAIL@ to report a - * failure, @PGEN_PASS@ to report a success and request another iteration, - * @PGEN_DONE@ to report final acceptance and @PGEN_ABORT@ to terminate the - * search unsuccessfully. Note that even if the search is aborted, a - * shutdown request is still made. - * - * A call with a request of @PGEN_DONE@ closes down the stepper or tester. - * After a successful initialization (i.e., a return of something other than - * @PGEN_ABORT@), a shutdown call is guaranteed. The return code is ignored. - */ - -typedef int pgen_proc(int /*rq*/, pgen_event */*ev*/, void */*p*/); - -/*----- Simple handler functions ------------------------------------------*/ - -/* --- @pgen_filter@ --- * - * - * A prime generation context contains the information required for the - * simple prime filter and tester presented here. - */ - -typedef struct pgen_filterctx { - unsigned step; /* Step size (set by client) */ - pfilt f; /* The rapid prime filter */ -} pgen_filterctx; - -extern pgen_proc pgen_filter; - -/* --- @pgen_jump@ --- * - * - * Similar to the standard @pgen_filter@, but jumps in large steps rather - * than small ones. - */ - -typedef struct pgen_jumpctx { - const pfilt *j; - pfilt f; -} pgen_jumpctx; - -extern pgen_proc pgen_jump; - -/* --- @pgen_test@ --- * - * - * Runs the Rabin-Miller primality test. The context block is simply a - * @rabin@ context. - */ - -extern pgen_proc pgen_test; - -/*----- Simultaneous primality checking -----------------------------------*/ - -typedef struct pgen_simulprime { - mp *mul, *add; /* Arguments from the client */ - unsigned f; /* Flags, set by client, changed */ -#define PGENF_KEEP 1u /* Keep this prime's value */ -#define PGENF_JUMP 8u /* Use jump table, not stepping */ - pfilt p; /* This prime's filter */ - rabin r; /* Rabin testing context */ - union { - mpw step; /* The simple step to use */ - pfilt *jump; /* The jump to move by */ - mp *x; /* The result, if wanted */ - } u; -} pgen_simulprime; - -typedef struct pgen_simulctx { - pgen_simulprime *v; /* Vector of related primes */ - unsigned n; /* Size of the vector */ - mp *step; /* Basic stepping value */ -} pgen_simulctx; - -/* --- @pgen_simulstep@ --- * - * - * Step a collection of numbers simultaneously. - */ - -extern pgen_proc pgen_simulstep; - -/* --- @pgen_simultest@ --- * - * - * Test a collection of numbers simultaneously. - */ - -extern pgen_proc pgen_simultest; - -/*----- Miscellaneous steppers and testers --------------------------------*/ - -typedef struct pgen_gcdstepctx { - pfilt p, jp; /* Prime filter and step filter */ - mp *q, *jq; /* %$p - 1$%, and a step value*/ - mp *r; /* Other argument for GCD */ - mp *g; /* GCD output (must be inited) */ - mp *max; /* Maximum permissible GCD */ -} pgen_gcdstepctx; - -/* --- @pgen_gcdstep@ --- * - * - * Steps @p@ and @q@, until @p@ has no small factors, and - * %$\gcd(p, r) \le max$%. - */ - -extern pgen_proc pgen_gcdstep; - -/*----- Standard event handlers -------------------------------------------*/ - -/* --- @pgen_evspin@ --- * - * - * Displays a spinning baton to show progress. - */ - -extern pgen_proc pgen_evspin; - -/* --- @pgen_ev@ --- * - * - * Traditional event handler, shows dots for each test. - */ - -extern pgen_proc pgen_ev; - -/* --- @pgen_subev@ --- * - * - * Subsidiary event handler, mainly for Lim-Lee searches and so on. - */ - -extern pgen_proc pgen_subev; - -/*----- The main driver ---------------------------------------------------*/ - -/* --- @pgen@ --- * - * - * Arguments: @const char *name@ = name of the value being searched for - * @mp *d@ = destination for resulting integer - * @mp *m@ = start value to pass to stepper - * @pgen_proc *event@ = event handler function - * @void *ectx@ = context argument for event andler - * @unsigned steps@ = number of steps to take in search - * @pgen_proc *step@ = stepper function to use - * @void *sctx@ = context argument for stepper - * @unsigned tests@ = number of tests to make - * @pgen_proc *test@ = tester function to use - * @void *tctx@ = context argument for tester - * - * Returns: The resulting value, or null. - * - * Use: A generalized prime-number search skeleton. Yes, that's a - * scary number of arguments. - */ - -extern mp *pgen(const char */*name*/, mp */*d*/, mp */*m*/, - pgen_proc */*event*/, void */*ectx*/, - unsigned /*steps*/, pgen_proc */*step*/, void */*sctx*/, - unsigned /*tests*/, pgen_proc */*test*/, void */*tctx*/); - -/* --- @pgen_primep@ --- * - * - * Arguments: @mp *p@ = a number to check - * @grand *gr@ = a random number source - * - * Returns: Nonzero if @p@ is really prime. - */ - -extern int pgen_primep(mp */*p*/, grand */*gr*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/pixie-common.c b/pixie-common.c deleted file mode 100644 index fbb7f11..0000000 --- a/pixie-common.c +++ /dev/null @@ -1,376 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Common code for Pixie client and server (Unix-specific) - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "pixie.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @pixie_address@ --- * - * - * Arguments: @const char *sock@ = pointer to socket name - * @size_t *psz@ = where to write the address size - * - * Returns: Pointer to filled-in Unix-domain socket address. - * - * Use: Returns a Unix-domain socket address to use to find the - * passphrase pixie. - */ - -struct sockaddr_un *pixie_address(const char *sock, size_t *psz) -{ - dstr d = DSTR_INIT; - - /* --- Get the default socket path if none specified --- */ - - if (!sock) - sock = getenv("CATACOMB_PIXIE_SOCKET"); - if (!sock) - sock = "%h/.catacomb/pixie"; - - /* --- Substitute interesting sequences in the path --- */ - - { - const char *q, *qq; - - q = sock; - for (;;) { - qq = strchr(q, '%'); - if (!qq || !qq[1]) { - DPUTS(&d, q); - break; - } - DPUTM(&d, q, qq - q); - q = qq + 1; - switch (*q) { - case 'u': - qq = getenv("USER"); - if (!qq) - qq = getenv("LOGNAME"); - if (!qq) { - struct passwd *pw = getpwuid(getuid()); - if (pw) - qq = pw->pw_name; - else - qq = ""; - } - DPUTS(&d, qq); - break; - case 'h': - qq = getenv("HOME"); - if (!qq) { - struct passwd *pw = getpwuid(getuid()); - if (pw) - qq = pw->pw_dir; - else - qq = ""; - } - DPUTS(&d, qq); - break; - default: - DPUTC(&d, '%'); - DPUTC(&d, *q); - break; - } - q++; - } - DPUTZ(&d); - } - - /* --- Allocate and initialize the socket address --- */ - - { - struct sockaddr_un *sun; - size_t bsz = offsetof(struct sockaddr_un, sun_path); - *psz = bsz + d.len + 1; - sun = xmalloc(bsz + d.len + 1); - memset(sun, 0, bsz); - sun->sun_family = AF_UNIX; - memcpy(sun->sun_path, d.buf, d.len + 1); - dstr_destroy(&d); - return (sun); - } -} - -/* --- @pixie_fdline@ --- * - * - * Arguments: @int fd@ = file descriptor to read from - * @char *buf@ = pointer to buffer - * @size_t sz@ = size of buffer - * - * Returns: --- - * - * Use: Reads a line from a file descriptor. The read is done one - * character at a time. If the entire line won't fit, the end - * is truncated. The line is null terminated. - */ - -void pixie_fdline(int fd, char *buf, size_t sz) -{ - char *p = buf; - char *q = p + sz - 1; - - for (;;) { - char c; - if (read(fd, &c, 1) < 1) - break; - if (c == '\n') - break; - if (p < q) - *p++ = c; - } - *p = 0; -} - -/* --- @pixie_getpass@ --- * - * - * Arguments: @const char *prompt@ = pointer to prompt string - * @char *buf@ = pointer to buffer - * @size_t sz@ = size of buffer - * - * Returns: Zero if it worked OK, nonzero otherwise. - * - * Use: Reads a passphrase from the terminal or some other requested - * source. - */ - -int pixie_getpass(const char *prompt, char *buf, size_t sz) -{ - const char *pfd = getenv("CATACOMB_PASSPHRASE_FD"); - int fd = 0; - - /* --- See whether a terminal is what's wanted --- */ - - if (pfd) { - fd = atoi(pfd); - pixie_fdline(fd, buf, sz); - } else { - struct termios ta; - struct termios ota; - char nl = '\n'; - - if ((fd = open("/dev/tty", O_RDWR)) < 0) - goto fail_0; - if (tcgetattr(fd, &ta) < 0) - goto fail_1; - ota = ta; - ta.c_lflag &= ~(ECHO | ISIG); - if (tcsetattr(fd, TCSAFLUSH, &ta)) - goto fail_1; - write(fd, prompt, strlen(prompt)); - pixie_fdline(fd, buf, sz); - tcsetattr(fd, TCSAFLUSH, &ota); - write(fd, &nl, 1); - close(fd); - } - return (0); - - /* --- Tidy up if things went wrong --- */ - -fail_1: - close(fd); -fail_0: - return (-1); -} - -/* --- @pixie_open@ --- * - * - * Arguments: @const char *sock@ = path to pixie socket - * - * Returns: Less than zero if it failed, or file descriptor. - * - * Use: Opens a connection to a passphrase pixie. - */ - -int pixie_open(const char *sock) -{ - struct sockaddr_un *sun; - size_t sz; - int fd; - - /* --- Open the connection --- */ - - if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) - goto fail_0; - sun = pixie_address(sock, &sz); - if (connect(fd, (struct sockaddr *)sun, sz)) - goto fail_1; - xfree(sun); - return (fd); - - /* --- Tidy up if things went wrong --- */ - -fail_1: - xfree(sun); - close(fd); -fail_0: - return (-1); -} - -/* --- @pixie_read@ --- * - * - * Arguments: @int fd@ = connection to passphrase pixie - * @const char *tag@ = pointer to tag string - * @unsigned mode@ = reading mode - * @char *buf@ = pointer to destination buffer - * @size_t sz@ = size of the buffer - * - * Returns: Zero if all went well, @-1@ if the read fails, @+1@ to - * request the passphrase from the user. - * - * Use: Reads a passphrase from the pixie. - */ - -int pixie_read(int fd, const char *tag, unsigned mode, char *buf, size_t sz) -{ - dstr d = DSTR_INIT; - char *p, *q; - - /* --- Send the request --- */ - - dstr_putf(&d, "%s %s\n", mode == PMODE_READ ? "PASS" : "VERIFY", tag); - write(fd, d.buf, d.len); - dstr_destroy(&d); - - /* --- Sort out the result --- */ - -again: - pixie_fdline(fd, buf, sz); - p = buf; - if ((q = str_getword(&p)) == 0) - return (-1); - if (strcmp(q, "INFO") == 0) - goto again; - else if (strcmp(q, "MISSING") == 0) - return (+1); - else if (strcmp(q, "OK") != 0) - return (-1); - - /* --- Return the final answer --- */ - - if (p) - memmove(buf, p, strlen(p) + 1); - else - *buf = 0; - return (0); -} - -/* --- @pixie_set@ --- * - * - * Arguments: @int fd@ = pixie file descriptor - * @const char *tag@ = pointer to tag string - * @const char *phrase@ = pointer to passphrase string - * - * Returns: --- - * - * Use: Sends a passphrase to the passphrase pixie. - */ - -void pixie_set(int fd, const char *tag, const char *phrase) -{ - dstr d = DSTR_INIT; - char buf[16]; - size_t sz = strlen(phrase); - char nl = '\n'; - char *p, *q; - - /* --- Send the request --- * - * - * I didn't want to copy it out of the caller's buffer. @writev@ may - * produce a copy, too, so I didn't do that either. - */ - - dstr_putf(&d, "SET %s -- ", tag); - write(fd, d.buf, d.len); - write(fd, phrase, sz); - write(fd, &nl, 1); - dstr_destroy(&d); - - /* --- Pick up the pieces --- */ - -again: - pixie_fdline(fd, buf, sizeof(buf)); - p = buf; - if ((q = str_getword(&p)) != 0 && strcmp(q, "INFO") == 0) - goto again; -} - -/* --- @pixie_cancel@ --- * - * - * Arguments: @int fd@ = pixie file descriptor - * @const char *tag@ = pointer to tag string - * - * Returns: --- - * - * Use: Cancels a passphrase if it turns out to be bogus. - */ - -void pixie_cancel(int fd, const char *tag) -{ - dstr d = DSTR_INIT; - char buf[16]; - char *p, *q; - - /* --- Send the request --- */ - - dstr_putf(&d, "FLUSH %s\n", tag); - write(fd, d.buf, d.len); - dstr_destroy(&d); - - /* --- Sort out the result --- */ - -again: - pixie_fdline(fd, buf, sizeof(buf)); - p = buf; - if ((q = str_getword(&p)) != 0 && strcmp(q, "INFO") == 0) - goto again; -} - -/*----- That's all, folks -------------------------------------------------*/ - diff --git a/pixie.c b/pixie.c deleted file mode 100644 index af6483a..0000000 --- a/pixie.c +++ /dev/null @@ -1,1462 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Passphrase pixie for Catacomb - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "arena.h" -#include "lmem.h" -#include "passphrase.h" -#include "pixie.h" - -/*----- Static variables --------------------------------------------------*/ - -static unsigned long timeout = 900; -static sel_state sel; -static unsigned verbose = 1; -static const char *command = 0; -static lmem lm; -static unsigned flags = 0; - -#define F_SYSLOG 1u -#define F_FETCH 2u - -/*----- Event logging -----------------------------------------------------*/ - -/* --- @log@ --- * - * - * Arguments: @const char *p@ = @printf@-style format string - * @...@ = extra arguments to fill in - * - * Returns: --- - * - * Use: Writes out a timestamped log message. - */ - -static void log(const char *p, ...) -{ - dstr d = DSTR_INIT; - va_list ap; - - if (!(flags & F_SYSLOG)) { - time_t t = time(0); - struct tm *tm = localtime(&t); - DENSURE(&d, 64); - d.len += strftime(d.buf, d.sz, "%Y-%m-%d %H:%M:%S ", tm); - } - va_start(ap, p); - dstr_vputf(&d, p, &ap); - va_end(ap); - - if (flags & F_SYSLOG) - syslog(LOG_NOTICE, "%s", d.buf); - else { - DPUTC(&d, '\n'); - dstr_write(&d, stderr); - } - DDESTROY(&d); -} - -/*----- Passphrase management ---------------------------------------------*/ - -/* --- Data structures --- */ - -typedef struct phrase { - struct phrase *next; - struct phrase *prev; - char *tag; - char *p; - unsigned long t; - sel_timer timer; - unsigned f; -} phrase; - -/* --- Variables --- */ - -#define P_ROOT ((phrase *)&p_root) -static struct { phrase *next; phrase *prev; } p_root = { P_ROOT, P_ROOT }; - -/* --- @p_free@ --- * - * - * Arguments: @phrase *p@ = pointer to phrase block - * - * Returns: --- - * - * Use: Frees a phrase block. - */ - -static void p_free(phrase *p) -{ - if (p->t) - sel_rmtimer(&p->timer); - xfree(p->tag); - l_free(&lm, p->p); - p->next->prev = p->prev; - p->prev->next = p->next; - DESTROY(p); -} - -/* --- @p_timer@ --- * - * - * Arguments: @struct timeval *tv@ = current time - * @void *p@ = pointer to phrase - * - * Returns: --- - * - * Use: Expires a passphrase. - */ - -static void p_timer(struct timeval *tv, void *p) -{ - phrase *pp = p; - if (verbose) - log("expiring passphrase `%s'", pp->tag); - p_free(pp); -} - -/* --- @p_alloc@ --- * - * - * Arguments: @size_t sz@ = amount of memory required - * - * Returns: Pointer to allocated memory, or null. - * - * Use: Allocates some locked memory, flushing old passphrases if - * there's not enough space. - */ - -static void *p_alloc(size_t sz) -{ - for (;;) { - char *p; - if ((p = l_alloc(&lm, sz)) != 0) - return (p); - if (P_ROOT->next == P_ROOT) - return (0); - if (verbose) { - log("flushing passphrase `%s' to free up needed space", - P_ROOT->next->tag); - } - p_free(P_ROOT->next); - } -} - -/* --- @p_find@ --- * - * - * Arguments: @const char *tag@ = pointer to tag to find - * - * Returns: Pointer to passphrase block, or null. - * - * Use: Finds a passphrase with a given tag. - */ - -static phrase *p_find(const char *tag) -{ - phrase *p; - - for (p = P_ROOT->next; p != P_ROOT; p = p->next) { - if (strcmp(p->tag, tag) == 0) { - if (p->t) { - struct timeval tv; - sel_rmtimer(&p->timer); - gettimeofday(&tv, 0); - tv.tv_sec += p->t; - sel_addtimer(&sel, &p->timer, &tv, p_timer, p); - } - p->next->prev = p->prev; - p->prev->next = p->next; - p->next = P_ROOT; - p->prev = P_ROOT->prev; - P_ROOT->prev->next = p; - P_ROOT->prev = p; - return (p); - } - } - return (0); -} - -/* --- @p_add@ --- * - * - * Arguments: @const char *tag@ = pointer to tag string - * @const char *p@ = pointer to passphrase - * @unsigned long t@ = expiry timeout - * - * Returns: Pointer to newly-added passphrase. - * - * Use: Adds a new passphrase. The tag must not already exist. - */ - -static phrase *p_add(const char *tag, const char *p, unsigned long t) -{ - size_t sz = strlen(p) + 1; - char *l = p_alloc(sz); - phrase *pp; - - /* --- Make sure the locked memory was allocated --- */ - - if (!l) - return (0); - - /* --- Fill in some other bits of the block --- */ - - pp = CREATE(phrase); - memcpy(l, p, sz); - pp->p = l; - pp->tag = xstrdup(tag); - pp->f = 0; - - /* --- Set the timer --- */ - - pp->t = t; - if (t) { - struct timeval tv; - gettimeofday(&tv, 0); - tv.tv_sec += t; - sel_addtimer(&sel, &pp->timer, &tv, p_timer, pp); - } - - /* --- Link the block into the chain --- */ - - pp->next = P_ROOT; - pp->prev = P_ROOT->prev; - P_ROOT->prev->next = pp; - P_ROOT->prev = pp; - return (pp); -} - -/* --- @p_flush@ --- * - * - * Arguments: @const char *tag@ = pointer to tag string, or zero for all - * - * Returns: --- - * - * Use: Immediately flushes either a single phrase or all of them. - */ - -static void p_flush(const char *tag) -{ - phrase *p; - - if (!tag && verbose > 1) - log("flushing all passphrases"); - p = P_ROOT->next; - while (p != P_ROOT) { - phrase *pp = p->next; - if (!tag) - p_free(p); - else if (strcmp(p->tag, tag) == 0) { - if (verbose > 1) - log("flushing passphrase `%s'", tag); - p_free(p); - break; - } - p = pp; - } -} - -/*----- Reading passphrases -----------------------------------------------*/ - -/* --- @p_request@ --- * - * - * Arguments: @const char *msg@ = message string - * @const char *tag@ = pointer to tag string - * @char *buf@ = pointer to (locked) buffer - * @size_t sz@ = size of buffer - * - * Returns: Zero if all went well, nonzero otherwise. - * - * Use: Requests a passphrase from the user. - */ - -static int p_request(const char *msg, const char *tag, char *buf, size_t sz) -{ - /* --- If there's a passphrase-fetching command, run it --- */ - - if (command) { - dstr d = DSTR_INIT; - const char *p; - int fd[2]; - pid_t kid; - int r; - int rc; - - /* --- Substitute the prompt string into the command --- */ - - p = command; - for (;;) { - const char *q = strchr(p, '%'); - if (!q || !q[1]) { - DPUTS(&d, p); - break; - } - DPUTM(&d, p, q - p); - p = q + 1; - switch (*p) { - case 'm': - DPUTS(&d, msg); - break; - case 't': - DPUTS(&d, tag); - break; - default: - DPUTC(&d, '%'); - DPUTC(&d, *p); - break; - } - p++; - } - DPUTZ(&d); - - /* --- Create a pipe and start a child process --- */ - - if (pipe(fd)) - goto fail_1; - if ((kid = fork()) < 0) - goto fail_2; - - /* --- Child process --- */ - - fflush(0); - if (kid == 0) { - if (dup2(fd[1], STDOUT_FILENO) < 0) - _exit(127); - close(fd[0]); - execl("/bin/sh", "sh", "-c", d.buf, (char *)0); - _exit(127); - } - - /* --- Read the data back into my buffer --- */ - - close(fd[1]); - if ((r = read(fd[0], buf, sz - 1)) >= 0) { - char *q = memchr(buf, '\n', r); - if (!q) - q = buf + r; - *q = 0; - } - close(fd[0]); - waitpid(kid, &rc, 0); - dstr_destroy(&d); - if (r < 0 || rc != 0) - goto fail_0; - goto ok; - - /* --- Tidy up when things go wrong --- */ - - fail_2: - close(fd[0]); - close(fd[1]); - fail_1: - dstr_destroy(&d); - fail_0: - return (-1); - } - - /* --- Read a passphrase from the terminal --- * - * - * Use the standard Catacomb passphrase-reading function, so it'll read the - * passphrase from a file descriptor or something if the appropriate - * environment variable is set. - */ - - { - dstr d = DSTR_INIT; - int rc; - dstr_putf(&d, "%s %s: ", msg, tag); - rc = pixie_getpass(d.buf, buf, sz); - dstr_destroy(&d); - if (rc) - return (rc); - goto ok; - } - - /* --- Sort out the buffer --- * - * - * Strip leading spaces. - */ - -ok: { - char *p = buf; - size_t len; - while (isspace((unsigned char)*p)) - p++; - len = strlen(p); - memmove(buf, p, len); - p[len] = 0; - } - - /* --- Done --- */ - - return (0); -} - -/* --- @p_get@ --- * - * - * Arguments: @const char **q@ = where to store the result - * @const char *tag@ = pointer to tag string - * @unsigned mode@ = reading mode (verify?) - * @time_t exp@ = expiry time suggestion - * - * Returns: Zero if successful, @-1@ on a read failure, or @+1@ if the - * passphrase is missing and there is no fetcher. (This will - * always happen if there is no fetcher and @mode@ is - * @PMODE_VERIFY@. - * - * Use: Reads a passphrase from somewhere. - */ - -static int p_get(const char **q, const char *tag, unsigned mode, time_t exp) -{ -#define LBUFSZ 1024 - - phrase *p; - char *pp = 0; - - /* --- Write a log message --- */ - - if (verbose > 1) - log("passphrase `%s' requested", tag); - - /* --- If there is no fetcher, life is simpler --- */ - - if (!(flags & F_FETCH)) { - if (mode == PMODE_VERIFY) - return (+1); - if ((p = p_find(tag)) == 0) - return (+1); - *q = p->p; - return (0); - } - - /* --- Try to find the phrase --- */ - - if (mode == PMODE_VERIFY) - p_flush(tag); - if (mode == PMODE_VERIFY || (p = p_find(tag)) == 0) { - if ((pp = p_alloc(LBUFSZ)) == 0) - goto fail; - if (p_request(mode == PMODE_READ ? "Passphrase" : "New passphrase", - tag, pp, LBUFSZ) < 0) - goto fail; - p = p_add(tag, pp, exp); - if (!p) - goto fail; - } - - /* --- If verification is requested, verify the passphrase --- */ - - if (mode == PMODE_VERIFY) { - if (!pp && (pp = p_alloc(LBUFSZ)) == 0) - goto fail; - if (p_request("Verify passphrase", tag, pp, LBUFSZ) < 0) - goto fail; - if (strcmp(pp, p->p) != 0) { - if (verbose) - log("passphrases for `%s' don't match", tag); - p_free(p); - goto fail; - } - } - - /* --- Tidy up and return the passphrase --- */ - - if (pp) { - memset(pp, 0, LBUFSZ); - l_free(&lm, pp); - } - *q = p->p; - return (0); - - /* --- Tidy up if things went wrong --- */ - -fail: - if (pp) { - memset(pp, 0, LBUFSZ); - l_free(&lm, pp); - } - return (-1); - -#undef LBUFSZ -} - -/*----- Server command parsing --------------------------------------------*/ - -/* --- Data structures --- */ - -typedef struct pixserv { - selbuf b; - int fd; - sel_timer timer; - unsigned f; -} pixserv; - -#define px_stdin 1u - -#define PIXSERV_TIMEOUT 30 - -/* --- @pixserv_expire@ --- * - * - * Arguments: @struct timeval *tv@ = pointer to current time - * @void *p@ = pointer to server block - * - * Returns: --- - * - * Use: Expires a pixie connection if the remote end decides he's not - * interested any more. - */ - -static void pixserv_expire(struct timeval *tv, void *p) -{ - pixserv *px = p; - if (px->fd != px->b.reader.fd) - close(px->fd); - selbuf_destroy(&px->b); - close(px->b.reader.fd); - DESTROY(px); -} - -/* --- @pixserv_write@ --- * - * - * Arguments: @pixserv *px@ = pointer to server block - * @const char *p@ = pointer to skeleton string - * @...@ = other arguments to fill in - * - * Returns: --- - * - * Use: Formats a string and emits it to the output file. - */ - -static void pixserv_write(pixserv *px, const char *p, ...) -{ - dstr d = DSTR_INIT; - va_list ap; - - va_start(ap, p); - dstr_vputf(&d, p, &ap); - write(px->fd, d.buf, d.len); - va_end(ap); - dstr_destroy(&d); -} - -/* --- @pixserv_timeout@ --- * - * - * Arguments: @const char *p@ = pointer to timeout string - * - * Returns: Timeout in seconds. - * - * Use: Translates a string to a timeout value in seconds. - */ - -static unsigned long pixserv_timeout(const char *p) -{ - unsigned long t; - char *q; - - if (!p) - return (timeout); - - t = strtoul(p, &q, 0); - switch (*q) { - case 'd': t *= 24; - case 'h': t *= 60; - case 'm': t *= 60; - case 's': if (q[1] != 0) - default: t = 0; - case 0: break; - } - return (t); -} - -/* --- @pixserv_line@ --- * - * - * Arguments: @char *s@ = pointer to the line read - * @size_t len@ = length of the line - * @void *p@ = pointer to server block - * - * Returns: --- - * - * Use: Handles a line read from the client. - */ - -static void pixserv_line(char *s, size_t len, void *p) -{ - pixserv *px = p; - char *q, *qq; - unsigned mode; - - /* --- Handle an end-of-file --- */ - - if (!(px->f & px_stdin)) - sel_rmtimer(&px->timer); - if (!s) { - if (px->fd != px->b.reader.fd) - close(px->fd); - selbuf_destroy(&px->b); - close(px->b.reader.fd); - return; - } - - /* --- Fiddle the timeout --- */ - - if (!(px->f & px_stdin)) { - struct timeval tv; - gettimeofday(&tv, 0); - tv.tv_sec += PIXSERV_TIMEOUT; - sel_addtimer(&sel, &px->timer, &tv, pixserv_expire, px); - } - - /* --- Scan out the first word --- */ - - if ((q = str_getword(&s)) == 0) - return; - for (qq = q; *qq; qq++) - *qq = tolower((unsigned char)*qq); - - /* --- Handle a help request --- */ - - if (strcmp(q, "help") == 0) { - pixserv_write(px, "\ -INFO Commands supported:\n\ -INFO HELP\n\ -INFO LIST\n\ -INFO PASS tag [expire]\n\ -INFO VERIFY tag [expire]\n\ -INFO FLUSH [tag]\n\ -INFO SET tag [expire] -- phrase\n\ -INFO QUIT\n\ -OK\n\ -"); - } - - /* --- List the passphrases --- */ - - else if (strcmp(q, "list") == 0) { - phrase *p; - - for (p = P_ROOT->next; p != P_ROOT; p = p->next) { - if (!p->t) - pixserv_write(px, "ITEM %s no-expire\n", p->tag); - else { - struct timeval tv; - gettimeofday(&tv, 0); - TV_SUB(&tv, &p->timer.tv, &tv); - pixserv_write(px, "ITEM %s %i\n", p->tag, tv.tv_sec); - } - } - pixserv_write(px, "OK\n"); - } - - /* --- Request a passphrase --- */ - - else if ((mode = PMODE_READ, strcmp(q, "pass") == 0) || - (mode = PMODE_VERIFY, strcmp(q, "verify") == 0)) { - unsigned long t; - const char *p; - int rc; - - if ((q = str_getword(&s)) == 0) - pixserv_write(px, "FAIL missing tag\n"); - else if ((t = pixserv_timeout(s)) == 0) - pixserv_write(px, "FAIL bad timeout\n"); - else { - rc = p_get(&p, q, mode, t > timeout ? timeout : t); - switch (rc) { - case 0: - pixserv_write(px, "OK %s\n", p); - break; - case -1: - pixserv_write(px, "FAIL error reading passphrase\n"); - break; - case +1: - pixserv_write(px, "MISSING\n"); - break; - } - } - } - - /* --- Flush existing passphrases --- */ - - else if (strcmp(q, "flush") == 0) { - q = str_getword(&s); - p_flush(q); - pixserv_write(px, "OK\n"); - } - - /* --- Set a passphrase --- */ - - else if (strcmp(q, "set") == 0) { - char *tag; - unsigned long t; - if ((tag = str_getword(&s)) == 0) - pixserv_write(px, "FAIL missing tag\n"); - else if ((q = str_getword(&s)) == 0) - pixserv_write(px, "FAIL no passphrase\n"); - else { - if (strcmp(q, "--") != 0) { - t = pixserv_timeout(q); - q = str_getword(&s); - } else - t = pixserv_timeout(0); - if (!q) - pixserv_write(px, "FAIL no passphrase\n"); - else if (strcmp(q, "--") != 0) - pixserv_write(px, "FAIL rubbish found before passphrase\n"); - else { - p_flush(tag); - p_add(tag, s, t); - pixserv_write(px, "OK\n"); - } - } - } - - /* --- Shut the server down --- */ - - else if (strcmp(q, "quit") == 0) { - if (verbose) - log("%s client requested shutdown", - px->f & px_stdin ? "local" : "remote"); - pixserv_write(px, "OK\n"); - exit(0); - } - - /* --- Report an error for other commands --- */ - - else - pixserv_write(px, "FAIL unknown command `%s'\n", q); -} - -/* --- @pixserv_create@ --- * - * - * Arguments: @int fd@ = file descriptor to read from - * @int ofd@ = file descriptor to write to - * - * Returns: Pointer to the new connection. - * - * Use: Creates a new Pixie server instance for a new connection. - */ - -static pixserv *pixserv_create(int fd, int ofd) -{ - pixserv *px = CREATE(pixserv); - struct timeval tv; - fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); - if (ofd != fd) - fdflags(ofd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); - px->fd = ofd; - selbuf_init(&px->b, &sel, fd, pixserv_line, px); - px->b.b.a = arena_secure; - selbuf_setsize(&px->b, 1024); - gettimeofday(&tv, 0); - tv.tv_sec += PIXSERV_TIMEOUT; - sel_addtimer(&sel, &px->timer, &tv, pixserv_expire, px); - px->f = 0; - return (px); -} - -/* --- @pixserv_accept@ --- * - * - * Arguments: @int fd@ = file descriptor - * @unsigned mode@ = what's happened - * @void *p@ = an uninteresting argument - * - * Returns: --- - * - * Use: Accepts a new connection. - */ - -static void pixserv_accept(int fd, unsigned mode, void *p) -{ - int nfd; - struct sockaddr_un sun; - size_t sunsz = sizeof(sun); - - if (mode != SEL_READ) - return; - if ((nfd = accept(fd, (struct sockaddr *)&sun, &sunsz)) < 0) { - if (verbose && errno != EAGAIN && errno != EWOULDBLOCK && - errno != ECONNABORTED && errno != EPROTO && errno != EINTR) - log("new connection failed: %s", strerror(errno)); - return; - } - pixserv_create(nfd, nfd); -} - -/*----- Setting up the server ---------------------------------------------*/ - -/* --- @unlinksocket@ --- * - * - * Arguments: --- - * - * Returns: --- - * - * Use: Tidies up the socket when it's finished with. - */ - -static char *sockpath; - -static void unlinksocket(void) -{ - unlink(sockpath); - l_purge(&lm); -} - -/* --- @pix_sigdie@ --- * - * - * Arguments: @int sig@ = signal number - * @void *p@ = uninteresting argument - * - * Returns: --- - * - * Use: Shuts down the program after a fatal signal. - */ - -static void pix_sigdie(int sig, void *p) -{ - if (verbose) { - char *p; - char buf[20]; - - switch (sig) { - case SIGTERM: p = "SIGTERM"; break; - case SIGINT: p = "SIGINT"; break; - default: - sprintf(buf, "signal %i", sig); - p = buf; - break; - } - log("shutting down on %s", p); - } - exit(0); -} - -/* --- @pix_sigflush@ --- * - * - * Arguments: @int sig@ = signal number - * @void *p@ = uninteresting argument - * - * Returns: --- - * - * Use: Flushes the passphrase cache on receipt of a signal. - */ - -static void pix_sigflush(int sig, void *p) -{ - if (verbose) { - char *p; - char buf[20]; - - switch (sig) { - case SIGHUP: p = "SIGHUP"; break; - case SIGQUIT: p = "SIGQUIT"; break; - default: - sprintf(buf, "signal %i", sig); - p = buf; - break; - } - log("received %s; flushing passphrases", p); - } - p_flush(0); -} - -/* --- @pix_setup@ --- * - * - * Arguments: @struct sockaddr_un *sun@ = pointer to address to use - * @size_t sz@ = size of socket address - * - * Returns: --- - * - * Use: Sets up the pixie's Unix-domain socket. - */ - -static void pix_setup(struct sockaddr_un *sun, size_t sz) -{ - int fd; - - /* --- Set up the parent directory --- */ - - { - char *p = sun->sun_path; - char *q = strrchr(p, '/'); - - if (q) { - dstr d = DSTR_INIT; - struct stat st; - - DPUTM(&d, p, q - p); - DPUTZ(&d); - - mkdir(d.buf, 0700); - if (stat(d.buf, &st)) - die(1, "couldn't stat `%s': %s", d.buf, strerror(errno)); - if (!S_ISDIR(st.st_mode)) - die(1, "object `%s' isn't a directory", d.buf); - if (st.st_mode & 0077) - die(1, "parent directory `%s' has group or world access", d.buf); - dstr_destroy(&d); - } - } - - /* --- Initialize the socket --- */ - - { - int n = 5; - int e; - - umask(0077); - again: - if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) - die(1, "couldn't create socket: %s", strerror(errno)); - if (bind(fd, (struct sockaddr *)sun, sz) < 0) { - e = errno; - if (errno != EADDRINUSE) - die(1, "couldn't bind to address: %s", strerror(e)); - if (!n) - die(1, "too many retries; giving up"); - n--; - if (connect(fd, (struct sockaddr *)sun, sz)) { - struct stat st; - if (errno != ECONNREFUSED) - die(1, "couldn't bind to address: %s", strerror(e)); - if (stat(sun->sun_path, &st)) - die(1, "couldn't stat `%s': %s", sun->sun_path, strerror(errno)); - if (!S_ISSOCK(st.st_mode)) - die(1, "object `%s' isn't a socket", sun->sun_path); - if (verbose) - log("stale socket found; removing it"); - unlink(sun->sun_path); - close(fd); - } else { - if (verbose) - log("server already running; shutting it down"); - write(fd, "QUIT\n", 5); - sleep(1); - close(fd); - } - goto again; - } - chmod(sun->sun_path, 0600); - fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); - if (listen(fd, 5)) - die(1, "couldn't listen on socket: %s", strerror(errno)); - } - - /* --- Set up the rest of the server --- */ - - { - static sel_file serv; - sockpath = sun->sun_path; - atexit(unlinksocket); - sel_initfile(&sel, &serv, fd, SEL_READ, pixserv_accept, 0); - sel_addfile(&serv); - } -} - -/*----- Client support code -----------------------------------------------*/ - -/* --- Variables --- */ - -static selbuf c_server, c_client; -static unsigned c_flags = 0; - -#define cf_uclose 1u -#define cf_sclose 2u -#define cf_cooked 4u - -/* --- Line handler functions --- */ - -static void c_uline(char *s, size_t len, void *p) -{ - if (!s) { - selbuf_destroy(&c_client); - shutdown(c_server.reader.fd, 1); - c_flags |= cf_uclose; - } else { - s[len++] = '\n'; - write(c_server.reader.fd, s, len); - } -} - -static void c_sline(char *s, size_t len, void *p) -{ - if (!s) { - selbuf_destroy(&c_server); - if (!(c_flags & cf_uclose)) { - moan("server closed the connection"); - selbuf_destroy(&c_client); - } - exit(0); - } - if (!(c_flags & cf_cooked)) - puts(s); - else { - char *q = str_getword(&s); - if (strcmp(q, "FAIL") == 0) - die(1, "%s", s); - else if (strcmp(q, "INFO") == 0 || - strcmp(q, "ITEM") == 0) - puts(s); - else if (strcmp(q, "OK") == 0) { - if (s && *s) puts(s); - } else if (strcmp(q, "MISSING") == 0) - ; - else - moan("unexpected output: %s %s", q, s); - } -} - -/* --- @pix_client@ --- * - * - * Arguments: @struct sockaddr_un *sun@ = pointer to socket address - * @size_t sz@ = size of socket address - * @char *argv[]@ = pointer to arguments to send - * - * Returns: --- - * - * Use: Performs client-side actions for the passphrase pixie. - */ - -static void pix_client(struct sockaddr_un *sun, size_t sz, char *argv[]) -{ - int fd; - - /* --- Dispose of locked memory --- */ - - l_destroy(&lm); - - /* --- Open the socket --- */ - - if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) - die(1, "couldn't create socket: %s", strerror(errno)); - if (connect(fd, (struct sockaddr *)sun, sz)) - die(1, "couldn't connect to server: %s", strerror(errno)); - selbuf_init(&c_server, &sel, fd, c_sline, 0); - - /* --- If there are any arguments, turn them into a string --- */ - - if (!*argv) - selbuf_init(&c_client, &sel, STDIN_FILENO, c_uline, 0); - else { - dstr d = DSTR_INIT; - DPUTS(&d, *argv++); - while (*argv) { - DPUTC(&d, ' '); - DPUTS(&d, *argv++); - } - DPUTC(&d, '\n'); - write(fd, d.buf, d.len); - shutdown(fd, 1); - c_flags |= cf_uclose | cf_cooked; - dstr_destroy(&d); - } - - /* --- And repeat --- */ - - for (;;) { - if (sel_select(&sel)) - die(EXIT_FAILURE, "select error: %s", strerror(errno)); - } -} - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @help@, @version@, @usage@ --- * - * - * Arguments: @FILE *fp@ = stream to write on - * - * Returns: --- - * - * Use: Emit helpful messages. - */ - -static void usage(FILE *fp) -{ - pquis(fp, "\ -Usage:\n\ - $ [-qvfidl] [-c COMMAND] [-t TIMEOUT] [-s SOCKET]\n\ - $ [-s SOCKET] -C [COMMAND ARGS...]\n\ - $ [-s SOCKET] -P[P] TAG\n\ -"); -} - -static void version(FILE *fp) -{ - pquis(fp, "$, Catacomb version " VERSION "\n"); -} - -static void help(FILE *fp) -{ - version(fp); - fputc('\n', fp); - usage(fp); - pquis(fp, "\n\ -The Catacomb passphrase pixie collects and caches passphrases used to\n\ -protect important keys. Options provided:\n\ -\n\ --h, --help Show this help text.\n\ --V, --version Show the program's version number.\n\ --u, --usage Show a (very) terse usage summary.\n\ -\n\ --C, --client Connect to a running pixie as a client.\n\ --P, --passphrase Request passphrase TAG and print to stdout.\n\ --PP, --verify-passphrase\n\ - Verify passphrase TAG and print to stdout.\n\ -\n\ --q, --quiet Emit fewer log messages.\n\ --v, --version Emit more log messages.\n\ --s, --socket=FILE Name the pixie's socket.\n\ --c, --command=COMMAND Shell command to read a passphrase.\n\ --f, --fetch Fetch passphrases from the terminal.\n\ --t, --timeout=TIMEOUT Length of time to retain a passphrase in memory.\n\ --i, --interactive Allow commands to be typed interactively.\n\ --d, --daemon Fork into the background after initialization.\n\ --l, --syslog Emit log messages to the system log.\n\ -\n\ -The COMMAND may contain `%m' and `%t' markers which are replaced by a\n\ -prompt message and the passphrase tag respectively. The TIMEOUT is an\n\ -integer, optionally followed by `d', `h', `m' or `s' to specify units of\n\ -days, hours, minutes or seconds respectively.\n\ -\n\ -In client mode, if a command is specified on the command line, it is sent\n\ -to the running server; otherwise the program reads requests from stdin.\n\ -Responses from the pixie are written to stdout. Send a HELP request for\n\ -a quick summary of the pixie communication protocol.\n\ -"); -} - -/* --- @main@ --- * - * - * Arguments: @int argc@ = number of arguments - * @char *argv[]@ = vector of argument values - * - * Returns: Zero if OK. - * - * Use: Main program. Listens on a socket and responds with a PGP - * passphrase when asked. - */ - -int main(int argc, char *argv[]) -{ - char *path = 0; - struct sockaddr_un *sun; - size_t sz; - unsigned f = 0; - -#define f_bogus 1u -#define f_client 2u -#define f_stdin 4u -#define f_daemon 8u -#define f_syslog 16u -#define f_fetch 32u -#define f_verify 64u - - /* --- Initialize libraries --- */ - - ego(argv[0]); - sub_init(); - - /* --- Set up the locked memory area --- */ - - l_init(&lm, 16384); - setuid(getuid()); - - /* --- Parse command line arguments --- */ - - for (;;) { - static struct option opts[] = { - - /* --- Standard GNUy help options --- */ - - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'V' }, - { "usage", 0, 0, 'u' }, - - /* --- Other options --- */ - - { "quiet", 0, 0, 'q' }, - { "verbose", 0, 0, 'v' }, - { "client", 0, 0, 'C' }, - { "passphrase", 0, 0, 'P' }, - { "verify-passphrase", 0, 0, '+' }, - { "socket", OPTF_ARGREQ, 0, 's' }, - { "command", OPTF_ARGREQ, 0, 'c' }, - { "fetch", 0, 0, 'f' }, - { "timeout", OPTF_ARGREQ, 0, 't' }, - { "interactive", 0, 0, 'i' }, - { "stdin", 0, 0, 'i' }, - { "daemon", 0, 0, 'd' }, - { "log", 0, 0, 'l' }, - { "syslog", 0, 0, 'l' }, - - /* --- Magic terminator --- */ - - { 0, 0, 0, 0 } - }; - - int i = mdwopt(argc, argv, "hVuqvCPs:c:ft:idl", opts, 0, 0, 0); - if (i < 0) - break; - - switch (i) { - - /* --- GNUy help options --- */ - - case 'h': - help(stdout); - exit(0); - case 'V': - version(stdout); - exit(0); - case 'u': - usage(stdout); - exit(0); - - /* --- Other interesting things --- */ - - case 'q': - if (verbose) - verbose--; - break; - case 'v': - verbose++; - break; - case 'C': - f |= f_client; - f &= ~f_fetch; - break; - case 'P': - if (!(f & f_fetch)) - f |= f_fetch; - else - f |= f_verify; - break; - case '+': - f |= f_fetch | f_verify; - f &= ~f_client; - break; - case 's': - path = optarg; - break; - case 't': - if ((timeout = pixserv_timeout(optarg)) == 0) - die(1, "bad timeout `%s'", optarg); - break; - case 'c': - command = optarg; - flags |= F_FETCH; - break; - case 'f': - flags |= F_FETCH; - break; - case 'i': - f |= f_stdin; - break; - case 'd': - f |= f_daemon; - break; - case 'l': - f |= f_syslog; - break; - - /* --- Something else --- */ - - default: - f |= f_bogus; - break; - } - } - - if (f & f_bogus || - (optind < argc && !(f & (f_client|f_fetch))) || - ((f & f_fetch) && optind != argc - 1)) { - usage(stderr); - exit(1); - } - - /* --- Handle request for a passphrase --- */ - - if (f & f_fetch) { - char *buf = l_alloc(&lm, 1024); - passphrase_connect(path); - if (passphrase_read(argv[optind], - (f & f_verify) ? PMODE_VERIFY : PMODE_READ, - buf, 1024)) - die(1, "failed to read passphrase: %s", strerror(errno)); - puts(buf); - return (0); - } - - /* --- Set up the socket address --- */ - - sun = pixie_address(path, &sz); - - /* --- Initialize selectory --- */ - - sel_init(&sel); - signal(SIGPIPE, SIG_IGN); - - /* --- Be a client if a client's wanted --- */ - - if (f & f_client) - pix_client(sun, sz, argv + optind); - - /* --- Open the syslog if requested --- */ - - if (f & f_syslog) { - flags |= F_SYSLOG; - openlog(QUIS, 0, LOG_DAEMON); - } - - /* --- Check on the locked memory area --- */ - - { - dstr d = DSTR_INIT; - int rc = l_report(&lm, &d); - if (rc < 0) - die(EXIT_FAILURE, d.buf); - else if (rc && verbose) { - log(d.buf); - log("couldn't lock passphrase buffer"); - } - dstr_destroy(&d); - arena_setsecure(&lm.a); - } - - /* --- Set signal behaviours --- */ - - { - static sig sigint, sigterm, sigquit, sighup; - struct sigaction sa; - sig_init(&sel); - sigaction(SIGINT, 0, &sa); - if (sa.sa_handler != SIG_IGN) - sig_add(&sigint, SIGINT, pix_sigdie, 0); - sig_add(&sigterm, SIGTERM, pix_sigdie, 0); - sig_add(&sigquit, SIGQUIT, pix_sigflush, 0); - sig_add(&sighup, SIGHUP, pix_sigflush, 0); - } - - /* --- Set up the server --- */ - - pix_setup(sun, sz); - if (f & f_stdin) { - pixserv *px = pixserv_create(STDIN_FILENO, STDOUT_FILENO); - sel_rmtimer(&px->timer); - px->f |= px_stdin; - } - - /* --- Fork into the background if requested --- */ - - if (f & f_daemon) { - pid_t kid; - - if (((f & f_stdin) && - (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO))) || - (!command && (flags & F_FETCH))) - die(1, "can't become a daemon if terminal required"); - - if ((kid = fork()) < 0) - die(1, "fork failed: %s", strerror(errno)); - if (kid) - _exit(0); -#ifdef TIOCNOTTY - { - int fd; - if ((fd = open("/dev/tty", O_RDONLY)) >= 0) { - ioctl(fd, TIOCNOTTY); - close(fd); - } - } -#endif - chdir("/"); - setsid(); - - if (fork() != 0) - _exit(0); - } - - if (verbose) - log("initialized ok"); - - { - int selerr = 0; - for (;;) { - if (!sel_select(&sel)) - selerr = 0; - else if (errno != EINTR && errno != EAGAIN) { - log("error from select: %s", strerror(errno)); - selerr++; - if (selerr > 8) { - log("too many consecutive select errors: bailing out"); - exit(EXIT_FAILURE); - } - } - } - } - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/pixie.h b/pixie.h deleted file mode 100644 index a5bc171..0000000 --- a/pixie.h +++ /dev/null @@ -1,218 +0,0 @@ -/* -*-c-*- - * - * $Id: pixie.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Passphrase pixie definitions (Unix-specific) - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_PIXIE_H -#define CATACOMB_PIXIE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include -#include - -#ifndef CATACOMB_PASSPHRASE_H -# include "passphrase.h" -#endif - -/*----- Protocol definition -----------------------------------------------* - * - * The protocol is simple and text-based. The client connects to the - * server's socket and sends `request lines', each of which elicits one or - * more `response lines' from the server. Request and response lines contain - * whitespace-separated fields, and are terminated by a single linefeed. The - * final field on a line may contain whitespace. The first field describes - * the type of the line. The type field is not case-sensitive, although - * writing them in uppercase is conventional. - * - * The requests are: - * - * HELP - * Provide (very) brief help with the pixie protocol. - * - * LIST - * Return a list of passphrases currently stored, together with expiry - * information. - * - * PASS tag [expire] - * Request the passphrase named `tag' from the pixie. - * - * VERIFY tag [expire] - * Request a new passphrase, which therefore requires verification. - * - * SET tag [expire] -- phrase - * Set the value of passphrase `tag'. This will usually be a follow-up - * to a MISSING response. - * - * FLUSH [tag] - * Flush the passphrase named `tag', or all passphrases, from memory. - * - * QUIT - * Requests that the pixie close down. - * - * Response lines are as follows: - * - * OK [phrase] - * Request completed successfully. If a passphrase was requested, it is - * returned by the pixie. This is the final response to a request. - * - * MISSING - * The passphrase requested is not known, and no requester mechanism is - * present. The client should request the passphrase itself and pass it - * back to the pixie. This is the final response to a request. - * - * FAIL error - * Reports an error. The message given is intended to be - * human-readable. This is the final response to a request. - * - * INFO message - * Reports a human-readable informational message. Further responses - * follow. - * - * ITEM tag expires - * Reports a passphrase in response to a LIST request. One ITEM - * response is given for each passphrase currently in memory. An OK or - * FAIL response follows the last ITEM. - * - * Expiry times in requests may be given in any format acceptable to - * `getdate'. Expiry times in responses are returned in ISO format - * (YYYY-MM-DD HH:MM:SS ZZZ) and are expressed relative to local time. - */ - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @pixie_open@ --- * - * - * Arguments: @const char *sock@ = path to pixie socket - * - * Returns: Less than zero if it failed, or file descriptor. - * - * Use: Opens a connection to a passphrase pixie. - */ - -extern int pixie_open(const char */*sock*/); - -/* --- @pixie_read@ --- * - * - * Arguments: @int fd@ = connection to passphrase pixie - * @const char *tag@ = pointer to tag string - * @unsigned mode@ = reading mode - * @char *buf@ = pointer to destination buffer - * @size_t sz@ = size of the buffer - * - * Returns: Zero if all went well, @-1@ if the read fails, @+1@ to - * request the passphrase from the user. - * - * Use: Reads a passphrase from the pixie. - */ - -extern int pixie_read(int /*fd*/, const char */*tag*/, unsigned /*mode*/, - char */*buf*/, size_t /*sz*/); - -/* --- @pixie_set@ --- * - * - * Arguments: @int fd@ = pixie file descriptor - * @const char *tag@ = pointer to tag string - * @const char *phrase@ = pointer to passphrase string - * - * Returns: --- - * - * Use: Sends a passphrase to the passphrase pixie. - */ - -extern void pixie_set(int /*fd*/, const char */*tag*/, - const char */*phrase*/); - -/* --- @pixie_cancel@ --- * - * - * Arguments: @int fd@ = pixie file descriptor - * @const char *tag@ = pointer to tag string - * - * Returns: --- - * - * Use: Cancels a passphrase if it turns out to be bogus. - */ - -extern void pixie_cancel(int /*fd*/, const char */*tag*/); - -/* --- @pixie_address@ --- * - * - * Arguments: @const char *sock@ = pointer to socket name - * @size_t *psz@ = where to write the address size - * - * Returns: Pointer to filled-in Unix-domain socket address. - * - * Use: Returns a Unix-domain socket address to use to find the - * passphrase pixie. - */ - -extern struct sockaddr_un *pixie_address(const char */*sock*/, - size_t */*psz*/); - -/* --- @pixie_fdline@ --- * - * - * Arguments: @int fd@ = file descriptor to read from - * @char *buf@ = pointer to buffer - * @size_t sz@ = size of buffer - * - * Returns: --- - * - * Use: Reads a line from a file descriptor. The read is done one - * character at a time. If the entire line won't fit, the end - * is truncated. The line is null terminated. - */ - -extern void pixie_fdline(int /*fd*/, char */*buf*/, size_t /*sz*/); - -/* --- @pixie_getpass@ --- * - * - * Arguments: @const char *prompt@ = pointer to prompt string - * @char *buf@ = pointer to buffer - * @size_t sz@ = size of buffer - * - * Returns: Zero if it worked OK, nonzero otherwise. - * - * Use: Reads a passphrase from the terminal or some other requested - * source. - */ - -extern int pixie_getpass(const char */*prompt*/, - char */*buf*/, size_t /*sz*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/pkcs1.c b/pkcs1.c deleted file mode 100644 index 47c135f..0000000 --- a/pkcs1.c +++ /dev/null @@ -1,261 +0,0 @@ -/* -*-c-*- - * - * $Id: pkcs1.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * PKCS#1 1.5 packing - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include -#include - -#include "ct.h" -#include "grand.h" -#include "rsa.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @pkcs1_cryptencode@ --- * - * - * Arguments: @mp *d@ = where to put the answer - * @const void *m@ = pointer to message data - * @size_t msz@ = size of message data - * @octet *b@ = spare buffer - * @size_t sz@ = size of the buffer (big enough) - * @unsigned long nbits@ = length of bits of @n@ - * @void *p@ = pointer to PKCS1 parameter block - * - * Returns: The encoded result, or null. - * - * Use: Implements the operation @EME-PKCS1-V1_5-ENCODE@, as defined - * in PKCS#1 v. 2.0 (RFC2437). - */ - -mp *pkcs1_cryptencode(mp *d, const void *m, size_t msz, octet *b, size_t sz, - unsigned long nbits, void *p) -{ - pkcs1 *pp = p; - grand *r = pp->r; - octet *q; - size_t i, n; - - /* --- Ensure that the buffer is sensibly sized --- */ - - if (pp->epsz + msz + 11 > sz) - return (0); - - /* --- Allocate the buffer and fill it in --- */ - - q = b; - *q++ = 0x00; - *q++ = 0x02; - n = sz - msz - pp->epsz - 3; - GR_FILL(r, q, n); - for (i = 0; i < n; i++) { - if (*q == 0) - *q = r->ops->range(r, 255) + 1; - q++; - } - *q++ = 0; - if (pp->ep) { - memcpy(q, pp->ep, pp->epsz); - q += pp->epsz; - } - memcpy(q, m, msz); - q += msz; - assert(q == b + sz); - - /* --- Collect the result --- */ - - return (mp_loadb(d, b, sz)); -} - -/* --- @pkcs1_cryptdecode@ --- * - * - * Arguments: @mp *m@ = the decrypted message - * @octet *b@ = pointer to a buffer to work in - * @size_t sz@ = the size of the buffer (big enough) - * @unsigned long nbits@ = the number of bits in @n@ - * @void *p@ = pointer to PKCS1 parameter block - * - * Returns: The length of the output string if successful, negative on - * failure. - * - * Use: Implements the operation @EME-PKCS1-V1_5-DECODE@, as defined - * in PKCS#1 v. 2.0 (RFC2437). - */ - -int pkcs1_cryptdecode(mp *m, octet *b, size_t sz, - unsigned long nbits, void *p) -{ - pkcs1 *pp = p; - const octet *q, *qq; - size_t n, i; - uint32 goodp = 1; - - /* --- Check the size of the block looks sane --- */ - - if (pp->epsz + 11 > sz) /* OK: independent of ciphertext */ - return (-1); - mp_storeb(m, b, sz); - q = b; - qq = q + sz; - - /* --- Ensure that the block looks OK --- */ - - goodp &= ct_inteq(*q++, 0); - goodp &= ct_inteq(*q++, 2); - - /* --- Check the nonzero padding --- */ - - i = 0; - while (*q != 0 && q < qq) - i++, q++; - goodp &= ct_intle(8, i); - goodp &= ~ct_intle(qq - q, pp->epsz + 1); - q++; - - /* --- Check the encoding parameters --- */ - - if (pp->ep) - goodp &= ct_memeq(b + ct_pick(goodp, 0, q - b), pp->ep, pp->epsz); - q += pp->epsz; - - /* --- Done --- */ - - n = qq - q; - memmove(b, b + ct_pick(goodp, 1, q - b), n); - return (goodp ? n : -1); -} - -/* --- @pkcs1_sigencode@ --- * - * - * Arguments: @mp *d@ = where to put the answer - * @const void *m@ = pointer to message data - * @size_t msz@ = size of message data - * @octet *b@ = spare buffer - * @size_t sz@ = size of the buffer (big enough) - * @unsigned long nbits@ = length of bits of @n@ - * @void *p@ = pointer to PKCS1 parameter block - * - * Returns: The encoded message representative, or null. - * - * Use: Implements the operation @EMSA-PKCS1-V1_5-ENCODE@, as defined - * in PKCS#1 v. 2.0 (RFC2437). - */ - -mp *pkcs1_sigencode(mp *d, const void *m, size_t msz, octet *b, size_t sz, - unsigned long nbits, void *p) -{ - pkcs1 *pp = p; - octet *q; - size_t n; - - /* --- Ensure that the buffer is sensibly sized --- */ - - if (pp->epsz + msz + 11 > sz) - return (0); - - /* --- Fill in the buffer --- */ - - q = b; - *q++ = 0x00; - *q++ = 0x01; - n = sz - msz - pp->epsz - 3; - memset(q, 0xff, n); - q += n; - *q++ = 0; - if (pp->ep) { - memcpy(q, pp->ep, pp->epsz); - q += pp->epsz; - } - memcpy(q, m, msz); - q += msz; - assert(q == b + sz); - return (mp_loadb(d, b, sz)); -} - -/* --- @pkcs1_sigdecode@ --- * - * - * Arguments: @mp *s@ = the message representative - * @const void *m@ = the original message, or null (ignored) - * @size_t msz@ = the message size (ignored) - * @octet *b@ = a scratch buffer - * @size_t sz@ = size of the buffer (large enough) - * @unsigned long nbits@ = number of bits in @n@ - * @void *p@ = pointer to PKCS1 parameters - * - * Returns: The length of the output string if successful, negative on - * failure. - * - * Use: Implements the operation @EMSA-PKCS1-V1_5-DECODE@, as defined - * in PKCS#1 v. 2.0 (RFC2437). - */ - -int pkcs1_sigdecode(mp *s, const void *m, size_t msz, octet *b, size_t sz, - unsigned long nbits, void *p) -{ - pkcs1 *pp = p; - const octet *q, *qq; - size_t i, n; - - /* --- Check the size of the block looks sane --- */ - - if (pp->epsz + 10 > sz) - return (-1); - mp_storeb(s, b, sz); - q = b; - qq = q + sz; - - /* --- Ensure that the block looks OK --- */ - - if (*q++ != 0x00 || *q++ != 0x01) - return (-1); - - /* --- Check the padding --- */ - - i = 0; - while (*q == 0xff && q < qq) - i++, q++; - if (i < 8 || qq - q < pp->epsz + 1 || *q++ != 0) - return (-1); - - /* --- Check the encoding parameters --- */ - - if (pp->ep && memcmp(q, pp->ep, pp->epsz) != 0) - return (-1); - q += pp->epsz; - - /* --- Done --- */ - - n = qq - q; - memmove(b, q, n); - return (n); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/prim.c b/prim.c deleted file mode 100644 index 4767912..0000000 --- a/prim.c +++ /dev/null @@ -1,109 +0,0 @@ -/* -*-c-*- - * - * $Id: prim.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Finding primitive elements - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpint.h" -#include "mpmont.h" -#include "mprand.h" -#include "pgen.h" -#include "prim.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @prim_test@ --- */ - -int prim_test(int rq, pgen_event *ev, void *p) -{ - prim_ctx *c = p; - int rc = rq; - - switch (rq) { - case PGEN_BEGIN: - return (PGEN_TRY); - case PGEN_TRY: { - mp *x; - rc = PGEN_FAIL; - - if (!c->exp) - x = mp_copy(ev->m); - else { - x = mpmont_exp(&c->mm, MP_NEW, ev->m, c->exp); - if (MP_EQ(x, MP_ONE)) - goto done; - } - if (c->n == 0) - goto ok; - else { - size_t n = c->n; - mp **f = c->f; - mp *y = MP_NEW; - while (n) { - y = mpmont_exp(&c->mm, y, x, *f); - if (MP_EQ(y, MP_ONE)) { - mp_drop(y); - goto done; - } - n--; f++; - } - mp_drop(y); - } - ok: - rc = PGEN_DONE; - mp_drop(ev->m); - ev->m = x; - break; - done: - mp_drop(x); - } break; - } - - return (rc); -} - -/* --- Trivial stepping functions -----------------------------------------*/ - -/* --- @prim_step@ --- */ - -int prim_step(int rq, pgen_event *ev, void *p) -{ - unsigned *i = p; - switch (rq) { - case PGEN_BEGIN: - case PGEN_TRY: - if (*i >= NPRIME) - return PGEN_FAIL; - ev->m = mp_fromint(ev->m, primetab[(*i)++]); - return (PGEN_TRY); - } - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/prim.h b/prim.h deleted file mode 100644 index 1df2ed6..0000000 --- a/prim.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -*-c-*- - * - * $Id: prim.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Finding primitive elements - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_PRIM_H -#define CATACOMB_PRIM_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_MPMONT_H -# include "mpmont.h" -#endif - -#ifndef CATACOMB_PGEN_H -# include "pgen.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- @prim_ctx@ --- * - * - * All fields must be configured by the client. Set @n@ to zero to discover - * generators of the subgroup of order %$m / f$%. - * - * Let %$p = \prod q_i + 1$% be a prime number. In order to find an element - * %$g$% with order %$o$%, we choose elements %$h_j$% from %$\gf{p}^*$%, - * compute $%g_j = h_j^{p/o}$%, rejecting %$h_j$% where %$g_j = 1$%, and then - * for each proper prime factor %$q_i$% of %$p/o$% we check that - * %$g^{f_i} \ne 1$%, where the %$f_i$% are cofactors of the %$q_i$% - * (%$f_i q_i = p/o$%). - */ - -typedef struct prim_ctx { - mpmont mm; /* Montgomery context for modulus */ - mp *exp; /* Exponent (%$p/o$%; may be zero) */ - size_t n; /* Number of cofactors */ - mp **f; /* Array of cofactors */ -} prim_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @prim_test@ --- */ - -extern pgen_proc prim_test; - -/* --- @prim_step@ --- */ - -extern pgen_proc prim_step; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/primeiter.c b/primeiter.c deleted file mode 100644 index d7126ba..0000000 --- a/primeiter.c +++ /dev/null @@ -1,254 +0,0 @@ -/* -*-c-*- - * - * Iterate over small primes efficiently - * - * (c) 2007 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "fibrand.h" -#include "mp.h" -#include "pgen.h" -#include "primeiter.h" -#include "primetab.h" -#include "wheel.h" - -/*----- Theory ------------------------------------------------------------* - * - * For small primes, we can just pluck them out of the small primes table. - * For larger primes, we can test them individually, or build a sieve or - * something, but since we don't know when to stop, that could be tricky. - * - * We've built a `wheel', as follows. Let %$m$% be the product of the first - * %$n$% primes. There are %$\phi(m)$% integers %$n_i$%, with %$0 < n_i < - * m$% coprime to %$m$%, and any integer %$j > n$% must be congruent to some - * %$n_i$% modulo %$m$%. The wheel itself doesn't list the %$n_i$%, but - * rather the differences %$\delta_i = n_i - n_{i-1}$% (wrapping around - * appropriately at the ends), so you can just add simple offsets to step - * onwards. The wheel assumes you start at 1 and move on round. - */ - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @wheelsync@ --- * - * - * Arguments: @primeiter *pi@ = iterator to synchronize - * @mp *where@ = value to synchronize - * - * Returns: --- - * - * Use: Sets up the wheel index to match the given integer. After - * this, we can step along the wheel to find candidate primes. - */ - -static void wheelsync(primeiter *pi, mp *where) -{ - mpw w; - mp t; - mpw rr; - mp *r = MP_NEW; - unsigned i, n; - - w = WHEELMOD; - mp_build(&t, &w, &w + 1); - mp_div(0, &r, where, &t); - rr = MP_ZEROP(r) ? 0 : r->v[0]; - - for (i = 0, n = 1; rr > n; n += wheel[i], i++); - w = n - rr; - pi->p = mp_add(MP_NEW, where, &t); - pi->i = i; - pi->r = fibrand_create(0); - MP_DROP(r); -} - -/* --- @primeiter_create@ --- * - * - * Arguments: @primeiter *pi@ = pointer to an iterator structure - * @mp *start@ = where to start - * - * Returns: --- - * - * Use: Initializes a prime iterator. The first output will be the - * smallest prime not less than @start@. - */ - -void primeiter_create(primeiter *pi, mp *start) -{ - mpw n; - unsigned l, h, m; - - if (!start || MP_CMP(start, <=, MP_TWO)) - start = MP_TWO; - - if (MP_LEN(start) <= 1) { - n = start->v[0]; - if (n <= MAXPRIME) { - l = 0; - h = NPRIME; - for (;;) { - m = l + (h - l)/2; - if (primetab[m] == n) break; - else if (m == l) { m++; break; } - else if (primetab[m] < n) l = m; - else h = m; - } - pi->i = m; - pi->mode = PIMODE_PTAB; - mp_build(&pi->pp, &pi->w, &pi->w + 1); - pi->p = &pi->pp; - return; - } - } - - wheelsync(pi, start); - pi->mode = PIMODE_STALL; -} - -/* --- @primeiter_destroy@ --- * - * - * Arguments: @primeiter *pi@ = pointer to iterator structure - * - * Returns: --- - * - * Use: Frees up an iterator structure when it's no longer wanted. - */ - -void primeiter_destroy(primeiter *pi) -{ - switch (pi->mode) { - case PIMODE_PTAB: - break; - case PIMODE_STALL: - case PIMODE_WHEEL: - MP_DROP(pi->p); - GR_DESTROY(pi->r); - break; - default: - abort(); - } -} - -/* --- @primeiter_next@ --- * - * - * Arguments: @primeiter *pi@ = pointer to an iterator structure - * @mp *d@ = fake destination - * - * Returns: The next prime number from the iterator. - * - * Use: Returns a new prime number. - */ - -mp *primeiter_next(primeiter *pi, mp *d) -{ - mp *p; - - switch (pi->mode) { - case PIMODE_PTAB: - pi->w = primetab[pi->i++]; - if (pi->i >= NPRIME) { - wheelsync(pi, pi->p); - pi->mode = PIMODE_WHEEL; - } - p = MP_COPY(pi->p); - MP_SPLIT(p); - break; - case PIMODE_STALL: - pi->mode = PIMODE_WHEEL; - goto loop; - case PIMODE_WHEEL: - do { - MP_DEST(pi->p, MP_LEN(pi->p) + 1, pi->p->f); - MPX_UADDN(pi->p->v, pi->p->vl, wheel[pi->i++]); - MP_SHRINK(pi->p); - if (pi->i >= WHEELN) pi->i = 0; - loop:; - } while (!pgen_primep(pi->p, pi->r)); - p = MP_COPY(pi->p); - break; - default: - abort(); - } - if (d) MP_DROP(d); - return (p); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include -#include - -static int test(dstr *v) -{ - mp *start = *(mp **)v[0].buf; - mp *pp[5], *ret[5]; - int i; - primeiter pi; - int ok = 1; - - for (i = 0; i < N(pp); i++) - pp[i] = *(mp **)v[i + 1].buf; - primeiter_create(&pi, start); - for (i = 0; i < N(pp); i++) { - ret[i] = primeiter_next(&pi, MP_NEW); - if (!MP_EQ(ret[i], pp[i])) ok = 0; - } - if (!ok) { - fprintf(stderr, "\n*** primeiter test failure:\n*** start = "); - mp_writefile(start, stderr, 10); - for (i = 0; i < N(pp); i++) { - fprintf(stderr, "\n*** p[%d] = ", i); - mp_writefile(ret[i], stderr, 10); - fprintf(stderr, " %s ", MP_EQ(ret[i], pp[i]) ? "==" : "!="); - mp_writefile(pp[i], stderr, 10); - } - fputc('\n', stderr); - } - for (i = 0; i < N(pp); i++) { - MP_DROP(pp[i]); - MP_DROP(ret[i]); - } - primeiter_destroy(&pi); - MP_DROP(start); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static test_chunk tests[] = { - { "primeiter", test, - { &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, } }, - { 0 } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, tests, SRCDIR "/tests/pgen"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/progs/Makefile.am b/progs/Makefile.am new file mode 100644 index 0000000..4d1dbd9 --- /dev/null +++ b/progs/Makefile.am @@ -0,0 +1,109 @@ +### -*-makefile-*- +### +### Build script for utility programs +### +### (c) 2013 Straylight/Edgeware +### + +###----- Licensing notice --------------------------------------------------- +### +### This file is part of Catacomb. +### +### Catacomb is free software; you can redistribute it and/or modify +### it under the terms of the GNU Library General Public License as +### published by the Free Software Foundation; either version 2 of the +### License, or (at your option) any later version. +### +### Catacomb is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU Library General Public License for more details. +### +### You should have received a copy of the GNU Library General Public +### License along with Catacomb; if not, write to the Free +### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +### MA 02111-1307, USA. + +include $(top_srcdir)/vars.am + +bin_PROGRAMS = +dist_man_MANS = + +UTILS_LIBS = \ + libcatcrypt.la $(top_builddir)/libcatacomb.la \ + $(mLib_LIBS) $(LIBS) + +LDADD = $(UTILS_LIBS) + +###-------------------------------------------------------------------------- +### The `catcrypt' library. + +noinst_LTLIBRARIES = libcatcrypt.la +libcatcrypt_la_SOURCES = + +## The main library. +libcatcrypt_la_SOURCES += cc.h +libcatcrypt_la_SOURCES += cc-enc.c +libcatcrypt_la_SOURCES += cc-hash.c +libcatcrypt_la_SOURCES += cc-kem.c +libcatcrypt_la_SOURCES += cc-list.c +libcatcrypt_la_SOURCES += cc-progress.c +libcatcrypt_la_SOURCES += cc-sig.c +libcatcrypt_la_SOURCES += cc-subcmd.c + +## Date parsing. +libcatcrypt_la_SOURCES += getdate.h +libcatcrypt_la_SOURCES += getdate.y + +###-------------------------------------------------------------------------- +### Utility programs. + +## Generate and verify datestamped cookies. +bin_PROGRAMS += cookie +dist_man_MANS += cookie.1 + +## Asymmetric message encryption and decryption with deniable authentication. +bin_PROGRAMS += catcrypt +dist_man_MANS += catcrypt.1 + +## Signing and verifying files. +bin_PROGRAMS += catsign +dist_man_MANS += catsign.1 + +## Issue and verify signatures on directory trees. +bin_PROGRAMS += dsig +dist_man_MANS += dsig.1 + +## Compute factorials to arbitrary precision. +bin_PROGRAMS += factorial + +## Compute Fibonacci numbers to arbitrary precision. +bin_PROGRAMS += fibonacci + +## Compute hashes of files. +bin_PROGRAMS += hashsum +dist_man_MANS += hashsum.1 + +## Key management utility. +bin_PROGRAMS += key +key_SOURCES = key.c +dist_man_MANS += key.1 keyring.5 + +## Generate passphrases with given entropy using wordlists and Markov models. +bin_PROGRAMS += mkphrase +dist_man_MANS += mkphrase.1 + +## Performance testing. +bin_PROGRAMS += perftest + +## Remember passphrases for limited periods of time. +bin_PROGRAMS += pixie +pixie_SOURCES = pixie.c +pixie_LDADD = $(UTILS_LIBS) $(PIXIE_LIBS) +dist_man_MANS += pixie.1 +EXTRA_DIST += xpixie + +## Generate random data. +bin_PROGRAMS += rspit + +###----- That's all, folks -------------------------------------------------- diff --git a/catcrypt.1 b/progs/catcrypt.1 similarity index 100% rename from catcrypt.1 rename to progs/catcrypt.1 diff --git a/progs/catcrypt.c b/progs/catcrypt.c new file mode 100644 index 0000000..6e0db1d --- /dev/null +++ b/progs/catcrypt.c @@ -0,0 +1,769 @@ +/* -*-c-*- + * + * Command-line encryption tool + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _FILE_OFFSET_BITS 64 + +#include "config.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "buf.h" +#include "rand.h" +#include "noise.h" +#include "mprand.h" +#include "key.h" +#include "cc.h" + +#include "ectab.h" +#include "ptab.h" + +/*----- Static variables --------------------------------------------------*/ + +static const char *keyring = "keyring"; + +/*----- Data format -------------------------------------------------------*/ + +/* --- Overview --- * + * + * The encrypted message is divided into chunks, each preceded by a two-octet + * length. The chunks don't need to be large -- the idea is that we can + * stream the chunks in and out. + * + * The first chunk is a header. It contains the decryption key-id, and maybe + * the verification key-id if the message is signed. + * + * Next comes the key-encapsulation chunk. This is decrypted in some + * KEM-specific way to yield a secret hash. The hash is expanded using an + * MGF (or similar) to make a symmetric encryption and MAC key. + * + * If the message is signed, there comes a signature chunk. The signature is + * on the header and key-encapsulation chunks, and further output of the MGF. + * This means that the recipient can modify the message and still have a + * valid signature, so it's not useful for proving things to other people; + * but it also means that the recipient knows that the message is from + * someone who knows the hash, which limits the possiblities to (a) whoever + * encrypted the message (good!) and (b) whoever knows the recipient's + * private key. + * + * Then come message chunks. Each one begins with a MAC over an implicit + * sequence number and the ciphertext. The final chunk's ciphertext is + * empty; no other chunk is empty. Thus can the correct end-of-file be + * discerned. + */ + +/*----- Chunk I/O ---------------------------------------------------------*/ + +static void chunk_write(enc *e, buf *b) +{ + octet l[2]; + size_t n = BLEN(b); + assert(n <= MASK16); + STORE16(l, n); + if (e->ops->write(e, l, 2) || + e->ops->write(e, BBASE(b), BLEN(b))) + die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); +} + +static void chunk_read(enc *e, dstr *d, buf *b) +{ + octet l[2]; + size_t n; + + dstr_reset(d); + errno = 0; + if (e->ops->read(e, l, 2) != 2) + goto err; + n = LOAD16(l); + dstr_ensure(d, n); + if (e->ops->read(e, d->buf, n) != n) + goto err; + d->len = n; + buf_init(b, d->buf, d->len); + return; + +err: + if (!errno) die(EXIT_FAILURE, "unexpected end-of-file on input"); + else die(EXIT_FAILURE, "error reading input: %s", strerror(errno)); +} + +/*----- Encryption --------------------------------------------------------*/ + +static int encrypt(int argc, char *argv[]) +{ + const char *fn, *of = 0, *kn = "ccrypt", *skn = 0; + FILE *ofp = 0; + FILE *fp = 0; + const char *ef = "binary"; + fprogress ff; + const char *err; + int i; + int en; + size_t n, chsz; + dstr d = DSTR_INIT; + octet *tag, *ct; + buf b; + size_t seq; + char bb[65536]; + unsigned f = 0; + key_file kf; + key *k; + key *sk = 0; + kem *km; + sig *s = 0; + gcipher *cx, *c; + gmac *m; + ghash *h; + const encops *eo; + enc *e; + +#define f_bogus 1u +#define f_nocheck 2u +#define f_progress 4u + + for (;;) { + static const struct option opt[] = { + { "key", OPTF_ARGREQ, 0, 'k' }, + { "sign-key", OPTF_ARGREQ, 0, 's' }, + { "armour", 0, 0, 'a' }, + { "armor", 0, 0, 'a' }, + { "format", OPTF_ARGREQ, 0, 'f' }, + { "output", OPTF_ARGREQ, 0, 'o' }, + { "progress", 0, 0, 'p' }, + { "nocheck", 0, 0, 'C' }, + { 0, 0, 0, 0 } + }; + i = mdwopt(argc, argv, "k:s:af:o:pC", opt, 0, 0, 0); + if (i < 0) break; + switch (i) { + case 'k': kn = optarg; break; + case 's': skn = optarg; break; + case 'a': ef = "pem"; break; + case 'f': ef = optarg; break; + case 'o': of = optarg; break; + case 'p': f |= f_progress; break; + case 'C': f |= f_nocheck; break; + default: f |= f_bogus; break; + } + } + if (argc - optind > 1 || (f & f_bogus)) + die(EXIT_FAILURE, "Usage: encrypt [-OPTIONS] [FILE]"); + + if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0)) + die(EXIT_FAILURE, "can't open keyring `%s'", keyring); + if ((k = key_bytag(&kf, kn)) == 0) + die(EXIT_FAILURE, "key `%s' not found", kn); + if (skn && (sk = key_bytag(&kf, skn)) == 0) + die(EXIT_FAILURE, "key `%s' not found", skn); + + if ((eo = getenc(ef)) == 0) + die(EXIT_FAILURE, "encoding `%s' not found", ef); + + fn = optind < argc ? argv[optind++] : "-"; + if (strcmp(fn, "-") == 0) + fp = stdin; + else if ((fp = fopen(fn, "rb")) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s': %s", + fn, strerror(errno)); + } + + if (!of || strcmp(of, "-") == 0) + ofp = stdout; + else if ((ofp = fopen(of, eo->wmode)) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", + ofp, strerror(errno)); + } + + dstr_reset(&d); + key_fulltag(k, &d); + e = initenc(eo, ofp, "CATCRYPT ENCRYPTED MESSAGE"); + km = getkem(k, "cckem", 0); + if (!(f & f_nocheck) && (err = km->ops->check(km)) != 0) + moan("key %s fails check: %s", d.buf, err); + if (sk) { + dstr_reset(&d); + key_fulltag(sk, &d); + s = getsig(sk, "ccsig", 1); + if ((err = s->ops->check(s)) != 0) + moan("key %s fails check: %s", d.buf, err); + } + + /* --- Build the header chunk --- */ + + dstr_reset(&d); + dstr_ensure(&d, 256); + buf_init(&b, d.buf, 256); + buf_putu32(&b, k->id); + if (sk) buf_putu32(&b, sk->id); + assert(BOK(&b)); + if (s) GH_HASHBUF16(s->h, BBASE(&b), BLEN(&b)); + chunk_write(e, &b); + + /* --- Build the KEM chunk --- */ + + dstr_reset(&d); + if (setupkem(km, &d, &cx, &c, &m)) + die(EXIT_FAILURE, "failed to encapsulate key"); + buf_init(&b, d.buf, d.len); + BSTEP(&b, d.len); + if (s) GH_HASHBUF16(s->h, BBASE(&b), BLEN(&b)); + chunk_write(e, &b); + + /* --- Write the signature chunk --- */ + + if (s) { + GC_ENCRYPT(cx, 0, bb, 1024); + GH_HASH(s->h, bb, 1024); + dstr_reset(&d); + if ((en = s->ops->doit(s, &d)) != 0) + die(EXIT_FAILURE, "error creating signature: %s", key_strerror(en)); + buf_init(&b, d.buf, d.len); + BSTEP(&b, d.len); + chunk_write(e, &b); + } + + /* --- Now do the main crypto --- */ + + if (f & f_progress) { + if (fprogress_init(&ff, fn, fp)) { + die(EXIT_FAILURE, "failed to initialize progress display: %s", + strerror(errno)); + } + } + + assert(GC_CLASS(c)->blksz <= sizeof(bb)); + dstr_ensure(&d, sizeof(bb) + GM_CLASS(m)->hashsz); + seq = 0; + chsz = MASK16 - GM_CLASS(m)->hashsz; + for (;;) { + h = GM_INIT(m); + GH_HASHU32(h, seq); + seq++; + if (GC_CLASS(c)->blksz) { + GC_ENCRYPT(cx, 0, bb, GC_CLASS(c)->blksz); + GC_SETIV(c, bb); + } + n = fread(bb, 1, chsz, fp); + if (!n) break; + if (f & f_progress) fprogress_update(&ff, n); + buf_init(&b, d.buf, d.sz); + tag = buf_get(&b, GM_CLASS(m)->hashsz); + ct = buf_get(&b, n); + assert(tag); assert(ct); + GC_ENCRYPT(c, bb, ct, n); + GH_HASH(h, ct, n); + GH_DONE(h, tag); + GH_DESTROY(h); + chunk_write(e, &b); + } + + /* --- Final terminator packet --- */ + + buf_init(&b, d.buf, d.sz); + tag = buf_get(&b, GM_CLASS(m)->hashsz); + assert(tag); + GH_DONE(h, tag); + GH_DESTROY(h); + chunk_write(e, &b); + + /* --- All done --- */ + + if (f & f_progress) fprogress_done(&ff); + e->ops->encdone(e); + GM_DESTROY(m); + GC_DESTROY(c); + GC_DESTROY(cx); + freeenc(e); + if (s) freesig(s); + freekem(km); + if (fp != stdin) fclose(fp); + if (of) fclose(ofp); + key_close(&kf); + dstr_destroy(&d); + return (0); + +#undef f_bogus +#undef f_nocheck +#undef f_progress +} + +/*---- Decryption ---------------------------------------------------------*/ + +static int decrypt(int argc, char *argv[]) +{ + const char *fn, *of = 0; + FILE *ofp = 0, *rfp = 0; + FILE *fp = 0; + const char *ef = "binary"; + fprogress ff; + int i; + size_t n; + dstr d = DSTR_INIT; + buf b; + key_file kf; + size_t seq; + uint32 id; + key *k; + key *sk = 0; + kem *km; + sig *s = 0; + gcipher *cx; + gcipher *c; + ghash *h; + gmac *m; + octet *tag; + unsigned f = 0; + const encops *eo; + const char *err; + int verb = 1; + enc *e; + +#define f_bogus 1u +#define f_buffer 2u +#define f_nocheck 4u +#define f_progress 8u + + for (;;) { + static const struct option opt[] = { + { "armour", 0, 0, 'a' }, + { "armor", 0, 0, 'a' }, + { "buffer", 0, 0, 'b' }, + { "verbose", 0, 0, 'v' }, + { "quiet", 0, 0, 'q' }, + { "nocheck", 0, 0, 'C' }, + { "format", OPTF_ARGREQ, 0, 'f' }, + { "output", OPTF_ARGREQ, 0, 'o' }, + { "progress", 0, 0, 'p' }, + { 0, 0, 0, 0 } + }; + i = mdwopt(argc, argv, "abf:o:pqvC", opt, 0, 0, 0); + if (i < 0) break; + switch (i) { + case 'a': ef = "pem"; break; + case 'b': f |= f_buffer; break; + case 'v': verb++; break; + case 'q': if (verb) verb--; break; + case 'C': f |= f_nocheck; break; + case 'f': ef = optarg; break; + case 'o': of = optarg; break; + case 'p': f |= f_progress; break; + default: f |= f_bogus; break; + } + } + if (argc - optind > 1 || (f & f_bogus)) + die(EXIT_FAILURE, "Usage: decrypt [-OPTIONS] [FILE]"); + + if ((eo = getenc(ef)) == 0) + die(EXIT_FAILURE, "encoding `%s' not found", ef); + + fn = optind < argc ? argv[optind++] : "-"; + if (strcmp(fn, "-") == 0) + fp = stdin; + else if ((fp = fopen(fn, eo->rmode)) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s': %s", + fn, strerror(errno)); + } + + if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0)) + die(EXIT_FAILURE, "can't open keyring `%s'", keyring); + + e = initdec(eo, fp, checkbdry, "CATCRYPT ENCRYPTED MESSAGE"); + + if (f & f_progress) { + if (fprogress_init(&ff, fn, fp)) { + die(EXIT_FAILURE, "failed to initialize progress display: %s", + strerror(errno)); + } + } + + /* --- Read the header chunk --- */ + + chunk_read(e, &d, &b); + if (f & f_progress) + fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw); + if (buf_getu32(&b, &id)) { + if (f & f_progress) fprogress_done(&ff); + if (verb) printf("FAIL malformed header: missing keyid\n"); + exit(EXIT_FAILURE); + } + if ((k = key_byid(&kf, id)) == 0) { + if (f & f_progress) fprogress_done(&ff); + if (verb) printf("FAIL key id %08lx not found\n", (unsigned long)id); + exit(EXIT_FAILURE); + } + if (BLEFT(&b)) { + if (buf_getu32(&b, &id)) { + if (f & f_progress) fprogress_done(&ff); + if (verb) printf("FAIL malformed header: missing signature keyid\n"); + exit(EXIT_FAILURE); + } + if ((sk = key_byid(&kf, id)) == 0) { + if (f & f_progress) fprogress_done(&ff); + if (verb) printf("FAIL key id %08lx not found\n", (unsigned long)id); + exit(EXIT_FAILURE); + } + } + if (BLEFT(&b)) { + if (f & f_progress) fprogress_done(&ff); + if (verb) printf("FAIL malformed header: junk at end\n"); + exit(EXIT_FAILURE); + } + if (sk) { + s = getsig(sk, "ccsig", 0); + if (!(f & f_nocheck) && verb && (err = s->ops->check(s)) != 0) { + dstr_reset(&d); + key_fulltag(sk, &d); + printf("WARN verification key %s fails check: %s\n", d.buf, err); + } + GH_HASHBUF16(s->h, BBASE(&b), BSZ(&b)); + } + + /* --- Find the key --- */ + + km = getkem(k, "cckem", 1); + + /* --- Read the KEM chunk --- */ + + chunk_read(e, &d, &b); + if (f & f_progress) + fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw); + if (setupkem(km, &d, &cx, &c, &m)) { + if (f & f_progress) fprogress_done(&ff); + if (verb) printf("FAIL failed to decapsulate key\n"); + exit(EXIT_FAILURE); + } + if (s) GH_HASHBUF16(s->h, d.buf, d.len); + + /* --- Verify the signature, if there is one --- */ + + if (sk) { + dstr_reset(&d); + dstr_ensure(&d, 1024); + GC_ENCRYPT(cx, 0, d.buf, 1024); + GH_HASH(s->h, d.buf, 1024); + chunk_read(e, &d, &b); + if (f & f_progress) + fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw); + if (s->ops->doit(s, &d)) { + if (f & f_progress) fprogress_done(&ff); + if (verb) printf("FAIL signature verification failed\n"); + exit(EXIT_FAILURE); + } + if (verb) { + dstr_reset(&d); + key_fulltag(sk, &d); + if (f & f_progress) fprogress_clear(&ff); + printf("INFO good-signature %s\n", d.buf); + } + freesig(s); + } else if (verb) { + if (f & f_progress) fprogress_clear(&ff); + printf("INFO no-signature\n"); + } + + /* --- Now decrypt the main body --- */ + + if (!of || strcmp(of, "-") == 0) { + ofp = stdout; + f |= f_buffer; + } + if (!(f & f_buffer)) { + if ((ofp = fopen(of, "wb")) == 0) { + if (f & f_progress) fprogress_done(&ff); + die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", + ofp, strerror(errno)); + } + rfp = ofp; + } else if ((rfp = tmpfile()) == 0) { + if (f & f_progress) fprogress_done(&ff); + die(EXIT_FAILURE, "couldn't create temporary file: %s", strerror(errno)); + } + + seq = 0; + dstr_ensure(&d, GC_CLASS(c)->blksz); + dstr_ensure(&d, 4); + for (;;) { + if (GC_CLASS(c)->blksz) { + GC_ENCRYPT(cx, 0, d.buf, GC_CLASS(c)->blksz); + GC_SETIV(c, d.buf); + } + h = GM_INIT(m); + GH_HASHU32(h, seq); + seq++; + chunk_read(e, &d, &b); + if (f & f_progress) + fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw); + if ((tag = buf_get(&b, GM_CLASS(m)->hashsz)) == 0) { + if (f & f_progress) fprogress_done(&ff); + if (verb) printf("FAIL bad ciphertext chunk: no tag\n"); + exit(EXIT_FAILURE); + } + GH_HASH(h, BCUR(&b), BLEFT(&b)); + if (memcmp(tag, GH_DONE(h, 0), GM_CLASS(m)->hashsz) != 0) { + if (f & f_progress) fprogress_done(&ff); + if (verb) + printf("FAIL bad ciphertext chunk: authentication failure\n"); + exit(EXIT_FAILURE); + } + GH_DESTROY(h); + if (!BLEFT(&b)) + break; + GC_DECRYPT(c, BCUR(&b), BCUR(&b), BLEFT(&b)); + if (fwrite(BCUR(&b), 1, BLEFT(&b), rfp) != BLEFT(&b)) { + if (f & f_progress) fprogress_done(&ff); + if (verb) printf("FAIL error writing output: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + } + + if (f & f_progress) fprogress_done(&ff); + if (fflush(rfp) || ferror(rfp)) { + if (verb) printf("FAIL error writing output: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + if (f & f_buffer) { + if (!ofp && (ofp = fopen(of, "wb")) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", + of, strerror(errno)); + } + rewind(rfp); + if (f & f_progress) fprogress_init(&ff, "copying buffer", rfp); + dstr_reset(&d); + dstr_ensure(&d, 65536); + if (verb && ofp == stdout) printf("DATA\n"); + for (;;) { + n = fread(d.buf, 1, d.sz, rfp); + if (!n) break; + if (f & f_progress) fprogress_update(&ff, n); + if (fwrite(d.buf, 1, n, ofp) < n) { + if (f & f_progress) fprogress_done(&ff); + die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); + } + } + if (f & f_progress) fprogress_done(&ff); + if (ferror(rfp) || fclose(rfp)) + die(EXIT_FAILURE, "error unbuffering output: %s", strerror(errno)); + } + + e->ops->decdone(e); + if (verb && ofp != stdout) + printf("OK decrypted successfully\n"); + if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp))) + die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); + freeenc(e); + GC_DESTROY(c); + GC_DESTROY(cx); + GM_DESTROY(m); + freekem(km); + if (fp != stdin) fclose(fp); + key_close(&kf); + dstr_destroy(&d); + return (0); + +#undef f_bogus +#undef f_buffer +#undef f_nocheck +#undef f_progress +} + +/*----- Main code ---------------------------------------------------------*/ + +#define LISTS(LI) \ + LI("Lists", list, \ + listtab[i].name, listtab[i].name) \ + LI("Key-encapsulation mechanisms", kem, \ + kemtab[i].name, kemtab[i].name) \ + LI("Signature schemes", sig, \ + sigtab[i].name, sigtab[i].name) \ + LI("Encodings", enc, \ + enctab[i].name, enctab[i].name) \ + LI("Symmetric encryption algorithms", cipher, \ + gciphertab[i], gciphertab[i]->name) \ + LI("Hash functions", hash, \ + ghashtab[i], ghashtab[i]->name) \ + LI("Message authentication codes", mac, \ + gmactab[i], gmactab[i]->name) + +MAKELISTTAB(listtab, LISTS) + +int cmd_show(int argc, char *argv[]) +{ + return (displaylists(listtab, argv + 1)); +} + +static int cmd_help(int, char **); + +static cmd cmdtab[] = { + { "help", cmd_help, "help [COMMAND...]" }, + { "show", cmd_show, "show [ITEM...]" }, + CMD_ENCODE, + CMD_DECODE, + { "encrypt", encrypt, + "encrypt [-apC] [-k TAG] [-s TAG] [-f FORMAT]\n\t\ +[-o OUTPUT] [FILE]", "\ +Options:\n\ +\n\ +-a, --armour Same as `-f pem'.\n\ +-f, --format=FORMAT Encode as FORMAT.\n\ +-k, --key=TAG Use public encryption key named by TAG.\n\ +-s, --sign-key=TAG Use private signature key named by TAG.\n\ +-o, --output=FILE Write output to FILE.\n\ +-p, --progress Show progress on large files.\n\ +-C, --nocheck Don't check the public key.\n\ +" }, + { "decrypt", decrypt, + "decrypt [-abpqvC] [-f FORMAT] [-o OUTPUT] [FILE]", "\ +Options:\n\ +\n\ +-a, --armour Same as `-f pem'.\n\ +-b, --buffer Buffer output until we're sure we have it all.\n\ +-f, --format=FORMAT Decode as FORMAT.\n\ +-o, --output=FILE Write output to FILE.\n\ +-p, --progress Show progress on large files.\n\ +-q, --quiet Produce fewer messages.\n\ +-v, --verbose Produce more verbose messages.\n\ +-C, --nocheck Don't check the private key.\n\ +" }, + { 0, 0, 0 } +}; + +static int cmd_help(int argc, char **argv) +{ + sc_help(cmdtab, stdout, argv + 1); + return (0); +} + +void version(FILE *fp) +{ + pquis(fp, "$, Catacomb version " VERSION "\n"); +} + +static void usage(FILE *fp) +{ + pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n"); +} + +void help_global(FILE *fp) +{ + usage(fp); + fputs("\n\ +Encrypt and decrypt files.\n\ +\n\ +Global command-line options:\n\ +\n\ +-h, --help [COMMAND...] Show this help message, or help for COMMANDs.\n\ +-v, --version Show program version number.\n\ +-u, --usage Show a terse usage message.\n\ +\n\ +-k, --keyring=FILE Read keys from FILE.\n", + fp); +} + +/* --- @main@ --- * + * + * Arguments: @int argc@ = number of command line arguments + * @char *argv[]@ = vector of command line arguments + * + * Returns: Zero if successful, nonzero otherwise. + * + * Use: Encrypts or decrypts files. + */ + +int main(int argc, char *argv[]) +{ + unsigned f = 0; + +#define f_bogus 1u + + /* --- Initialize the library --- */ + + ego(argv[0]); + sub_init(); + rand_noisesrc(RAND_GLOBAL, &noise_source); + rand_seed(RAND_GLOBAL, 160); + + /* --- Parse options --- */ + + for (;;) { + static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "usage", 0, 0, 'u' }, + { "keyring", OPTF_ARGREQ, 0, 'k' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+hvu k:", opts, 0, 0, 0); + if (i < 0) + break; + switch (i) { + case 'h': + sc_help(cmdtab, stdout, argv + optind); + exit(0); + break; + case 'v': + version(stdout); + exit(0); + break; + case 'u': + usage(stdout); + exit(0); + case 'k': + keyring = optarg; + break; + default: + f |= f_bogus; + break; + } + } + + argc -= optind; + argv += optind; + optind = 0; + if (f & f_bogus || argc < 1) { + usage(stderr); + exit(EXIT_FAILURE); + } + + /* --- Dispatch to the correct subcommand handler --- */ + + return (findcmd(cmdtab, argv[0])->cmd(argc, argv)); + +#undef f_bogus +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/catsign.1 b/progs/catsign.1 similarity index 100% rename from catsign.1 rename to progs/catsign.1 diff --git a/progs/catsign.c b/progs/catsign.c new file mode 100644 index 0000000..48f8fcb --- /dev/null +++ b/progs/catsign.c @@ -0,0 +1,1274 @@ +/* -*-c-*- + * + * Sign files + * + * (c) 2005 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _FILE_OFFSET_BITS 64 + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "buf.h" +#include "rand.h" +#include "noise.h" +#include "mprand.h" +#include "key.h" +#include "getdate.h" +#include "cc.h" + +#include "ectab.h" +#include "ptab.h" + +/*----- Static variables --------------------------------------------------*/ + +static const char *keyring = "keyring"; + +/*----- Data formats ------------------------------------------------------* + * + * Our crypto stuff is split into three parts: a header describing the key, + * the message itself, and the signature. In a detached signature, the + * message is separate, and the header and signature are combined into one + * encoded chunk. In an attached signature, the message is included. There + * are two forms of message: binary and text. Binary messages are divided + * into chunks, each preceded by a 2-octet length, and terminated by a + * zero-length chunk. Text messages are byte-stuffed, as for RFC821, and + * trailing whitespace before a newline is ignored. + */ + +typedef struct sigmsg { + unsigned f; /* Flags */ +#define F_DETACH 1u +#define F_BINARY 2u +#define F_SIGMASK 3u +#define F_HASHMASK (F_BINARY) + uint32 keyid; /* Key identifier */ + time_t t; /* When the signature was made */ + dstr kh; /* Key fingerprint (sanity check) */ + dstr sig; /* Signature */ + sig *s; /* Signature algorithm */ +} sigmsg; + +#define F_MIDLINE 16u +#define F_EOF 32u +#define F_NOCLOSE 64u +#define F_BOGUS 128u +#define F_BUFFER 256u +#define F_UTC 512u +#define F_NOCHECK 1024u +#define F_PROGRESS 2048u + +/*----- Chunk I/O ---------------------------------------------------------*/ + +static void chunk_write(enc *e, const void *p, size_t n) +{ + octet b[2]; + + assert(n <= 0xffff); + STORE16(b, n); + if (e->ops->write(e, b, 2) || e->ops->write(e, p, n)) + die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); +} + +static size_t chunk_read(enc *e, void *p) +{ + octet b[2]; + size_t n; + + if (e->ops->read(e, b, 2) != 2) + goto err; + n = LOAD16(b); + if (n && e->ops->read(e, p, n) != n) + goto err; + return (n); + +err: + if (!errno) die(EXIT_FAILURE, "unexpected end-of-file on input"); + else die(EXIT_FAILURE, "error reading input: %s", strerror(errno)); + return (0); +} + +/*----- Message canonification --------------------------------------------*/ + +#define MSGBUFSZ 65536 +#define MSGBUFTHRESH 32768 + +typedef struct msgcanon { + unsigned f; + FILE *fp; + enc *e; + fprogress ff; + size_t (*read)(struct msgcanon *, void *); + void (*write)(struct msgcanon *, const void *, size_t); + void (*close)(struct msgcanon *); +} msgcanon; + +#define MC_INIT { 0 } + +static size_t textread(msgcanon *m, void *bp) +{ + size_t n = 0, nsp = 0; + int ch; + char *b = bp; + unsigned f = m->f; + + if (f & F_EOF) return (0); + for (;;) { + if ((ch = getc(m->fp)) == EOF) goto eof; + if (!(f & (F_DETACH | F_MIDLINE)) && ch == '.') { + ch = getc(m->fp); + if (ch == '\n') goto eof; + } + if (ch == '\n') { + n -= nsp; nsp = 0; + if (n >= MSGBUFTHRESH) goto full; + b[n++] = ch; + f &= ~F_MIDLINE; + } else if (isspace(ch)) { + f |= F_MIDLINE; + if (n >= MSGBUFSZ) goto full; + b[n++] = ch; nsp++; + } else { + f |= F_MIDLINE; + nsp = 0; + if (n >= MSGBUFTHRESH) goto full; + b[n++] = ch; + } + } +eof: + f |= F_EOF; + goto done; +full: + ungetc(ch, m->fp); +done: + m->f = f; + if (m->f & F_PROGRESS) fprogress_update(&m->ff, n); + return (n); +} + +static void textwrite(msgcanon *m, const void *bp, size_t n) +{ + const char *p = bp, *l = p + n; + unsigned f = m->f; + + while (p < l) { + if (!(f & (F_MIDLINE | F_DETACH)) && + (*p == '.' || *p == '-')) + putc('.', m->fp); + if (*p == '\n') f &= ~F_MIDLINE; + else f |= F_MIDLINE; + putc(*p, m->fp); + p++; + } + m->f = f; +} + +static size_t binreadembed(msgcanon *m, void *bp) +{ + size_t n = chunk_read(m->e, bp); + if (m->f & F_PROGRESS) fprogress_update(&m->ff, n); + return (n); +} + +static size_t binreaddetach(msgcanon *m, void *bp) +{ + size_t n = fread(bp, 1, MSGBUFSZ - 1, m->fp); + if (m->f & F_PROGRESS) fprogress_update(&m->ff, n); + return (n); +} + +static void binwriteembed(msgcanon *m, const void *bp, size_t n) + { chunk_write(m->e, bp, n); } + +static void nullwrite(msgcanon *m, const void *bp, size_t n) { ; } + +static void mcsetup_readfile(msgcanon *m, unsigned f, const char *fn) +{ + m->f = F_DETACH | (f & (F_BINARY | F_PROGRESS)); + if (!fn || strcmp(fn, "-") == 0) { + m->fp = stdin; + m->f |= F_NOCLOSE; + } else if ((m->fp = fopen(fn, (f & F_BINARY) ? "rb" : "r")) == 0) + die(EXIT_FAILURE, "couldn't open file `%s': %s", fn, strerror(errno)); + if (m->f & F_PROGRESS) { + if (fprogress_init(&m->ff, fn, m->fp)) { + die(EXIT_FAILURE, "failed to initialize progress indicator: %s", + strerror(errno)); + } + } + m->read = (f & F_BINARY) ? binreaddetach : textread; +} + +static void mcsetup_writenull(msgcanon *m) { m->write = nullwrite; } + +static void mcsetup_read(msgcanon *m, unsigned f, enc **ee, + const char *fn, const char *dfn) +{ + enc *e = *ee; + + m->f = f | F_NOCLOSE; + + if (dfn && !(f & F_DETACH)) die(EXIT_FAILURE, "signature is not detached"); + if (f & F_BINARY) { + if (!(f & F_DETACH)) { + m->e = e; + *ee = 0; + m->fp = e->fp; + m->read = binreadembed; + if (m->f & F_PROGRESS) { + if (fprogress_init(&m->ff, fn, m->fp)) { + die(EXIT_FAILURE, "failed to initialize progress indicator: %s", + strerror(errno)); + } + } + } else { + m->read = binreaddetach; + if (!dfn || strcmp(dfn, "-") == 0) + m->fp = stdin; + else if ((m->fp = fopen(dfn, "rb")) == 0) + die(EXIT_FAILURE, "can't open `%s': %s", dfn, strerror(errno)); + else + m->f &= ~F_NOCLOSE; + if (m->f & F_PROGRESS) { + if (fprogress_init(&m->ff, dfn, m->fp)) { + die(EXIT_FAILURE, "failed to initialize progress indicator: %s", + strerror(errno)); + } + } + } + } else { + m->read = textread; + if (!(f & F_DETACH)) { + if (e->ops->decdone(e) || ferror(e->fp)) + die(EXIT_FAILURE, "error at end of signature header"); + m->fp = e->fp; + e->ops->destroy(e); + *ee = 0; + if (m->f & F_PROGRESS) { + if (fprogress_init(&m->ff, fn, m->fp)) { + die(EXIT_FAILURE, "failed to initialize progress indicator: %s", + strerror(errno)); + } + } + } else { + if (!dfn || strcmp(dfn, "-") == 0) + m->fp = stdin; + else if ((m->fp = fopen(dfn, "r")) == 0) + die(EXIT_FAILURE, "can't read file `%s': %s", dfn, strerror(errno)); + else + m->f &= ~F_NOCLOSE; + if (m->f & F_PROGRESS) { + if (fprogress_init(&m->ff, dfn, m->fp)) { + die(EXIT_FAILURE, "failed to initialize progress indicator: %s", + strerror(errno)); + } + } + } + } +} + +static void mcsetup_write(msgcanon *m, unsigned f, enc **ee) +{ + enc *e = *ee; + + m->f = f | F_NOCLOSE; + + if (f & F_DETACH) + m->write = nullwrite; + else if (f & F_BINARY) { + m->e = e; + *ee = 0; + m->fp = e->fp; + m->write = binwriteembed; + } else { + if (e->ops->encdone(e) || ferror(e->fp)) + die(EXIT_FAILURE, "error at end of signature header"); + m->fp = e->fp; + e->ops->destroy(e); + *ee = 0; + m->write = textwrite; + } +} + +static void mc_endread(msgcanon *m, const encops *eops, enc **ee) +{ + if (!(m->f & F_DETACH)) { + if (m->f & F_BINARY) + *ee = m->e; + else + *ee = initdec(eops, m->fp, checkbdry, "CATSIGN SIGNATURE"); + } + if (m->fp && !(m->f & F_NOCLOSE)) { + if (ferror(m->fp) || fclose(m->fp)) + die(EXIT_FAILURE, "error closing message file: %s", strerror(errno)); + } + if (m->f & F_PROGRESS) fprogress_done(&m->ff); +} + +static void mc_endwrite(msgcanon *m, const encops *eops, enc **ee) +{ + if (!(m->f & F_BINARY)) { + if (m->f & F_MIDLINE) putc('\n', m->fp); + if (!(m->f & F_DETACH)) { + putc('.', m->fp); putc('\n', m->fp); + *ee = initenc(eops, m->fp, "CATSIGN SIGNATURE"); + } + } else if (!(m->f & F_DETACH)) { + chunk_write(m->e, 0, 0); + *ee = m->e; + } + if (m->fp && !(m->f & F_NOCLOSE)) { + if (fflush(m->fp) || ferror(m->fp) || fclose(m->fp)) + die(EXIT_FAILURE, "error closing message file: %s", strerror(errno)); + } +} + +/*----- Signature reading and writing -------------------------------------*/ + +static void sig_init(sigmsg *s, unsigned f, uint32 keyid) +{ + s->f = f & F_SIGMASK; + s->keyid = keyid; + time(&s->t); + s->s = 0; + dstr_create(&s->kh); + dstr_create(&s->sig); +} + +static void sig_destroy(sigmsg *s) +{ + dstr_destroy(&s->kh); + dstr_destroy(&s->sig); + if (s->s) freesig(s->s); +} + +static void sigtobuffer(sigmsg *s, buf *b, int hashp) +{ + kludge64 t; + + ASSIGN64(t, s->t); + if (hashp) buf_putu16(b, s->f & F_HASHMASK); + else buf_putu16(b, s->f & F_SIGMASK); + buf_putu32(b, s->keyid); + buf_putu32(b, HI64(t)); + buf_putu32(b, LO64(t)); + buf_putdstr16(b, &s->kh); + assert(BOK(b)); +} + +static void dohash(ghash *h, const void *p, size_t n) +{ +/* trace_block(1, "hashing", p, n); */ + GH_HASH(h, p, n); +} + +static void sig_hash(sigmsg *s) +{ + octet bb[16384]; + buf b; + + buf_init(&b, bb, sizeof(bb)); + sigtobuffer(s, &b, 1); + dohash(s->s->h, BBASE(&b), BLEN(&b)); +} + +static void keyhash(key *k, sig *s, dstr *d) +{ + ghash *h; + key_filter kf; + + h = GH_INIT(s->ch); + kf.f = KCAT_PUB; + kf.m = KF_CATMASK; + key_fingerprint(k, h, &kf); + dstr_ensure(d, GH_CLASS(h)->hashsz); + GH_DONE(h, d->buf + d->len); + d->len += GH_CLASS(h)->hashsz; + GH_DESTROY(h); +} + +static void sig_writeheader(enc *e, sigmsg *s) +{ + octet bb[16384]; + buf b; + + buf_init(&b, bb, sizeof(bb)); + sigtobuffer(s, &b, 0); + chunk_write(e, BBASE(&b), BLEN(&b)); +} + +static void sig_writesig(enc *e, sigmsg *s) + { chunk_write(e, s->sig.buf, s->sig.len); } + +static void diechoke(const char *m, void *p) + { die(EXIT_FAILURE, "%s%s%s", p, p ? ": " : "", m); } + +static void sig_readheader(enc *e, sigmsg *s, + void (*choke)(const char *, void *), void *p) +{ + uint16 f; + octet bb[MSGBUFSZ]; + uint32 x, y; + kludge64 t; + buf b; + size_t n; + + n = chunk_read(e, bb); + buf_init(&b, bb, n); + if (buf_getu16(&b, &f)) choke("missing flags", p); + if (buf_getu32(&b, &x)) choke("missing keyid", p); + sig_init(s, f, x); + if (buf_getu32(&b, &x) || buf_getu32(&b, &y)) + choke("missing datestamp", p); + SET64(t, x, y); s->t = GET64(time_t, t); + if (buf_getdstr16(&b, &s->kh)) + choke("missing key hash", p); + if (BLEFT(&b)) + choke("junk at end", p); +} + +static void sig_readsig(enc *e, sigmsg *s) +{ + octet bb[MSGBUFSZ]; + size_t n; + + n = chunk_read(e, bb); + dstr_putm(&s->sig, bb, n); +} + +/*----- Signing -----------------------------------------------------------*/ + +static int sign(int argc, char *argv[]) +{ + const char *ef = "binary", *fn = 0, *of = 0, *kn = "ccsig", *err; + unsigned f = 0; + key_file kf; + key *k; + sigmsg s; + FILE *ofp = 0; + int i; + char bb[MSGBUFSZ]; + size_t n; + dstr d = DSTR_INIT; + const encops *eo; + msgcanon mc_in = MC_INIT, mc_out = MC_INIT; + enc *e; + + for (;;) { + static const struct option opt[] = { + { "armour", 0, 0, 'a' }, + { "armor", 0, 0, 'a' }, + { "binary", 0, 0, 'b' }, + { "detach", 0, 0, 'd' }, + { "key", OPTF_ARGREQ, 0, 'k' }, + { "format", OPTF_ARGREQ, 0, 'f' }, + { "output", OPTF_ARGREQ, 0, 'o' }, + { "progress", 0, 0, 'p' }, + { "text", 0, 0, 't' }, + { "nocheck", 0, 0, 'C' }, + { 0, 0, 0, 0 } + }; + i = mdwopt(argc, argv, "k:f:o:abdptC", opt, 0, 0, 0); + if (i < 0) break; + switch (i) { + case 'k': kn = optarg; break; + case 'f': ef = optarg; break; + case 'o': of = optarg; break; + case 'a': ef = "pem"; break; + case 't': f &= ~F_BINARY; break; + case 'b': f |= F_BINARY; break; + case 'd': f |= F_DETACH; break; + case 'C': f |= F_NOCHECK; break; + case 'p': f |= F_PROGRESS; break; + default: f |= F_BOGUS; break; + } + } + if (argc - optind > 1 || (f & F_BOGUS)) + die(EXIT_FAILURE, "Usage: sign [-OPTIONS] [FILE]"); + + if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0)) + die(EXIT_FAILURE, "can't open keyring `%s'", keyring); + if ((k = key_bytag(&kf, kn)) == 0) + die(EXIT_FAILURE, "key `%s' not found", kn); + + if ((eo = getenc(ef)) == 0) + die(EXIT_FAILURE, "encoding `%s' not found", ef); + + fn = (optind >= argc) ? 0 : argv[optind++]; + + if (!of || strcmp(of, "-") == 0) + ofp = stdout; + else if ((ofp = fopen(of, eo->wmode)) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", + ofp, strerror(errno)); + } + + /* --- Start the work --- */ + + sig_init(&s, f, k->id); + dstr_reset(&d); + key_fulltag(k, &d); + s.s = getsig(k, "ccsig", 1); + if (!(f & F_NOCHECK) && (err = s.s->ops->check(s.s)) != 0) + moan("key %s fails check: %s", d.buf, err); + keyhash(k, s.s, &s.kh); + e = initenc(eo, ofp, + (f & F_DETACH) ? "CATSIGN SIGNATURE" : + (f & F_BINARY) ? "CATSIGN MESSAGE" : + "CATSIGN MESSAGE HEADER"); + sig_writeheader(e, &s); + + /* --- Hash the message --- */ + + mcsetup_readfile(&mc_in, f, fn); + mcsetup_write(&mc_out, f, &e); + sig_hash(&s); + for (;;) { + n = mc_in.read(&mc_in, bb); + if (!n) break; + dohash(s.s->h, bb, n); + mc_out.write(&mc_out, bb, n); + } + mc_endread(&mc_in, 0, 0); + mc_endwrite(&mc_out, eo, &e); + + /* --- Write the signature --- */ + + if (s.s->ops->doit(s.s, &s.sig)) + die(EXIT_FAILURE, "signature failed"); + sig_writesig(e, &s); + e->ops->encdone(e); + if (fflush(ofp) || ferror(ofp) || fclose(ofp)) + die(EXIT_FAILURE, "error writing signature: %s", strerror(errno)); + + /* --- All done --- */ + + freeenc(e); + key_close(&kf); + sig_destroy(&s); + dstr_destroy(&d); + return (0); +} + +/*----- Verifying ---------------------------------------------------------*/ + +typedef struct vrfctx { + unsigned f, m; + int verb; + const char *what; +} vrfctx; + +static int vrfbdry(const char *b, void *p) +{ + vrfctx *v = p; + + if (strcmp(b, "CATSIGN MESSAGE") == 0) { + v->f |= F_BINARY; + v->m |= F_BINARY | F_DETACH; + return (1); + } else if (strcmp(b, "CATSIGN MESSAGE HEADER") == 0) { + v->m |= F_BINARY | F_DETACH; + return (1); + } else if (strcmp(b, "CATSIGN SIGNATURE") == 0) { + v->f |= F_DETACH; + v->m |= F_DETACH; + return (1); + } else + return (0); +} + +static void vrfchoke(const char *m, void *p) +{ + vrfctx *v = p; + if (v->verb) printf("FAIL %s: %s\n", v->what, m); + exit(EXIT_FAILURE); +} + +static int verify(int argc, char *argv[]) +{ + const char *ef = "binary", *of = 0, *fn, *dfn = 0, *kn = 0, *err; + vrfctx v = { 0, 0, 1 }; + key_file kf; + key *k, *kk = 0; + sigmsg s; + FILE *fp, *ofp = 0, *rfp = 0; + fprogress ff; + struct tm *tm; + int i; + char bb[MSGBUFSZ]; + size_t n; + time_t t_fresh = 0; + dstr d = DSTR_INIT, dd = DSTR_INIT; + const encops *eo; + msgcanon mc_in = MC_INIT; + enc *e; + + for (;;) { + static const struct option opt[] = { + { "armour", 0, 0, 'a' }, + { "armor", 0, 0, 'a' }, + { "buffer", 0, 0, 'b' }, + { "key", OPTF_ARGREQ, 0, 'k' }, + { "format", OPTF_ARGREQ, 0, 'f' }, + { "output", OPTF_ARGREQ, 0, 'o' }, + { "progress", 0, 0, 'p' }, + { "quiet", 0, 0, 'q' }, + { "utc", 0, 0, 'u' }, + { "fresh-time", 0, 0, 't' }, + { "gmt", 0, 0, 'u' }, + { "verbose", 0, 0, 'v' }, + { "nocheck", 0, 0, 'C' }, + { 0, 0, 0, 0 } + }; + i = mdwopt(argc, argv, "k:f:o:abpqt:uvC", opt, 0, 0, 0); + if (i < 0) break; + switch (i) { + case 'a': ef = "pem"; break; + case 'b': v.f |= F_BUFFER; break; + case 'k': kn = optarg; break; + case 'f': ef = optarg; break; + case 'o': of = optarg; break; + case 'u': v.f |= F_UTC; break; + case 'C': v.f |= F_NOCHECK; break; + case 't': + if (strcmp(optarg, "always") == 0) t_fresh = 0; + else if ((t_fresh = get_date(optarg, 0)) < 0) + die(EXIT_FAILURE, "bad freshness time"); + break; + case 'q': if (v.verb > 0) v.verb--; break; + case 'v': if (v.verb < 10) v.verb++; break; + case 'p': v.f |= F_PROGRESS; break; + default: v.f |= F_BOGUS; break; + } + } + if (argc - optind > 2 || (v.f & F_BOGUS)) + die(EXIT_FAILURE, "Usage: verify [-OPTIONS] [FILE [MESSAGE]]"); + + if ((eo = getenc(ef)) == 0) + die(EXIT_FAILURE, "encoding `%s' not found", ef); + + fn = optind < argc ? argv[optind++] : "-"; + if (strcmp(fn, "-") == 0) + fp = stdin; + else if ((fp = fopen(fn, eo->rmode)) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s': %s", + fn, strerror(errno)); + } + + if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0)) + die(EXIT_FAILURE, "can't open keyring `%s'", keyring); + if (kn && (kk = key_bytag(&kf, kn)) == 0) + die(EXIT_FAILURE, "key `%s' not found", kn); + + e = initdec(eo, fp, vrfbdry, &v); + + /* --- Read the header chunk --- */ + + v.what = "malformed header"; + sig_readheader(e, &s, vrfchoke, &v); + + if (((s.f ^ v.f) & v.m) != 0) { + if (v.verb) printf("FAIL boundary string inconsistent with contents\n"); + exit(EXIT_FAILURE); + } + v.f |= s.f; + + if ((k = key_byid(&kf, s.keyid)) == 0) { + if (v.verb) printf("FAIL key id %08lx not found\n", + (unsigned long)s.keyid); + exit(EXIT_FAILURE); + } + if (kk && k->id != kk->id) { + if (v.verb) { + dstr_reset(&d); key_fulltag(k, &d); + dstr_reset(&dd); key_fulltag(kk, &dd); + printf("FAIL signing key is %s; expected key %s\n", d.buf, dd.buf); + } + exit(EXIT_FAILURE); + } + + s.s = getsig(k, "ccsig", 0); + dstr_reset(&d); key_fulltag(k, &d); + if (!(v.f & F_NOCHECK) && v.verb && (err = s.s->ops->check(s.s)) != 0) + printf("WARN verification key %s fails check: %s\n", d.buf, err); + + dstr_reset(&dd); keyhash(k, s.s, &dd); + if (dd.len != s.kh.len || memcmp(dd.buf, s.kh.buf, dd.len) != 0) { + if (v.verb) printf("FAIL key hash mismatch\n"); + exit(EXIT_FAILURE); + } + + /* --- Now a merry dance --- */ + + if (v.f & F_DETACH) + sig_readsig(e, &s); + if (optind < argc) + dfn = argv[optind++]; + mcsetup_read(&mc_in, v.f, &e, fn, dfn); + + if (!of && (v.f & F_DETACH)) { + rfp = ofp = 0; + v.f &= ~F_BUFFER; + } else if (!of || strcmp(of, "-") == 0) { + v.f |= F_BUFFER; + ofp = stdout; + } + if (of && !(v.f & F_BUFFER)) { + if ((ofp = fopen(of, (v.f & F_BINARY) ? "wb" : "w")) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", + of, strerror(errno)); + } + rfp = ofp; + } else if ((rfp = tmpfile()) == 0) + die(EXIT_FAILURE, "couldn't create temporary file: %s", strerror(errno)); + + /* --- Read the message and verify the signature --- */ + + sig_hash(&s); + for (;;) { + n = mc_in.read(&mc_in, bb); + if (!n) break; + dohash(s.s->h, bb, n); + if (rfp) fwrite(bb, 1, n, rfp); + } + mc_endread(&mc_in, eo, &e); + if (!(v.f & F_DETACH)) + sig_readsig(e, &s); + if (rfp && (ferror(rfp) || fflush(rfp))) { + if (v.verb) printf("FAIL error writing message: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* --- Check the signature --- */ + + if (s.s->ops->doit(s.s, &s.sig)) { + if (v.verb) printf("FAIL signature verification failed\n"); + exit(EXIT_FAILURE); + } + if (t_fresh && s.t < t_fresh) { + if (v.verb) printf("FAIL signature is stale\n"); + exit(EXIT_FAILURE); + } + if (s.t > time(0)) { + if (v.verb) printf("FAIL signature timestamp in the future\n"); + exit(EXIT_FAILURE); + } + if (v.verb) { + tm = (v.f & F_UTC) ? gmtime(&s.t) : localtime(&s.t); + strftime(bb, sizeof(bb), "%Y-%m-%d %H:%M:%S %Z", tm); + printf("INFO good-signature %s\n", d.buf); + printf("INFO date %s\n", bb); + } + + /* --- Unbuffer buffered input --- */ + + if (v.f & F_BUFFER) { + if (!ofp && (ofp = fopen(of, "wb")) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", + of, strerror(errno)); + } + rewind(rfp); + if (v.f & F_PROGRESS) fprogress_init(&ff, "copying buffer", rfp); + if (v.verb && ofp == stdout) printf("DATA\n"); + for (;;) { + n = fread(bb, 1, sizeof(bb), rfp); + if (!n) break; + if (v.f & F_PROGRESS) fprogress_update(&ff, n); + if (fwrite(bb, 1, n, ofp) < n) { + if (v.f & F_PROGRESS) fprogress_done(&ff); + die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); + } + } + if (v.f & F_PROGRESS) fprogress_done(&ff); + if (ferror(rfp) || fclose(rfp)) + die(EXIT_FAILURE, "error unbuffering output: %s", strerror(errno)); + } + if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp))) + die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); + + /* --- Tidy up --- */ + + e->ops->decdone(e); + if (v.verb && ofp != stdout) + printf("OK verified successfully\n"); + freeenc(e); + key_close(&kf); + sig_destroy(&s); + dstr_destroy(&d); + dstr_destroy(&dd); + return (0); +} + +/*----- Reformatting ------------------------------------------------------*/ + +static int format(int argc, char *argv[]) +{ + const char *ief = "binary", *oef = "binary"; + const char *fn, *dfn = 0, *of = 0, *mf = 0; + sigmsg s; + FILE *fp, *ofp = 0, *mfp = 0; + int i; + size_t n; + msgcanon mc_in = MC_INIT, mc_out = MC_INIT; + char bb[MSGBUFSZ]; + vrfctx v = { 0, 0, 1 }; + unsigned f = 0, fm = ~F_SIGMASK, sf; + const encops *ieo, *oeo; + enc *ie, *oe; + + for (;;) { + static const struct option opt[] = { + { "armour-in", 0, 0, 'a' }, + { "armor-in", 0, 0, 'a' }, + { "armour-out", 0, 0, 'A' }, + { "armor-out", 0, 0, 'A' }, + { "detach", 0, 0, 'D' }, + { "embed", 0, 0, 'E' }, + { "format-in", OPTF_ARGREQ, 0, 'f' }, + { "format-out", OPTF_ARGREQ, 0, 'F' }, + { "message", OPTF_ARGREQ, 0, 'm' }, + { "output", OPTF_ARGREQ, 0, 'o' }, + { "progress", 0, 0, 'p' }, + { 0, 0, 0, 0 } + }; + i = mdwopt(argc, argv, "f:F:m:o:apADE", opt, 0, 0, 0); + if (i < 0) break; + switch (i) { + case 'a': ief = "pem"; break; + case 'A': oef = "pem"; break; + case 'f': ief = optarg; break; + case 'F': oef = optarg; break; + case 'D': f |= F_DETACH; fm |= F_DETACH; break; + case 'E': f &= ~F_DETACH; fm |= F_DETACH; break; + case 'm': mf = optarg; break; + case 'o': of = optarg; break; + case 'p': f |= F_PROGRESS; break; + default: f |= F_BOGUS; break; + } + } + + if (argc - optind > 2 || (f & F_BOGUS)) + die(EXIT_FAILURE, "Usage: format [-OPTIONS] [FILE [MESSAGE]]"); + + if ((ieo = getenc(ief)) == 0) + die(EXIT_FAILURE, "encoding `%s' not found", ief); + if ((oeo = getenc(oef)) == 0) + die(EXIT_FAILURE, "encoding `%s' not found", oef); + + fn = optind < argc ? argv[optind++] : "-"; + if (strcmp(fn, "-") == 0) + fp = stdin; + else if ((fp = fopen(fn, ieo->rmode)) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s': %s", + fn, strerror(errno)); + } + + if (optind < argc) + dfn = argv[optind++]; + + ie = initdec(ieo, fp, vrfbdry, &v); + + /* --- Read the header chunk --- */ + + sig_readheader(ie, &s, diechoke, "malformed header"); + + if (((s.f ^ v.f) & v.m) != 0) + moan("boundary string inconsistent with contents (ignoring)"); + + mcsetup_read(&mc_in, s.f, &ie, fn, dfn); + + /* --- Prepare the output stuff --- */ + + if (!of && !mf) of = "-"; + sf = s.f; + f = (f & fm) | (s.f & ~fm); + s.f = f & F_SIGMASK; + + if (sf & F_DETACH) + sig_readsig(ie, &s); + + if (!of) + mcsetup_writenull(&mc_out); + else { + if (strcmp(of, "-") == 0) + ofp = stdout; + else if ((ofp = fopen(of, oeo->wmode)) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", + of, strerror(errno)); + } + oe = initenc(oeo, ofp, + (f & F_DETACH) ? "CATSIGN SIGNATURE" : + (f & F_BINARY) ? "CATSIGN MESSAGE" : + "CATSIGN MESSAGE HEADER"); + sig_writeheader(oe, &s); + mcsetup_write(&mc_out, f, &oe); + } + + if (mf) { + if (strcmp(mf, "-") == 0) + mfp = stdout; + else if ((mfp = fopen(mf, (f & F_BINARY) ? "wb" : "w")) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", + mf, strerror(errno)); + } + } + + /* --- Wade through the message body --- */ + + for (;;) { + n = mc_in.read(&mc_in, bb); + if (!n) break; + mc_out.write(&mc_out, bb, n); + if (mfp) fwrite(bb, 1, n, mfp); + } + mc_endread(&mc_in, ieo, &ie); + if (of) mc_endwrite(&mc_out, oeo, &oe); + + /* --- Write the signature --- */ + + if (!(sf & F_DETACH)) + sig_readsig(ie, &s); + if (of) { + sig_writesig(oe, &s); + oe->ops->encdone(oe); + } + + /* --- All done --- */ + + ie->ops->decdone(ie); + if (ferror(fp) || fclose(fp)) + die(EXIT_FAILURE, "error reading input signature: %s", strerror(errno)); + if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp))) + die(EXIT_FAILURE, "error writing output signature: %s", strerror(errno)); + if (mfp && (fflush(mfp) || ferror(mfp) || fclose(mfp))) + die(EXIT_FAILURE, "error writing output message: %s", strerror(errno)); + freeenc(ie); + if (of) freeenc(oe); + sig_destroy(&s); + return (0); +} + +static void infochoke(const char *m, void *p) +{ + vrfctx *v = p; + printf("BAD %s: %s\n", v->what, m); + exit(EXIT_FAILURE); +} + +static void infokeyreport(const char *file, int line, + const char *err, void *p) +{ /*whatever*/; } + +static int info(int argc, char *argv[]) +{ + const char *ef = "binary"; + vrfctx v = { 0, 0, 1 }; + key_file kf; + key *k; + sigmsg s; + FILE *fp; + int i; + struct tm *tm; + char bb[256]; + dstr d = DSTR_INIT; + const encops *eo; + enc *e; + + for (;;) { + static const struct option opt[] = { + { "armour", 0, 0, 'a' }, + { "armor", 0, 0, 'a' }, + { "format", OPTF_ARGREQ, 0, 'f' }, + { "gmt", 0, 0, 'u' }, + { "utc", 0, 0, 'u' }, + { 0, 0, 0, 0 } + }; + i = mdwopt(argc, argv, "f:au", opt, 0, 0, 0); + if (i < 0) break; + switch (i) { + case 'a': ef = "pem"; break; + case 'f': ef = optarg; break; + case 'u': v.f |= F_UTC; break; + default: v.f |= F_BOGUS; break; + } + } + if (argc - optind > 1 || (v.f & F_BOGUS)) + die(EXIT_FAILURE, "Usage: info [-OPTIONS] [FILE]"); + + if ((eo = getenc(ef)) == 0) + die(EXIT_FAILURE, "encoding `%s' not found", ef); + + if (optind >= argc) + fp = stdin; + else if (strcmp(argv[optind], "-") == 0) { + fp = stdin; + optind++; + } else if ((fp = fopen(argv[optind], eo->rmode)) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s': %s", + argv[optind], strerror(errno)); + } else + optind++; + + if (key_open(&kf, keyring, KOPEN_READ, infokeyreport, 0)) { + printf("NOTE can't open keyring `%s'\n", keyring); + keyring = 0; + } + e = initdec(eo, fp, vrfbdry, &v); + + v.what = "malformed header"; + sig_readheader(e, &s, infochoke, &v); + + printf("INFO flags %sdetach %sbinary\n", + (s.f & F_DETACH) ? "" : "!", + (s.f & F_BINARY) ? "" : "!"); + + if (((s.f ^ v.f) & v.m) != 0) { + printf("WARN boundary string inconsistent with contents\n"); + printf("INFO expected-flags"); + if (v.m & F_DETACH) printf(" %sdetach", (v.f & F_DETACH) ? "" : "!"); + if (v.m & F_BINARY) printf(" %sbinary", (v.f & F_BINARY) ? "" : "!"); + putchar('\n'); + } + v.f |= s.f; + + tm = (v.f & F_UTC) ? gmtime(&s.t) : localtime(&s.t); + strftime(bb, sizeof(bb), "%Y-%m-%d %H:%M:%S %Z", tm); + printf("INFO date %s\n", bb); + + if (keyring && (k = key_byid(&kf, s.keyid)) != 0) { + dstr_reset(&d); key_fulltag(k, &d); + printf("INFO key %s\n", d.buf); + } else + printf("INFO unknown-key %08lx\n", (unsigned long)s.keyid); + + if (keyring) key_close(&kf); + dstr_destroy(&d); + sig_destroy(&s); + return (0); +} + +/*----- Main code ---------------------------------------------------------*/ + +#define LISTS(LI) \ + LI("Lists", list, \ + listtab[i].name, listtab[i].name) \ + LI("Signature schemes", sig, \ + sigtab[i].name, sigtab[i].name) \ + LI("Encodings", enc, \ + enctab[i].name, enctab[i].name) \ + LI("Hash functions", hash, \ + ghashtab[i], ghashtab[i]->name) + +MAKELISTTAB(listtab, LISTS) + +int cmd_show(int argc, char *argv[]) +{ + return (displaylists(listtab, argv + 1)); +} + +static int cmd_help(int, char **); + +static cmd cmdtab[] = { + { "help", cmd_help, "help [COMMAND...]" }, + { "show", cmd_show, "show [ITEM...]" }, + CMD_ENCODE, + CMD_DECODE, + { "sign", sign, + "sign [-adptC] [-k TAG] [-f FORMAT] [-o OUTPUT] [FILE]", "\ +Options:\n\ +\n\ +-a, --armour Same as `-f pem'.\n\ +-b, --binary Treat the input message as binary data.\n\ +-d, --detach Produce a detached signature.\n\ +-f, --format=FORMAT Encode as FORMAT.\n\ +-k, --key=TAG Use public encryption key named by TAG.\n\ +-o, --output=FILE Write output to FILE.\n\ +-p, --progress Show progress on large files.\n\ +-t, --text Canonify input message as a text file.\n\ +-C, --nocheck Don't check the private key.\n\ +" }, + { "verify", verify, + "verify [-abpquvC] [-f FORMAT] [-k TAG] [-o OUTPUT]\n\t\ +[FILE [MESSAGE]]", "\ +Options:\n\ +\n\ +-a, --armour Same as `-f pem'.\n\ +-b, --buffer Buffer message until signature is verified.\n\ +-f, --format=FORMAT Decode as FORMAT.\n\ +-k, --key=TAG Require that the message be signed by key TAG.\n\ +-o, --output=FILE Write message to FILE.\n\ +-p, --progress Show progress on large files.\n\ +-q, --quiet Produce fewer messages.\n\ +-t, --freshtime=TIME Only accept signatures made after this time.\n\ +-u, --utc Show dates in UTC rather than local time.\n\ +-v, --verbose Produce more verbose messages.\n\ +-C, --nocheck Don't check the public key.\n\ +" }, + { "info", info, + "info [-au] [-f FORMAT] [FILE]", "\ +Options:\n\ +\n\ +-a, --armour Same as `-f pem'.\n\ +-f, --format=FORMAT Decode as FORMAT.\n\ +-u, --utc Show dates in UTC rather than local time.\n\ +"}, + { "format", format, + "format [-apuADE] [-f FORMAT] [-F format] [-m FILE] [-o FILE]\n\t\ +[FILE [MESSAGE]]", "\ +Options:\n\ +\n\ +-a, --armour-in Same as `-f pem'.\n\ +-A, --armour-out Same as `-F pem'.\n\ +-D, --detach Create detached signature.\n\ +-E, --embed Create signature with embedded message.\n\ +-f, --format-in=FORMAT Decode input as FORMAT.\n\ +-F, --format-out=FORMAT Encode output as FORMAT.\n\ +-m, --message=FILE Write message to FILE.\n\ +-o, --output=FILE Write new signature to FILE.\n\ +-p, --progress Show progress on large files.\n\ +"}, + { 0, 0, 0 } +}; /* " Emacs seems confused. */ + +static int cmd_help(int argc, char **argv) +{ + sc_help(cmdtab, stdout, argv + 1); + return (0); +} + +void version(FILE *fp) +{ + pquis(fp, "$, Catacomb version " VERSION "\n"); +} + +static void usage(FILE *fp) +{ + pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n"); +} + +void help_global(FILE *fp) +{ + usage(fp); + fputs("\n\ +Sign and verify data.\n\ +\n\ +Global command-line options:\n\ +\n\ +-h, --help [COMMAND...] Show this help message, or help for COMMANDs.\n\ +-v, --version Show program version number.\n\ +-u, --usage Show a terse usage message.\n\ +\n\ +-k, --keyring=FILE Read keys from FILE.\n", + fp); +} + +/* --- @main@ --- * + * + * Arguments: @int argc@ = number of command line arguments + * @char *argv[]@ = vector of command line arguments + * + * Returns: Zero if successful, nonzero otherwise. + * + * Use: Encrypts or decrypts files. + */ + +int main(int argc, char *argv[]) +{ + unsigned f = 0; + +#define f_bogus 1u + + /* --- Initialize the library --- */ + + ego(argv[0]); + sub_init(); + rand_noisesrc(RAND_GLOBAL, &noise_source); + rand_seed(RAND_GLOBAL, 160); +/* trace_on(stderr, 1); */ + + /* --- Parse options --- */ + + for (;;) { + static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "usage", 0, 0, 'u' }, + { "keyring", OPTF_ARGREQ, 0, 'k' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+hvu k:", opts, 0, 0, 0); + if (i < 0) + break; + switch (i) { + case 'h': + sc_help(cmdtab, stdout, argv + optind); + exit(0); + break; + case 'v': + version(stdout); + exit(0); + break; + case 'u': + usage(stdout); + exit(0); + case 'k': + keyring = optarg; + break; + default: + f |= f_bogus; + break; + } + } + + argc -= optind; + argv += optind; + optind = 0; + if (f & f_bogus || argc < 1) { + usage(stderr); + exit(EXIT_FAILURE); + } + + /* --- Dispatch to the correct subcommand handler --- */ + + return (findcmd(cmdtab, argv[0])->cmd(argc, argv)); + +#undef f_bogus +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/progs/cc-enc.c b/progs/cc-enc.c new file mode 100644 index 0000000..61d9805 --- /dev/null +++ b/progs/cc-enc.c @@ -0,0 +1,528 @@ +/* -*-c-*- + * + * Catcrypt data encoding + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _FILE_OFFSET_BITS 64 + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "cc.h" + +typedef int encbdryp(const char *, void *); + +/*----- Main code ---------------------------------------------------------*/ + +/* --- Binary --- */ + +static enc *bin_encinit(FILE *fp, const char *msg) + { enc *e = CREATE(enc); return (e); } +static enc *bin_decinit(FILE *fp, encbdryp *func, void *p) + { enc *e = CREATE(enc); return (e); } + +static int bin_read(enc *e, void *p, size_t sz) +{ + size_t n; + + if (!sz) return (0); + n = fread(p, 1, sz, e->fp); + if (!n || ferror(e->fp)) return (-1); + return (n); +} + +static int bin_write(enc *e, const void *p, size_t sz) + { if (sz && fwrite(p, 1, sz, e->fp) < sz) return (-1); return (0); } + +static int bin_done(enc *e) { return (0); } + +static void bin_destroy(enc *e) { DESTROY(e); } + +/* --- PEM --- */ + +typedef struct pem_encctx { + enc e; + char *msg; + unsigned f; + base64_ctx b; + dstr d; + size_t n; +#define PEMF_NL 1u +#define PEMF_EOF 2u +} pem_encctx; + +static enc *pem_encinit(FILE *fp, const char *msg) +{ + pem_encctx *pe = CREATE(pem_encctx); + base64_init(&pe->b); + fprintf(fp, "-----BEGIN %s-----\n", msg); + pe->msg = xstrdup(msg); + dstr_create(&pe->d); + pe->n = 0; + pe->f = 0; + return (&pe->e); +} + +int checkbdry(const char *b, void *p) { return (!p || strcmp(b, p) == 0); } + +static enc *pem_decinit(FILE *fp, encbdryp *func, void *p) +{ + char buf[128]; + int i, d; + pem_encctx *pe; + int ch; + + /* --- Go until I find a newline and `-----' --- */ + +top: + d = 0; + for (;;) { + if ((ch = getc(fp)) == EOF) goto fail; + switch (ch) { + case '\n': d = 0; break; + case '-': if (d >= 0) { d++; if (d == 5) goto banner; }; break; + default: d = -1; break; + } + } + + /* --- See what the banner looks like --- */ + +banner: + i = d = 0; + for (;;) { + if ((ch = getc(fp)) == EOF) goto fail; + if (ch == '-') { d++; continue; } + if (ch == '\n') break; + if (i + d + 1 >= sizeof(buf)) goto top; + while (d) { buf[i++] = '-'; d--; } + buf[i++] = ch; + } + buf[i] = 0; + + /* --- Check we have the right framing --- */ + + if (d != 5) goto top; + if (strncmp(buf, "BEGIN ", 6) != 0 || (func && !func(buf + 6, p))) + goto top; + + /* --- Ready --- */ + + pe = CREATE(pem_encctx); + base64_init(&pe->b); + pe->msg = xstrdup(buf + 6); + dstr_create(&pe->d); + pe->n = 0; + pe->f = PEMF_NL; + return (&pe->e); + + /* --- Failed --- */ + +fail: + die(EXIT_FAILURE, "initial encapsulation boundary not found"); + return (0); +} + +#define PEM_CHUNKSZ 4096 + +static int pem_read(enc *e, void *p, size_t sz) +{ + pem_encctx *pe = (pem_encctx *)e; + char buf[PEM_CHUNKSZ]; + char *pp = p; + int ch; + size_t n; + int rc = 0; + + for (;;) { + n = pe->d.len - pe->n; + if (n > sz) n = sz; + memcpy(pp, pe->d.buf + pe->n, n); + pe->n += n; + pp += n; + rc += n; + sz -= n; + if (!sz) break; + if (pe->f & PEMF_EOF) return (rc ? rc : -1); + dstr_reset(&pe->d); + n = 0; + for (;;) { + if ((ch = getc(pe->e.fp)) == EOF) return (-1); + if ((pe->f & PEMF_NL) && ch == '-') { + ungetc(ch, pe->e.fp); + pe->f |= PEMF_EOF; + break; + } + if (ch == '\n') { pe->f |= PEMF_NL; continue; } + pe->f &= ~PEMF_NL; + buf[n++] = ch; + if (n >= PEM_CHUNKSZ) break; + } + if (n) + base64_decode(&pe->b, buf, n, &pe->d); + if (pe->f & PEMF_EOF) + base64_decode(&pe->b, 0, 0, &pe->d); + pe->n = 0; + } + return (rc); +} + +static int pem_write(enc *e, const void *p, size_t sz) +{ + pem_encctx *pe = (pem_encctx *)e; + const char *pp = p; + size_t n; + + while (sz) { + n = PEM_CHUNKSZ; + if (n > sz) n = sz; + dstr_reset(&pe->d); + base64_encode(&pe->b, pp, n, &pe->d); + if (fwrite(pe->d.buf, 1, pe->d.len, pe->e.fp) < pe->d.len) + return (-1); + pp += n; + sz -= n; + } + return (0); +} + +static int pem_encdone(enc *e) +{ + pem_encctx *pe = (pem_encctx *)e; + dstr_reset(&pe->d); + base64_encode(&pe->b, 0, 0, &pe->d); + if (fwrite(pe->d.buf, 1, pe->d.len, pe->e.fp) < pe->d.len) + return (-1); + if (pe->b.lnlen) fputc('\n', pe->e.fp); + fprintf(pe->e.fp, "-----END %s-----\n", pe->msg); + return (0); +} + +static int pem_decdone(enc *e) +{ + pem_encctx *pe = (pem_encctx *)e; + char buf[128]; + int i, d; + int ch; + + for (d = 0; d < 5; d++) + if ((ch = getc(pe->e.fp)) != '-') goto fail; + i = d = 0; + for (;;) { + if ((ch = getc(pe->e.fp)) == EOF) goto fail; + if (ch == '-') { d++; continue; } + if (ch == '\n') break; + if (i + d + 1 >= sizeof(buf)) goto fail; + while (d) { buf[i++] = '-'; d--; } + buf[i++] = ch; + } + if (d != 5) goto fail; + buf[i] = 0; + if (strncmp(buf, "END ", 4) != 0 || strcmp(buf + 4, pe->msg) != 0) + goto fail; + return (0); + +fail: + die(EXIT_FAILURE, "final encapsulation boundary not found"); + return (-1); +} + +static void pem_destroy(enc *e) +{ + pem_encctx *pe = (pem_encctx *)e; + dstr_destroy(&pe->d); + xfree(pe->msg); + DESTROY(pe); +} + +/* --- Encoder table --- */ + +const encops enctab[] = { + { "binary", "rb", "wb", 1, 1, + bin_encinit, bin_decinit, + bin_read, bin_write, + bin_done, bin_done, + bin_destroy }, + { "pem", "r", "w", 3, 4, + pem_encinit, pem_decinit, + pem_read, pem_write, + pem_encdone, pem_decdone, + pem_destroy }, + { 0 } +}; + +/* --- @getenc@ --- * + * + * Arguments: @const char *enc@ = name of wanted encoding + * + * Returns: Pointer to encoder operations. + * + * Use: Finds a named encoder or decoder. + */ + +const encops *getenc(const char *enc) +{ + const encops *eo; + + for (eo = enctab; eo->name; eo++) { + if (strcmp(eo->name, enc) == 0) + goto e_found; + } + die(EXIT_FAILURE, "couldn't find encoding `%s'", enc); +e_found: + return (eo); +} + +/* --- @initenc@ --- * + * + * Arguments: @const encops *eo@ = operations (from @getenc@) + * @FILE *fp@ = file handle to attach + * @const char *msg@ = banner message + * + * Returns: The encoder object. + * + * Use: Initializes an encoder. + */ + +enc *initenc(const encops *eo, FILE *fp, const char *msg) +{ + enc *e = eo->initenc(fp, msg); + e->ops = eo; + e->fp = fp; + return (e); +} + +/* --- @initdec@ --- * + * + * Arguments: @const encops *eo@ = operations (from @getenc@) + * @FILE *fp@ = file handle to attach + * @int (*func)(const char *, void *)@ = banner check function + * @void *p@ = argument for @func@ + * + * Returns: The encoder object. + * + * Use: Initializes an encoder. + */ + +enc *initdec(const encops *eo, FILE *fp, + int (*func)(const char *, void *), void *p) +{ + enc *e = eo->initdec(fp, func, p); + e->ops = eo; + e->fp = fp; + return (e); +} + +/* --- @freeenc@ --- * + * + * Arguments: @enc *e@ = encoder object + * + * Returns: --- + * + * Use: Frees an encoder object. + */ + +void freeenc(enc *e) { e->ops->destroy(e); } + +/*----- Encoding and decoding commands ------------------------------------*/ + +int cmd_encode(int argc, char *argv[]) +{ + const char *fn, *of = 0; + FILE *ofp = 0; + FILE *fp = 0; + const char *ef = "binary"; + const char *bd = "MESSAGE"; + fprogress ff; + int i; + size_t n; + char buf[4096]; + unsigned f = 0; + const encops *eo; + enc *e; + +#define f_bogus 1u +#define f_progress 2u + + for (;;) { + static const struct option opt[] = { + { "format", OPTF_ARGREQ, 0, 'f' }, + { "boundary", OPTF_ARGREQ, 0, 'b' }, + { "output", OPTF_ARGREQ, 0, 'o' }, + { "progress", 0, 0, 'p' }, + { 0, 0, 0, 0 } + }; + i = mdwopt(argc, argv, "f:b:o:p", opt, 0, 0, 0); + if (i < 0) break; + switch (i) { + case 'f': ef = optarg; break; + case 'b': bd = optarg; break; + case 'o': of = optarg; break; + case 'p': f |= f_progress; break; + default: f |= f_bogus; break; + } + } + if (argc - optind > 1 || (f & f_bogus)) + die(EXIT_FAILURE, "Usage: encode [-OPTIONS] [FILE]"); + + if ((eo = getenc(ef)) == 0) + die(EXIT_FAILURE, "encoding `%s' not found", ef); + + fn = optind < argc ? argv[optind++] : "-"; + if (strcmp(fn, "-") == 0) + fp = stdin; + else if ((fp = fopen(fn, "rb")) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s': %s", + fn, strerror(errno)); + } + + if (!of || strcmp(of, "-") == 0) + ofp = stdout; + else if ((ofp = fopen(of, eo->wmode)) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", + ofp, strerror(errno)); + } + + e = initenc(eo, ofp, bd); + + if (f & f_progress) { + if (fprogress_init(&ff, fn, fp)) { + die(EXIT_FAILURE, "failed to initialize progress display: %s", + strerror(errno)); + } + } + + do { + n = fread(buf, 1, sizeof(buf), fp); + if (f & f_progress) fprogress_update(&ff, n); + if (e->ops->write(e, buf, n)) { + if (f & f_progress) fprogress_done(&ff); + die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); + } + } while (n == sizeof(buf)); + if (f & f_progress) fprogress_done(&ff); + e->ops->encdone(e); + freeenc(e); + return (0); + +#undef f_bogus +#undef f_progress +} + +int cmd_decode(int argc, char *argv[]) +{ + const char *fn, *of = 0; + FILE *ofp = 0; + FILE *fp = 0; + const char *ef = "binary"; + const char *bd = 0; + fprogress ff; + int i; + char buf[4096]; + unsigned f = 0; + const encops *eo; + enc *e; + +#define f_bogus 1u +#define f_progress 2u + + for (;;) { + static const struct option opt[] = { + { "format", OPTF_ARGREQ, 0, 'f' }, + { "boundary", OPTF_ARGREQ, 0, 'b' }, + { "output", OPTF_ARGREQ, 0, 'o' }, + { "progress", 0, 0, 'p' }, + { 0, 0, 0, 0 } + }; + i = mdwopt(argc, argv, "f:b:o:p", opt, 0, 0, 0); + if (i < 0) break; + switch (i) { + case 'f': ef = optarg; break; + case 'b': bd = optarg; break; + case 'o': of = optarg; break; + case 'p': f |= f_progress; break; + default: f |= f_bogus; break; + } + } + if (argc - optind > 1 || (f & f_bogus)) + die(EXIT_FAILURE, "Usage: decode [-OPTIONS] [FILE]"); + + if ((eo = getenc(ef)) == 0) + die(EXIT_FAILURE, "encoding `%s' not found", ef); + + fn = optind < argc ? argv[optind++] : "-"; + if (strcmp(fn, "-") == 0) + fp = stdin; + else if ((fp = fopen(fn, eo->rmode)) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s': %s", + fn, strerror(errno)); + } + + if (!of || strcmp(of, "-") == 0) + ofp = stdout; + else if ((ofp = fopen(of, "wb")) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", + ofp, strerror(errno)); + } + + e = initdec(eo, fp, checkbdry, (/*unconst*/ void *)bd); + + if (f & f_progress) { + if (fprogress_init(&ff, fn, fp)) { + die(EXIT_FAILURE, "failed to initialize progress display: %s", + strerror(errno)); + } + } + + do { + if ((i = e->ops->read(e, buf, sizeof(buf))) < 0) { + if (f & f_progress) fprogress_done(&ff); + die(EXIT_FAILURE, "error reading input: %s", strerror(errno)); + } + if (f & f_progress) + fprogress_update(&ff, i*e->ops->ncook/e->ops->nraw); + if (fwrite(buf, 1, i, ofp) < i) { + if (f & f_progress) fprogress_done(&ff); + die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); + } + } while (i == sizeof(buf)); + e->ops->decdone(e); + if (f & f_progress) fprogress_done(&ff); + freeenc(e); + return (0); + +#undef f_bogus +#undef f_progress +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/cc-hash.c b/progs/cc-hash.c similarity index 100% rename from cc-hash.c rename to progs/cc-hash.c diff --git a/progs/cc-kem.c b/progs/cc-kem.c new file mode 100644 index 0000000..e165389 --- /dev/null +++ b/progs/cc-kem.c @@ -0,0 +1,627 @@ +/* -*-c-*- + * + * Catcrypt key-encapsulation + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _FILE_OFFSET_BITS 64 + +#include + +#include +#include +#include +#include + +#include "mprand.h" +#include "rand.h" + +#include "ec.h" +#include "ec-keys.h" +#include "dh.h" +#include "rsa.h" + +#include "rmd160.h" +#include "blowfish-cbc.h" + +#include "cc.h" + +/*----- Key encapsulation -------------------------------------------------*/ + +/* --- RSA --- */ + +typedef struct rsa_encctx { + kem k; + rsa_pubctx rp; +} rsa_encctx; + +static kem *rsa_encinit(key *k, void *kd) +{ + rsa_encctx *re = CREATE(rsa_encctx); + rsa_pubcreate(&re->rp, kd); + return (&re->k); +} + +static int rsa_encdoit(kem *k, dstr *d, ghash *h) +{ + rsa_encctx *re = (rsa_encctx *)k; + mp *x = mprand_range(MP_NEW, re->rp.rp->n, &rand_global, 0); + mp *y = rsa_pubop(&re->rp, MP_NEW, x); + size_t n = mp_octets(re->rp.rp->n); + dstr_ensure(d, n); + mp_storeb(x, d->buf, n); + GH_HASH(h, d->buf, n); + mp_storeb(y, d->buf, n); + d->len += n; + mp_drop(x); + mp_drop(y); + return (0); +} + +static const char *rsa_lengthcheck(mp *n) +{ + if (mp_bits(n) < 1020) return ("key too short"); + return (0); +} + +static const char *rsa_enccheck(kem *k) +{ + rsa_encctx *re = (rsa_encctx *)k; + const char *e; + if ((e = rsa_lengthcheck(re->rp.rp->n)) != 0) return (e); + return (0); +} + +static void rsa_encdestroy(kem *k) +{ + rsa_encctx *re = (rsa_encctx *)k; + rsa_pubdestroy(&re->rp); + DESTROY(re); +} + +static const kemops rsa_encops = { + rsa_pubfetch, sizeof(rsa_pub), + rsa_encinit, rsa_encdoit, rsa_enccheck, rsa_encdestroy +}; + +typedef struct rsa_decctx { + kem k; + rsa_privctx rp; +} rsa_decctx; + +static kem *rsa_decinit(key *k, void *kd) +{ + rsa_decctx *rd = CREATE(rsa_decctx); + rsa_privcreate(&rd->rp, kd, &rand_global); + return (&rd->k); +} + +static int rsa_decdoit(kem *k, dstr *d, ghash *h) +{ + rsa_decctx *rd = (rsa_decctx *)k; + mp *x = mp_loadb(MP_NEW, d->buf, d->len); + size_t n; + char *p; + + if (MP_CMP(x, >=, rd->rp.rp->n)) { + mp_drop(x); + return (-1); + } + n = mp_octets(rd->rp.rp->n); + p = xmalloc(n); + x = rsa_privop(&rd->rp, x, x); + mp_storeb(x, p, n); + GH_HASH(h, p, n); + mp_drop(x); + xfree(p); + return (0); +} + +static const char *rsa_deccheck(kem *k) +{ + rsa_decctx *rd = (rsa_decctx *)k; + const char *e; + if ((e = rsa_lengthcheck(rd->rp.rp->n)) != 0) return (e); + return (0); +} + +static void rsa_decdestroy(kem *k) +{ + rsa_decctx *rd = (rsa_decctx *)k; + rsa_privdestroy(&rd->rp); + DESTROY(rd); +} + +static const kemops rsa_decops = { + rsa_privfetch, sizeof(rsa_priv), + rsa_decinit, rsa_decdoit, rsa_deccheck, rsa_decdestroy +}; + +/* --- DH and EC --- */ + +typedef struct dh_encctx { + kem k; + group *g; + mp *x; + ge *y; +} dh_encctx; + +static dh_encctx *dh_doinit(key *k, const gprime_param *gp, mp *y, + group *(*makegroup)(const gprime_param *), + const char *what) +{ + dh_encctx *de = CREATE(dh_encctx); + dstr t = DSTR_INIT; + + key_fulltag(k, &t); + if ((de->g = makegroup(gp)) == 0) + die(EXIT_FAILURE, "bad %s group in key `%s'", what, t.buf); + de->x = MP_NEW; + de->y = G_CREATE(de->g); + if (G_FROMINT(de->g, de->y, y)) + die(EXIT_FAILURE, "bad public key `%s'", t.buf); + dstr_destroy(&t); + return (de); +} + +static dh_encctx *ec_doinit(key *k, const char *cstr, const ec *y) +{ + dh_encctx *de = CREATE(dh_encctx); + ec_info ei; + const char *e; + dstr t = DSTR_INIT; + + key_fulltag(k, &t); + if ((e = ec_getinfo(&ei, cstr)) != 0 || + (de->g = group_ec(&ei)) == 0) + die(EXIT_FAILURE, "bad elliptic curve spec in key `%s': %s", t.buf, e); + de->x = MP_NEW; + de->y = G_CREATE(de->g); + if (G_FROMEC(de->g, de->y, y)) + die(EXIT_FAILURE, "bad public curve point `%s'", t.buf); + dstr_destroy(&t); + return (de); +} + +static kem *dh_encinit(key *k, void *kd) +{ + dh_pub *dp = kd; + dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_prime, "prime"); + return (&de->k); +} + +static kem *bindh_encinit(key *k, void *kd) +{ + dh_pub *dp = kd; + dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_binary, "binary"); + return (&de->k); +} + +static kem *ec_encinit(key *k, void *kd) +{ + ec_pub *ep = kd; + dh_encctx *de = ec_doinit(k, ep->cstr, &ep->p); + return (&de->k); +} + +static int dh_encdoit(kem *k, dstr *d, ghash *h) +{ + dh_encctx *de = (dh_encctx *)k; + mp *r = mprand_range(MP_NEW, de->g->r, &rand_global, 0); + ge *x = G_CREATE(de->g); + ge *y = G_CREATE(de->g); + size_t n = de->g->noctets; + buf b; + + G_EXP(de->g, x, de->g->g, r); + G_EXP(de->g, y, de->y, r); + dstr_ensure(d, n); + buf_init(&b, d->buf, n); + G_TORAW(de->g, &b, y); + GH_HASH(h, BBASE(&b), BLEN(&b)); + buf_init(&b, d->buf, n); + G_TORAW(de->g, &b, x); + GH_HASH(h, BBASE(&b), BLEN(&b)); + d->len += BLEN(&b); + mp_drop(r); + G_DESTROY(de->g, x); + G_DESTROY(de->g, y); + return (0); +} + +static const char *dh_enccheck(kem *k) +{ + dh_encctx *de = (dh_encctx *)k; + const char *e; + if ((e = G_CHECK(de->g, &rand_global)) != 0) + return (0); + if (group_check(de->g, de->y)) + return ("public key not in subgroup"); + return (0); +} + +static void dh_encdestroy(kem *k) +{ + dh_encctx *de = (dh_encctx *)k; + G_DESTROY(de->g, de->y); + mp_drop(de->x); + G_DESTROYGROUP(de->g); + DESTROY(de); +} + +static const kemops dh_encops = { + dh_pubfetch, sizeof(dh_pub), + dh_encinit, dh_encdoit, dh_enccheck, dh_encdestroy +}; + +static const kemops bindh_encops = { + dh_pubfetch, sizeof(dh_pub), + bindh_encinit, dh_encdoit, dh_enccheck, dh_encdestroy +}; + +static const kemops ec_encops = { + ec_pubfetch, sizeof(ec_pub), + ec_encinit, dh_encdoit, dh_enccheck, dh_encdestroy +}; + +static kem *dh_decinit(key *k, void *kd) +{ + dh_priv *dp = kd; + dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_prime, "prime"); + de->x = MP_COPY(dp->x); + return (&de->k); +} + +static kem *bindh_decinit(key *k, void *kd) +{ + dh_priv *dp = kd; + dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_binary, "binary"); + de->x = MP_COPY(dp->x); + return (&de->k); +} + +static kem *ec_decinit(key *k, void *kd) +{ + ec_priv *ep = kd; + dh_encctx *de = ec_doinit(k, ep->cstr, &ep->p); + de->x = MP_COPY(ep->x); + return (&de->k); +} + +static int dh_decdoit(kem *k, dstr *d, ghash *h) +{ + dh_encctx *de = (dh_encctx *)k; + ge *x = G_CREATE(de->g); + size_t n = de->g->noctets; + void *p = xmalloc(n); + buf b; + int rc = -1; + + buf_init(&b, d->buf, d->len); + if (G_FROMRAW(de->g, &b, x) || group_check(de->g, x)) + goto done; + G_EXP(de->g, x, x, de->x); + buf_init(&b, p, n); + G_TORAW(de->g, &b, x); + GH_HASH(h, BBASE(&b), BLEN(&b)); + GH_HASH(h, d->buf, d->len); + rc = 0; +done: + G_DESTROY(de->g, x); + xfree(p); + return (rc); +} + +static const kemops dh_decops = { + dh_privfetch, sizeof(dh_priv), + dh_decinit, dh_decdoit, dh_enccheck, dh_encdestroy +}; + +static const kemops bindh_decops = { + dh_privfetch, sizeof(dh_priv), + bindh_decinit, dh_decdoit, dh_enccheck, dh_encdestroy +}; + +static const kemops ec_decops = { + ec_privfetch, sizeof(ec_priv), + ec_decinit, dh_decdoit, dh_enccheck, dh_encdestroy +}; + +/* --- Symmetric --- */ + +typedef struct symm_ctx { + kem k; + key_packdef kp; + key_bin kb; +} symm_ctx; + +static kem *symm_init(key *k, void *kd) +{ + symm_ctx *s; + dstr d = DSTR_INIT; + int err; + + s = CREATE(symm_ctx); + + key_fulltag(k, &d); + s->kp.e = KENC_BINARY; + s->kp.p = &s->kb; + s->kp.kd = 0; + + if ((err = key_unpack(&s->kp, kd, &d)) != 0) { + die(EXIT_FAILURE, "failed to unpack symmetric key `%s': %s", + d.buf, key_strerror(err)); + } + dstr_destroy(&d); + return (&s->k); +} + +static int symm_decdoit(kem *k, dstr *d, ghash *h) +{ + symm_ctx *s = (symm_ctx *)k; + + GH_HASH(h, s->kb.k, s->kb.sz); + GH_HASH(h, d->buf, d->len); + return (0); +} + +static int symm_encdoit(kem *k, dstr *d, ghash *h) +{ + dstr_ensure(d, h->ops->c->hashsz); + d->len += h->ops->c->hashsz; + rand_get(RAND_GLOBAL, d->buf, d->len); + return (symm_decdoit(k, d, h)); +} + +static const char *symm_check(kem *k) { return (0); } + +static void symm_destroy(kem *k) + { symm_ctx *s = (symm_ctx *)k; key_unpackdone(&s->kp); } + +static const kemops symm_encops = { + 0, 0, + symm_init, symm_encdoit, symm_check, symm_destroy +}; + +static const kemops symm_decops = { + 0, 0, + symm_init, symm_decdoit, symm_check, symm_destroy +}; + +/* --- The switch table --- */ + +const struct kemtab kemtab[] = { + { "rsa", &rsa_encops, &rsa_decops }, + { "dh", &dh_encops, &dh_decops }, + { "bindh", &bindh_encops, &bindh_decops }, + { "ec", &ec_encops, &ec_decops }, + { "symm", &symm_encops, &symm_decops }, + { 0, 0, 0 } +}; + +/* --- @getkem@ --- * + * + * Arguments: @key *k@ = the key to load + * @const char *app@ = application name + * @int wantpriv@ = nonzero if we want to decrypt + * + * Returns: A key-encapsulating thing. + * + * Use: Loads a key. + */ + +kem *getkem(key *k, const char *app, int wantpriv) +{ + const char *kalg, *halg = 0, *calg = 0; + dstr d = DSTR_INIT; + dstr t = DSTR_INIT; + size_t n; + char *p = 0; + const char *q; + kem *kk; + const struct kemtab *kt; + const kemops *ko; + void *kd; + int e; + key_packdef *kp; + + /* --- Setup stuff --- */ + + key_fulltag(k, &t); + + /* --- Get the KEM name --- * + * + * Take the attribute if it's there; otherwise use the key type. + */ + + n = strlen(app); + if ((q = key_getattr(0, k, "kem")) != 0) { + dstr_puts(&d, q); + p = d.buf; + } else if (strncmp(k->type, app, n) == 0 && k->type[n] == '-') { + dstr_puts(&d, k->type); + p = d.buf + n + 1; + } else + die(EXIT_FAILURE, "no KEM for key `%s'", t.buf); + kalg = p; + + /* --- Grab the encryption scheme --- * + * + * Grab it from the KEM if it's there, but override it from the attribute. + */ + + if (p && (p = strchr(p, '/')) != 0) { + *p++ = 0; + calg = p; + } + if ((q = key_getattr(0, k, "cipher")) != 0) + calg = q; + + /* --- Grab the hash function --- */ + + if (p && (p = strchr(p, '/')) != 0) { + *p++ = 0; + halg = p; + } + if ((q = key_getattr(0, k, "hash")) != 0) + halg = q; + + /* --- Instantiate the KEM --- */ + + for (kt = kemtab; kt->name; kt++) { + if (strcmp(kt->name, kalg) == 0) + goto k_found; + } + die(EXIT_FAILURE, "key encapsulation mechanism `%s' not found in key `%s'", + kalg, t.buf); +k_found:; + ko = wantpriv ? kt->decops : kt->encops; + if (!ko->kf) { + kd = k->k; + key_incref(kd); + kp = 0; + } else { + kd = xmalloc(ko->kdsz); + kp = key_fetchinit(ko->kf, 0, kd); + if ((e = key_fetch(kp, k)) != 0) { + die(EXIT_FAILURE, "error fetching key `%s': %s", + t.buf, key_strerror(e)); + } + } + kk = ko->init(k, kd); + kk->kp = kp; + kk->ops = ko; + kk->kd = kd; + + /* --- Set up the algorithms --- */ + + if (!halg) + kk->h = &rmd160; + else if ((kk->h = ghash_byname(halg)) == 0) { + die(EXIT_FAILURE, "hash algorithm `%s' not found in key `%s'", + halg, t.buf); + } + + if (!calg) + kk->c = &blowfish_cbc; + else if ((kk->c = gcipher_byname(calg)) == 0) { + die(EXIT_FAILURE, "encryption scheme `%s' not found in key `%s'", + calg, t.buf); + } + + dstr_reset(&d); + if ((q = key_getattr(0, k, "kdf")) == 0) { + dstr_putf(&d, "%s-mgf", kk->h->name); + q = d.buf; + } + if ((kk->cx = gcipher_byname(q)) == 0) { + die(EXIT_FAILURE, "encryption scheme (KDF) `%s' not found in key `%s'", + q, t.buf); + } + + dstr_reset(&d); + if ((q = key_getattr(0, k, "mac")) == 0) { + dstr_putf(&d, "%s-hmac", kk->h->name); + q = d.buf; + } + if ((kk->m = gmac_byname(q)) == 0) { + die(EXIT_FAILURE, + "message authentication code `%s' not found in key `%s'", + q, t.buf); + } + + /* --- Tidy up --- */ + + dstr_destroy(&d); + dstr_destroy(&t); + return (kk); +} + +/* --- @setupkem@ --- * + * + * Arguments: @kem *k@ = key-encapsulation thing + * @dstr *d@ = key-encapsulation data + * @gcipher **cx@ = key-expansion function (for IVs) + * @gcipher **c@ = where to put initialized encryption scheme + * @gmac **m@ = where to put initialized MAC + * + * Returns: Zero on success, nonzero on failure. + * + * Use: Initializes all the various symmetric things from a KEM. + */ + +int setupkem(kem *k, dstr *d, gcipher **cx, gcipher **c, gmac **m) +{ + octet *kd; + size_t n, cn, mn; + ghash *h; + int rc = -1; + + h = GH_INIT(k->h); + if (k->ops->doit(k, d, h)) + goto done; + n = keysz(GH_CLASS(h)->hashsz, k->cx->keysz); + if (!n) + goto done; + kd = GH_DONE(h, 0); + *cx = GC_INIT(k->cx, kd, n); + + cn = keysz(0, k->c->keysz); n = cn; + mn = keysz(0, k->m->keysz); if (mn > n) n = mn; + kd = xmalloc(n); + GC_ENCRYPT(*cx, 0, kd, cn); + *c = GC_INIT(k->c, kd, cn); + GC_ENCRYPT(*cx, 0, kd, mn); + *m = GM_KEY(k->m, kd, mn); + xfree(kd); + + rc = 0; +done: + GH_DESTROY(h); + return (rc); +} + +/* --- @freekem@ --- * + * + * Arguments: @kem *k@ = key-encapsulation thing + * + * Returns: --- + * + * Use: Frees up a key-encapsulation thing. + */ + +void freekem(kem *k) +{ + if (!k->ops->kf) + key_drop(k->kd); + else { + key_fetchdone(k->kp); + xfree(k->kd); + } + k->ops->destroy(k); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/progs/cc-list.c b/progs/cc-list.c new file mode 100644 index 0000000..8bc2219 --- /dev/null +++ b/progs/cc-list.c @@ -0,0 +1,73 @@ +/* -*-c-*- + * + * Emit lists of things in tables + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _FILE_OFFSET_BITS 64 + +#include + +#include "cc.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @displaylists@ --- * + * + * Arguments: @const struct listent *listtab@ = table of lists to show + * @char *const argv[]@ = list of lists to show + * + * Returns: Nonzero if anything failed. + * + * Use: Dumps the named lists, or all of them. + */ + +int displaylists(const struct listent *listtab, char *const argv[]) +{ + const struct listent *li; + int i; + int rc = 0; + + if (!argv || !*argv) { + for (li = listtab; li->name; li++) + li->list(); + } else { + for (i = 0; argv[i]; i++) { + for (li = listtab; li->name; li++) { + if (strcmp(li->name, argv[i]) == 0) { + li->list(); + goto cool; + } + } + moan("unknown list `%s'", argv[i]); + rc = 1; + cool:; + } + } + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/cc-progress.c b/progs/cc-progress.c similarity index 100% rename from cc-progress.c rename to progs/cc-progress.c diff --git a/progs/cc-sig.c b/progs/cc-sig.c new file mode 100644 index 0000000..35f1701 --- /dev/null +++ b/progs/cc-sig.c @@ -0,0 +1,804 @@ +/* -*-c-*- + * + * Catcrypt signatures + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _FILE_OFFSET_BITS 64 + +#include + +#include + +#include "rand.h" +#include "sha.h" +#include "has160.h" + +#include "ec.h" +#include "ec-keys.h" +#include "dh.h" +#include "gdsa.h" +#include "gkcdsa.h" +#include "rsa.h" + +#include "cc.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- RSA PKCS1 --- */ + +typedef struct rsap1_sigctx { + sig s; + rsa_privctx rp; + pkcs1 p1; +} rsap1_sigctx; + +static sig *rsap1_siginit(key *k, void *kd, const gchash *hc) +{ + rsap1_sigctx *rs = CREATE(rsap1_sigctx); + rsa_privcreate(&rs->rp, kd, &rand_global); + rs->p1.r = &rand_global; + rs->p1.ep = hc->name; + rs->p1.epsz = strlen(hc->name) + 1; + rs->s.h = 0; + return (&rs->s); +} + +static int rsap1_sigdoit(sig *s, dstr *d) +{ + rsap1_sigctx *rs = (rsap1_sigctx *)s; + size_t n; + mp *m = rsa_sign(&rs->rp, MP_NEW, + GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz, + pkcs1_sigencode, &rs->p1); + if (!m) return (-1); + n = mp_octets(rs->rp.rp->n); dstr_ensure(d, n); mp_storeb(m, d->buf, n); + d->len += n; mp_drop(m); + return (0); +} + +static const char *rsa_lengthcheck(mp *n) +{ + if (mp_bits(n) < 1024) return ("key too short"); + return (0); +} + +static const char *rsap1_sigcheck(sig *s) +{ + rsap1_sigctx *rs = (rsap1_sigctx *)s; + const char *e; + if ((e = rsa_lengthcheck(rs->rp.rp->n)) != 0) return (e); + return (0); +} + +static void rsap1_sigdestroy(sig *s) +{ + rsap1_sigctx *rs = (rsap1_sigctx *)s; + rsa_privdestroy(&rs->rp); + DESTROY(rs); +} + +static const sigops rsap1_sig = { + rsa_privfetch, sizeof(rsa_priv), + rsap1_siginit, rsap1_sigdoit, rsap1_sigcheck, rsap1_sigdestroy +}; + +typedef struct rsap1_vrfctx { + sig s; + rsa_pubctx rp; + pkcs1 p1; +} rsap1_vrfctx; + +static sig *rsap1_vrfinit(key *k, void *kd, const gchash *hc) +{ + rsap1_vrfctx *rv = CREATE(rsap1_vrfctx); + rsa_pubcreate(&rv->rp, kd); + rv->p1.r = &rand_global; + rv->p1.ep = hc->name; + rv->p1.epsz = strlen(hc->name) + 1; + rv->s.h = 0; + return (&rv->s); +} + +static int rsap1_vrfdoit(sig *s, dstr *d) +{ + rsap1_vrfctx *rv = (rsap1_vrfctx *)s; + mp *m = mp_loadb(MP_NEW, d->buf, d->len); + int rc = rsa_verify(&rv->rp, m, + GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz, + 0, pkcs1_sigdecode, &rv->p1); + mp_drop(m); + return (rc); +} + +static const char *rsap1_vrfcheck(sig *s) +{ + rsap1_vrfctx *rv = (rsap1_vrfctx *)s; + const char *e; + if ((e = rsa_lengthcheck(rv->rp.rp->n)) != 0) return (e); + return (0); +} + +static void rsap1_vrfdestroy(sig *s) +{ + rsap1_vrfctx *rv = (rsap1_vrfctx *)s; + rsa_pubdestroy(&rv->rp); + DESTROY(rv); +} + +static const sigops rsap1_vrf = { + rsa_pubfetch, sizeof(rsa_pub), + rsap1_vrfinit, rsap1_vrfdoit, rsap1_vrfcheck, rsap1_vrfdestroy +}; + +/* --- RSA PSS --- */ + +static const gccipher *getmgf(key *k, const gchash *hc) +{ + dstr d = DSTR_INIT; + const gccipher *gc; + const char *mm; + + if ((mm = key_getattr(0, k, "mgf")) == 0) { + dstr_putf(&d, "%s-mgf", hc->name); + mm = d.buf; + } + if ((gc = gcipher_byname(mm)) == 0) + die(EXIT_FAILURE, "unknown encryption scheme `%s'", mm); + dstr_destroy(&d); + return (gc); +} + +typedef struct rsapss_sigctx { + sig s; + rsa_privctx rp; + pss p; +} rsapss_sigctx; + +static sig *rsapss_siginit(key *k, void *kd, const gchash *hc) +{ + rsapss_sigctx *rs = CREATE(rsapss_sigctx); + rsa_privcreate(&rs->rp, kd, &rand_global); + rs->p.r = &rand_global; + rs->p.cc = getmgf(k, hc); + rs->p.ch = hc; + rs->p.ssz = hc->hashsz; + rsa_privdestroy(&rs->rp); + return (&rs->s); +} + +static int rsapss_sigdoit(sig *s, dstr *d) +{ + rsapss_sigctx *rs = (rsapss_sigctx *)s; + size_t n; + mp *m = rsa_sign(&rs->rp, MP_NEW, + GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz, + pss_encode, &rs->p); + if (!m) return (-1); + n = mp_octets(rs->rp.rp->n); dstr_ensure(d, n); mp_storeb(m, d->buf, n); + d->len += n; mp_drop(m); + return (0); +} + +static const char *rsapss_sigcheck(sig *s) +{ + rsapss_sigctx *rs = (rsapss_sigctx *)s; + const char *e; + if ((e = rsa_lengthcheck(rs->rp.rp->n)) != 0) return (e); + return (0); +} + +static void rsapss_sigdestroy(sig *s) +{ + rsapss_sigctx *rs = (rsapss_sigctx *)s; + rsa_privdestroy(&rs->rp); + DESTROY(rs); +} + +static const sigops rsapss_sig = { + rsa_privfetch, sizeof(rsa_priv), + rsapss_siginit, rsapss_sigdoit, rsapss_sigcheck, rsapss_sigdestroy +}; + +typedef struct rsapss_vrfctx { + sig s; + rsa_pubctx rp; + pss p; +} rsapss_vrfctx; + +static sig *rsapss_vrfinit(key *k, void *kd, const gchash *hc) +{ + rsapss_vrfctx *rv = CREATE(rsapss_vrfctx); + rsa_pubcreate(&rv->rp, kd); + rv->p.r = &rand_global; + rv->p.cc = getmgf(k, hc); + rv->p.ch = hc; + rv->p.ssz = hc->hashsz; + return (&rv->s); +} + +static int rsapss_vrfdoit(sig *s, dstr *d) +{ + rsapss_vrfctx *rv = (rsapss_vrfctx *)s; + mp *m = mp_loadb(MP_NEW, d->buf, d->len); + int rc = rsa_verify(&rv->rp, m, + GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz, + 0, pss_decode, &rv->p); + mp_drop(m); + return (rc); +} + +static const char *rsapss_vrfcheck(sig *s) +{ + rsapss_vrfctx *rv = (rsapss_vrfctx *)s; + const char *e; + if ((e = rsa_lengthcheck(rv->rp.rp->n)) != 0) return (e); + return (0); +} + +static void rsapss_vrfdestroy(sig *s) +{ + rsapss_vrfctx *rv = (rsapss_vrfctx *)s; + rsa_pubdestroy(&rv->rp); + DESTROY(rv); +} + +static const sigops rsapss_vrf = { + rsa_pubfetch, sizeof(rsa_pub), + rsapss_vrfinit, rsapss_vrfdoit, rsapss_vrfcheck, rsapss_vrfdestroy +}; + +/* --- DSA and ECDSA --- */ + +typedef struct dsa_sigctx { + sig s; + gdsa g; +} dsa_sigctx; + +static void dsa_initcommon(dsa_sigctx *ds, const gchash *hc, + const char *ktag) +{ + ds->g.r = &rand_global; + ds->g.h = hc; + ds->g.u = MP_NEW; + ds->s.h = 0; +} + +static dsa_sigctx *dsa_doinit(key *k, const gprime_param *gp, + mp *y, const gchash *hc, + group *(*makegroup)(const gprime_param *), + const char *what) +{ + dsa_sigctx *ds = CREATE(dsa_sigctx); + dstr t = DSTR_INIT; + + key_fulltag(k, &t); + if ((ds->g.g = makegroup(gp)) == 0) + die(EXIT_FAILURE, "bad %s group in key `%s'", what, t.buf); + ds->g.p = G_CREATE(ds->g.g); + if (G_FROMINT(ds->g.g, ds->g.p, y)) + die(EXIT_FAILURE, "bad public key in key `%s'", t.buf); + dsa_initcommon(ds, hc, t.buf); + dstr_destroy(&t); + return (ds); +} + +static dsa_sigctx *ecdsa_doinit(key *k, const char *cstr, + ec *y, const gchash *hc) +{ + dsa_sigctx *ds = CREATE(dsa_sigctx); + ec_info ei; + const char *e; + dstr t = DSTR_INIT; + + key_fulltag(k, &t); + if ((e = ec_getinfo(&ei, cstr)) != 0) + die(EXIT_FAILURE, "bad curve in key `%s': %s", t.buf, e); + ds->g.g = group_ec(&ei); + ds->g.p = G_CREATE(ds->g.g); + if (G_FROMEC(ds->g.g, ds->g.p, y)) + die(EXIT_FAILURE, "bad public key in key `%s'", t.buf); + dsa_initcommon(ds, hc, t.buf); + dstr_destroy(&t); + return (ds); +} + +static sig *dsa_siginit(key *k, void *kd, const gchash *hc) +{ + dh_priv *dp = kd; + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime"); + ds->g.u = MP_COPY(dp->x); + return (&ds->s); +} + +static sig *bindsa_siginit(key *k, void *kd, const gchash *hc) +{ + dh_priv *dp = kd; + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary"); + ds->g.u = MP_COPY(dp->x); + return (&ds->s); +} + +static sig *ecdsa_siginit(key *k, void *kd, const gchash *hc) +{ + ec_priv *ep = kd; + dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc); + ds->g.u = MP_COPY(ep->x); + return (&ds->s); +} + +static int dsa_sigdoit(sig *s, dstr *d) +{ + dsa_sigctx *ds = (dsa_sigctx *)s; + gdsa_sig ss = GDSA_SIG_INIT; + size_t n = mp_octets(ds->g.g->r); + + gdsa_sign(&ds->g, &ss, GH_DONE(ds->s.h, 0), 0); + dstr_ensure(d, 2 * n); + mp_storeb(ss.r, d->buf, n); + mp_storeb(ss.s, d->buf + n, n); + d->len += 2 * n; + mp_drop(ss.r); mp_drop(ss.s); + return (0); +} + +static const char *dsa_sigcheck(sig *s) +{ + dsa_sigctx *ds = (dsa_sigctx *)s; + const char *e; + if ((e = G_CHECK(ds->g.g, &rand_global)) != 0) + return (0); + if (group_check(ds->g.g, ds->g.p)) + return ("public key not in subgroup"); + return (0); +} + +static void dsa_sigdestroy(sig *s) +{ + dsa_sigctx *ds = (dsa_sigctx *)s; + G_DESTROY(ds->g.g, ds->g.p); + mp_drop(ds->g.u); + G_DESTROYGROUP(ds->g.g); + DESTROY(ds); +} + +static const sigops dsa_sig = { + dh_privfetch, sizeof(dh_priv), + dsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy +}; + +static const sigops bindsa_sig = { + dh_privfetch, sizeof(dh_priv), + bindsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy +}; + +static const sigops ecdsa_sig = { + ec_privfetch, sizeof(ec_priv), + ecdsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy +}; + +static sig *dsa_vrfinit(key *k, void *kd, const gchash *hc) +{ + dh_pub *dp = kd; + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime"); + return (&ds->s); +} + +static sig *bindsa_vrfinit(key *k, void *kd, const gchash *hc) +{ + dh_pub *dp = kd; + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary"); + return (&ds->s); +} + +static sig *ecdsa_vrfinit(key *k, void *kd, const gchash *hc) +{ + ec_pub *ep = kd; + dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc); + return (&ds->s); +} + +static int dsa_vrfdoit(sig *s, dstr *d) +{ + dsa_sigctx *ds = (dsa_sigctx *)s; + gdsa_sig ss; + size_t n = d->len/2; + int rc; + + ss.r = mp_loadb(MP_NEW, d->buf, n); + ss.s = mp_loadb(MP_NEW, d->buf + n, d->len - n); + rc = gdsa_verify(&ds->g, &ss, GH_DONE(ds->s.h, 0)); + mp_drop(ss.r); mp_drop(ss.s); + return (rc); +} + +static const sigops dsa_vrf = { + dh_pubfetch, sizeof(dh_pub), + dsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy +}; + +static const sigops bindsa_vrf = { + dh_pubfetch, sizeof(dh_pub), + bindsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy +}; + +static const sigops ecdsa_vrf = { + ec_pubfetch, sizeof(ec_pub), + ecdsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy +}; + +/* --- KCDSA and ECKCDSA --- */ + +static void kcdsa_privkey(dsa_sigctx *ds, mp *x) + { ds->g.u = mp_modinv(MP_NEW, x, ds->g.g->r); } + +static void kcdsa_sethash(dsa_sigctx *ds, const gchash *hc) + { ds->s.h = gkcdsa_beginhash(&ds->g); } + +static sig *kcdsa_siginit(key *k, void *kd, const gchash *hc) +{ + dh_priv *dp = kd; + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime"); + kcdsa_privkey(ds, dp->x); + kcdsa_sethash(ds, hc); + return (&ds->s); +} + +static sig *binkcdsa_siginit(key *k, void *kd, const gchash *hc) +{ + dh_priv *dp = kd; + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary"); + kcdsa_privkey(ds, dp->x); + kcdsa_sethash(ds, hc); + return (&ds->s); +} + +static sig *eckcdsa_siginit(key *k, void *kd, const gchash *hc) +{ + ec_priv *ep = kd; + dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc); + kcdsa_privkey(ds, ep->x); + kcdsa_sethash(ds, hc); + return (&ds->s); +} + +static int kcdsa_sigdoit(sig *s, dstr *d) +{ + dsa_sigctx *ds = (dsa_sigctx *)s; + gkcdsa_sig ss = GKCDSA_SIG_INIT; + size_t hsz = ds->g.h->hashsz, n = mp_octets(ds->g.g->r); + + gkcdsa_sign(&ds->g, &ss, GH_DONE(ds->s.h, 0), 0); + dstr_ensure(d, hsz + n); + memcpy(d->buf, ss.r, hsz); + mp_storeb(ss.s, d->buf + hsz, n); + d->len += hsz + n; + xfree(ss.r); mp_drop(ss.s); + return (0); +} + +static const sigops kcdsa_sig = { + dh_privfetch, sizeof(dh_priv), + kcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy +}; + +static const sigops binkcdsa_sig = { + dh_privfetch, sizeof(dh_priv), + binkcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy +}; + +static const sigops eckcdsa_sig = { + ec_privfetch, sizeof(ec_priv), + eckcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy +}; + +static sig *kcdsa_vrfinit(key *k, void *kd, const gchash *hc) +{ + dh_pub *dp = kd; + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime"); + kcdsa_sethash(ds, hc); + return (&ds->s); +} + +static sig *binkcdsa_vrfinit(key *k, void *kd, const gchash *hc) +{ + dh_pub *dp = kd; + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary"); + kcdsa_sethash(ds, hc); + return (&ds->s); +} + +static sig *eckcdsa_vrfinit(key *k, void *kd, const gchash *hc) +{ + ec_pub *ep = kd; + dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc); + kcdsa_sethash(ds, hc); + return (&ds->s); +} + +static int kcdsa_vrfdoit(sig *s, dstr *d) +{ + dsa_sigctx *ds = (dsa_sigctx *)s; + gkcdsa_sig ss; + size_t hsz = ds->g.h->hashsz, n = d->len - hsz; + int rc; + + if (d->len < hsz) + return (-1); + ss.r = (octet *)d->buf; + ss.s = mp_loadb(MP_NEW, d->buf + hsz, n); + rc = gkcdsa_verify(&ds->g, &ss, GH_DONE(ds->s.h, 0)); + mp_drop(ss.s); + return (rc); +} + +static const sigops kcdsa_vrf = { + dh_pubfetch, sizeof(dh_pub), + kcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy +}; + +static const sigops binkcdsa_vrf = { + dh_pubfetch, sizeof(dh_pub), + binkcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy +}; + +static const sigops eckcdsa_vrf = { + ec_pubfetch, sizeof(ec_pub), + eckcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy +}; + +/* --- Symmetric message authentication --- */ + +typedef struct mac_ctx { + sig s; + const gcmac *mc; + gmac *m; + key_packdef kp; + key_bin kb; +} mac_ctx; + +static sig *mac_init(key *k, void *kd, const gchash *hc) +{ + mac_ctx *m; + dstr d = DSTR_INIT; + int err; + const char *mm; + + m = CREATE(mac_ctx); + + key_fulltag(k, &d); + m->kp.e = KENC_BINARY; + m->kp.p = &m->kb; + m->kp.kd = 0; + + if ((mm = key_getattr(0 /*yik*/, k, "mac")) == 0) { + dstr_putf(&d, "%s-hmac", hc->name); + mm = d.buf; + } + if ((m->mc = gmac_byname(mm)) == 0) + die(EXIT_FAILURE, "unknown message authentication scheme `%s'", mm); + dstr_reset(&d); + + if ((err = key_unpack(&m->kp, kd, &d)) != 0) { + die(EXIT_FAILURE, "failed to unpack symmetric key `%s': %s", + d.buf, key_strerror(err)); + } + dstr_destroy(&d); + + if (keysz(m->kb.sz, m->mc->keysz) != m->kb.sz) { + die(EXIT_FAILURE, "bad key size %lu for `%s'", + (unsigned long)m->kb.sz, m->mc->name); + } + m->m = GM_KEY(m->mc, m->kb.k, m->kb.sz); + m->s.h = GM_INIT(m->m); + return (&m->s); +} + +static int mac_sigdoit(sig *s, dstr *d) +{ + mac_ctx *m = (mac_ctx *)s; + + dstr_ensure(d, m->mc->hashsz); + GH_DONE(m->s.h, d->buf); + d->len += m->mc->hashsz; + return (0); +} + +static int mac_vrfdoit(sig *s, dstr *d) +{ + mac_ctx *m = (mac_ctx *)s; + const octet *t; + + t = GH_DONE(m->s.h, 0); + if (d->len != m->mc->hashsz || memcmp(d->buf, t, d->len) != 0) + return (-1); + return (0); +} + +static const char *mac_check(sig *s) { return (0); } + +static void mac_destroy(sig *s) +{ + mac_ctx *m = (mac_ctx *)s; + GM_DESTROY(m->m); + key_unpackdone(&m->kp); +} + +static const sigops mac_sig = { + 0, 0, + mac_init, mac_sigdoit, mac_check, mac_destroy +}; + +static const sigops mac_vrf = { + 0, 0, + mac_init, mac_vrfdoit, mac_check, mac_destroy +}; + +/* --- The switch table --- */ + +const struct sigtab sigtab[] = { + { "rsapkcs1", &rsap1_sig, &rsap1_vrf, &sha }, + { "rsapss", &rsapss_sig, &rsapss_vrf, &sha }, + { "dsa", &dsa_sig, &dsa_vrf, &sha }, + { "bindsa", &bindsa_sig, &bindsa_vrf, &sha }, + { "ecdsa", &ecdsa_sig, &ecdsa_vrf, &sha }, + { "kcdsa", &kcdsa_sig, &kcdsa_vrf, &has160 }, + { "binkcdsa", &binkcdsa_sig, &binkcdsa_vrf, &has160 }, + { "eckcdsa", &eckcdsa_sig, &eckcdsa_vrf, &has160 }, + { "mac", &mac_sig, &mac_vrf, &rmd160 }, + { 0, 0, 0 } +}; + +/* --- @getsig@ --- * + * + * Arguments: @key *k@ = the key to load + * @const char *app@ = application name + * @int wantpriv@ = nonzero if we want to sign + * + * Returns: A signature-making thing. + * + * Use: Loads a key and starts hashing. + */ + +sig *getsig(key *k, const char *app, int wantpriv) +{ + const char *salg, *halg = 0; + dstr d = DSTR_INIT; + dstr t = DSTR_INIT; + char *p = 0; + const char *q; + sig *s; + size_t n; + const struct sigtab *st; + const sigops *so; + const gchash *ch; + void *kd; + int e; + key_packdef *kp; + + /* --- Setup stuff --- */ + + key_fulltag(k, &t); + + /* --- Get the signature algorithm --- * + * + * Take the attribute if it's there; otherwise use the key type. + */ + + n = strlen(app); + if ((q = key_getattr(0, k, "sig")) != 0) { + dstr_puts(&d, q); + p = d.buf; + } else if (strncmp(k->type, app, n) == 0 && k->type[n] == '-') { + dstr_puts(&d, k->type); + p = d.buf + n + 1; + } else + die(EXIT_FAILURE, "no signature algorithm for key `%s'", t.buf); + + /* --- Grab the hash algorithm --- * + * + * Grab it from the signature algorithm if it's there. But override that + * from the attribute. + */ + + salg = p; + if ((p = strchr(p, '/')) != 0) { + *p++ = 0; + halg = p; + } + if ((q = key_getattr(0, k, "hash")) != 0) + halg = q; + + /* --- Look up the algorithms in the table --- */ + + for (st = sigtab; st->name; st++) { + if (strcmp(st->name, salg) == 0) + goto s_found; + } + die(EXIT_FAILURE, "signature algorithm `%s' not found in key `%s'", + salg, t.buf); +s_found:; + if (!halg) + ch = st->ch; + else { + if ((ch = ghash_byname(halg)) == 0) { + die(EXIT_FAILURE, "hash algorithm `%s' not found in key `%s'", + halg, t.buf); + } + } + so = wantpriv ? st->signops : st->verifyops; + + /* --- Load the key --- */ + + if (!so->kf) { + kd = k->k; + key_incref(kd); + kp = 0; + } else { + kd = xmalloc(so->kdsz); + kp = key_fetchinit(so->kf, 0, kd); + if ((e = key_fetch(kp, k)) != 0) { + die(EXIT_FAILURE, "error fetching key `%s': %s", + t.buf, key_strerror(e)); + } + } + s = so->init(k, kd, ch); + if (!s->h) + s->h = GH_INIT(ch); + s->kp = kp; + s->ops = so; + s->kd = kd; + s->ch = ch; + + /* --- Free stuff up --- */ + + dstr_destroy(&d); + dstr_destroy(&t); + return (s); +} + +/* --- @freesig@ --- * + * + * Arguments: @sig *s@ = signature-making thing + * + * Returns: --- + * + * Use: Frees up a signature-making thing + */ + +void freesig(sig *s) +{ + GH_DESTROY(s->h); + if (!s->ops->kf) + key_drop(s->kd); + else { + key_fetchdone(s->kp); + xfree(s->kd); + } + s->ops->destroy(s); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/progs/cc-subcmd.c b/progs/cc-subcmd.c new file mode 100644 index 0000000..83c4a78 --- /dev/null +++ b/progs/cc-subcmd.c @@ -0,0 +1,109 @@ +/* -*-c-*- + * + * Subcommand infrastructure + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _FILE_OFFSET_BITS 64 + +#include +#include + +#include "cc.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @findcmd@ --- * + * + * Arguments: @const cmd *cmds@ = pointer to command table + * @const char *name@ = a command name + * + * Returns: Pointer to the command structure. + * + * Use: Looks up a command by name. If the command isn't found, an + * error is reported and the program is terminated. + */ + +const cmd *findcmd(const cmd *cmds, const char *name) +{ + const cmd *c, *chosen = 0; + size_t sz = strlen(name); + + for (c = cmds; c->name; c++) { + if (strncmp(name, c->name, sz) == 0) { + if (c->name[sz] == 0) { + chosen = c; + break; + } else if (chosen) + die(EXIT_FAILURE, "ambiguous command name `%s'", name); + else + chosen = c; + } + } + if (!chosen) + die(EXIT_FAILURE, "unknown command name `%s'", name); + return (chosen); +} + +/* --- @sc_help@ --- * + * + * Arguments: @const cmd *cmds@ = pointer to command table + * @FILE *fp@ = output file handle + * @char *const *argv@ = remaining arguments + * + * Returns: --- + * + * Use: Prints a help message, maybe with help about subcommands. + */ + +void sc_help(const cmd *cmds, FILE *fp, char *const *argv) +{ + const cmd *c; + + version(fp); + fputc('\n', fp); + if (!*argv) { + help_global(fp); + fputs("\n\ +The following commands are understood:\n\n", + fp); + for (c = cmds; c->name; c++) + fprintf(fp, "%s\n", c->usage); + } else { + while (*argv) { + c = findcmd(cmds, *argv); + fprintf(fp, "Usage: %s [-OPTIONS] %s\n", QUIS, c->usage); + if (c->help) { + fputc('\n', fp); + pquis(fp, c->help); + } + argv++; + if (*argv) fputc('\n', fp); + } + } +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/progs/cc.h b/progs/cc.h new file mode 100644 index 0000000..610a765 --- /dev/null +++ b/progs/cc.h @@ -0,0 +1,657 @@ +/* -*-c-*- + * + * Catcrypt common stuff + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_CC_H +#define CATACOMB_CC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#if _FILE_OFFSET_BITS != 64 +# error "Must set _FILE_OFFSET_BITS to 64." +#endif + +#include +#include +#include + +#include +#include + +#include + +#include "key.h" +#include "gcipher.h" +#include "ghash.h" +#include "gmac.h" + +/*----- Cryptographic object tables ---------------------------------------*/ + +/* --- Key encapsulation --- */ + +typedef struct kem { + const struct kemops *ops; + key_packdef *kp; + void *kd; + const gchash *h; + const gccipher *c, *cx; + const gcmac *m; +} kem; + +typedef struct kemops { + const key_fetchdef *kf; /* Key fetching structure */ + size_t kdsz; /* Size of the key-data structure */ + kem *(*init)(key */*k*/, void */*kd*/); + int (*doit)(kem */*k*/, dstr */*d*/, ghash */*h*/); + const char *(*check)(kem */*k*/); + void (*destroy)(kem */*k*/); +} kemops; + +struct kemtab { + const char *name; + const kemops *encops; + const kemops *decops; +}; + +extern const struct kemtab kemtab[]; + +/* --- @getkem@ --- * + * + * Arguments: @key *k@ = the key to load + * @const char *app@ = application name + * @int wantpriv@ = nonzero if we want to decrypt + * + * Returns: A key-encapsulating thing. + * + * Use: Loads a key. + */ + +extern kem *getkem(key */*k*/, const char */*app*/, int /*wantpriv*/); + +/* --- @setupkem@ --- * + * + * Arguments: @kem *k@ = key-encapsulation thing + * @dstr *d@ = key-encapsulation data + * @gcipher **cx@ = key-expansion function (for IVs) + * @gcipher **c@ = where to put initialized encryption scheme + * @gmac **m@ = where to put initialized MAC + * + * Returns: Zero for success, nonzero on faliure. + * + * Use: Initializes all the various symmetric things from a KEM. + */ + +extern int setupkem(kem */*k*/, dstr */*d*/, + gcipher **/*cx*/, gcipher **/*c*/, gmac **/*m*/); + +/* --- @freekem@ --- * + * + * Arguments: @kem *k@ = key-encapsulation thing + * + * Returns: --- + * + * Use: Frees up a key-encapsulation thing. + */ + +extern void freekem(kem */*k*/); + +/* --- Signing --- */ + +typedef struct sig { + const struct sigops *ops; + key_packdef *kp; + void *kd; + const gchash *ch; + ghash *h; +} sig; + +typedef struct sigops { + const key_fetchdef *kf; /* Key fetching structure */ + size_t kdsz; /* Size of the key-data structure */ + sig *(*init)(key */*k*/, void */*kd*/, const gchash */*hc*/); + int (*doit)(sig */*s*/, dstr */*d*/); + const char *(*check)(sig */*s*/); + void (*destroy)(sig */*s*/); +} sigops; + +struct sigtab { + const char *name; + const sigops *signops; + const sigops *verifyops; + const gchash *ch; +}; + +extern const struct sigtab sigtab[]; + +/* --- @getsig@ --- * + * + * Arguments: @key *k@ = the key to load + * @const char *app@ = application name + * @int wantpriv@ = nonzero if we want to sign + * + * Returns: A signature-making thing. + * + * Use: Loads a key and starts hashing. + */ + +extern sig *getsig(key */*k*/, const char */*app*/, int /*wantpriv*/); + +/* --- @freesig@ --- * + * + * Arguments: @sig *s@ = signature-making thing + * + * Returns: --- + * + * Use: Frees up a signature-making thing + */ + +extern void freesig(sig */*s*/); + +/*----- File encodings ----------------------------------------------------*/ + +/* --- Data encoding --- */ + +typedef struct enc { + const struct encops *ops; + FILE *fp; +} enc; + +typedef struct encops { + const char *name; + const char *rmode, *wmode; + int nraw, ncook; + enc *(*initenc)(FILE */*fp*/, const char */*msg*/); + enc *(*initdec)(FILE */*fp*/, + int (*/*func*/)(const char *, void *), void */*p*/); + int (*read)(enc */*e*/, void */*p*/, size_t /*sz*/); + int (*write)(enc */*e*/, const void */*p*/, size_t /*sz*/); + int (*encdone)(enc */*e*/); + int (*decdone)(enc */*e*/); + void (*destroy)(enc */*e*/); +} encops; + +extern const encops enctab[]; + +/* --- @getenc@ --- * + * + * Arguments: @const char *enc@ = name of wanted encoding + * + * Returns: Pointer to encoder operations. + * + * Use: Finds a named encoder or decoder. + */ + +extern const encops *getenc(const char */*enc*/); + +/* --- @checkbdry@ --- * + * + * Arguments: @const char *b@ = boundary string found + * @void *p@ = boundary string wanted + * + * Returns: Nonzero if the boundary string is the one we wanted. + * + * Use: Pass as @func@ to @initdec@ if you just want a simple life. + */ + +extern int checkbdry(const char */*b*/, void */*p*/); + +/* --- @initenc@ --- * + * + * Arguments: @const encops *eo@ = operations (from @getenc@) + * @FILE *fp@ = file handle to attach + * @const char *msg@ = banner message + * + * Returns: The encoder object. + * + * Use: Initializes an encoder. + */ + +extern enc *initenc(const encops */*eo*/, FILE */*fp*/, const char */*msg*/); + +/* --- @initdec@ --- * + * + * Arguments: @const encops *eo@ = operations (from @getenc@) + * @FILE *fp@ = file handle to attach + * @int (*func)(const char *, void *)@ = banner check function + * @void *p@ = argument for @func@ + * + * Returns: The encoder object. + * + * Use: Initializes an encoder. + */ + +extern enc *initdec(const encops */*eo*/, FILE */*fp*/, + int (*/*func*/)(const char *, void *), void */*p*/); + +/* --- @freeenc@ --- * + * + * Arguments: @enc *e@ = encoder object + * + * Returns: --- + * + * Use: Frees an encoder object. + */ + +extern void freeenc(enc */*e*/); + +/* --- @cmd_encode@, @cmd_decode@ --- */ + +#define CMD_ENCODE { \ + "encode", cmd_encode, \ + "encode [-p] [-f FORMAT] [-b LABEL] [-o OUTPUT] [FILE]", \ + "\ +Options:\n\ +\n\ +-f, --format=FORMAT Encode to FORMAT.\n\ +-b, --boundary=LABEL PEM boundary is LABEL.\n\ +-o, --output=FILE Write output to FILE.\n\ +-p, --progress Show progress on large files.\n\ +" } + +#define CMD_DECODE { \ + "decode", cmd_decode, \ + "decode [-p] [-f FORMAT] [-b LABEL] [-o OUTPUT] [FILE]", \ + "\ +Options:\n\ +\n\ +-f, --format=FORMAT Decode from FORMAT.\n\ +-b, --boundary=LABEL PEM boundary is LABEL.\n\ +-o, --output=FILE Write output to FILE.\n\ +-p, --progress Show progress on large files.\n\ +" } + +extern int cmd_encode(int /*argc*/, char */*argv*/[]); +extern int cmd_decode(int /*argc*/, char */*argv*/[]); + +/*----- Hash encoding functions -------------------------------------------*/ + +/* --- Table --- */ + +#define ENCODINGS(_) \ + _(HEX, hex) \ + _(BASE64, base64) \ + _(BASE32, base32) + +enum { +#define ENUM(tag, name) ENC_##tag, + ENCODINGS(ENUM) +#undef ENUM + ENC_LIMIT +}; + +typedef struct encodeops { + const char *name; + void (*put)(const octet *, size_t, FILE *); + size_t (*get)(const char *, octet *, size_t, char **); +} encodeops; + +extern const encodeops encodingtab[]; + +/* --- @getencoding@ --- * + * + * Arguments: @const char *ename@ = encoding name + * + * Returns: Pointer to encoding table entry, or null. + * + * Use: Finds an encoding entry given its name. + */ + +extern const encodeops *getencoding(const char */*ename*/); + +/*----- File hashing ------------------------------------------------------*/ + +typedef struct fhashstate { + const gchash *gch; + unsigned f; + struct fhent *ents; +} fhashstate; + +#define FHF_BINARY 0x100u +#define FHF_PROGRESS 0x200u +#define FHF_JUNK 0x400u + +#define FHF_MASK 0xff00u + +/* --- @gethash@ --- * + * + * Arguments: @const char *name@ = pointer to name string + * + * Returns: Pointer to appropriate hash class. + * + * Use: Chooses a hash function by name. + */ + +extern const gchash *gethash(const char */*name*/); + +/* --- @describefile@ --- * + * + * Arguments: @const struct stat *st@ = pointer to file state + * + * Returns: A snappy one-word description of the file. + */ + +extern const char *describefile(const struct stat */*st*/); + +/* --- @fhash_init@ ---* + * + * Arguments: @fhashstate *fh@ = pointer to fhash state to initialize + * @const gchash *gch@ = hash class to set + * @unsigned f@ initial flags to set + * + * Returns: --- + * + * Use: Initializes an @fhashstate@ structure. + */ + +extern void fhash_init(fhashstate */*fh*/, + const gchash */*gch*/, unsigned /*f*/); + +/* --- @fhash_free@ --- * + * + * Arguments: @fhashstate *fh@ = pointer to fhash state to free + * + * Returns: --- + * + * Use: Frees an fhash state. + */ + +extern void fhash_free(fhashstate */*fh*/); + +/* --- @fhash@ --- * + * + * Arguments: @fhashstate *fh@ = pointer to fhash state + * @const char *file@ = file name to be hashed (null for stdin) + * @void *buf@ = pointer to hash output buffer + * + * Returns: Zero if it worked, nonzero on error. + * + * Use: Hashes a file. + */ + +extern int fhash(fhashstate */*fh*/, const char */*file*/, void */*buf*/); + +/* --- @fhash_junk@ --- * + * + * Arguments: @fhashstate *fh@ = pointer to fhash state + * @void (*func)(const char *, const struct stat *, void *)@ + * @void *p@ = pointer to pass to function + * + * Returns: Positive if any junk was found, negative on error, zero if + * everything was fine. + * + * Use: Reports junk files in any directories covered by the hash + * state. + */ + +extern int fhash_junk(fhashstate */*fh*/, + int (*/*func*/)(const char *, + const struct stat *, + void *), + void */*p*/); + +/* --- @hfparse@ --- * + * + * Arguments: @hfpctx *hfp@ = pointer to the context structure + * + * Returns: A code indicating what happened. + * + * Use: Parses a line from the input file. + */ + +enum { /* Meaning and members set */ + HF_FILE, /* File hash: @dline@ and @hbuf@ */ + HF_ENC, /* Encoding: @ee@ */ + HF_HASH, /* Hash function: @gch@ */ + HF_ESC, /* Name escape: @f@ */ + HF_EOF, /* End of file */ + HF_BAD /* Unrecognized line */ +}; + +typedef struct hfpctx { + unsigned f; /* Flags to read */ +#define HFF_ESCAPE 1u /* File names are escaped */ + FILE *fp; /* Input file to read */ + dstr *dline; /* Line contents, corrupted */ + const gchash *gch; /* Hash function to use */ + const encodeops *ee; /* Encoding to apply to hashes */ + dstr *dfile; /* File name for @HF_FILE@ lines */ + octet *hbuf; /* Output buffer for hash data */ +} hfpctx; + +extern int hfparse(hfpctx */*hfp*/); + +/*----- String I/O --------------------------------------------------------*/ + +#define GSF_RAW 4096u +#define GSF_FILE 0u +#define GSF_STRING 8192u + +#define GSF_MASK 61440u + +/* --- @getstring@ --- * + * + * Arguments: @void *in@ = input source + * @dstr *d@ = destination string + * @unsigned f@ = input flags + * + * Returns: Zero if OK, nonzero on end-of-file. + * + * Use: Reads a filename (or something similar) from a stream. + */ + +extern int getstring(void */*in*/, dstr */*d*/, unsigned /*f*/); + +/* --- @putstring@ --- * + * + * Arguments: @FILE *fp@ = stream to write on + * @const char *p@ = pointer to text + * @unsigned f@ = output flags + * + * Returns: --- + * + * Use: Emits a string to a stream. + */ + +extern void putstring(FILE */*fp*/, const char */*p*/, unsigned /*f*/); + +/*----- Lists of things ---------------------------------------------------*/ + +/* --- @LIST(STRING, FP, END-TEST, NAME-EXPR)@ --- * + * + * Produce list of things. Requires @i@ and @w@ variables in scope. + * END-TEST and NAME-EXPR are in terms of @i@. + */ + +#define LIST(what, fp, end, name) do { \ + fputs(what ":\n ", fp); \ + w = 2; \ + for (i = 0; end; i++) { \ + if (w == 2) \ + w += strlen(name); \ + else { \ + if (strlen(name) + w > 76) { \ + fputs("\n ", fp); \ + w = 2 + strlen(name); \ + } else { \ + fputc(' ', fp); \ + w += strlen(name) + 1; \ + } \ + } \ + fputs(name, fp); \ + } \ + fputc('\n', fp); \ +} while (0) + +#define STDLISTS(LI) \ + LI("Hash functions", hash, \ + ghashtab[i], ghashtab[i]->name) \ + LI("Encryption schemes", enc, \ + gciphertab[i], gciphertab[i]->name) \ + LI("Message authentication schemes", mac, \ + gmactab[i], gmactab[i]->name) \ + LI("Elliptic curves", ec, \ + ectab[i].name, ectab[i].name) \ + LI("Diffie-Hellman groups", dh, \ + ptab[i].name, ptab[i].name) + +#define LIDECL(text, tag, test, name) \ + static void show_##tag(void); + +#define LIDEF(text, tag, test, name) \ + static void show_##tag(void) \ + { \ + unsigned i, w; \ + LIST(text, stdout, test, name); \ + } + +#define LIENT(text, tag, test, name) \ + { #tag, show_##tag }, + +struct listent { + const char *name; + void (*list)(void); +}; + +#define MAKELISTTAB(listtab, LISTS) \ + LISTS(LIDECL) \ + static const struct listent listtab[] = { \ + LISTS(LIENT) \ + { 0, 0 } \ + }; \ + LISTS(LIDEF) + +extern int displaylists(const struct listent */*listtab*/, + char *const /*argv*/[]); + +/*----- Progress indicators -----------------------------------------------*/ + +typedef struct fprogress { + const char *bp; + off_t o, sz, olast; + time_t start, last; + char name[24]; +} fprogress; + +/* --- @fprogress_init@ --- * + * + * Arguments: @fprogress *f@ = progress context to be initialized + * @const char *name@ = file name string to show + * @FILE *fp@ = file we're reading from + * + * Returns: Zero on success, nonzero if the file's state is now broken. + * + * Use: Initializes a progress context. Nothing is actually + * displayed yet. + */ + +extern int fprogress_init(fprogress */*f*/, + const char */*name*/, FILE */*fp*/); + +/* --- @fprogress_update@ --- * + * + * Arguments: @fprogress *f@ = progress context + * @size_t n@ = how much progress has been made + * + * Returns: --- + * + * Use: Maybe updates the display to show that some progress has been + * made. + */ + +extern void fprogress_update(fprogress */*f*/, size_t /*n*/); + +/* --- @fprogress_clear@ --- * + * + * Arguments: @fprogress *f@ = progress context + * + * Returns: --- + * + * Use: Clears the progress display from the screen. + */ + +extern void fprogress_clear(fprogress */*f*/); + +/* --- @fprogress_done@ --- * + * + * Arguments: @fprogress *f@ = progress context + * + * Returns: --- + * + * Use: Clear up the progress context and removes any display. + */ + +extern void fprogress_done(fprogress */*f*/); + +/*----- Subcommand dispatch -----------------------------------------------*/ + +typedef struct cmd { + const char *name; + int (*cmd)(int /*argc*/, char */*argv*/[]); + const char *usage; + const char *help; +} cmd; + +extern void version(FILE */*fp*/); +extern void help_global(FILE */*fp*/); + +/* --- @findcmd@ --- * + * + * Arguments: @const cmd *cmds@ = pointer to command table + * @const char *name@ = a command name + * + * Returns: Pointer to the command structure. + * + * Use: Looks up a command by name. If the command isn't found, an + * error is reported and the program is terminated. + */ + +const cmd *findcmd(const cmd */*cmds*/, const char */*name*/); + +/* --- @sc_help@ --- * + * + * Arguments: @const cmd *cmds@ = pointer to command table + * @FILE *fp@ = output file handle + * @char *const *argv@ = remaining arguments + * + * Returns: --- + * + * Use: Prints a help message, maybe with help about subcommands. + */ + +extern void sc_help(const cmd */*cmds*/, FILE */*fp*/, + char *const */*argv*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/cookie.1 b/progs/cookie.1 similarity index 100% rename from cookie.1 rename to progs/cookie.1 diff --git a/progs/cookie.c b/progs/cookie.c new file mode 100644 index 0000000..56849e5 --- /dev/null +++ b/progs/cookie.c @@ -0,0 +1,692 @@ +/* -*-c-*- + * + * Generate and validate cryptographic cookies + * + * (c) 1999 Mark Wooding + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb 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 2 of the License, or + * (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Catacomb; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _FILE_OFFSET_BITS 64 + +#include "config.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "cc.h" +#include "key.h" +#include "gmac.h" +#include "getdate.h" + +/*----- Handy global state ------------------------------------------------*/ + +static const char *keyfile = "keyring"; + +/*----- Cookie format -----------------------------------------------------*/ + +/* --- Cookie header structure (unpacked) --- */ + +typedef struct cookie { + uint32 k; + time_t exp; +} cookie; + +/* --- Size of a cookie header (packed) --- */ + +#define COOKIE_SZ (4 + 8) + +/* --- @COOKIE_PACK@ --- * + * + * Arguments: @p@ = pointer to destination buffer + * @c@ = pointer to source cookie header block + * + * Use: Packs a cookie header into an octet buffer in a machine- + * independent way. + */ + +#define COOKIE_PACK(p, c) do { \ + octet *_p = (octet *)(p); \ + const cookie *_c = (c); \ + STORE32(_p + 0, _c->k); \ + STORE32(_p + 4, ((_c->exp & ~MASK32) >> 16) >> 16); \ + STORE32(_p + 8, _c->exp); \ +} while (0) + +/* --- @COOKIE_UNPACK@ --- * + * + * Arguments: @c@ = pointer to destination cookie header + * @p@ = pointer to source buffer + * + * Use: Unpacks a cookie header from an octet buffer into a + * machine-specific but comprehensible structure. + */ + +#define COOKIE_UNPACK(c, p) do { \ + cookie *_c = (c); \ + const octet *_p = (const octet *)(p); \ + _c->k = LOAD32(_p + 0); \ + _c->exp = ((time_t)(((LOAD32(_p + 4) << 16) << 16) & ~MASK32) | \ + (time_t)LOAD32(_p + 8)); \ +} while (0) + +/*----- Useful shared functions -------------------------------------------*/ + +/* --- @doopen@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * @unsigned how@ = method to open file with + * + * Returns: --- + * + * Use: Opens a key file and handles errors by panicking + * appropriately. + */ + +static void doopen(key_file *f, unsigned how) +{ + if (key_open(f, keyfile, how, key_moan, 0)) { + die(EXIT_FAILURE, "couldn't open file `%s': %s", + keyfile, strerror(errno)); + } +} + +/* --- @doclose@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * + * Returns: --- + * + * Use: Closes a key file and handles errors by panicking + * appropriately. + */ + +static void doclose(key_file *f) +{ + switch (key_close(f)) { + case KWRITE_FAIL: + die(EXIT_FAILURE, "couldn't write file `%s': %s", + keyfile, strerror(errno)); + case KWRITE_BROKEN: + die(EXIT_FAILURE, "keyring file `%s' broken: %s (repair manually)", + keyfile, strerror(errno)); + } +} + +/* --- @getmac@ --- * + * + * Arguments: @key *k@ = key to use + * @const char *app@ = application name + * + * Returns: The MAC to use. + * + * Use: Finds the right MAC for the given key. + */ + +static gmac *getmac(key *k, const char *app) +{ + dstr t = DSTR_INIT; + dstr d = DSTR_INIT; + char *p = 0; + const char *q; + size_t n; + key_bin kb; + key_packdef kp; + const gcmac *cm; + int e; + gmac *m; + + /* --- Set up --- */ + + key_fulltag(k, &t); + + /* --- Pick out the right MAC --- */ + + n = strlen(app); + if ((q = key_getattr(0, k, "mac")) != 0) { + dstr_puts(&d, q); + p = d.buf; + } else if (strncmp(k->type, app, n) == 0 && k->type[n] == '-') { + dstr_puts(&d, k->type); + p = d.buf + n + 1; + } else + die(EXIT_FAILURE, "no MAC algorithm for key `%s'", t.buf); + if ((cm = gmac_byname(p)) == 0) { + die(EXIT_FAILURE, "MAC algorithm `%s' not found in key `%s'", + p, t.buf); + } + + /* --- Unlock the key --- */ + + kp.e = KENC_BINARY; + kp.p = &kb; + if ((e = key_unpack(&kp, k->k, &t)) != 0) { + die(EXIT_FAILURE, "error unpacking key `%s': %s", + t.buf, key_strerror(e)); + } + + /* --- Make the MAC object --- */ + + if (keysz(kb.sz, cm->keysz) != kb.sz) + die(EXIT_FAILURE, "key %s has bad length (%lu) for MAC %s", + t.buf, (unsigned long)kb.sz, cm->name); + m = cm->key(kb.k, kb.sz); + key_unpackdone(&kp); + return (m); +} + +/*----- Command implementation --------------------------------------------*/ + +/* --- @cmd_gen@ --- */ + +static int cmd_gen(int argc, char *argv[]) +{ + key_file f; + key *k; + gmac *m; + ghash *h; + const char *tag = "cookie"; + int err; + cookie c = { 0, KEXP_EXPIRE }; + unsigned fl = 0; + int bits = 32; + const octet *t; + dstr d = DSTR_INIT; + octet buf[COOKIE_SZ]; + base64_ctx b; + + /* --- Various useful flag bits --- */ + +#define f_bogus 1u + + /* --- Parse options for the subcommand --- */ + + for (;;) { + static struct option opt[] = { + { "bits", OPTF_ARGREQ, 0, 'b' }, + { "expire", OPTF_ARGREQ, 0, 'e' }, + { "key", OPTF_ARGREQ, 0, 'k' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+b:e:i:t:", opt, 0, 0, 0); + if (i < 0) + break; + + /* --- Handle the various options --- */ + + switch (i) { + + /* --- Fetch a size in bits --- */ + + case 'b': + if (!(bits = atoi(optarg)) || bits % 8) + die(EXIT_FAILURE, "bad number of bits: `%s'", optarg); + break; + + /* --- Fetch an expiry time --- */ + + case 'e': + if (strcmp(optarg, "forever") == 0) + c.exp = KEXP_FOREVER; + else if ((c.exp = get_date(optarg, 0)) == -1) + die(EXIT_FAILURE, "bad expiry date: `%s'", optarg); + break; + + /* --- Fetch a key type --- */ + + case 'k': + tag = optarg; + break; + + /* --- Other things are bogus --- */ + + default: + fl |= f_bogus; + break; + } + } + + /* --- Various sorts of bogosity --- */ + + if (fl & f_bogus || optind + 1 < argc) + die(EXIT_FAILURE, + "Usage: generate [-b BITS] [-e TIME] [-k TAG] [DATA]"); + + /* --- Choose a default expiry time --- */ + + if (c.exp == KEXP_EXPIRE) + c.exp = time(0) + 7 * 24 * 60 * 60; + + /* --- Open the key file and get the key --- */ + + doopen(&f, KOPEN_WRITE); + if ((k = key_bytag(&f, tag)) == 0) { + die(EXIT_FAILURE, "no key with tag `%s' in keyring `%s'", + tag, keyfile); + } + + c.k = k->id; + if ((err = key_used(&f, k, c.exp)) != 0) + die(EXIT_FAILURE, "can't generate cookie: %s", key_strerror(err)); + m = getmac(k, "cookie"); + if (bits/8 > GM_CLASS(m)->hashsz) { + die(EXIT_FAILURE, "inapproriate bit length for `%s' MACs", + GM_CLASS(m)->name); + } + + /* --- Store and MAC the cookie --- */ + + COOKIE_PACK(buf, &c); + + h = GM_INIT(m); + GH_HASH(h, buf, sizeof(buf)); + if (argv[optind]) + GH_HASH(h, argv[optind], strlen(argv[optind])); + t = GH_DONE(h, 0); + + /* --- Encode and emit the finished cookie --- */ + + base64_init(&b); + b.indent = ""; + base64_encode(&b, buf, sizeof(buf), &d); + base64_encode(&b, t, bits/8, &d); + base64_encode(&b, 0, 0, &d); + DWRITE(&d, stdout); + fputc('\n', stdout); + DDESTROY(&d); + GH_DESTROY(h); + GM_DESTROY(m); + + doclose(&f); + return (0); + +#undef f_bogus +} + +/* --- @cmd_verify@ --- */ + +static int cmd_verify(int argc, char *argv[]) +{ + key_file f; + dstr d = DSTR_INIT; + unsigned fl = 0; + int bits = -1, minbits = 32; + int v = 1; + base64_ctx b; + gmac *m; + ghash *h; + cookie c; + key *k; + int cbits; + const octet *t; + time_t now = time(0); + + /* --- Various useful flag bits --- */ + +#define f_bogus 1u +#define f_forever 2u +#define f_utc 4u + + /* --- Parse options for the subcommand --- */ + + for (;;) { + static struct option opt[] = { + { "bits", OPTF_ARGREQ, 0, 'b' }, + { "min-bits", OPTF_ARGREQ, 0, 'm' }, + { "forever", 0, 0, 'f' }, + { "quiet", 0, 0, 'q' }, + { "verbose", 0, 0, 'v' }, + { "utc", 0, 0, 'u' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+b:m:fqvu", opt, 0, 0, 0); + if (i < 0) + break; + + /* --- Handle the various options --- */ + + switch (i) { + + /* --- Fetch a size in bits --- */ + + case 'b': + if (!(bits = atoi(optarg)) || bits % 8) + die(EXIT_FAILURE, "bad number of bits: `%s'", optarg); + break; + case 'm': + if (!(minbits = atoi(optarg)) || minbits % 8) + die(EXIT_FAILURE, "bad number of bits: `%s'", optarg); + break; + + /* --- Miscellaneous flags --- */ + + case 'f': + fl |= f_forever; + break; + case 'u': + fl |= f_utc; + break; + case 'q': + if (v > 0) v--; + break; + case 'v': + v++; + break; + + /* --- Other things are bogus --- */ + + default: + fl |= f_bogus; + break; + } + } + + /* --- Various sorts of bogosity --- */ + + if (fl & f_bogus || optind == argc || optind + 2 < argc) { + die(EXIT_FAILURE, + "Usage: verify [-fuqv] [-b BITS] [-m BITS] COOKIE [DATA]"); + } + doopen(&f, KOPEN_READ); + + /* --- Decode the base64 wrapping --- */ + + base64_init(&b); + base64_decode(&b, argv[optind], strlen(argv[optind]), &d); + base64_decode(&b, 0, 0, &d); + + if (d.len < COOKIE_SZ + 1) { + if (v) printf("FAIL cookie too small\n"); + goto fail; + } + + /* --- Extract the relevant details --- */ + + COOKIE_UNPACK(&c, d.buf); + + if (v > 1) { + char buf[64]; + if (c.exp == KEXP_FOREVER) + strcpy(buf, "forever"); + else { + struct tm *tm; + const char *fmt; + + if (fl & f_utc) { + tm = gmtime(&c.exp); + fmt = "%Y-%m-%d %H:%M:%S UTC"; + } else { + tm = localtime(&c.exp); + fmt = "%Y-%m-%d %H:%M:%S %Z"; + } + strftime(buf, sizeof(buf), fmt, tm); + } + printf("INFO keyid = %08lx; expiry = %s\n", (unsigned long)c.k, buf); + } + + /* --- Check the authentication token width --- */ + + cbits = (d.len - COOKIE_SZ) * 8; + if (v > 2) printf("INFO authentication token width = %i bits\n", cbits); + if (bits == -1) { + if (cbits < minbits) { + if (v) printf("FAIL authentication token too narrow\n"); + goto fail; + } + } else { + if (cbits != bits) { + if (v) printf("FAIL authentication token width doesn't match\n"); + goto fail; + } + } + /* --- Get the key --- */ + + if ((k = key_byid(&f, c.k)) == 0) { + if (v) printf("FAIL keyid %08lx unavailable\n", (unsigned long)c.k); + goto fail; + } + + /* --- Check that the cookie authenticates OK --- */ + + m = getmac(k, "cookie"); + h = GM_INIT(m); + GH_HASH(h, d.buf, COOKIE_SZ); + if (argv[optind + 1]) + GH_HASH(h, argv[optind + 1], strlen(argv[optind + 1])); + t = GH_DONE(h, 0); + + if (memcmp(t, d.buf + COOKIE_SZ, cbits / 8) != 0) { + if (v) printf("FAIL bad authentication token\n"); + goto fail; + } + + /* --- See whether the cookie has expired --- */ + + if (c.exp == KEXP_FOREVER) { + if (!(fl & f_forever)) { + if (v) printf("FAIL forever cookies not allowed\n"); + goto fail; + } + if (k->exp != KEXP_FOREVER) { + if (v) printf("FAIL cookie lasts forever but key will expire\n"); + goto fail; + } + } else if (c.exp < now) { + if (v) printf("FAIL cookie has expired\n"); + goto fail; + } + + if (v) printf("OK\n"); + key_close(&f); + GM_DESTROY(m); + GH_DESTROY(h); + dstr_destroy(&d); + return (0); + +fail: + key_close(&f); + dstr_destroy(&d); + return (1); + +#undef f_bogus +#undef f_forever +#undef f_utc +} + +/*----- Main command table ------------------------------------------------*/ + +static int cmd_help(int, char **); + +#define LISTS(LI) \ + LI("Lists", list, \ + listtab[i].name, listtab[i].name) \ + LI("Message authentication algorithms", mac, \ + gmactab[i], gmactab[i]->name) + +MAKELISTTAB(listtab, LISTS) + +static int cmd_show(int argc, char *argv[]) +{ + return (displaylists(listtab, argv + 1)); +} + +static cmd cmds[] = { + { "help", cmd_help, "help [COMMAND...]" }, + { "show", cmd_show, "show [ITEM...]" }, + { "generate", cmd_gen, + "generate [-b BITS] [-e TIME] [-k TAG] [DATA]", "\ +Options:\n\ +\n\ +-b, --bits=N Use an N-bit token in the cookie.\n\ +-e, --expire=TIME Make the cookie expire after TIME.\n\ +-k, --key=TAG Use key TAG to create the token.\n\ +" }, + { "verify", cmd_verify, + "verify [-fuqv] [-b BITS] [-m BITS] COOKIE [DATA]", "\ +Options:\n\ +\n\ +-b, --bits=N Accept tokens exactly N bits long only.\n\ +-m, --min-bits=N Accept tokens N bits long or more.\n\ +-f, --forever Accept cookies which never expire.\n\ +-u, --utc Output cookie expiry dates in UTC.\n\ +-q, --quiet Produce less output while checking cookies.\n\ +-v, --verbose Produce more output while checking cookies.\n\ +" }, + { 0, 0, 0 } +}; + +static int cmd_help(int argc, char *argv[]) +{ + sc_help(cmds, stdout, argv + 1); + return (0); +} + +/*----- Main code ---------------------------------------------------------*/ + +/* --- Helpful GNUy functions --- */ + +static void usage(FILE *fp) +{ + fprintf(fp, "Usage: %s [-k KEYRING] COMMAND [ARGS]\n", QUIS); +} + +void version(FILE *fp) +{ + fprintf(fp, "%s, Catacomb version " VERSION "\n", QUIS); +} + +void help_global(FILE *fp) +{ + usage(fp); + fputs("\n\ +Generates and validates cryptographic cookies. Command line options\n\ +recognized are:\n\ +\n\ +-h, --help [COMMAND] Display this help text (or help for COMMAND).\n\ +-v, --version Display version number.\n\ +-u, --usage Display short usage summary.\n\ +\n\ +-k, --key-file=FILE Read and write keys in FILE.\n", + fp); +} + +/* --- @main@ --- * + * + * Arguments: @int argc@ = number of command line arguments + * @char *argv[]@ = array of arguments + * + * Returns: Zero if OK, nonzero if not. + * + * Use: Generates and validates cryptographic cookies. + */ + +int main(int argc, char *argv[]) +{ + unsigned f = 0; + +#define f_bogus 1u +#define f_forever 2u + + /* --- Initialize the library --- */ + + ego(argv[0]); + sub_init(); + + /* --- Options parsing --- */ + + for (;;) { + static struct option opt[] = { + + /* --- Standard GNUy help options --- */ + + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "usage", 0, 0, 'u' }, + + /* --- Actual relevant options --- */ + + { "keyring", OPTF_ARGREQ, 0, 'k' }, + + /* --- Magic terminator --- */ + + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+hvu k:", opt, 0, 0, 0); + + if (i < 0) + break; + switch (i) { + + /* --- Helpful GNUs --- */ + + case 'u': + usage(stdout); + exit(0); + case 'v': + version(stdout); + exit(0); + case 'h': + sc_help(cmds, stdout, argv + optind); + exit(0); + + /* --- Real genuine useful options --- */ + + case 'k': + keyfile = optarg; + break; + + /* --- Bogus things --- */ + + default: + f |= f_bogus; + break; + } + } + + if ((f & f_bogus) || optind == argc) { + usage(stderr); + exit(EXIT_FAILURE); + } + + /* --- Dispatch to appropriate command handler --- */ + + argc -= optind; + argv += optind; + optind = 0; + return (findcmd(cmds, argv[0])->cmd(argc, argv)); + +#undef f_bogus +#undef f_forever +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/dsig.1 b/progs/dsig.1 similarity index 100% rename from dsig.1 rename to progs/dsig.1 diff --git a/progs/dsig.c b/progs/dsig.c new file mode 100644 index 0000000..5e5a3cf --- /dev/null +++ b/progs/dsig.c @@ -0,0 +1,1124 @@ +/* -*-c-*- + * + * Verify signatures on distribuitions of files + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _FILE_OFFSET_BITS 64 + +#include "config.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "getdate.h" +#include "rand.h" +#include "ghash.h" +#include "key.h" +#include "key-data.h" +#include "noise.h" +#include "cc.h" + +/*----- Data formatting ---------------------------------------------------*/ + +/* --- Binary data structure --- * + * + * The binary format, which is used for hashing and for the optional binary + * output, consists of a sequence of tagged blocks. The tag describes the + * format and meaining of the following data. + */ + +enum { + /* --- Block tags --- */ + + T_IDENT = 0, /* An identifying marker */ + T_KEYID, /* Key identifier */ + T_BEGIN, /* Begin hashing here */ + T_COMMENT = T_BEGIN, /* A textual comment */ + T_DATE, /* Creation date of signature */ + T_EXPIRE, /* Expiry date of signature */ + T_FILE, /* File and corresponding hash */ + T_SIGNATURE, /* Final signature block */ + + /* --- Error messages --- */ + + E_EOF = -1, + E_BIN = -2, + E_TAG = -3, + E_DATE = -4 +}; + +/* --- Name translation table --- */ + +static const char *tagtab[] = { + "ident:", "keyid:", + "comment:", "date:", "expires:", "file:", + "signature:", + 0 +}; + +static const char *errtab[] = { + "Off-by-one bug", + "Unexpected end-of-file", + "Binary object too large", + "Unrecognized tag", + "Bad date string" +}; + +/* --- Memory representation of block types --- */ + +typedef struct block { + int tag; /* Type tag */ + dstr d; /* String data */ + dstr b; /* Binary data */ + time_t t; /* Timestamp */ + uint32 k; /* Keyid */ +} block; + +/* --- @timestring@ --- * + * + * Arguments: @time_t t@ = a timestamp + * @dstr *d@ = a string to write on + * + * Returns: --- + * + * Use: Writes a textual representation of the timestamp to the + * string. + */ + +static void timestring(time_t t, dstr *d) +{ + if (t == KEXP_FOREVER) + DPUTS(d, "forever"); + else { + struct tm *tm = localtime(&t); + DENSURE(d, 32); + d->len += strftime(d->buf + d->len, 32, "%Y-%m-%d %H:%M:%S %Z", tm); + DPUTZ(d); + } +} + +/* --- @breset@ --- * + * + * Arguments: @block *b@ = block to reset + * + * Returns: --- + * + * Use: Resets a block so that more stuff can be put in it. + */ + +static void breset(block *b) +{ + b->tag = 0; + DRESET(&b->d); + DRESET(&b->b); + b->k = 0; + b->t = KEXP_EXPIRE; +} + +/* --- @binit@ --- * + * + * Arguments: @block *b@ = block to initialize + * + * Returns: --- + * + * Use: Initializes a block as something to read into. + */ + +static void binit(block *b) +{ + dstr_create(&b->d); + dstr_create(&b->b); + breset(b); +} + +/* --- @bdestroy@ --- * + * + * Arguments: @block *b@ = block to destroy + * + * Returns: --- + * + * Use: Destroys a block's contents. + */ + +static void bdestroy(block *b) +{ + dstr_destroy(&b->d); + dstr_destroy(&b->b); +} + +/* --- @bget@ --- * + * + * Arguments: @block *b@ = pointer to block + * @FILE *fp@ = stream to read from + * @unsigned bin@ = binary switch + * + * Returns: Tag of block, or an error tag. + * + * Use: Reads a block from a stream. + */ + +static int bget(block *b, FILE *fp, unsigned bin) +{ + int tag; + + /* --- Read the tag --- */ + + if (bin) + tag = getc(fp); + else { + dstr d = DSTR_INIT; + if (getstring(fp, &d, GSF_FILE)) + return (E_EOF); + for (tag = 0; tagtab[tag]; tag++) { + if (strcmp(tagtab[tag], d.buf) == 0) + goto done; + } + return (E_TAG); + done:; + } + + /* --- Decide what to do next --- */ + + breset(b); + b->tag = tag; + switch (tag) { + + /* --- Reading of strings --- */ + + case T_IDENT: + case T_COMMENT: + if (getstring(fp, &b->d, GSF_FILE | (bin ? GSF_RAW : 0))) + return (E_EOF); + break; + + /* --- Timestamps --- */ + + case T_DATE: + case T_EXPIRE: + if (bin) { + octet buf[8]; + if (fread(buf, sizeof(buf), 1, fp) < 1) + return (E_EOF); + b->t = ((time_t)(((LOAD32(buf + 0) << 16) << 16) & ~MASK32) | + (time_t)LOAD32(buf + 4)); + } else { + if (getstring(fp, &b->d, GSF_FILE)) + return (E_EOF); + if (strcmp(b->d.buf, "forever") == 0) + b->t = KEXP_FOREVER; + else if ((b->t = get_date(b->d.buf, 0)) == -1) + return (E_DATE); + } + break; + + /* --- Key ids --- */ + + case T_KEYID: + if (bin) { + octet buf[4]; + if (fread(buf, sizeof(buf), 1, fp) < 1) + return (E_EOF); + b->k = LOAD32(buf); + } else { + if (getstring(fp, &b->d, GSF_FILE)) + return (E_EOF); + b->k = strtoul(b->d.buf, 0, 16); + } + break; + + /* --- Reading of binary data --- */ + + case T_FILE: + case T_SIGNATURE: + if (bin) { + octet buf[2]; + uint32 sz; + if (fread(buf, sizeof(buf), 1, fp) < 1) + return (E_EOF); + sz = LOAD16(buf); + if (sz > 4096) + return (E_BIN); + DENSURE(&b->b, sz); + if (fread(b->b.buf + b->b.len, 1, sz, fp) < sz) + return (E_EOF); + b->b.len += sz; + } else { + base64_ctx b64; + if (getstring(fp, &b->d, GSF_FILE)) + return (E_EOF); + base64_init(&b64); + base64_decode(&b64, b->d.buf, b->d.len, &b->b); + base64_decode(&b64, 0, 0, &b->b); + DRESET(&b->d); + } + if (tag == T_FILE && + getstring(fp, &b->d, GSF_FILE | (bin ? GSF_RAW : 0))) + return (E_EOF); + break; + + /* --- Anything else --- */ + + default: + return (E_TAG); + } + + return (tag); +} + +/* --- @blob@ --- * + * + * Arguments: @block *b@ = pointer to block to emit + * @dstr *d@ = output buffer + * + * Returns: --- + * + * Use: Encodes a block in a binary format. + */ + +static void blob(block *b, dstr *d) +{ + DPUTC(d, b->tag); + switch (b->tag) { + case T_IDENT: + case T_COMMENT: + DPUTD(d, &b->d); + DPUTC(d, 0); + break; + case T_DATE: + case T_EXPIRE: + DENSURE(d, 8); + if (b->t == KEXP_FOREVER) { + STORE32(d->buf + d->len, 0xffffffff); + STORE32(d->buf + d->len + 4, 0xffffffff); + } else { + STORE32(d->buf + d->len, ((b->t & ~MASK32) >> 16) >> 16); + STORE32(d->buf + d->len + 4, b->t); + } + d->len += 8; + break; + case T_KEYID: + DENSURE(d, 4); + STORE32(d->buf + d->len, b->k); + d->len += 4; + break; + case T_FILE: + case T_SIGNATURE: + DENSURE(d, 2); + STORE16(d->buf + d->len, b->b.len); + d->len += 2; + DPUTD(d, &b->b); + if (b->tag == T_FILE) { + DPUTD(d, &b->d); + DPUTC(d, 0); + } + break; + } +} + +/* --- @bwrite@ --- * + * + * Arguments: @block *b@ = pointer to block to write + * @FILE *fp@ = stream to write on + * + * Returns: --- + * + * Use: Writes a block on a stream in a textual format. + */ + +static void bwrite(block *b, FILE *fp) +{ + fputs(tagtab[b->tag], fp); + putc(' ', fp); + switch (b->tag) { + case T_IDENT: + case T_COMMENT: + putstring(fp, b->d.buf, 0); + break; + case T_DATE: + case T_EXPIRE: { + dstr d = DSTR_INIT; + timestring(b->t, &d); + putstring(fp, d.buf, 0); + dstr_destroy(&d); + } break; + case T_KEYID: + fprintf(fp, "%08lx", (unsigned long)b->k); + break; + case T_FILE: + case T_SIGNATURE: { + dstr d = DSTR_INIT; + base64_ctx b64; + base64_init(&b64); + b64.maxline = 0; + base64_encode(&b64, b->b.buf, b->b.len, &d); + base64_encode(&b64, 0, 0, &d); + dstr_write(&d, fp); + if (b->tag == T_FILE) { + putc(' ', fp); + putstring(fp, b->d.buf, 0); + } + } break; + } + putc('\n', fp); +} + +/* --- @bemit@ --- * + * + * Arguments: @block *b@ = pointer to block to write + * @FILE *fp@ = file to write on + * @ghash *h@ = pointer to hash function + * @unsigned bin@ = binary/text flag + * + * Returns: --- + * + * Use: Spits out a block properly. + */ + +static void bemit(block *b, FILE *fp, ghash *h, unsigned bin) +{ + if (h || (fp && bin)) { + dstr d = DSTR_INIT; + blob(b, &d); + if (h) + GH_HASH(h, d.buf, d.len); + if (fp && bin) + fwrite(d.buf, d.len, 1, fp); + } + if (fp && !bin) + bwrite(b, fp); +} + +/*----- Static variables --------------------------------------------------*/ + +static const char *keyring = "keyring"; + +/*----- Other shared functions --------------------------------------------*/ + +/* --- @fhex@ --- * + * + * Arguments: @FILE *fp@ = file to write on + * @const void *p@ = pointer to data to be written + * @size_t sz@ = size of the data to write + * + * Returns: --- + * + * Use: Emits a hex dump to a stream. + */ + +static void fhex(FILE *fp, const void *p, size_t sz) +{ + const octet *q = p; + if (!sz) + return; + for (;;) { + fprintf(fp, "%02x", *q++); + sz--; + if (!sz) + break; + } +} + +/*----- Signature generation ----------------------------------------------*/ + +static int sign(int argc, char *argv[]) +{ +#define f_bogus 1u +#define f_bin 2u +#define f_nocheck 4u + + unsigned f = 0; + const char *ki = "dsig"; + key_file kf; + key *k; + sig *s; + fhashstate fh; + time_t exp = KEXP_EXPIRE; + unsigned verb = 0; + const char *ifile = 0, *hfile = 0; + const char *ofile = 0; + const char *c = 0; + const char *err; + FILE *ifp, *ofp; + dstr d = DSTR_INIT; + hfpctx hfp; + block b; + int e, hf, n; + + for (;;) { + static struct option opts[] = { + { "null", 0, 0, '0' }, + { "binary", 0, 0, 'b' }, + { "verbose", 0, 0, 'v' }, + { "progress", 0, 0, 'p' }, + { "quiet", 0, 0, 'q' }, + { "comment", OPTF_ARGREQ, 0, 'c' }, + { "file", OPTF_ARGREQ, 0, 'f' }, + { "hashes", OPTF_ARGREQ, 0, 'h' }, + { "output", OPTF_ARGREQ, 0, 'o' }, + { "key", OPTF_ARGREQ, 0, 'k' }, + { "expire", OPTF_ARGREQ, 0, 'e' }, + { "nocheck", OPTF_ARGREQ, 0, 'C' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+0vpqbC" "c:" "f:h:o:" "k:e:", + opts, 0, 0, 0); + if (i < 0) + break; + switch (i) { + case '0': + f |= GSF_RAW; + break; + case 'b': + f |= f_bin; + break; + case 'v': + verb++; + break; + case 'p': + f |= FHF_PROGRESS; + break; + case 'q': + if (verb > 0) + verb--; + break; + case 'C': + f |= f_nocheck; + break; + case 'c': + c = optarg; + break; + case 'f': + ifile = optarg; + break; + case 'h': + hfile = optarg; + break; + case 'o': + ofile = optarg; + break; + case 'k': + ki = optarg; + break; + case 'e': + if (strcmp(optarg, "forever") == 0) + exp = KEXP_FOREVER; + else if ((exp = get_date(optarg, 0)) == -1) + die(EXIT_FAILURE, "bad expiry time"); + break; + default: + f |= f_bogus; + break; + } + } + if (optind != argc || (f & f_bogus)) + die(EXIT_FAILURE, "Usage: sign [-OPTIONS]"); + if (hfile && ifile) + die(EXIT_FAILURE, "Inconsistent options `-h' and `-f'"); + + /* --- Locate the signing key --- */ + + if (key_open(&kf, keyring, KOPEN_WRITE, key_moan, 0)) + die(EXIT_FAILURE, "couldn't open keyring `%s'", keyring); + if ((k = key_bytag(&kf, ki)) == 0) + die(EXIT_FAILURE, "couldn't find key `%s'", ki); + key_fulltag(k, &d); + if (exp == KEXP_FOREVER && k->exp != KEXP_FOREVER) { + die(EXIT_FAILURE, "key `%s' expires: can't create nonexpiring signature", + d.buf); + } + s = getsig(k, "dsig", 1); + + /* --- Check the key --- */ + + if (!(f & f_nocheck) && (err = s->ops->check(s)) != 0) + moan("key `%s' fails check: %s", d.buf, err); + + /* --- Open files --- */ + + if (hfile) ifile = hfile; + if (!ifile || strcmp(ifile, "-") == 0) + ifp = stdin; + else if ((ifp = fopen(ifile, (f & f_bin) ? "rb" : "r")) == 0) { + die(EXIT_FAILURE, "couldn't open input file `%s': %s", + ifile, strerror(errno)); + } + + if (!ofile || strcmp(ofile, "-") == 0) + ofp = stdout; + else if ((ofp = fopen(ofile, (f & f_bin) ? "wb" : "w")) == 0) { + die(EXIT_FAILURE, "couldn't open output file `%s': %s", + ofile, strerror(errno)); + } + + /* --- Emit the start of the output --- */ + + binit(&b); b.tag = T_IDENT; + dstr_putf(&b.d, "%s, Catacomb version " VERSION, QUIS); + bemit(&b, ofp, 0, f & f_bin); + + breset(&b); b.tag = T_KEYID; b.k = k->id; + bemit(&b, ofp, 0, f & f_bin); + + /* --- Start hashing, and emit the datestamps and things --- */ + + { + time_t now = time(0); + + breset(&b); b.tag = T_DATE; b.t = now; bemit(&b, ofp, s->h, f & f_bin); + if (exp == KEXP_EXPIRE) + exp = now + 86400 * 28; + breset(&b); b.tag = T_EXPIRE; b.t = exp; bemit(&b, ofp, s->h, f & f_bin); + if (c) { + breset(&b); b.tag = T_COMMENT; DPUTS(&b.d, c); + bemit(&b, ofp, s->h, f & f_bin); + } + + if (!(f & f_bin)) + putc('\n', ofp); + } + + /* --- Now hash the various files --- */ + + if (hfile) { + hfp.f = f; + hfp.fp = ifp; + hfp.ee = &encodingtab[ENC_HEX]; + hfp.gch = GH_CLASS(s->h); + hfp.dline = &d; + hfp.dfile = &b.d; + + n = 0; + for (;;) { + breset(&b); + DENSURE(&b.b, hfp.gch->hashsz); + hfp.hbuf = (octet *)b.b.buf; + if (ferror(ofp)) { f |= f_bogus; break; } + if ((hf = hfparse(&hfp)) == HF_EOF) break; + n++; + + switch (hf) { + case HF_HASH: + if (hfp.gch != GH_CLASS(s->h)) { + moan("%s:%d: incorrect hash function `%s' (should be `%s')", + hfile, n, hfp.gch->name, GH_CLASS(s->h)->name); + f |= f_bogus; + } + break; + case HF_BAD: + moan("%s:%d: invalid hash-file line", hfile, n); + f |= f_bogus; + break; + case HF_FILE: + b.tag = T_FILE; + b.b.len += hfp.gch->hashsz; + bemit(&b, ofp, s->h, f & f_bin); + break; + } + } + } else { + for (;;) { + + /* --- Stop on an output error --- */ + + if (ferror(ofp)) { + f |= f_bogus; + break; + } + + /* --- Read the next filename to hash --- */ + + fhash_init(&fh, GH_CLASS(s->h), f | FHF_BINARY); + breset(&b); + if (getstring(ifp, &b.d, GSF_FILE | f)) + break; + b.tag = T_FILE; + DENSURE(&b.b, GH_CLASS(s->h)->hashsz); + if (fhash(&fh, b.d.buf, b.b.buf)) { + moan("error reading `%s': %s", b.d.buf, strerror(errno)); + f |= f_bogus; + } else { + b.b.len += GH_CLASS(s->h)->hashsz; + if (verb) { + fhex(stderr, b.b.buf, b.b.len); + fprintf(stderr, " %s\n", b.d.buf); + } + bemit(&b, ofp, s->h, f & f_bin); + } + fhash_free(&fh); + } + } + + /* --- Create the signature --- */ + + if (!(f & f_bogus)) { + breset(&b); + b.tag = T_SIGNATURE; + if ((e = s->ops->doit(s, &b.b)) != 0) { + moan("error creating signature: %s", key_strerror(e)); + f |= f_bogus; + } + if (!(f & f_bogus)) { + bemit(&b, ofp, 0, f & f_bin); + key_used(&kf, k, exp); + } + } + + /* --- Tidy up at the end --- */ + + freesig(s); + bdestroy(&b); + if (ifile) + fclose(ifp); + if (ofile) { + if (fclose(ofp)) + f |= f_bogus; + } else { + if (fflush(ofp)) + f |= f_bogus; + } + if ((e = key_close(&kf)) != 0) { + switch (e) { + case KWRITE_FAIL: + die(EXIT_FAILURE, "couldn't write file `%s': %s", + keyring, strerror(errno)); + case KWRITE_BROKEN: + die(EXIT_FAILURE, "keyring file `%s' broken: %s (repair manually)", + keyring, strerror(errno)); + } + } + if (f & f_bogus) + die(EXIT_FAILURE, "error(s) occurred while creating signature"); + return (EXIT_SUCCESS); + +#undef f_bin +#undef f_bogus +#undef f_nocheck +} + +/*----- Signature verification --------------------------------------------*/ + +static int checkjunk(const char *path, const struct stat *st, void *p) +{ + if (!st) printf("JUNK (error %s) %s\n", strerror(errno), path); + else printf("JUNK %s %s\n", describefile(st), path); + return (0); +} + +static int verify(int argc, char *argv[]) +{ +#define f_bogus 1u +#define f_bin 2u +#define f_ok 4u +#define f_nocheck 8u + + unsigned f = 0; + unsigned verb = 1; + key_file kf; + key *k = 0; + sig *s; + dstr d = DSTR_INIT; + const char *err; + fhashstate fh; + FILE *fp; + block b; + int e; + + /* --- Parse the options --- */ + + for (;;) { + static struct option opts[] = { + { "verbose", 0, 0, 'v' }, + { "progress", 0, 0, 'p' }, + { "quiet", 0, 0, 'q' }, + { "nocheck", 0, 0, 'C' }, + { "junk", 0, 0, 'j' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+vpqCj", opts, 0, 0, 0); + if (i < 0) + break; + switch (i) { + case 'v': + verb++; + break; + case 'p': + f |= FHF_PROGRESS; + break; + case 'q': + if (verb) + verb--; + break; + case 'C': + f |= f_nocheck; + break; + case 'j': + f |= FHF_JUNK; + break; + default: + f |= f_bogus; + break; + } + } + argc -= optind; + argv += optind; + if ((f & f_bogus) || argc > 1) + die(EXIT_FAILURE, "Usage: verify [-qvC] [FILE]"); + + /* --- Open the key file, and start reading the input file --- */ + + if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0)) + die(EXIT_FAILURE, "couldn't open keyring `%s'\n", keyring); + if (argc < 1) + fp = stdin; + else { + if ((fp = fopen(argv[0], "rb")) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s': %s\n", + argv[0], strerror(errno)); + } + if (getc(fp) == 0) { + ungetc(0, fp); + f |= f_bin; + } else { + fclose(fp); + if ((fp = fopen(argv[0], "r")) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s': %s\n", + argv[0], strerror(errno)); + } + } + } + + /* --- Read the introductory matter --- */ + + binit(&b); + for (;;) { + breset(&b); + e = bget(&b, fp, f & f_bin); + if (e < 0) + die(EXIT_FAILURE, "error reading packet: %s", errtab[-e]); + if (e >= T_BEGIN) + break; + switch (e) { + case T_IDENT: + if (verb > 2) + printf("INFO ident: `%s'\n", b.d.buf); + break; + case T_KEYID: + if ((k = key_byid(&kf, b.k)) == 0) { + if (verb) + printf("FAIL key %08lx not found\n", (unsigned long)b.k); + exit(EXIT_FAILURE); + } + if (verb > 2) { + DRESET(&b.d); + key_fulltag(k, &b.d); + printf("INFO key: %s\n", b.d.buf); + } + break; + default: + die(EXIT_FAILURE, "(internal) unknown packet type\n"); + break; + } + } + + /* --- Initialize the hash function and start reading hashed packets --- */ + + if (!k) { + if (verb) + puts("FAIL no keyid packet found"); + exit(EXIT_FAILURE); + } + + s = getsig(k, "dsig", 0); + if (!(f & f_nocheck) && verb && (err = s->ops->check(s)) != 0) + printf("WARN public key fails check: %s", err); + + fhash_init(&fh, GH_CLASS(s->h), f | FHF_BINARY); + for (;;) { + switch (e) { + case T_COMMENT: + if (verb > 1) + printf("INFO comment: `%s'\n", b.d.buf); + bemit(&b, 0, s->h, 0); + break; + case T_DATE: + if (verb > 2) { + DRESET(&b.d); + timestring(b.t, &b.d); + printf("INFO date: %s\n", b.d.buf); + } + bemit(&b, 0, s->h, 0); + break; + case T_EXPIRE: { + time_t now = time(0); + if (b.t != KEXP_FOREVER && b.t < now) { + if (verb > 1) + puts("BAD signature has expired"); + f |= f_bogus; + } + if (verb > 2) { + DRESET(&b.d); + timestring(b.t, &b.d); + printf("INFO expires: %s\n", b.d.buf); + } + bemit(&b, 0, s->h, 0); + } break; + case T_FILE: + DRESET(&d); + DENSURE(&d, GH_CLASS(s->h)->hashsz); + if (fhash(&fh, b.d.buf, d.buf)) { + if (verb > 1) { + printf("BAD error reading file `%s': %s\n", + b.d.buf, strerror(errno)); + } + f |= f_bogus; + } else if (b.b.len != GH_CLASS(s->h)->hashsz || + memcmp(d.buf, b.b.buf, b.b.len) != 0) { + if (verb > 1) + printf("BAD file `%s' has incorrect hash\n", b.d.buf); + f |= f_bogus; + } else if (verb > 3) { + fputs("INFO hash: ", stdout); + fhex(stdout, b.b.buf, b.b.len); + printf(" %s\n", b.d.buf); + } + bemit(&b, 0, s->h, 0); + break; + case T_SIGNATURE: + if (s->ops->doit(s, &b.b)) { + if (verb > 1) + puts("BAD bad signature"); + f |= f_bogus; + } else if (verb > 2) + puts("INFO good signature"); + goto done; + default: + if (verb) + printf("FAIL invalid packet type %i\n", e); + exit(EXIT_FAILURE); + break; + } + breset(&b); + e = bget(&b, fp, f & f_bin); + if (e < 0) { + if (verb) + printf("FAIL error reading packet: %s\n", errtab[-e]); + exit(EXIT_FAILURE); + } + } +done: + if ((f & FHF_JUNK) && fhash_junk(&fh, checkjunk, 0)) + f |= f_bogus; + fhash_free(&fh); + bdestroy(&b); + dstr_destroy(&d); + freesig(s); + key_close(&kf); + if (fp != stdin) + fclose(fp); + if (verb) { + if (f & f_bogus) + puts("FAIL signature invalid"); + else + puts("OK signature verified"); + } + return (f & f_bogus ? EXIT_FAILURE : EXIT_SUCCESS); + +#undef f_bogus +#undef f_bin +#undef f_ok +#undef f_nocheck +} + +/*----- Main code ---------------------------------------------------------*/ + +#define LISTS(LI) \ + LI("Lists", list, \ + listtab[i].name, listtab[i].name) \ + LI("Signature schemes", sig, \ + sigtab[i].name, sigtab[i].name) \ + LI("Hash functions", hash, \ + ghashtab[i], ghashtab[i]->name) + +MAKELISTTAB(listtab, LISTS) + +int cmd_show(int argc, char *argv[]) +{ + return (displaylists(listtab, argv + 1)); +} + +static int cmd_help(int, char **); + +static cmd cmdtab[] = { + { "help", cmd_help, "help [COMMAND...]" }, + { "show", cmd_show, "show [ITEM...]" }, + { "sign", sign, + "sign [-0bpqvC] [-c COMMENT] [-k TAG] [-e EXPIRE]\n\t\ +[-f FILE] [-h FILE] [-o OUTPUT]", + "\ +Options:\n\ +\n\ +-0, --null Read null-terminated filenames from stdin.\n\ +-b, --binary Produce a binary output file.\n\ +-q, --quiet Produce fewer messages while working.\n\ +-v, --verbose Produce more messages while working.\n\ +-p, --progress Show progress on large files.\n\ +-C, --nocheck Don't check the private key.\n\ +-c, --comment=COMMENT Include COMMENT in the output file.\n\ +-f, --file=FILE Read filenames to hash from FILE.\n\ +-h, --hashes=FILE Read precomputed hashes from FILE.\n\ +-o, --output=FILE Write the signed result to FILE.\n\ +-k, --key=TAG Use a key named by TAG.\n\ +-e, --expire=TIME The signature should expire after TIME.\n\ +" }, + { "verify", verify, + "verify [-pqvC] [FILE]", "\ +Options:\n\ +\n\ +-q, --quiet Produce fewer messages while working.\n\ +-v, --verbose Produce more messages while working.\n\ +-p, --progress Show progress on large files.\n\ +-C, --nocheck Don't check the public key.\n\ +" }, + { 0, 0, 0 } +}; + +static int cmd_help(int argc, char **argv) +{ + sc_help(cmdtab, stdout, argv + 1); + return (0); +} + +void version(FILE *fp) +{ + pquis(fp, "$, Catacomb version " VERSION "\n"); +} + +static void usage(FILE *fp) +{ + pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n"); +} + +void help_global(FILE *fp) +{ + usage(fp); + fputs("\n\ +Create and verify signatures on lists of files.\n\ +\n\ +Global command-line options:\n\ +\n\ +-h, --help [COMMAND...] Show this help message, or help for COMMANDs.\n\ +-v, --version Show program version number.\n\ +-u, --usage Show a terse usage message.\n\ +\n\ +-k, --keyring=FILE Read keys from FILE.\n", + fp); +} + +/* --- @main@ --- * + * + * Arguments: @int argc@ = number of command line arguments + * @char *argv[]@ = vector of command line arguments + * + * Returns: Zero if successful, nonzero otherwise. + * + * Use: Signs or verifies signatures on lists of files. Useful for + * ensuring that a distribution is unmolested. + */ + +int main(int argc, char *argv[]) +{ + unsigned f = 0; + +#define f_bogus 1u + + /* --- Initialize the library --- */ + + ego(argv[0]); + sub_init(); + rand_noisesrc(RAND_GLOBAL, &noise_source); + rand_seed(RAND_GLOBAL, 160); + + /* --- Parse options --- */ + + for (;;) { + static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "usage", 0, 0, 'u' }, + { "keyring", OPTF_ARGREQ, 0, 'k' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+hvu k:", opts, 0, 0, 0); + if (i < 0) + break; + switch (i) { + case 'h': + sc_help(cmdtab, stdout, argv + optind); + exit(0); + break; + case 'v': + version(stdout); + exit(0); + break; + case 'u': + usage(stdout); + exit(0); + case 'k': + keyring = optarg; + break; + default: + f |= f_bogus; + break; + } + } + + argc -= optind; + argv += optind; + optind = 0; + if (f & f_bogus || argc < 1) { + usage(stderr); + exit(EXIT_FAILURE); + } + + /* --- Dispatch to the correct subcommand handler --- */ + + return (findcmd(cmdtab, argv[0])->cmd(argc, argv)); + +#undef f_bogus +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/progs/factorial.c b/progs/factorial.c new file mode 100644 index 0000000..a46debd --- /dev/null +++ b/progs/factorial.c @@ -0,0 +1,150 @@ +/* -*-c-*- + * + * Example factorial computation + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "config.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include "mpint.h" +#include "mpmul.h" +#include "mptext.h" + +/*----- Main code ---------------------------------------------------------*/ + +static void usage(FILE *fp) +{ + pquis(fp, "Usage: $ [-r RADIX] INTEGER\n"); +} + +static void version(FILE *fp) +{ + pquis(fp, "$, Catacomb version " VERSION "\n"); +} + +static void help(FILE *fp) +{ + version(fp); + putc('\n', fp); + usage(fp); + fputs("\n\ +Prints the factorial of the given integer on its output. Input may be\n\ +in decimal (the default), octal with preceding zero, hex with preceding\n\ +`0x', or any base N between 2 and 62 inclusive with preceding `N_'.\n\ +Output may be in any base between 2 and 62; the default is base 10. For\n\ +bases between 11 and 36 inclusive, lowercase letters of either case are\n\ +used as additional digits with values 10 upwards; lowercase is always\n\ +used for output. For bases between 37 and 62 inclusive, lowercase letters\n\ +have lower value than uppercase; hence `a' has the value 10, while `A' has\n\ +the value 36.\n\ +\n\ +Options provided:\n\ +\n\ +-h, --help Display this help message.\n\ +-v, --version Display the version number.\n\ +-u, --usage Display a usage message.\n\ +\n\ +-r, --radix=N Write output in base N.\n\ +", fp); +} + +int main(int argc, char *argv[]) +{ + unsigned long x; + int r = 10; + char *p; + mp *f, *ulmax, *xx; + unsigned fl = 0; + +#define f_bogus 1u + + ego(argv[0]); + + for (;;) { + static const struct option opt[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "usage", 0, 0, 'u' }, + { "radix", OPTF_ARGREQ, 0, 'r' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "hvur:", opt, 0, 0, 0); + if (i < 0) + break; + switch (i) { + case 'h': + help(stdout); + exit(0); + case 'v': + version(stdout); + exit(0); + case 'u': + usage(stdout); + exit(0); + case 'r': + r = atoi(optarg); + if (r < 2 || r > 62) + die(EXIT_FAILURE, "bad radix `%s'", optarg); + break; + default: + fl |= f_bogus; + break; + } + } + + if (optind + 1 != argc || (fl & f_bogus)) { + usage(stderr); + exit(EXIT_FAILURE); + } + ulmax = mp_fromulong(MP_NEW, ULONG_MAX); + p = argv[optind]; + while (isspace((unsigned char)*p)) + p++; + xx = mp_readstring(MP_NEW, argv[optind], &p, 0); + while (isspace((unsigned char)*p)) + p++; + if (!xx || *p || MP_CMP(xx, >, ulmax)) + die(EXIT_FAILURE, "bad integer `%s'", argv[optind]); + x = mp_toulong(xx); + mp_drop(xx); + mp_drop(ulmax); + f = mp_factorial(x); + mp_writefile(f, stdout, r); + fputc('\n', stdout); + mp_drop(f); + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/fibonacci.c b/progs/fibonacci.c similarity index 100% rename from fibonacci.c rename to progs/fibonacci.c diff --git a/hashsum.1 b/progs/hashsum.1 similarity index 100% rename from hashsum.1 rename to progs/hashsum.1 diff --git a/progs/hashsum.c b/progs/hashsum.c new file mode 100644 index 0000000..8cc1926 --- /dev/null +++ b/progs/hashsum.c @@ -0,0 +1,410 @@ +/* -*-c-*- + * + * Hash files using some secure hash function + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _FILE_OFFSET_BITS 64 + +#include "config.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ghash.h" +#include "cc.h" + +/*----- Static variables --------------------------------------------------*/ + +#define f_bogus 1u +#define f_verbose 2u +#define f_check 4u +#define f_files 8u +#define f_oddhash 16u +#define f_escape 32u +#define f_oddenc 64u + +/*----- Guts --------------------------------------------------------------*/ + +static int checkjunk(const char *path, const struct stat *st, void *p) +{ + const char *what; + fhashstate *fh = p; + + if (!st) { + if (fh->f & f_verbose) + fprintf(stderr, "JUNK (error %s) %s\n", strerror(errno), path); + else + moan("couldn't stat junk file `%s': %s", path, strerror(errno)); + } else { + what = describefile(st); + if (fh->f & f_verbose) + fprintf(stderr, "JUNK %s %s\n", what, path); + else + moan("found junk %s `%s'", what, path); + } + return (0); +} + +static int warnjunk(const char *path, const struct stat *st, void *p) +{ + if (st) + moan("unexpected %s `%s'", describefile(st), path); + else + moan("couldn't stat unexpected file `%s': %s", path, strerror(errno)); + return (0); +} + +static int checkhash(fhashstate *fh, const char *file, const encodeops *e) +{ + int rc; + hfpctx hfp; + dstr dl = DSTR_INIT; + dstr df = DSTR_INIT; + unsigned long n = 0, nfail = 0; + int hf; + + if (!file || strcmp(file, "-") == 0) + hfp.fp = stdin; + else if ((hfp.fp = fopen(file, fh->f & GSF_RAW ? "r" : "rb")) == 0) { + moan("couldn't open `%s': %s", file, strerror(errno)); + return (EXIT_FAILURE); + } + + hfp.dline = &dl; + hfp.dfile = &df; + hfp.hbuf = xmalloc(2 * fh->gch->hashsz); + hfp.gch = fh->gch; + hfp.ee = e; + hfp.f = fh->f; + + while ((hf = hfparse(&hfp)) != HF_EOF) { + switch (hf) { + case HF_HASH: + xfree(hfp.hbuf); + hfp.hbuf = xmalloc(2 * hfp.gch->hashsz); + break; + case HF_FILE: + if (fhash(fh, df.buf, hfp.hbuf + hfp.gch->hashsz)) { + moan("couldn't read `%s': %s", df.buf, strerror(errno)); + rc = EXIT_FAILURE; + continue; + } + if (memcmp(hfp.hbuf, hfp.hbuf + hfp.gch->hashsz, + hfp.gch->hashsz) != 0) { + if (hfp.f & f_verbose) + fprintf(stderr, "FAIL %s\n", df.buf); + else + moan("%s check failed for `%s'", hfp.gch->name, df.buf); + nfail++; + rc = EXIT_FAILURE; + } else { + if (hfp.f & f_verbose) + fprintf(stderr, "OK %s\n", df.buf); + } + n++; + } + } + + if (ferror(hfp.fp)) { + moan("error reading input `%s': %s", + file ? file : "", strerror(errno)); + rc = EXIT_FAILURE; + } + dstr_destroy(&dl); + dstr_destroy(&df); + xfree(hfp.hbuf); + if ((fh->f & f_verbose) && nfail) + moan("%lu of %lu file(s) failed %s check", nfail, n, hfp.gch->name); + else if (!n) + moan("no files checked"); + return (rc); +} + +static int dohash(fhashstate *fh, const char *file, const encodeops *e) +{ + int rc = 0; + octet *p = xmalloc(fh->gch->hashsz); + + if (fhash(fh, file, p)) { + moan("couldn't read `%s': %s", file ? file : "", strerror(errno)); + rc = EXIT_FAILURE; + } else { + e->put(p, fh->gch->hashsz, stdout); + if (file) { + fputc(' ', stdout); + fputc(fh->f & FHF_BINARY ? '*' : ' ', stdout); + if (fh->f & f_escape) + putstring(stdout, file, 0); + else + fputs(file, stdout); + } + fputc('\n', stdout); + } + + xfree(p); + return (rc); +} + +static int dofile(fhashstate *fh, const char *file, const encodeops *e) + { return (fh->f & f_check ? checkhash : dohash)(fh, file, e); } + +static int hashfiles(fhashstate *fh, const char *file, const encodeops *e) +{ + FILE *fp; + dstr d = DSTR_INIT; + int rc = 0; + int rrc; + + if (!file || strcmp(file, "-") == 0) + fp = stdin; + else if ((fp = fopen(file, fh->f & GSF_RAW ? "r" : "rb")) == 0) { + moan("couldn't open `%s': %s", file, strerror(errno)); + return (EXIT_FAILURE); + } + + for (;;) { + DRESET(&d); + if (getstring(fp, &d, GSF_FILE | fh->f)) + break; + if ((rrc = dofile(fh, d.buf, e)) != 0) + rc = rrc; + } + + return (rc); +} + +static int hashsum(fhashstate *fh, const char *file, const encodeops *e) + { return (fh->f & f_files ? hashfiles : dofile)(fh, file, e); } + +/*----- Main driver -------------------------------------------------------*/ + +void version(FILE *fp) +{ + pquis(fp, "$, Catacomb version " VERSION "\n"); +} + +static void usage(FILE *fp) +{ + pquis(fp, "Usage: $ [-f0ebcv] [-a ALGORITHM] [-E ENC] [FILES...]\n"); +} + +static void help(FILE *fp, const gchash *gch) +{ + version(fp); + fputc('\n', fp); + usage(fp); + pquis(fp, "\n\ +Generates or checks message digests on files. Options available:\n\ +\n\ +-h, --help Display this help message.\n\ +-V, --version Display program's version number.\n\ +-u, --usage Display a terse usage message.\n\ +-l, --list [ITEM...] Show known hash functions and/or encodings.\n\ +\n\ +-a, --algorithm=ALG Use the message digest algorithm ALG.\n\ +-E, --encoding=ENC Represent hashes using encoding ENC.\n\ +\n\ +-f, --files Read a list of file names from standard input.\n\ +-0, --null File names are null terminated, not plain text.\n\ +\n\ +-e, --escape Escape funny characters in filenames.\n\ +-c, --check Check message digests rather than emitting them.\n\ +-b, --binary When reading files, treat them as binary.\n\ +-p, --progress Show a progress indicator for large files.\n\ +-v, --verbose Be verbose when checking digests.\n\ +\n\ +For a list of hashing algorithms and encodings, type `$ --list'.\n\ +"); + if (gch) + fprintf(fp, "The default message digest algorithm is %s.\n", gch->name); +} + +#define LISTS(LI) \ + LI("Lists", list, listtab[i].name, listtab[i].name) \ + LI("Hash functions", hash, ghashtab[i], ghashtab[i]->name) \ + LI("Encodings", enc, encodingtab[i].name, encodingtab[i].name) + +MAKELISTTAB(listtab, LISTS) + +int main(int argc, char *argv[]) +{ + fhashstate fh; + const encodeops *e = &encodingtab[ENC_HEX]; + int rc; + + /* --- Initialization --- */ + + ego(argv[0]); + sub_init(); + fhash_init(&fh, 0, 0); + + /* --- Choose a hash function from the name --- */ + + { + char *q = xstrdup(QUIS); + size_t len = strlen(q); + if (len > 3 && strcmp(q + len - 3, "sum") == 0) { + q[len - 3] = 0; + fh.gch = gethash(q); + } + if (!fh.gch) + fh.gch = gethash("md5"); + xfree(q); + } + + /* --- Read options --- */ + + for (;;) { + static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "verbose", 0, 0, 'V' }, + { "usage", 0, 0, 'u' }, + + { "algorithm", OPTF_ARGREQ, 0, 'a' }, + { "hash", OPTF_ARGREQ, 0, 'a' }, + { "encoding", OPTF_ARGREQ, 0, 'E' }, + { "list", 0, 0, 'l' }, + + { "files", 0, 0, 'f' }, + { "find", 0, 0, 'f' }, + { "null", 0, 0, '0' }, + + { "escape", 0, 0, 'e' }, + { "check", 0, 0, 'c' }, + { "junk", 0, 0, 'j' }, + { "binary", 0, 0, 'b' }, + { "verbose", 0, 0, 'v' }, + { "progress", 0, 0, 'p' }, + + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "hVu a:E:l f0 ecjbvp", opts, 0, 0, 0); + if (i < 0) + break; + + switch (i) { + case 'h': + help(stdout, fh.gch); + exit(0); + case 'V': + version(stdout); + exit(0); + case 'u': + usage(stdout); + exit(0); + case 'l': + exit(displaylists(listtab, argv + optind)); + case 'a': + if ((fh.gch = gethash(optarg)) == 0) + die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg); + fh.f |= f_oddhash; + break; + case 'E': + if ((e = getencoding(optarg)) == 0) + die(EXIT_FAILURE, "unknown encoding `%s'", optarg); + fh.f |= f_oddenc; + break; + case 'f': + fh.f |= f_files; + break; + case '0': + fh.f |= GSF_RAW; + break; + case 'e': + fh.f |= f_escape; + break; + case 'c': + fh.f |= f_check; + break; + case 'j': + fh.f |= FHF_JUNK; + break; + case 'b': + fh.f |= FHF_BINARY; + break; + case 'v': + fh.f |= f_verbose; + break; + case 'p': + fh.f |= FHF_PROGRESS; + break; + default: + fh.f |= f_bogus; + break; + } + } + + if (fh.f & f_bogus) { + usage(stderr); + exit(EXIT_FAILURE); + } + argv += optind; + argc -= optind; + + /* --- Generate output --- */ + + if (!(fh.f & f_check) && (argc || (fh.f & f_files))) { + if (fh.f & f_oddhash) printf("#hash %s\n", fh.gch->name); + if (fh.f & f_oddenc) printf("#encoding %s\n", e->name); + if (fh.f & f_escape) fputs("#escape\n", stdout); + } + if (!argc) + rc = hashsum(&fh, 0, e); + else { + int i; + int rrc; + + rc = 0; + for (i = 0; i < argc; i++) { + if ((rrc = hashsum(&fh, argv[i], e)) != 0) + rc = rrc; + } + } + + if (fh.f & FHF_JUNK) { + if (fh.f & f_check) { + if (fhash_junk(&fh, checkjunk, &fh)) rc = EXIT_FAILURE; + } else { + if (fhash_junk(&fh, warnjunk, 0) < 0) rc = EXIT_FAILURE; + } + } + fhash_free(&fh); + + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/key.1 b/progs/key.1 similarity index 100% rename from key.1 rename to progs/key.1 diff --git a/progs/key.c b/progs/key.c new file mode 100644 index 0000000..f263aaf --- /dev/null +++ b/progs/key.c @@ -0,0 +1,2306 @@ +/* -*-c-*- + * + * Simple key manager program + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _FILE_OFFSET_BITS 64 + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "bintab.h" +#include "bbs.h" +#include "dh.h" +#include "dsa.h" +#include "dsarand.h" +#include "ec.h" +#include "ec-keys.h" +#include "ectab.h" +#include "fibrand.h" +#include "getdate.h" +#include "gfreduce.h" +#include "key.h" +#include "mp.h" +#include "mpmont.h" +#include "mprand.h" +#include "mptext.h" +#include "pgen.h" +#include "ptab.h" +#include "rsa.h" + +#include "cc.h" +#include "sha-mgf.h" +#include "sha256-mgf.h" +#include "sha224-mgf.h" +#include "sha384-mgf.h" +#include "sha512-mgf.h" +#include "tiger-mgf.h" +#include "rmd128-mgf.h" +#include "rmd160-mgf.h" +#include "rmd256-mgf.h" +#include "rmd320-mgf.h" +#include "md5-mgf.h" +#include "dsarand.h" + +/*----- Handy global state ------------------------------------------------*/ + +static const char *keyfile = "keyring"; + +/*----- Useful shared functions -------------------------------------------*/ + +/* --- @doopen@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * @unsigned how@ = method to open file with + * + * Returns: --- + * + * Use: Opens a key file and handles errors by panicking + * appropriately. + */ + +static void doopen(key_file *f, unsigned how) +{ + if (key_open(f, keyfile, how, key_moan, 0)) + die(1, "couldn't open keyring `%s': %s", keyfile, strerror(errno)); +} + +/* --- @doclose@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * + * Returns: --- + * + * Use: Closes a key file and handles errors by panicking + * appropriately. + */ + +static void doclose(key_file *f) +{ + switch (key_close(f)) { + case KWRITE_FAIL: + die(EXIT_FAILURE, "couldn't write file `%s': %s", + keyfile, strerror(errno)); + case KWRITE_BROKEN: + die(EXIT_FAILURE, "keyring file `%s' broken: %s (repair manually)", + keyfile, strerror(errno)); + } +} + +/* --- @setattr@ --- * + * + * Arguments: @key_file *f@ = pointer to key file block + * @key *k@ = pointer to key block + * @char *v[]@ = array of assignments (overwritten!) + * + * Returns: --- + * + * Use: Applies the attribute assignments to the key. + */ + +static void setattr(key_file *f, key *k, char *v[]) +{ + while (*v) { + int err; + char *p = *v; + size_t eq = strcspn(p, "="); + if (!p[eq]) { + moan("invalid assignment: `%s' (ignored)", p); + v++; + continue; + } + p[eq] = 0; + p += eq + 1; + if ((err = key_putattr(f, k, *v, *p ? p : 0)) != 0) + die(EXIT_FAILURE, "couldn't set attributes: %s", key_strerror(err)); + v++; + } +} + +/*----- Seeding -----------------------------------------------------------*/ + +const struct seedalg { const char *p; grand *(*gen)(const void *, size_t); } +seedtab[] = { + { "dsarand", dsarand_create }, + { "rmd128-mgf", rmd128_mgfrand }, + { "rmd160-mgf", rmd160_mgfrand }, + { "rmd256-mgf", rmd256_mgfrand }, + { "rmd320-mgf", rmd320_mgfrand }, + { "sha-mgf", sha_mgfrand }, + { "sha224-mgf", sha224_mgfrand }, + { "sha256-mgf", sha256_mgfrand }, + { "sha384-mgf", sha384_mgfrand }, + { "sha512-mgf", sha512_mgfrand }, + { "tiger-mgf", tiger_mgfrand }, + { 0, 0 } +}; + +#define SEEDALG_DEFAULT (seedtab + 2) + +/*----- Key generation ----------------------------------------------------*/ + +/* --- Key generation parameters --- */ + +typedef struct keyopts { + key_file *kf; /* Pointer to key file */ + key *k; /* Pointer to the actual key */ + dstr tag; /* Full tag name for the key */ + unsigned f; /* Flags for the new key */ + unsigned bits, qbits; /* Bit length for the new key */ + const char *curve; /* Elliptic curve name/info */ + grand *r; /* Random number source */ + key *p; /* Parameters key-data */ +} keyopts; + +#define f_bogus 1u /* Error in parsing */ +#define f_lock 2u /* Passphrase-lock private key */ +#define f_quiet 4u /* Don't show a progress indicator */ +#define f_limlee 8u /* Generate Lim-Lee primes */ +#define f_subgroup 16u /* Generate a subgroup */ +#define f_retag 32u /* Remove any existing tag */ +#define f_kcdsa 64u /* Generate KCDSA primes */ + +/* --- @dolock@ --- * + * + * Arguments: @keyopts *k@ = key generation options + * @key_data **kd@ = pointer to key data to lock + * @const char *t@ = tag suffix or null + * + * Returns: --- + * + * Use: Does passphrase locking on new keys. + */ + +static void dolock(keyopts *k, key_data **kd, const char *t) +{ + if (!(k->f & f_lock)) + return; + if (t) + dstr_putf(&k->tag, ".%s", t); + if (key_plock(kd, 0, k->tag.buf)) + die(EXIT_FAILURE, "couldn't lock key"); +} + +/* --- @copyparam@ --- * + * + * Arguments: @keyopts *k@ = pointer to key options + * @const char **pp@ = checklist of parameters + * + * Returns: Nonzero if parameters copied; zero if you have to generate + * them. + * + * Use: Copies parameters from a source key to the current one. + */ + +static int copyparam(keyopts *k, const char **pp) +{ + key_filter kf; + key_attriter i; + key_data *kd; + const char *n, *v; + + kf.f = KCAT_SHARE; + kf.m = KF_CATMASK; + + /* --- Quick check if no parameters supplied --- */ + + if (!k->p) + return (0); + + /* --- Run through the checklist --- */ + + while (*pp) { + key_data *kd = key_structfind(k->p->k, *pp); + if (!kd) + die(EXIT_FAILURE, "bad parameter key: parameter `%s' not found", *pp); + if (!KEY_MATCH(kd, &kf)) + die(EXIT_FAILURE, "bad parameter key: subkey `%s' is not shared", *pp); + pp++; + } + + /* --- Copy over the parameters --- */ + + kd = key_copydata(k->p->k, &kf); + assert(kd); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); + + /* --- Copy over attributes --- */ + + for (key_mkattriter(&i, k->p); key_nextattr(&i, &n, &v); ) + key_putattr(k->kf, k->k, n, v); + + /* --- Done --- */ + + return (1); +} + +/* --- @getmp@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @const char *tag@ = tag string to use + * + * Returns: Pointer to multiprecision integer key item. + * + * Use: Fetches an MP key component. + */ + +static mp *getmp(key_data *k, const char *tag) +{ + k = key_structfind(k, tag); + if (!k) + die(EXIT_FAILURE, "unexpected failure looking up subkey `%s'", tag); + if ((k->e & KF_ENCMASK) != KENC_MP) + die(EXIT_FAILURE, "subkey `%s' has an incompatible type"); + return (k->u.m); +} + +/* --- @keyrand@ --- * + * + * Arguments: @key_file *kf@ = pointer to key file + * @const char *id@ = pointer to key id (or null) + * + * Returns: --- + * + * Use: Keys the random number generator. + */ + +static void keyrand(key_file *kf, const char *id) +{ + key *k; + + /* --- Find the key --- */ + + if (id) { + if ((k = key_bytag(kf, id)) == 0) + die(EXIT_FAILURE, "key `%s' not found", id); + } else + k = key_bytype(kf, "catacomb-rand"); + + if (k) { + key_data *kd = k->k, *kkd; + key_incref(kd); + + again: + switch (kd->e & KF_ENCMASK) { + case KENC_BINARY: + break; + case KENC_ENCRYPT: { + dstr d = DSTR_INIT; + key_fulltag(k, &d); + if (key_punlock(&kkd, kd, d.buf)) + die(EXIT_FAILURE, "error unlocking key `%s'", d.buf); + dstr_destroy(&d); + key_drop(kd); + kd = kkd; + } goto again; + default: { + dstr d = DSTR_INIT; + key_fulltag(k, &d); + die(EXIT_FAILURE, "bad encoding type for key `%s'", d.buf); + } break; + } + + /* --- Key the generator --- */ + + rand_key(RAND_GLOBAL, kd->u.k.k, kd->u.k.sz); + key_drop(kd); + } +} + +/* --- Key generation algorithms --- */ + +static void alg_binary(keyopts *k) +{ + unsigned sz; + unsigned m; + key_data *kd; + octet *p; + + if (!k->bits) + k->bits = 128; + if (k->p) + die(EXIT_FAILURE, "no shared parameters for binary keys"); + + sz = (k->bits + 7) >> 3; + p = sub_alloc(sz); + m = (1 << (((k->bits - 1) & 7) + 1)) - 1; + k->r->ops->fill(k->r, p, sz); + *p &= m; + kd = key_newbinary(KCAT_SYMM | KF_BURN, p, sz); + memset(p, 0, sz); + dolock(k, &kd, 0); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); + sub_free(p, sz); +} + +static void alg_des(keyopts *k) +{ + unsigned sz; + octet *p; + key_data *kd; + int i; + + if (!k->bits) + k->bits = 168; + if (k->p) + die(EXIT_FAILURE, "no shared parameters for DES keys"); + if (k->bits % 56 || k->bits > 168) + die(EXIT_FAILURE, "DES keys must be 56, 112 or 168 bits long"); + + sz = k->bits / 7; + p = sub_alloc(sz); + k->r->ops->fill(k->r, p, sz); + for (i = 0; i < sz; i++) { + octet x = p[i] | 0x01; + x = x ^ (x >> 4); + x = x ^ (x >> 2); + x = x ^ (x >> 1); + p[i] = (p[i] & 0xfe) | (x & 0x01); + } + kd = key_newbinary(KCAT_SYMM | KF_BURN, p, sz); + memset(p, 0, sz); + dolock(k, &kd, 0); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); + sub_free(p, sz); +} + +static void alg_rsa(keyopts *k) +{ + rsa_priv rp; + key_data *kd, *kkd; + + /* --- Sanity checking --- */ + + if (k->p) + die(EXIT_FAILURE, "no shared parameters for RSA keys"); + if (!k->bits) + k->bits = 1024; + + /* --- Generate the RSA parameters --- */ + + if (rsa_gen(&rp, k->bits, k->r, 0, + (k->f & f_quiet) ? 0 : pgen_ev, 0)) + die(EXIT_FAILURE, "RSA key generation failed"); + + /* --- Run a test encryption --- */ + + { + grand *g = fibrand_create(k->r->ops->word(k->r)); + rsa_pub rpp; + mp *m = mprand_range(MP_NEW, rp.n, g, 0); + mp *c; + + rpp.n = rp.n; + rpp.e = rp.e; + c = rsa_qpubop(&rpp, MP_NEW, m); + c = rsa_qprivop(&rp, c, c, g); + + if (!MP_EQ(c, m)) + die(EXIT_FAILURE, "test encryption failed"); + mp_drop(c); + mp_drop(m); + g->ops->destroy(g); + } + + /* --- Allrighty then --- */ + + kd = key_newstruct(); + key_structsteal(kd, "n", key_newmp(KCAT_PUB, rp.n)); + key_structsteal(kd, "e", key_newmp(KCAT_PUB, rp.e)); + + kkd = key_newstruct(); + key_structsteal(kkd, "d", key_newmp(KCAT_PRIV | KF_BURN, rp.d)); + key_structsteal(kkd, "p", key_newmp(KCAT_PRIV | KF_BURN, rp.p)); + key_structsteal(kkd, "q", key_newmp(KCAT_PRIV | KF_BURN, rp.q)); + key_structsteal(kkd, "q-inv", key_newmp(KCAT_PRIV | KF_BURN, rp.q_inv)); + key_structsteal(kkd, "d-mod-p", key_newmp(KCAT_PRIV | KF_BURN, rp.dp)); + key_structsteal(kkd, "d-mod-q", key_newmp(KCAT_PRIV | KF_BURN, rp.dq)); + dolock(k, &kkd, "private"); + key_structsteal(kd, "private", kkd); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); + rsa_privfree(&rp); +} + +static void alg_dsaparam(keyopts *k) +{ + static const char *pl[] = { "q", "p", "g", 0 }; + if (!copyparam(k, pl)) { + dsa_param dp; + octet *p; + size_t sz; + dstr d = DSTR_INIT; + base64_ctx c; + key_data *kd; + dsa_seed ds; + + /* --- Choose appropriate bit lengths if necessary --- */ + + if (!k->qbits) + k->qbits = 160; + if (!k->bits) + k->bits = 1024; + + /* --- Allocate a seed block --- */ + + sz = (k->qbits + 7) >> 3; + p = sub_alloc(sz); + k->r->ops->fill(k->r, p, sz); + + /* --- Allocate the parameters --- */ + + if (dsa_gen(&dp, k->qbits, k->bits, 0, p, sz, &ds, + (k->f & f_quiet) ? 0 : pgen_ev, 0)) + die(EXIT_FAILURE, "DSA parameter generation failed"); + + /* --- Store the parameters --- */ + + kd = key_newstruct(); + key_structsteal(kd, "q", key_newmp(KCAT_SHARE, dp.q)); + key_structsteal(kd, "p", key_newmp(KCAT_SHARE, dp.p)); + key_structsteal(kd, "g", key_newmp(KCAT_SHARE, dp.g)); + mp_drop(dp.q); + mp_drop(dp.p); + mp_drop(dp.g); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); + + /* --- Store the seed for future verification --- */ + + base64_init(&c); + c.maxline = 0; + c.indent = ""; + base64_encode(&c, ds.p, ds.sz, &d); + base64_encode(&c, 0, 0, &d); + DPUTZ(&d); + key_putattr(k->kf, k->k, "seed", d.buf); + DRESET(&d); + dstr_putf(&d, "%u", ds.count); + key_putattr(k->kf, k->k, "count", d.buf); + xfree(ds.p); + sub_free(p, sz); + dstr_destroy(&d); + } +} + +static void alg_dsa(keyopts *k) +{ + mp *q, *p, *g; + mp *x, *y; + mpmont mm; + key_data *kd, *kkd; + + /* --- Get the shared parameters --- */ + + alg_dsaparam(k); + key_split(&k->k->k); kd = k->k->k; + q = getmp(kd, "q"); + p = getmp(kd, "p"); + g = getmp(kd, "g"); + + /* --- Choose a private key --- */ + + x = mprand_range(MP_NEWSEC, q, k->r, 0); + mpmont_create(&mm, p); + y = mpmont_exp(&mm, MP_NEW, g, x); + + /* --- Store everything away --- */ + + key_structsteal(kd, "y", key_newmp(KCAT_PUB, y)); + + kkd = key_newstruct(); + key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x)); + dolock(k, &kkd, "private"); + key_structsteal(kd, "private", kkd); + + mp_drop(x); mp_drop(y); +} + +static void alg_dhparam(keyopts *k) +{ + static const char *pl[] = { "p", "q", "g", 0 }; + key_data *kd; + if (!copyparam(k, pl)) { + dh_param dp; + int rc; + + if (k->curve) { + qd_parse qd; + group *g; + const char *e; + + if (strcmp(k->curve, "list") == 0) { + unsigned i, w; + LIST("Built-in prime fields", stdout, ptab[i].name, ptab[i].name); + exit(0); + } + qd.p = k->curve; + if (dh_parse(&qd, &dp)) + die(EXIT_FAILURE, "error in field spec: %s", qd.e); + if (!qd_eofp(&qd)) + die(EXIT_FAILURE, "junk at end of field spec"); + if ((g = group_prime(&dp)) == 0) + die(EXIT_FAILURE, "invalid prime field"); + if (!(k->f & f_quiet) && (e = G_CHECK(g, &rand_global)) != 0) + moan("WARNING! group check failed: %s", e); + G_DESTROYGROUP(g); + goto done; + } + + if (!k->bits) + k->bits = 1024; + + /* --- Choose a large safe prime number --- */ + + if (k->f & f_limlee) { + mp **f; + size_t nf; + if (!k->qbits) + k->qbits = 256; + rc = dh_limlee(&dp, k->qbits, k->bits, + (k->f & f_subgroup) ? DH_SUBGROUP : 0, + 0, k->r, (k->f & f_quiet) ? 0 : pgen_ev, 0, + (k->f & f_quiet) ? 0 : pgen_evspin, 0, &nf, &f); + if (!rc) { + dstr d = DSTR_INIT; + size_t i; + for (i = 0; i < nf; i++) { + if (i) + dstr_puts(&d, ", "); + mp_writedstr(f[i], &d, 10); + mp_drop(f[i]); + } + key_putattr(k->kf, k->k, "factors", d.buf); + dstr_destroy(&d); + } + } else if (k->f & f_kcdsa) { + if (!k->qbits) + k->qbits = 256; + rc = dh_kcdsagen(&dp, k->qbits, k->bits, 0, + 0, k->r, (k->f & f_quiet) ? 0 : pgen_ev, 0); + if (!rc) { + dstr d = DSTR_INIT; + mp *v = MP_NEW; + + mp_writedstr(dp.q, &d, 10); + mp_div(&v, 0, dp.p, dp.q); + v = mp_lsr(v, v, 1); + dstr_puts(&d, ", "); + mp_writedstr(v, &d, 10); + mp_drop(v); + key_putattr(k->kf, k->k, "factors", d.buf); + dstr_destroy(&d); + } + } else + rc = dh_gen(&dp, k->qbits, k->bits, 0, k->r, + (k->f & f_quiet) ? 0 : pgen_ev, 0); + + if (rc) + die(EXIT_FAILURE, "Diffie-Hellman parameter generation failed"); + + done: + kd = key_newstruct(); + key_structsteal(kd, "p", key_newmp(KCAT_SHARE, dp.p)); + key_structsteal(kd, "q", key_newmp(KCAT_SHARE, dp.q)); + key_structsteal(kd, "g", key_newmp(KCAT_SHARE, dp.g)); + mp_drop(dp.q); + mp_drop(dp.p); + mp_drop(dp.g); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); + } +} + +static void alg_dh(keyopts *k) +{ + mp *x, *y; + mp *p, *q, *g; + mpmont mm; + key_data *kd, *kkd; + + /* --- Get the shared parameters --- */ + + alg_dhparam(k); + key_split(&k->k->k); kd = k->k->k; + p = getmp(kd, "p"); + q = getmp(kd, "q"); + g = getmp(kd, "g"); + + /* --- Choose a suitable private key --- * + * + * Since %$g$% has order %$q$%, choose %$x < q$%. + */ + + x = mprand_range(MP_NEWSEC, q, k->r, 0); + + /* --- Compute the public key %$y = g^x \bmod p$% --- */ + + mpmont_create(&mm, p); + y = mpmont_exp(&mm, MP_NEW, g, x); + mpmont_destroy(&mm); + + /* --- Store everything away --- */ + + key_structsteal(kd, "y", key_newmp(KCAT_PUB, y)); + + kkd = key_newstruct(); + key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x)); + dolock(k, &kkd, "private"); + key_structsteal(kd, "private", kkd); + + mp_drop(x); mp_drop(y); +} + +static void alg_bbs(keyopts *k) +{ + bbs_priv bp; + key_data *kd, *kkd; + + /* --- Sanity checking --- */ + + if (k->p) + die(EXIT_FAILURE, "no shared parameters for Blum-Blum-Shub keys"); + if (!k->bits) + k->bits = 1024; + + /* --- Generate the BBS parameters --- */ + + if (bbs_gen(&bp, k->bits, k->r, 0, + (k->f & f_quiet) ? 0 : pgen_ev, 0)) + die(EXIT_FAILURE, "Blum-Blum-Shub key generation failed"); + + /* --- Allrighty then --- */ + + kd = key_newstruct(); + key_structsteal(kd, "n", key_newmp(KCAT_PUB, bp.n)); + + kkd = key_newstruct(); + key_structsteal(kkd, "p", key_newmp(KCAT_PRIV | KF_BURN, bp.p)); + key_structsteal(kkd, "q", key_newmp(KCAT_PRIV | KF_BURN, bp.q)); + dolock(k, &kkd, "private"); + key_structsteal(kd, "private", kkd); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); + + bbs_privfree(&bp); +} + +static void alg_binparam(keyopts *k) +{ + static const char *pl[] = { "p", "q", "g", 0 }; + if (!copyparam(k, pl)) { + gbin_param gb; + qd_parse qd; + group *g; + const char *e; + key_data *kd; + + /* --- Decide on a field --- */ + + if (!k->bits) k->bits = 128; + if (k->curve && strcmp(k->curve, "list") == 0) { + unsigned i, w; + LIST("Built-in binary fields", stdout, + bintab[i].name, bintab[i].name); + exit(0); + } + if (!k->curve) { + if (k->bits <= 40) k->curve = "p1363-40"; + else if (k->bits <= 56) k->curve = "p1363-56"; + else if (k->bits <= 64) k->curve = "p1363-64"; + else if (k->bits <= 80) k->curve = "p1363-80"; + else if (k->bits <= 112) k->curve = "p1363-112"; + else if (k->bits <= 128) k->curve = "p1363-128"; + else { + die(EXIT_FAILURE, + "no built-in binary fields provide %u-bit security", + k->bits); + } + } + + /* --- Check it --- */ + + qd.e = 0; + qd.p = k->curve; + if (dhbin_parse(&qd, &gb)) + die(EXIT_FAILURE, "error in field spec: %s", qd.e); + if (!qd_eofp(&qd)) + die(EXIT_FAILURE, "junk at end of field spec"); + if ((g = group_binary(&gb)) == 0) + die(EXIT_FAILURE, "invalid binary field"); + if (!(k->f & f_quiet) && (e = G_CHECK(g, &rand_global)) != 0) + moan("WARNING! group check failed: %s", e); + G_DESTROYGROUP(g); + + /* --- Write out the answer --- */ + + kd = key_newstruct(); + key_structsteal(kd, "p", key_newmp(KCAT_SHARE, gb.p)); + key_structsteal(kd, "q", key_newmp(KCAT_SHARE, gb.q)); + key_structsteal(kd, "g", key_newmp(KCAT_SHARE, gb.g)); + mp_drop(gb.q); + mp_drop(gb.p); + mp_drop(gb.g); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); + } +} + +static void alg_bin(keyopts *k) +{ + mp *x, *y; + mp *p, *q, *g; + gfreduce r; + key_data *kd, *kkd; + + /* --- Get the shared parameters --- */ + + alg_binparam(k); + key_split(&k->k->k); kd = k->k->k; + p = getmp(kd, "p"); + q = getmp(kd, "q"); + g = getmp(kd, "g"); + + /* --- Choose a suitable private key --- * + * + * Since %$g$% has order %$q$%, choose %$x < q$%. + */ + + x = mprand_range(MP_NEWSEC, q, k->r, 0); + + /* --- Compute the public key %$y = g^x \bmod p$% --- */ + + gfreduce_create(&r, p); + y = gfreduce_exp(&r, MP_NEW, g, x); + gfreduce_destroy(&r); + + /* --- Store everything away --- */ + + key_structsteal(kd, "y", key_newmp(KCAT_PUB, y)); + + kkd = key_newstruct(); + key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x)); + dolock(k, &kkd, "private"); + key_structsteal(kd, "private", kkd); + + mp_drop(x); mp_drop(y); +} + +static void alg_ecparam(keyopts *k) +{ + static const char *pl[] = { "curve", 0 }; + if (!copyparam(k, pl)) { + ec_info ei; + const char *e; + key_data *kd; + + /* --- Decide on a curve --- */ + + if (!k->bits) k->bits = 256; + if (k->curve && strcmp(k->curve, "list") == 0) { + unsigned i, w; + LIST("Built-in elliptic curves", stdout, + ectab[i].name, ectab[i].name); + exit(0); + } + if (!k->curve) { + if (k->bits <= 56) k->curve = "secp112r1"; + else if (k->bits <= 64) k->curve = "secp128r1"; + else if (k->bits <= 80) k->curve = "secp160r1"; + else if (k->bits <= 96) k->curve = "secp192r1"; + else if (k->bits <= 112) k->curve = "secp224r1"; + else if (k->bits <= 128) k->curve = "secp256r1"; + else if (k->bits <= 192) k->curve = "secp384r1"; + else if (k->bits <= 256) k->curve = "secp521r1"; + else + die(EXIT_FAILURE, "no built-in curves provide %u-bit security", + k->bits); + } + + /* --- Check it --- */ + + if ((e = ec_getinfo(&ei, k->curve)) != 0) + die(EXIT_FAILURE, "error in curve spec: %s", e); + if (!(k->f & f_quiet) && (e = ec_checkinfo(&ei, k->r)) != 0) + moan("WARNING! curve check failed: %s", e); + ec_freeinfo(&ei); + + /* --- Write out the answer --- */ + + kd = key_newstruct(); + key_structsteal(kd, "curve", key_newstring(KCAT_SHARE, k->curve)); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); + } +} + +static void alg_ec(keyopts *k) +{ + key_data *kd; + key_data *kkd; + mp *x = MP_NEW; + ec p = EC_INIT; + const char *e; + ec_info ei; + + /* --- Get the curve --- */ + + alg_ecparam(k); + key_split(&k->k->k); kd = k->k->k; + if ((kkd = key_structfind(kd, "curve")) == 0) + die(EXIT_FAILURE, "unexpected failure looking up subkey `curve')"); + if ((kkd->e & KF_ENCMASK) != KENC_STRING) + die(EXIT_FAILURE, "subkey `curve' is not a string"); + if ((e = ec_getinfo(&ei, kkd->u.p)) != 0) + die(EXIT_FAILURE, "error in curve spec: %s", e); + + /* --- Invent a private exponent and compute the public key --- */ + + x = mprand_range(MP_NEWSEC, ei.r, k->r, 0); + ec_mul(ei.c, &p, &ei.g, x); + + /* --- Store everything away --- */ + + key_structsteal(kd, "p", key_newec(KCAT_PUB, &p)); + + kkd = key_newstruct(); + key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x)); + dolock(k, &kkd, "private"); + key_structsteal(kd, "private", kkd); + + /* --- Done --- */ + + ec_freeinfo(&ei); + mp_drop(x); +} + +/* --- The algorithm tables --- */ + +typedef struct keyalg { + const char *name; + void (*proc)(keyopts *o); + const char *help; +} keyalg; + +static keyalg algtab[] = { + { "binary", alg_binary, "Plain binary data" }, + { "des", alg_des, "Binary with DES-style parity" }, + { "rsa", alg_rsa, "RSA public-key encryption" }, + { "bbs", alg_bbs, "Blum-Blum-Shub generator" }, + { "dsa", alg_dsa, "DSA digital signatures" }, + { "dsa-param", alg_dsaparam, "DSA shared parameters" }, + { "dh", alg_dh, "Diffie-Hellman key exchange" }, + { "dh-param", alg_dhparam, "Diffie-Hellman parameters" }, + { "bindh", alg_bin, "DH over a binary field" }, + { "bindh-param", alg_binparam, "Binary-field DH parameters" }, + { "ec-param", alg_ecparam, "Elliptic curve parameters" }, + { "ec", alg_ec, "Elliptic curve crypto" }, + { 0, 0 } +}; + +/* --- @cmd_add@ --- */ + +static int cmd_add(int argc, char *argv[]) +{ + key_file f; + time_t exp = KEXP_EXPIRE; + uint32 kid = rand_global.ops->word(&rand_global); + const char *tag = 0, *ptag = 0; + const char *c = 0; + keyalg *alg = algtab; + const char *rtag = 0; + const struct seedalg *sa = SEEDALG_DEFAULT; + keyopts k = { 0, 0, DSTR_INIT, 0, 0, 0, 0, 0 }; + const char *seed = 0; + k.r = &rand_global; + + /* --- Parse options for the subcommand --- */ + + for (;;) { + static struct option opt[] = { + { "algorithm", OPTF_ARGREQ, 0, 'a' }, + { "bits", OPTF_ARGREQ, 0, 'b' }, + { "qbits", OPTF_ARGREQ, 0, 'B' }, + { "parameters", OPTF_ARGREQ, 0, 'p' }, + { "expire", OPTF_ARGREQ, 0, 'e' }, + { "comment", OPTF_ARGREQ, 0, 'c' }, + { "tag", OPTF_ARGREQ, 0, 't' }, + { "rand-id", OPTF_ARGREQ, 0, 'R' }, + { "key-id", OPTF_ARGREQ, 0, 'I' }, + { "curve", OPTF_ARGREQ, 0, 'C' }, + { "seedalg", OPTF_ARGREQ, 0, 'A' }, + { "seed", OPTF_ARGREQ, 0, 's' }, + { "newseed", OPTF_ARGREQ, 0, 'n' }, + { "lock", 0, 0, 'l' }, + { "quiet", 0, 0, 'q' }, + { "lim-lee", 0, 0, 'L' }, + { "subgroup", 0, 0, 'S' }, + { "kcdsa", 0, 0, 'K' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+a:b:B:p:e:c:t:R:I:C:A:s:n:lqrLKS", + opt, 0, 0, 0); + if (i < 0) + break; + + /* --- Handle the various options --- */ + + switch (i) { + + /* --- Read an algorithm name --- */ + + case 'a': { + keyalg *a; + size_t sz = strlen(optarg); + + if (strcmp(optarg, "list") == 0) { + for (a = algtab; a->name; a++) + printf("%-10s %s\n", a->name, a->help); + return (0); + } + + alg = 0; + for (a = algtab; a->name; a++) { + if (strncmp(optarg, a->name, sz) == 0) { + if (a->name[sz] == 0) { + alg = a; + break; + } else if (alg) + die(EXIT_FAILURE, "ambiguous algorithm name `%s'", optarg); + else + alg = a; + } + } + if (!alg) + die(EXIT_FAILURE, "unknown algorithm name `%s'", optarg); + } break; + + /* --- Bits must be nonzero and a multiple of 8 --- */ + + case 'b': { + char *p; + k.bits = strtoul(optarg, &p, 0); + if (k.bits == 0 || *p != 0) + die(EXIT_FAILURE, "bad bitlength `%s'", optarg); + } break; + + case 'B': { + char *p; + k.qbits = strtoul(optarg, &p, 0); + if (k.qbits == 0 || *p != 0) + die(EXIT_FAILURE, "bad bitlength `%s'", optarg); + } break; + + /* --- Parameter selection --- */ + + case 'p': + ptag = optarg; + break; + + /* --- Expiry dates get passed to @get_date@ for parsing --- */ + + case 'e': + if (strcmp(optarg, "forever") == 0) + exp = KEXP_FOREVER; + else { + exp = get_date(optarg, 0); + if (exp == -1) + die(EXIT_FAILURE, "bad expiry date `%s'", optarg); + } + break; + + /* --- Store comments without interpretation --- */ + + case 'c': + if (key_chkcomment(optarg)) + die(EXIT_FAILURE, "bad comment string `%s'", optarg); + c = optarg; + break; + + /* --- Elliptic curve parameters --- */ + + case 'C': + k.curve = optarg; + break; + + /* --- Store tags --- */ + + case 't': + if (key_chkident(optarg)) + die(EXIT_FAILURE, "bad tag string `%s'", optarg); + tag = optarg; + break; + case 'r': + k.f |= f_retag; + break; + + /* --- Seeding --- */ + + case 'A': { + const struct seedalg *ss; + if (strcmp(optarg, "list") == 0) { + printf("Seed algorithms:\n"); + for (ss = seedtab; ss->p; ss++) + printf(" %s\n", ss->p); + exit(0); + } + if (seed) die(EXIT_FAILURE, "seed already set -- put -A first"); + sa = 0; + for (ss = seedtab; ss->p; ss++) { + if (strcmp(optarg, ss->p) == 0) + sa = ss; + } + if (!sa) + die(EXIT_FAILURE, "seed algorithm `%s' not known", optarg); + } break; + + case 's': { + base64_ctx b; + dstr d = DSTR_INIT; + if (seed) die(EXIT_FAILURE, "seed already set"); + base64_init(&b); + base64_decode(&b, optarg, strlen(optarg), &d); + base64_decode(&b, 0, 0, &d); + k.r = sa->gen(d.buf, d.len); + seed = optarg; + dstr_destroy(&d); + } break; + + case 'n': { + base64_ctx b; + dstr d = DSTR_INIT; + char *p; + unsigned n = strtoul(optarg, &p, 0); + if (n == 0 || *p != 0 || n % 8 != 0) + die(EXIT_FAILURE, "bad seed length `%s'", optarg); + if (seed) die(EXIT_FAILURE, "seed already set"); + n /= 8; + p = xmalloc(n); + rand_get(RAND_GLOBAL, p, n); + base64_init(&b); + base64_encode(&b, p, n, &d); + base64_encode(&b, 0, 0, &d); + seed = d.buf; + k.r = sa->gen(p, n); + } break; + + /* --- Key id --- */ + + case 'I': { + char *p; + unsigned long id; + + errno = 0; + id = strtoul(optarg, &p, 16); + if (errno || *p || id > MASK32) + die(EXIT_FAILURE, "bad key-id `%s'", optarg); + kid = id; + } break; + + /* --- Other flags --- */ + + case 'R': + rtag = optarg; + break; + case 'l': + k.f |= f_lock; + break; + case 'q': + k.f |= f_quiet; + break; + case 'L': + k.f |= f_limlee; + break; + case 'K': + k.f |= f_kcdsa; + break; + case 'S': + k.f |= f_subgroup; + break; + + /* --- Other things are bogus --- */ + + default: + k.f |= f_bogus; + break; + } + } + + /* --- Various sorts of bogosity --- */ + + if ((k.f & f_bogus) || optind + 1 > argc) { + die(EXIT_FAILURE, + "Usage: add [OPTIONS] TYPE [ATTR...]"); + } + if (key_chkident(argv[optind])) + die(EXIT_FAILURE, "bad key type `%s'", argv[optind]); + + /* --- Set up various bits of the state --- */ + + if (exp == KEXP_EXPIRE) + exp = time(0) + 14 * 24 * 60 * 60; + + /* --- Open the file and create the basic key block --- * + * + * Keep on generating keyids until one of them doesn't collide. + */ + + doopen(&f, KOPEN_WRITE); + k.kf = &f; + + /* --- Key the generator --- */ + + keyrand(&f, rtag); + + for (;;) { + int err; + if ((err = key_new(&f, kid, argv[optind], exp, &k.k)) == 0) + break; + else if (err != KERR_DUPID) + die(EXIT_FAILURE, "error adding new key: %s", key_strerror(err)); + } + + /* --- Set various simple attributes --- */ + + if (tag) { + int err; + key *kk; + if (k.f & f_retag) { + if ((kk = key_bytag(&f, tag)) != 0 && + kk->tag && + strcmp(kk->tag, tag) == 0) + key_settag(&f, kk, 0); + } + if ((err = key_settag(&f, k.k, tag)) != 0) + die(EXIT_FAILURE, "error setting key tag: %s", key_strerror(err)); + } + + if (c) { + int err = key_setcomment(&f, k.k, c); + if (err) + die(EXIT_FAILURE, "error setting key comment: %s", key_strerror(err)); + } + + setattr(&f, k.k, argv + optind + 1); + if (seed) { + key_putattr(&f, k.k, "genseed", seed); + key_putattr(&f, k.k, "seedalg", sa->p); + } + + key_fulltag(k.k, &k.tag); + + /* --- Find the parameter key --- */ + + if (ptag) { + if ((k.p = key_bytag(&f, ptag)) == 0) + die(EXIT_FAILURE, "parameter key `%s' not found", ptag); + if ((k.p->k->e & KF_ENCMASK) != KENC_STRUCT) + die(EXIT_FAILURE, "parameter key `%s' is not structured", ptag); + } + + /* --- Now generate the actual key data --- */ + + alg->proc(&k); + + /* --- Done --- */ + + dstr_destroy(&k.tag); + doclose(&f); + return (0); +} + +/*----- Key listing -------------------------------------------------------*/ + +/* --- Listing options --- */ + +typedef struct listopts { + const char *tfmt; /* Date format (@strftime@-style) */ + int v; /* Verbosity level */ + unsigned f; /* Various flags */ + time_t t; /* Time now (for key expiry) */ + key_filter kf; /* Filter for matching keys */ +} listopts; + +/* --- Listing flags --- */ + +#define f_newline 2u /* Write newline before next entry */ +#define f_attr 4u /* Written at least one attribute */ +#define f_utc 8u /* Emit UTC time, not local time */ + +/* --- @showkeydata@ --- * + * + * Arguments: @key_data *k@ = pointer to key to write + * @int ind@ = indentation level + * @listopts *o@ = listing options + * @dstr *d@ = tag string for this subkey + * + * Returns: --- + * + * Use: Emits a piece of key data in a human-readable format. + */ + +static void showkeydata(key_data *k, int ind, listopts *o, dstr *d) +{ +#define INDENT(i) do { \ + int _i; \ + for (_i = 0; _i < (i); _i++) { \ + putchar(' '); \ + } \ +} while (0) + + switch (k->e & KF_ENCMASK) { + + /* --- Binary key data --- * + * + * Emit as a simple hex dump. + */ + + case KENC_BINARY: { + const octet *p = k->u.k.k; + const octet *l = p + k->u.k.sz; + size_t sz = 0; + + fputs(" {", stdout); + while (p < l) { + if (sz % 16 == 0) { + putchar('\n'); + INDENT(ind + 2); + } else if (sz % 8 == 0) + fputs(" ", stdout); + else + putc(' ', stdout); + printf("%02x", *p++); + sz++; + } + putchar('\n'); + INDENT(ind); + fputs("}\n", stdout); + } break; + + /* --- Encrypted data --- * + * + * If the user is sufficiently keen, ask for a passphrase and decrypt the + * key. Otherwise just say that it's encrypted and move on. + */ + + case KENC_ENCRYPT: + if (o->v <= 3) + fputs(" encrypted\n", stdout); + else { + key_data *kd; + if (key_punlock(&kd, k, d->buf)) + printf(" \n", d->buf); + else { + fputs(" encrypted", stdout); + showkeydata(kd, ind, o, d); + key_drop(kd); + } + } + break; + + /* --- Integer keys --- * + * + * Emit as a large integer in decimal. This makes using the key in + * `calc' or whatever easier. + */ + + case KENC_MP: + putchar(' '); + mp_writefile(k->u.m, stdout, 10); + putchar('\n'); + break; + + /* --- Strings --- */ + + case KENC_STRING: + printf(" `%s'\n", k->u.p); + break; + + /* --- Elliptic curve points --- */ + + case KENC_EC: + if (EC_ATINF(&k->u.e)) + fputs(" inf\n", stdout); + else { + fputs(" 0x", stdout); mp_writefile(k->u.e.x, stdout, 16); + fputs(", 0x", stdout); mp_writefile(k->u.e.y, stdout, 16); + putchar('\n'); + } + break; + + /* --- Structured keys --- * + * + * Just iterate over the subkeys. + */ + + case KENC_STRUCT: { + key_subkeyiter i; + const char *tag; + size_t n = d->len; + + fputs(" {\n", stdout); + for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) { + if (!key_match(k, &o->kf)) + continue; + INDENT(ind + 2); + printf("%s =", tag); + d->len = n; + dstr_putf(d, ".%s", tag); + showkeydata(k, ind + 2, o, d); + } + INDENT(ind); + fputs("}\n", stdout); + } break; + } + +#undef INDENT +} + +/* --- @showkey@ --- * + * + * Arguments: @key *k@ = pointer to key to show + * @listopts *o@ = pointer to listing options + * + * Returns: --- + * + * Use: Emits a listing of a particular key. + */ + +static void showkey(key *k, listopts *o) +{ + char ebuf[24], dbuf[24]; + struct tm *tm; + + /* --- Skip the key if the filter doesn't match --- */ + + if (!key_match(k->k, &o->kf)) + return; + + /* --- Sort out the expiry and deletion times --- */ + + if (KEY_EXPIRED(o->t, k->exp)) + strcpy(ebuf, "expired"); + else if (k->exp == KEXP_FOREVER) + strcpy(ebuf, "forever"); + else { + tm = (o->f & f_utc) ? gmtime(&k->exp) : localtime(&k->exp); + strftime(ebuf, sizeof(ebuf), o->tfmt, tm); + } + + if (KEY_EXPIRED(o->t, k->del)) + strcpy(dbuf, "deleted"); + else if (k->del == KEXP_FOREVER) + strcpy(dbuf, "forever"); + else { + tm = (o->f & f_utc) ? gmtime(&k->del) : localtime(&k->del); + strftime(dbuf, sizeof(dbuf), o->tfmt, tm); + } + + /* --- If in compact format, just display and quit --- */ + + if (!o->v) { + if (!(o->f & f_newline)) { + printf("%8s %-20s %-20s %-10s %s\n", + "Id", "Tag", "Type", "Expire", "Delete"); + } + printf("%08lx %-20s %-20s %-10s %s\n", + (unsigned long)k->id, k->tag ? k->tag : "", + k->type, ebuf, dbuf); + o->f |= f_newline; + return; + } + + /* --- Display the standard header --- */ + + if (o->f & f_newline) + fputc('\n', stdout); + printf("keyid: %08lx\n", (unsigned long)k->id); + printf("tag: %s\n", k->tag ? k->tag : ""); + printf("type: %s\n", k->type); + printf("expiry: %s\n", ebuf); + printf("delete: %s\n", dbuf); + printf("comment: %s\n", k->c ? k->c : ""); + + /* --- Display the attributes --- */ + + if (o->v > 1) { + key_attriter i; + const char *av, *an; + + o->f &= ~f_attr; + printf("attributes:"); + for (key_mkattriter(&i, k); key_nextattr(&i, &an, &av); ) { + printf("\n %s = %s", an, av); + o->f |= f_attr; + } + if (o->f & f_attr) + fputc('\n', stdout); + else + puts(" "); + } + + /* --- If dumping requested, dump the raw key data --- */ + + if (o->v > 2) { + dstr d = DSTR_INIT; + fputs("key:", stdout); + key_fulltag(k, &d); + showkeydata(k->k, 0, o, &d); + dstr_destroy(&d); + } + + o->f |= f_newline; +} + +/* --- @cmd_list@ --- */ + +static int cmd_list(int argc, char *argv[]) +{ + key_file f; + key *k; + listopts o = { 0, 0, 0, 0, { 0, 0 } }; + + /* --- Parse subcommand options --- */ + + for (;;) { + static struct option opt[] = { + { "quiet", 0, 0, 'q' }, + { "verbose", 0, 0, 'v' }, + { "utc", 0, 0, 'u' }, + { "filter", OPTF_ARGREQ, 0, 'f' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+uqvf:", opt, 0, 0, 0); + if (i < 0) + break; + + switch (i) { + case 'u': + o.f |= f_utc; + break; + case 'q': + if (o.v) + o.v--; + break; + case 'v': + o.v++; + break; + case 'f': { + char *p; + int e = key_readflags(optarg, &p, &o.kf.f, &o.kf.m); + if (e || *p) + die(EXIT_FAILURE, "bad filter string `%s'", optarg); + } break; + default: + o.f |= f_bogus; + break; + } + } + + if (o.f & f_bogus) + die(EXIT_FAILURE, "Usage: list [-uqv] [-f FILTER] [TAG...]"); + + /* --- Open the key file --- */ + + doopen(&f, KOPEN_READ); + o.t = time(0); + + /* --- Set up the time format --- */ + + if (!o.v) + o.tfmt = "%Y-%m-%d"; + else if (o.f & f_utc) + o.tfmt = "%Y-%m-%d %H:%M:%S UTC"; + else + o.tfmt = "%Y-%m-%d %H:%M:%S %Z"; + + /* --- If specific keys were requested use them, otherwise do all --- * + * + * Some day, this might turn into a wildcard match. + */ + + if (optind < argc) { + do { + if ((k = key_bytag(&f, argv[optind])) != 0) + showkey(k, &o); + else { + moan("key `%s' not found", argv[optind]); + o.f |= f_bogus; + } + optind++; + } while (optind < argc); + } else { + key_iter i; + for (key_mkiter(&i, &f); (k = key_next(&i)) != 0; ) + showkey(k, &o); + } + + /* --- Done --- */ + + doclose(&f); + if (o.f & f_bogus) + return (EXIT_FAILURE); + else + return (0); +} + +/*----- Command implementation --------------------------------------------*/ + +/* --- @cmd_expire@ --- */ + +static int cmd_expire(int argc, char *argv[]) +{ + key_file f; + key *k; + int i; + int rc = 0; + + if (argc < 2) + die(EXIT_FAILURE, "Usage: expire TAG..."); + doopen(&f, KOPEN_WRITE); + for (i = 1; i < argc; i++) { + if ((k = key_bytag(&f, argv[i])) != 0) + key_expire(&f, k); + else { + moan("key `%s' not found", argv[i]); + rc = 1; + } + } + doclose(&f); + return (rc); +} + +/* --- @cmd_delete@ --- */ + +static int cmd_delete(int argc, char *argv[]) +{ + key_file f; + key *k; + int i; + int rc = 0; + + if (argc < 2) + die(EXIT_FAILURE, "Usage: delete TAG..."); + doopen(&f, KOPEN_WRITE); + for (i = 1; i < argc; i++) { + if ((k = key_bytag(&f, argv[i])) != 0) + key_delete(&f, k); + else { + moan("key `%s' not found", argv[i]); + rc = 1; + } + } + doclose(&f); + return (rc); +} + +/* --- @cmd_setattr@ --- */ + +static int cmd_setattr(int argc, char *argv[]) +{ + key_file f; + key *k; + + if (argc < 3) + die(EXIT_FAILURE, "Usage: setattr TAG ATTR..."); + doopen(&f, KOPEN_WRITE); + if ((k = key_bytag(&f, argv[1])) == 0) + die(EXIT_FAILURE, "key `%s' not found", argv[1]); + setattr(&f, k, argv + 2); + doclose(&f); + return (0); +} + +/* --- @cmd_getattr@ --- */ + +static int cmd_getattr(int argc, char *argv[]) +{ + key_file f; + key *k; + dstr d = DSTR_INIT; + const char *p; + + if (argc != 3) + die(EXIT_FAILURE, "Usage: getattr TAG ATTR"); + doopen(&f, KOPEN_READ); + if ((k = key_bytag(&f, argv[1])) == 0) + die(EXIT_FAILURE, "key `%s' not found", argv[1]); + key_fulltag(k, &d); + if ((p = key_getattr(&f, k, argv[2])) == 0) + die(EXIT_FAILURE, "no attribute `%s' for key `%s'", argv[2], d.buf); + puts(p); + dstr_destroy(&d); + doclose(&f); + return (0); +} + +/* --- @cmd_finger@ --- */ + +static void fingerprint(key *k, const gchash *ch, const key_filter *kf) +{ + ghash *h; + dstr d = DSTR_INIT; + const octet *p; + size_t i; + + h = GH_INIT(ch); + if (key_fingerprint(k, h, kf)) { + p = GH_DONE(h, 0); + key_fulltag(k, &d); + for (i = 0; i < ch->hashsz; i++) { + if (i && i % 4 == 0) + putchar('-'); + printf("%02x", p[i]); + } + printf(" %s\n", d.buf); + } + dstr_destroy(&d); + GH_DESTROY(h); +} + +static int cmd_finger(int argc, char *argv[]) +{ + key_file f; + int rc = 0; + const gchash *ch = &rmd160; + key_filter kf = { KF_NONSECRET, KF_NONSECRET }; + + for (;;) { + static struct option opt[] = { + { "filter", OPTF_ARGREQ, 0, 'f' }, + { "algorithm", OPTF_ARGREQ, 0, 'a' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+f:a:", opt, 0, 0, 0); + if (i < 0) + break; + switch (i) { + case 'f': { + char *p; + int err = key_readflags(optarg, &p, &kf.f, &kf.m); + if (err || *p) + die(EXIT_FAILURE, "bad filter string `%s'", optarg); + } break; + case 'a': + if ((ch = ghash_byname(optarg)) == 0) + die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg); + break; + default: + rc = 1; + break; + } + } + + argv += optind; argc -= optind; + if (rc) + die(EXIT_FAILURE, "Usage: fingerprint [-f FILTER] [TAG...]"); + + doopen(&f, KOPEN_READ); + + if (argc) { + int i; + for (i = 0; i < argc; i++) { + key *k = key_bytag(&f, argv[i]); + if (k) + fingerprint(k, ch, &kf); + else { + rc = 1; + moan("key `%s' not found", argv[i]); + } + } + } else { + key_iter i; + key *k; + for (key_mkiter(&i, &f); (k = key_next(&i)) != 0; ) + fingerprint(k, ch, &kf); + } + return (rc); +} + +/* --- @cmd_verify@ --- */ + +static unsigned xdigit(char c) +{ + if ('A' <= c && c <= 'Z') return (c + 10 - 'A'); + if ('a' <= c && c <= 'z') return (c + 10 - 'a'); + if ('0' <= c && c <= '9') return (c - '0'); + return (~0u); +} + +static void unhexify(octet *q, char *p, size_t n) +{ + unsigned a = 0; + int i = 0; + + for (;;) { + if (*p == '-' || *p == ':' || isspace((unsigned char)*p)) { + p++; + continue; + } + if (!n && !*p) + break; + if (!*p) + die(EXIT_FAILURE, "hex string too short"); + if (!isxdigit((unsigned char)*p)) + die(EXIT_FAILURE, "bad hex string"); + if (!n) + die(EXIT_FAILURE, "hex string too long"); + a = (a << 4) | xdigit(*p++); + i++; + if (i == 2) { + *q++ = U8(a); + a = 0; + i = 0; + n--; + } + } +} + +static int cmd_verify(int argc, char *argv[]) +{ + key_file f; + int rc = 0; + const gchash *ch = &rmd160; + ghash *h; + key *k; + octet *buf; + const octet *fpr; + key_filter kf = { KF_NONSECRET, KF_NONSECRET }; + + for (;;) { + static struct option opt[] = { + { "filter", OPTF_ARGREQ, 0, 'f' }, + { "algorithm", OPTF_ARGREQ, 0, 'a' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+f:a:", opt, 0, 0, 0); + if (i < 0) + break; + switch (i) { + case 'f': { + char *p; + int err = key_readflags(optarg, &p, &kf.f, &kf.m); + if (err || *p) + die(EXIT_FAILURE, "bad filter string `%s'", optarg); + } break; + case 'a': + if ((ch = ghash_byname(optarg)) == 0) + die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg); + break; + default: + rc = 1; + break; + } + } + + argv += optind; argc -= optind; + if (rc || argc != 2) + die(EXIT_FAILURE, "Usage: verify [-f FILTER] TAG FINGERPRINT"); + + doopen(&f, KOPEN_READ); + + if ((k = key_bytag(&f, argv[0])) == 0) + die(EXIT_FAILURE, "key `%s' not found", argv[0]); + buf = xmalloc(ch->hashsz); + unhexify(buf, argv[1], ch->hashsz); + h = GH_INIT(ch); + if (!key_fingerprint(k, h, &kf)) + die(EXIT_FAILURE, "key has no fingerprintable components (as filtered)"); + fpr = GH_DONE(h, 0); + if (memcmp(fpr, buf, ch->hashsz) != 0) + die(EXIT_FAILURE, "key fingerprint mismatch"); + doclose(&f); + return (0); +} + +/* --- @cmd_comment@ --- */ + +static int cmd_comment(int argc, char *argv[]) +{ + key_file f; + key *k; + int err; + + if (argc < 2 || argc > 3) + die(EXIT_FAILURE, "Usage: comment TAG [COMMENT]"); + doopen(&f, KOPEN_WRITE); + if ((k = key_bytag(&f, argv[1])) == 0) + die(EXIT_FAILURE, "key `%s' not found", argv[1]); + if ((err = key_setcomment(&f, k, argv[2])) != 0) + die(EXIT_FAILURE, "bad comment `%s': %s", argv[2], key_strerror(err)); + doclose(&f); + return (0); +} + +/* --- @cmd_tag@ --- */ + +static int cmd_tag(int argc, char *argv[]) +{ + key_file f; + key *k; + int err; + unsigned flags = 0; + int rc = 0; + + for (;;) { + static struct option opt[] = { + { "retag", 0, 0, 'r' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+r", opt, 0, 0, 0); + if (i < 0) + break; + switch (i) { + case 'r': + flags |= f_retag; + break; + default: + rc = 1; + break; + } + } + + argv += optind; argc -= optind; + if (argc < 1 || argc > 2 || rc) + die(EXIT_FAILURE, "Usage: tag [-r] TAG [NEW-TAG]"); + doopen(&f, KOPEN_WRITE); + if (flags & f_retag) { + if ((k = key_bytag(&f, argv[1])) != 0 && strcmp(k->tag, argv[1]) == 0) + key_settag(&f, k, 0); + } + if ((k = key_bytag(&f, argv[0])) == 0) + die(EXIT_FAILURE, "key `%s' not found", argv[0]); + if ((err = key_settag(&f, k, argv[1])) != 0) + die(EXIT_FAILURE, "bad tag `%s': %s", argv[1], key_strerror(err)); + doclose(&f); + return (0); +} + +/* --- @cmd_lock@ --- */ + +static int cmd_lock(int argc, char *argv[]) +{ + key_file f; + key *k; + key_data **kd; + dstr d = DSTR_INIT; + + if (argc != 2) + die(EXIT_FAILURE, "Usage: lock QTAG"); + doopen(&f, KOPEN_WRITE); + if (key_qtag(&f, argv[1], &d, &k, &kd)) + die(EXIT_FAILURE, "key `%s' not found", argv[1]); + if ((*kd)->e == KENC_ENCRYPT && key_punlock(kd, 0, d.buf)) + die(EXIT_FAILURE, "couldn't unlock key `%s'", d.buf); + if (key_plock(kd, 0, d.buf)) + die(EXIT_FAILURE, "failed to lock key `%s'", d.buf); + f.f |= KF_MODIFIED; + doclose(&f); + return (0); +} + +/* --- @cmd_unlock@ --- */ + +static int cmd_unlock(int argc, char *argv[]) +{ + key_file f; + key *k; + key_data **kd; + dstr d = DSTR_INIT; + + if (argc != 2) + die(EXIT_FAILURE, "Usage: unlock QTAG"); + doopen(&f, KOPEN_WRITE); + if (key_qtag(&f, argv[1], &d, &k, &kd)) + die(EXIT_FAILURE, "key `%s' not found", argv[1]); + if ((*kd)->e != KENC_ENCRYPT) + die(EXIT_FAILURE, "key `%s' is not encrypted", d.buf); + if (key_punlock(kd, 0, d.buf)) + die(EXIT_FAILURE, "couldn't unlock key `%s'", d.buf); + f.f |= KF_MODIFIED; + doclose(&f); + return (0); +} + +/* --- @cmd_extract@ --- */ + +static int cmd_extract(int argc, char *argv[]) +{ + key_file f; + key *k; + int i; + int rc = 0; + key_filter kf = { 0, 0 }; + dstr d = DSTR_INIT; + const char *outfile = 0; + FILE *fp; + + for (;;) { + static struct option opt[] = { + { "filter", OPTF_ARGREQ, 0, 'f' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "f:", opt, 0, 0, 0); + if (i < 0) + break; + switch (i) { + case 'f': { + char *p; + int err = key_readflags(optarg, &p, &kf.f, &kf.m); + if (err || *p) + die(EXIT_FAILURE, "bad filter string `%s'", optarg); + } break; + default: + rc = 1; + break; + } + } + + argv += optind; argc -= optind; + if (rc || argc < 1) + die(EXIT_FAILURE, "Usage: extract [-f FILTER] FILE [TAG...]"); + if (strcmp(*argv, "-") == 0) + fp = stdout; + else { + outfile = *argv; + dstr_putf(&d, "%s.new", outfile); + if (!(fp = fopen(d.buf, "w"))) { + die(EXIT_FAILURE, "couldn't open `%s' for writing: %s", + d.buf, strerror(errno)); + } + } + + doopen(&f, KOPEN_READ); + if (argc < 2) { + key_iter i; + key *k; + for (key_mkiter(&i, &f); (k = key_next(&i)) != 0; ) + key_extract(&f, k, fp, &kf); + } else { + for (i = 1; i < argc; i++) { + if ((k = key_bytag(&f, argv[i])) != 0) + key_extract(&f, k, fp, &kf); + else { + moan("key `%s' not found", argv[i]); + rc = 1; + } + } + } + if (fclose(fp) || (outfile && rename(d.buf, outfile))) + die(EXIT_FAILURE, "error writing file: %s", strerror(errno)); + dstr_destroy(&d); + doclose(&f); + return (rc); +} + +/* --- @cmd_tidy@ --- */ + +static int cmd_tidy(int argc, char *argv[]) +{ + key_file f; + if (argc != 1) + die(EXIT_FAILURE, "Usage: tidy"); + doopen(&f, KOPEN_WRITE); + f.f |= KF_MODIFIED; /* Nasty hack */ + doclose(&f); + return (0); +} + +/* --- @cmd_merge@ --- */ + +static int cmd_merge(int argc, char *argv[]) +{ + key_file f; + FILE *fp; + + if (argc != 2) + die(EXIT_FAILURE, "Usage: merge FILE"); + if (strcmp(argv[1], "-") == 0) + fp = stdin; + else if (!(fp = fopen(argv[1], "r"))) { + die(EXIT_FAILURE, "couldn't open `%s' for reading: %s", + argv[1], strerror(errno)); + } + + doopen(&f, KOPEN_WRITE); + key_merge(&f, argv[1], fp, key_moan, 0); + doclose(&f); + return (0); +} + +/* --- @cmd_show@ --- */ + +#define LISTS(LI) \ + LI("Lists", list, \ + listtab[i].name, listtab[i].name) \ + LI("Hash functions", hash, \ + ghashtab[i], ghashtab[i]->name) \ + LI("Elliptic curves", ec, \ + ectab[i].name, ectab[i].name) \ + LI("Prime Diffie-Hellman groups", dh, \ + ptab[i].name, ptab[i].name) \ + LI("Binary Diffie-Hellman groups", bindh, \ + bintab[i].name, bintab[i].name) \ + LI("Key-generation algorithms", keygen, \ + algtab[i].name, algtab[i].name) \ + LI("Random seeding algorithms", seed, \ + seedtab[i].p, seedtab[i].p) + +MAKELISTTAB(listtab, LISTS) + +static int cmd_show(int argc, char *argv[]) +{ + return (displaylists(listtab, argv + 1)); +} + +/*----- Main command table ------------------------------------------------*/ + +static int cmd_help(int argc, char *argv[]); + +static cmd cmds[] = { + { "help", cmd_help, "help [COMMAND...]" }, + { "show", cmd_show, "show [ITEM...]" }, + { "list", cmd_list, "list [-uqv] [-f FILTER] [TAG...]", "\ +Options:\n\ +\n\ +-u, --utc Display expiry times etc. in UTC, not local time.\n\ +-q, --quiet Show less information.\n\ +-v, --verbose Show more information.\n\ +" }, + { "fingerprint", cmd_finger, "fingerprint [-f FILTER] [TAG...]", "\ +Options:\n\ +\n\ +-f, --filter=FILT Only hash key components matching FILT.\n\ +-a, --algorithm=HASH Use the named HASH algorithm.\n\ + ($ show hash for list.)\n\ +" }, + { "verify", cmd_verify, "verify [-f FILTER] TAG FINGERPRINT", "\ +Options:\n\ +\n\ +-f, --filter=FILT Only hash key components matching FILT.\n\ +-a, --algorithm=HASH Use the named HASH algorithm.\n\ + ($ show hash for list.)\n\ +" }, + { "extract", cmd_extract, "extract [-f FILTER] FILE [TAG...]", "\ +Options:\n\ +\n\ +-f, --filter=FILT Only extract key components matching FILT.\n\ +" }, + { "merge", cmd_merge, "merge FILE" }, + { "expire", cmd_expire, "expire TAG..." }, + { "delete", cmd_delete, "delete TAG..." }, + { "setattr", cmd_setattr, "setattr TAG ATTR..." }, + { "getattr", cmd_getattr, "getattr TAG ATTR" }, + { "comment", cmd_comment, "comment TAG [COMMENT]" }, + { "lock", cmd_lock, "lock QTAG" }, + { "unlock", cmd_unlock, "unlock QTAG" }, + { "tag", cmd_tag, "tag [-r] TAG [NEW-TAG]", "\ +Options:\n\ +\n\ +-r, --retag Untag any key currently called new-tag.\n\ +" }, + { "tidy", cmd_tidy, "tidy" }, + { "add", cmd_add, + "add [-OPTIONS] TYPE [ATTR...]\n\ + Options: [-lqrLKS] [-a ALG] [-bB BITS] [-p PARAM] [-R TAG]\n\ + [-A SEEDALG] [-s SEED] [-n BITS] [-I KEYID]\n\ + [-e EXPIRE] [-t TAG] [-c COMMENT]", "\ +Options:\n\ +\n\ +-a, --algorithm=ALG Generate keys suitable for ALG.\n\ + ($ show keygen for list.)\n\ +-b, --bits=N Generate an N-bit key.\n\ +-B, --qbits=N Use an N-bit subgroup or factors.\n\ +-p, --parameters=TAG Get group parameters from TAG.\n\ +-C, --curve=NAME Use elliptic curve or DH group NAME.\n\ + ($ show ec or $ show dh for list.)\n\ +-A, --seedalg=ALG Use pseudorandom generator ALG to generate key.\n\ + ($ show seed for list.)\n\ +-s, --seed=BASE64 Use Base64-encoded string BASE64 as seed.\n\ +-n, --newseed=COUNT Generate new COUNT-bit seed.\n\ +-e, --expire=TIME Make the key expire after TIME.\n\ +-c, --comment=STRING Attach the command STRING to the key.\n\ +-t, --tag=TAG Tag the key with the name TAG.\n\ +-r, --retag Untag any key currently with that tag.\n\ +-R, --rand-id=TAG Use key named TAG for the random number generator.\n\ +-I, --key-id=ID Force the key-id for the new key.\n\ +-l, --lock Lock the generated key with a passphrase.\n\ +-q, --quiet Don't give progress indicators while working.\n\ +-L, --lim-lee Generate Lim-Lee primes for Diffie-Hellman groups.\n\ +-K, --kcdsa Generate KCDSA-style Lim-Lee primes for DH groups.\n\ +-S, --subgroup Use a prime-order subgroup for Diffie-Hellman.\n\ +" }, + { 0, 0, 0 } +}; + +static int cmd_help(int argc, char *argv[]) +{ + sc_help(cmds, stdout, argv + 1); + return (0); +} + +/*----- Main code ---------------------------------------------------------*/ + +/* --- Helpful GNUy functions --- */ + +static void usage(FILE *fp) +{ + pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n"); +} + +void version(FILE *fp) +{ + pquis(fp, "$, Catacomb version " VERSION "\n"); +} + +void help_global(FILE *fp) +{ + usage(fp); + fputs("\n\ +Performs various simple key management operations.\n\ +\n\ +Global command line options:\n\ +\n\ +-h, --help [COMMAND...] Display this help text (or help for COMMANDs).\n\ +-v, --version Display version number.\n\ +-u, --usage Display short usage summary.\n\ +\n\ +-k, --keyring=FILE Read and write keys in FILE.\n", + fp); +} + +/* --- @main@ --- * + * + * Arguments: @int argc@ = number of command line arguments + * @char *argv[]@ = array of command line arguments + * + * Returns: Nonzero on failure. + * + * Use: Main program. Performs simple key management functions. + */ + +int main(int argc, char *argv[]) +{ + unsigned f = 0; + +#define f_bogus 1u + + /* --- Initialization --- */ + + ego(argv[0]); + sub_init(); + + /* --- Parse command line options --- */ + + for (;;) { + static struct option opt[] = { + + /* --- Standard GNUy help options --- */ + + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "usage", 0, 0, 'u' }, + + /* --- Real live useful options --- */ + + { "keyring", OPTF_ARGREQ, 0, 'k' }, + + /* --- Magic terminator --- */ + + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "+hvu k:", opt, 0, 0, 0); + + if (i < 0) + break; + switch (i) { + + /* --- GNU help options --- */ + + case 'h': + sc_help(cmds, stdout, argv + optind); + exit(0); + case 'v': + version(stdout); + exit(0); + case 'u': + usage(stdout); + exit(0); + + /* --- Real useful options --- */ + + case 'k': + keyfile = optarg; + break; + + /* --- Bogosity --- */ + + default: + f |= f_bogus; + break; + } + } + + /* --- Complain about excessive bogons --- */ + + if (f & f_bogus || optind == argc) { + usage(stderr); + exit(1); + } + + /* --- Initialize the Catacomb random number generator --- */ + + rand_noisesrc(RAND_GLOBAL, &noise_source); + rand_seed(RAND_GLOBAL, 160); + + /* --- Dispatch to appropriate command handler --- */ + + argc -= optind; + argv += optind; + optind = 0; + return (findcmd(cmds, argv[0])->cmd(argc, argv)); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/keyring.5 b/progs/keyring.5 similarity index 100% rename from keyring.5 rename to progs/keyring.5 diff --git a/mkphrase.1 b/progs/mkphrase.1 similarity index 100% rename from mkphrase.1 rename to progs/mkphrase.1 diff --git a/progs/mkphrase.c b/progs/mkphrase.c new file mode 100644 index 0000000..17fcb9c --- /dev/null +++ b/progs/mkphrase.c @@ -0,0 +1,456 @@ +/* -*-c-*- + * + * Generate passphrases from word lists + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "grand.h" +#include "noise.h" +#include "rand.h" + +/*----- Global state ------------------------------------------------------*/ + +static unsigned min = 0, max = 256; /* Word length bounds */ +static unsigned minbits = 128, maxbits = UINT_MAX; /* Acceptable entropy */ +static unsigned count = 1; /* How many passphrases to make */ + +static const char wchars[] = "abcdefghijklmnopqrstuvwxyz'"; + +typedef struct ppgen_ops { + const char *name; /* Name of the generator */ + void *(*init)(void); /* Initialize generator */ + void (*scan)(FILE */*fp*/, void */*p*/); /* Scan an input word list */ + void (*endscan)(void */*p*/); /* Scanning phase completed */ + double (*gen)(dstr */*d*/, grand */*r*/, void */*p*/); + /* Emit word and return entropy */ + void (*done)(void */*p*/); /* Close down generator */ +} ppgen_ops; + +/*----- Word list ---------------------------------------------------------*/ + +#ifndef STRING_V +# define STRING_V + DA_DECL(string_v, char *); +#endif + +typedef struct wlist { + string_v sv; + sym_table tab; + char *buf; + double logp; +} wlist; + +static void *wordlist_init(void) +{ + wlist *w = xmalloc(sizeof(wlist)); + sym_create(&w->tab); + w->logp = 0; + return (w); +} + +static void wordlist_scan(FILE *fp, void *p) +{ + wlist *w = p; + dstr d = DSTR_INIT; + unsigned f = 0; + + for (;;) { + int ch = getc(fp); + if (ch == EOF || isspace(ch)) { + DPUTZ(&d); + if (f && d.len >= min && d.len <= max) + sym_find(&w->tab, d.buf, d.len + 1, sizeof(sym_base), 0); + f = 0; + DRESET(&d); + if (ch == EOF) + break; + continue; + } + ch = tolower(ch); + if (strchr(wchars, ch)) { + DPUTC(&d, ch); + f = 1; + } + } + + dstr_destroy(&d); +} + +static void wordlist_endscan(void *p) +{ + wlist *w = p; + size_t buflen = 0; + sym_iter i; + sym_base *b; + char *q; + + for (sym_mkiter(&i, &w->tab); (b = sym_next(&i)) != 0; ) + buflen += b->len; + w->buf = xmalloc(buflen); + q = w->buf; + DA_CREATE(&w->sv); + for (sym_mkiter(&i, &w->tab); (b = sym_next(&i)) != 0; ) { + memcpy(q, SYM_NAME(b), b->len); + DA_PUSH(&w->sv, q); + q += b->len; + } + sym_destroy(&w->tab); + w->logp = log(DA_LEN(&w->sv))/log(2); +} + +static double wordlist_gen(dstr *d, grand *r, void *p) +{ + wlist *w = p; + uint32 i = r->ops->range(r, DA_LEN(&w->sv)); + DPUTS(d, DA(&w->sv)[i]); + return (w->logp); +} + +static void wordlist_done(void *p) +{ + wlist *w = p; + xfree(w->buf); + DA_DESTROY(&w->sv); + xfree(w); +} + +static ppgen_ops wordlist_ops = { + "wordlist", + wordlist_init, wordlist_scan, wordlist_endscan, wordlist_gen, wordlist_done +}; + +/*----- Markov word model -------------------------------------------------*/ + +enum { + C_START = 27, + C_END, + VECSZ +}; + +typedef struct node { + uint32 count; + uint32 p[VECSZ]; +} node; + +static void *markov_init(void) +{ + node (*model)[VECSZ][VECSZ][VECSZ] = xmalloc(sizeof(*model)); + unsigned i, j, k, l; + + for (i = 0; i < VECSZ; i++) { + for (j = 0; j < VECSZ; j++) { + for (k = 0; k < VECSZ; k++) { + node *n = &(*model)[i][j][k]; + n->count = 0; + for (l = 0; l < VECSZ; l++) + n->p[l] = 0; + } + } + } + + return (model); +} + +static void markov_scan(FILE *fp, void *p) +{ + node (*model)[VECSZ][VECSZ][VECSZ] = p; + unsigned i = C_START, j = C_START, k = C_START, l = C_END; + + for (;;) { + int ch = getc(fp); + const char *q; + node *n = &(*model)[i][j][k]; + + if (ch == EOF || isspace(ch)) { + if (l != C_END) { + l = C_END; + n->count++; + n->p[l]++; + i = j = k = C_START; + } + if (ch == EOF) + break; + continue; + } + + if ((q = strchr(wchars, tolower(ch))) == 0) + continue; + l = q - wchars; + n->count++; + n->p[l]++; + i = j; j = k; k = l; + } +} + +static double markov_gen(dstr *d, grand *r, void *p) +{ + node (*model)[VECSZ][VECSZ][VECSZ] = p; + unsigned i = C_START, j = C_START, k = C_START, l; + double logp = 0; + double log2 = log(2); + + for (;;) { + node *n = &(*model)[i][j][k]; + uint32 z = r->ops->range(r, n->count); + for (l = 0; z >= n->p[l]; z -= n->p[l++]) + ; + logp -= log((double)n->p[l]/(double)n->count)/log2; + if (l == C_END) + break; + DPUTC(d, wchars[l]); + i = j; j = k; k = l; + } + + return (logp); +} + +static void markov_done(void *p) +{ + node (*model)[VECSZ][VECSZ][VECSZ] = p; + xfree(model); +} + +static ppgen_ops markov_ops = { + "markov", + markov_init, markov_scan, 0, markov_gen, markov_done +}; + +/*----- Main code ---------------------------------------------------------*/ + +static ppgen_ops *ppgentab[] = { + &markov_ops, + &wordlist_ops, + 0 +}; + +static void version(FILE *fp) +{ + pquis(fp, "$, Catacomb version " VERSION "\n"); +} + +static void usage(FILE *fp) +{ + pquis(fp, "\ +Usage: $ [-p] [-b MIN[-MAX]] [-g GEN] [-n COUNT]\n\ +\t[-r [MIN-]MAX] WORDLIST...\n \ +"); +} + +static void help(FILE *fp) +{ + ppgen_ops **ops; + version(fp); + fputc('\n', fp); + usage(fp); + pquis(fp, "\n\ +Generates random passphrases with the requested level of entropy. Options\n\ +supported are:\n\ +\n\ +-h, --help Show this help text.\n\ +-v, --version Show the program's version number.\n\ +-u, --usage Show a terse usage summary.\n\ +-b, --bits=MIN[-MAX] Minimum and maximum bits of entropy.\n\ +-g, --generator=GEN Use passphrase generator GEN.\n\ +-n, --count=COUNT Generate COUNT passphrases.\n\ +-p, --probability Show -log_2 of probability for each phrase.\n\ +-r, --range=[MIN-]MAX Supply minimum and maximum word lengths.\n\ +\n\ +Generators currently available:"); + for (ops = ppgentab; *ops; ops++) + fprintf(fp, " %s", (*ops)->name); + fputc('\n', fp); +} + +int main(int argc, char *argv[]) +{ + ppgen_ops *ops = ppgentab[0]; + unsigned f = 0; + void *ctx; + dstr d = DSTR_INIT; + dstr dd = DSTR_INIT; + unsigned i; + +#define f_bogus 1u +#define f_showp 2u + + ego(argv[0]); + for (;;) { + static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "usage", 0, 0, 'u' }, + { "bits", OPTF_ARGREQ, 0, 'b' }, + { "generator", OPTF_ARGREQ, 0, 'g' }, + { "count", OPTF_ARGREQ, 0, 'n' }, + { "probability", 0, 0, 'p' }, + { "range", OPTF_ARGREQ, 0, 'r' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "hvu b:g:n:pr:", opts, 0, 0, 0); + + if (i < 0) + break; + switch (i) { + case 'h': + help(stdout); + exit(0); + case 'v': + version(stdout); + exit(0); + case 'u': + usage(stdout); + exit(0); + case 'b': { + char *p; + minbits = strtoul(optarg, &p, 0); + if (*p == '-') + maxbits = strtoul(p + 1, &p, 0); + else + maxbits = UINT_MAX; + if (*p || minbits > maxbits) + die(EXIT_FAILURE, "bad entropy range `%s'", optarg); + } break; + case 'g': { + ppgen_ops **p; + size_t n = strlen(optarg); + ops = 0; + for (p = ppgentab; *p; p++) { + if (strncmp(optarg, (*p)->name, n) == 0) { + if (!(*p)->name[n]) { + ops = *p; + break; + } else if (ops) + die(EXIT_FAILURE, "ambiguous generator name `%s'", optarg); + ops = *p; + } + } + if (!ops) + die(EXIT_FAILURE, "unknown generator name `%s'", optarg); + } break; + case 'n': { + char *p; + unsigned long n = strtoul(optarg, &p, 0); + if (*p) + die(EXIT_FAILURE, "bad integer `%s'", optarg); + count = n; + } break; + case 'p': + f |= f_showp; + break; + case 'r': { + char *p; + unsigned long n = min, nn = max; + nn = strtoul(optarg, &p, 0); + if (*p == '-') { + n = nn; + nn = strtoul(p + 1, &p, 0); + } + if (*p || min > max) + die(EXIT_FAILURE, "bad range string `%s'", optarg); + min = n; max = nn; + } break; + default: + f |= f_bogus; + break; + } + } + + argc -= optind; + argv += optind; + if ((f & f_bogus) || !argc) { + usage(stderr); + exit(EXIT_FAILURE); + } + + rand_noisesrc(RAND_GLOBAL, &noise_source); + rand_seed(RAND_GLOBAL, 160); + + ctx = ops->init(); + while (*argv) { + if (strcmp(*argv, "-") == 0) + ops->scan(stdin, ctx); + else { + FILE *fp = fopen(*argv, "r"); + if (!fp) { + die(EXIT_FAILURE, "error opening file `%s': %s", + *argv, strerror(errno)); + } + ops->scan(fp, ctx); + fclose(fp); + } + argv++; + } + if (ops->endscan) + ops->endscan(ctx); + + for (i = 0; !count || i < count; ) { + double logp = 0; + DRESET(&d); + while (logp < minbits) { + double pp; + DRESET(&dd); + pp = ops->gen(&dd, &rand_global, ctx); + if (!pp || dd.len < min || dd.len > max) + continue; + if (logp) + DPUTC(&d, ' '); + DPUTD(&d, &dd); + logp += pp; + } + if (logp >= (double)maxbits + 1) + continue; + dstr_write(&d, stdout); + if (f & f_showp) + printf(" [%g]", logp); + fputc('\n', stdout); + i++; + } + + ops->done(ctx); + dstr_destroy(&d); + dstr_destroy(&dd); + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/progs/perftest.c b/progs/perftest.c new file mode 100644 index 0000000..97a2e0f --- /dev/null +++ b/progs/perftest.c @@ -0,0 +1,614 @@ +/* -*-c-*- + * + * Measure performance of various operations (Unix-specific) + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#define _FILE_OFFSET_BITS 64 + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "rand.h" +#include "mp.h" +#include "mprand.h" +#include "fibrand.h" +#include "rsa.h" +#include "mpmont.h" +#include "mpbarrett.h" +#include "dh.h" +#include "pgen.h" +#include "ec.h" +#include "group.h" + +#include "cc.h" +#include "gcipher.h" +#include "ghash.h" +#include "gmac.h" +#include "ectab.h" +#include "ptab.h" + +/*----- Options -----------------------------------------------------------*/ + +typedef struct opts { + const char *name; /* Pre-configured named thing */ + unsigned fbits; /* Field size bits */ + unsigned gbits; /* Group size bits */ + unsigned n; /* Number of factors */ + unsigned i; /* Number of intervals (or zero) */ + double t; /* Time for each interval (secs) */ + unsigned f; /* Flags */ +#define OF_NOCHECK 1u /* Don't do group checking */ +} opts; + +/*----- Job switch --------------------------------------------------------*/ + +/* --- Barrett exponentiation --- */ + +typedef struct bar_ctx { + size_t n; + mpbarrett b; + mp_expfactor *e; +} bar_ctx; + +static void *bar_init(opts *o) +{ + bar_ctx *c = CREATE(bar_ctx); + gprime_param gp; + qd_parse qd; + size_t i; + + if (o->name) { + qd.p = o->name; + if (dh_parse(&qd, &gp)) + die(1, "bad prime group: %s", qd.e); + } else { + if (!o->fbits) o->fbits = 1024; + dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0); + } + mpbarrett_create(&c->b, gp.p); + if (!o->n) o->n = 1; + c->n = o->n; + c->e = xmalloc(c->n * sizeof(group_expfactor)); + for (i = 0; i < c->n; i++) { + c->e[i].base = mprand_range(MP_NEW, gp.p, &rand_global, 0); + c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0); + } + dh_paramfree(&gp); + return (c); +} + +static void bar_run(void *cc) +{ + bar_ctx *c = cc; + mp *d = mpbarrett_exp(&c->b, MP_NEW, c->e[0].base, c->e[0].exp); + MP_DROP(d); +} + +static void barsim_run(void *cc) +{ + bar_ctx *c = cc; + mp *d = mpbarrett_mexp(&c->b, MP_NEW, c->e, c->n); + MP_DROP(d); +} + +/* --- Montgomery exponentiation --- */ + +typedef struct mont_ctx { + size_t n; + mpmont m; + mp_expfactor *e; +} mont_ctx; + +static void *mont_init(opts *o) +{ + mont_ctx *c = CREATE(mont_ctx); + gprime_param gp; + qd_parse qd; + size_t i; + + if (o->name) { + qd.p = o->name; + if (dh_parse(&qd, &gp)) + die(1, "bad prime group: %s", qd.e); + } else { + if (!o->fbits) o->fbits = 1024; + dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0); + } + mpmont_create(&c->m, gp.p); + if (!o->n) o->n = 1; + c->n = o->n; + c->e = xmalloc(c->n * sizeof(mp_expfactor)); + for (i = 0; i < c->n; i++) { + c->e[i].base = mprand_range(MP_NEW, gp.p, &rand_global, 0); + c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0); + } + dh_paramfree(&gp); + return (c); +} + +static void mont_run(void *cc) +{ + mont_ctx *c = cc; + mp *d = mpmont_expr(&c->m, MP_NEW, c->e[0].base, c->e[0].exp); + MP_DROP(d); +} + +static void montsim_run(void *cc) +{ + mont_ctx *c = cc; + mp *d = mpmont_mexpr(&c->m, MP_NEW, c->e, c->n); + MP_DROP(d); +} + +/* --- Group exponentiation --- */ + +typedef struct gr_ctx { + size_t n; + group *g; + group_expfactor *e; +} gr_ctx; + +static void *grp_init(opts *o) +{ + gr_ctx *c = CREATE(gr_ctx); + const char *e; + gprime_param gp; + qd_parse qd; + size_t i; + + if (o->name) { + qd.p = o->name; + if (dh_parse(&qd, &gp)) + die(1, "bad prime group: %s", qd.e); + } else { + if (!o->fbits) o->fbits = 1024; + dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0); + } + c->g = group_prime(&gp); + if (!(o->f & OF_NOCHECK) && (e = G_CHECK(c->g, &rand_global)) != 0) + die(1, "bad group: %s", e); + if (!o->n) o->n = 1; + c->n = o->n; + c->e = xmalloc(c->n * sizeof(group_expfactor)); + for (i = 0; i < c->n; i++) { + c->e[i].base = G_CREATE(c->g); + G_FROMINT(c->g, c->e[i].base, + mprand_range(MP_NEW, gp.p, &rand_global, 0)); + c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0); + } + dh_paramfree(&gp); + return (c); +} + +static void *grec_init(opts *o) +{ + gr_ctx *c = CREATE(gr_ctx); + const char *e; + ec_info ei; + ec p = EC_INIT; + size_t i; + + if (!o->name) + die(1, "can't generate elliptic curves"); + if ((e = ec_getinfo(&ei, o->name)) != 0) + die(1, "bad curve: %s", e); + c->g = group_ec(&ei); + if (!(o->f & OF_NOCHECK) && (e = G_CHECK(c->g, &rand_global)) != 0) + die(1, "bad group: %s", e); + if (!o->n) o->n = 1; + c->n = o->n; + c->e = xmalloc(c->n * sizeof(group_expfactor)); + for (i = 0; i < c->n; i++) { + c->e[i].base = G_CREATE(c->g); + ec_rand(ei.c, &p, &rand_global); + G_FROMEC(c->g, c->e[i].base, &p); + c->e[i].exp = mprand_range(MP_NEW, ei.r, &rand_global, 0); + } + EC_DESTROY(&p); + return (c); +} + +static void gr_run(void *cc) +{ + gr_ctx *c = cc; + ge *x = G_CREATE(c->g); + G_EXP(c->g, x, c->e[0].base, c->e[0].exp); + G_DESTROY(c->g, x); +} + +static void grsim_run(void *cc) +{ + gr_ctx *c = cc; + ge *x = G_CREATE(c->g); + G_MEXP(c->g, x, c->e, c->n); + G_DESTROY(c->g, x); +} + +/* --- RSA --- */ + +typedef struct rsapriv_ctx { + rsa_priv rp; + rsa_privctx rpc; + mp *m; +} rsapriv_ctx; + +static void *rsapriv_init(opts *o) +{ + rsapriv_ctx *c = CREATE(rsapriv_ctx); + + if (!o->fbits) o->fbits = 1024; + rsa_gen(&c->rp, o->fbits, &rand_global, 0, pgen_evspin, 0); + rsa_privcreate(&c->rpc, &c->rp, 0); + c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0); + return (c); +} + +static void *rsaprivblind_init(opts *o) +{ + rsapriv_ctx *c = CREATE(rsapriv_ctx); + + if (!o->fbits) o->fbits = 1024; + rsa_gen(&c->rp, o->fbits, &rand_global, 0, pgen_evspin, 0); + rsa_privcreate(&c->rpc, &c->rp, fibrand_create(0)); + c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0); + return (c); +} + +static void rsapriv_run(void *cc) +{ + rsapriv_ctx *c = cc; + mp *d = rsa_privop(&c->rpc, MP_NEW, c->m); + MP_DROP(d); +} + +typedef struct rsapub_ctx { + rsa_pub rp; + rsa_pubctx rpc; + mp *m; +} rsapub_ctx; + +static void *rsapub_init(opts *o) +{ + rsapub_ctx *c = CREATE(rsapub_ctx); + rsa_priv rp; + + if (!o->fbits) o->fbits = 1024; + rsa_gen(&rp, o->fbits, &rand_global, 0, pgen_evspin, 0); + c->rp.n = MP_COPY(rp.n); + c->rp.e = MP_COPY(rp.e); + rsa_privfree(&rp); + rsa_pubcreate(&c->rpc, &c->rp); + c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0); + return (c); +} + +static void rsapub_run(void *cc) +{ + rsapub_ctx *c = cc; + mp *d = rsa_pubop(&c->rpc, MP_NEW, c->m); + MP_DROP(d); +} + +/* --- Symmetric encryption --- */ + +typedef struct ksched_ctx { + const gccipher *c; + octet *k; + size_t ksz; +} ksched_ctx; + +static void *ksched_init(opts *o) +{ + ksched_ctx *c = CREATE(ksched_ctx); + if (!o->name) + die(1, "must specify encryption scheme name"); + if ((c->c = gcipher_byname(o->name)) == 0) + die(1, "encryption scheme `%s' not known", o->name); + c->ksz = keysz(o->gbits/8, c->c->keysz); + c->k = xmalloc(c->ksz); + rand_get(RAND_GLOBAL, c->k, c->ksz); + return (c); +} + +static void ksched_run(void *cc) +{ + ksched_ctx *c = cc; + gcipher *gc = GC_INIT(c->c, c->k, c->ksz); + GC_DESTROY(gc); +} + +typedef struct enc_ctx { + gcipher *c; + octet *m; + size_t sz; + size_t n; +} enc_ctx; + +static void *enc_init(opts *o) +{ + enc_ctx *c = CREATE(enc_ctx); + const gccipher *cc; + size_t ksz; + octet *k; + if (!o->name) + die(1, "must specify encryption scheme name"); + if ((cc = gcipher_byname(o->name)) == 0) + die(1, "encryption scheme `%s' not known", o->name); + ksz = keysz(0, cc->keysz); + k = xmalloc(ksz); + rand_get(RAND_GLOBAL, k, ksz); + c->c = GC_INIT(cc, k, ksz); + xfree(k); + c->sz = o->gbits ? o->gbits : 65536; + c->n = o->n ? o->n : 16; + c->m = xmalloc(c->sz); + return (c); +} + +static void enc_run(void *cc) +{ + enc_ctx *c = cc; + size_t i; + for (i = 0; i < c->n; i++) + GC_ENCRYPT(c->c, c->m, c->m, c->sz); +} + +/* --- Hashing --- */ + +typedef struct hash_ctx { + const gchash *h; + octet *m; + size_t sz; + size_t n; +} hash_ctx; + +static void *hash_init(opts *o) +{ + hash_ctx *c = CREATE(hash_ctx); + if (!o->name) + die(1, "must specify hash function name"); + if ((c->h = ghash_byname(o->name)) == 0) + die(1, "hash function `%s' not known", o->name); + c->sz = o->gbits ? o->gbits : 65536; + c->n = o->n ? o->n : 16; + c->m = xmalloc(c->sz); + return (c); +} + +static void hash_run(void *cc) +{ + hash_ctx *c = cc; + size_t i; + ghash *h = GH_INIT(c->h); + for (i = 0; i < c->n; i++) + GH_HASH(h, c->m, c->sz); + GH_DONE(h, 0); + GH_DESTROY(h); +} + +/* --- Job table --- */ + +typedef struct jobops { + const char *name; + void *(*init)(opts *); + void (*run)(void *); +} jobops; + +static const jobops jobtab[] = { + { "g-prime-exp", grp_init, gr_run }, + { "g-ec-mul", grec_init, gr_run }, + { "g-prime-exp-sim", grp_init, grsim_run }, + { "g-ec-mul-sim", grec_init, grsim_run }, + { "barrett-exp", bar_init, bar_run }, + { "barrett-exp-sim", bar_init, barsim_run }, + { "mont-exp", mont_init, mont_run }, + { "mont-exp-sim", mont_init, montsim_run }, + { "rsa-priv", rsapriv_init, rsapriv_run }, + { "rsa-priv-blind", rsaprivblind_init, rsapriv_run }, + { "rsa-pub", rsapub_init, rsapub_run }, + { "ksched", ksched_init, ksched_run }, + { "enc", enc_init, enc_run }, + { "hash", hash_init, hash_run }, + { 0, 0, 0 } +}; + +/*----- Main code ---------------------------------------------------------*/ + +void version(FILE *fp) +{ + pquis(fp, "$, Catacomb " VERSION "\n"); +} + +static void usage(FILE *fp) +{ + pquis(fp, "Usage: $ [-options] job\n"); +} + +static void help(FILE *fp) +{ + version(fp); + putc('\n', fp); + usage(fp); + pquis(fp, "\n\ +Various performance tests.\n\ +\n\ +Options:\n\ +\n\ +-h, --help Show this help text.\n\ +-v, --version Show program version number.\n\ +-u, --usage Show terse usage message.\n\ +-l, --list [ITEM...] List all the various names of things.\n\ +\n\ +-C, --name=NAME Select curve/DH-group/enc/hash name.\n\ +-b, --field-bits Field size for g-prime and rsa.\n\ +-q, --no-check Don't check field/group for validity.\n\ +-B, --group-bits Group size for g-prime; key size for ksched;\n\ + data size for enc and hash.\n\ +-n, --factors=COUNT Number of factors for {exp,mul}-sim.\n\ +-i, --intervals=COUNT Number of intervals to run for. [0; forever]\n\ +-t, --time=TIME Length of an interval in seconds. [1]\n\ +"); +} + +#define LISTS(LI) \ + LI("Lists", list, \ + listtab[i].name, listtab[i].name) \ + LI("Jobs", job, \ + jobtab[i].name, jobtab[i].name) \ + LI("Elliptic curves", ec, \ + ectab[i].name, ectab[i].name) \ + LI("Diffie-Hellman groups", dh, \ + ptab[i].name, ptab[i].name) \ + LI("Encryption algorithms", cipher, \ + gciphertab[i], gciphertab[i]->name) \ + LI("Hash functions", hash, \ + ghashtab[i], ghashtab[i]->name) + +MAKELISTTAB(listtab, LISTS) + +static unsigned uarg(const char *what, const char *p) +{ + char *q; + unsigned long u; + errno = 0; + u = strtoul(p, &q, 0); + if (*q || u > UINT_MAX || q == p || errno) + die(1, "bad %s `%s'", what, p); + return (u); +} + +static double farg(const char *what, const char *p) +{ + char *q; + double f; + errno = 0; + f = strtod(p, &q); + if (*q || q == p || errno) + die(1, "bad %s `%s'", what, p); + return (f); +} + +int main(int argc, char *argv[]) +{ + int i; + opts o = { 0 }; + const jobops *j; + struct timeval tv_next, tv_now; + double t, ttot; + unsigned n; + unsigned long ii; + clock_t c_start, c_stop; + double itot; + void *p; + + ego(argv[0]); + o.t = 1; + for (;;) { + static const struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "usage", 0, 0, 'u' }, + { "list", 0, 0, 'l' }, + { "name", OPTF_ARGREQ, 0, 'C' }, + { "field-bits", OPTF_ARGREQ, 0, 'b' }, + { "group-bits", OPTF_ARGREQ, 0, 'B' }, + { "factors", OPTF_ARGREQ, 0, 'n' }, + { "intervals", OPTF_ARGREQ, 0, 'i' }, + { "time", OPTF_ARGREQ, 0, 't' }, + { "no-check", 0, 0, 'q' }, + { 0, 0, 0, 0 } + }; + + i = mdwopt(argc, argv, "hvulC:b:B:n:i:t:q", opts, 0, 0, 0); + if (i < 0) break; + switch (i) { + case 'h': help(stdout); exit(0); + case 'v': version(stdout); exit(0); + case 'u': usage(stdout); exit(0); + case 'l': exit(displaylists(listtab, argv + optind)); + case 'C': o.name = optarg; break; + case 'b': o.fbits = uarg("field bits", optarg); break; + case 'B': o.gbits = uarg("subgroup bits", optarg); break; + case 'n': o.n = uarg("factor count", optarg); break; + case 'i': o.i = uarg("interval count", optarg); break; + case 't': o.t = farg("interval length", optarg); break; + case 'q': o.f |= OF_NOCHECK; break; + default: usage(stderr); exit(1); + } + } + if (optind + 1 != argc) { usage(stderr); exit(1); } + + for (j = jobtab; j->name; j++) + if (strcmp(j->name, argv[optind]) == 0) break; + if (!j->name) die(1, "unknown job type `%s'", argv[optind]); + p = j->init(&o); + + n = 0; + ttot = itot = 0; + gettimeofday(&tv_now, 0); + do { + tv_addl(&tv_next, &tv_now, o.t, fmod(o.t * MILLION, MILLION)); + ii = 0; + c_start = clock(); + do { + j->run(p); + ii++; + gettimeofday(&tv_now, 0); + } while (TV_CMP(&tv_now, <, &tv_next)); + c_stop = clock(); + t = (double)(c_stop - c_start)/CLOCKS_PER_SEC; + itot += ii; + ttot += t; + printf("%5u: did = %5lu; /sec = %5f; avg /sec = %5f\n", + n, ii, ii/t, itot/ttot); + fflush(stdout); + n++; + } while (!o.i || n < o.i); + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pixie.1 b/progs/pixie.1 similarity index 100% rename from pixie.1 rename to progs/pixie.1 diff --git a/progs/pixie.c b/progs/pixie.c new file mode 100644 index 0000000..4a5e9ab --- /dev/null +++ b/progs/pixie.c @@ -0,0 +1,1460 @@ +/* -*-c-*- + * + * Passphrase pixie for Catacomb + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "arena.h" +#include "lmem.h" +#include "passphrase.h" +#include "pixie.h" + +/*----- Static variables --------------------------------------------------*/ + +static unsigned long timeout = 900; +static sel_state sel; +static unsigned verbose = 1; +static const char *command = 0; +static lmem lm; +static unsigned flags = 0; + +#define F_SYSLOG 1u +#define F_FETCH 2u + +/*----- Event logging -----------------------------------------------------*/ + +/* --- @log@ --- * + * + * Arguments: @const char *p@ = @printf@-style format string + * @...@ = extra arguments to fill in + * + * Returns: --- + * + * Use: Writes out a timestamped log message. + */ + +static void log(const char *p, ...) +{ + dstr d = DSTR_INIT; + va_list ap; + + if (!(flags & F_SYSLOG)) { + time_t t = time(0); + struct tm *tm = localtime(&t); + DENSURE(&d, 64); + d.len += strftime(d.buf, d.sz, "%Y-%m-%d %H:%M:%S ", tm); + } + va_start(ap, p); + dstr_vputf(&d, p, &ap); + va_end(ap); + + if (flags & F_SYSLOG) + syslog(LOG_NOTICE, "%s", d.buf); + else { + DPUTC(&d, '\n'); + dstr_write(&d, stderr); + } + DDESTROY(&d); +} + +/*----- Passphrase management ---------------------------------------------*/ + +/* --- Data structures --- */ + +typedef struct phrase { + struct phrase *next; + struct phrase *prev; + char *tag; + char *p; + unsigned long t; + sel_timer timer; + unsigned f; +} phrase; + +/* --- Variables --- */ + +#define P_ROOT ((phrase *)&p_root) +static struct { phrase *next; phrase *prev; } p_root = { P_ROOT, P_ROOT }; + +/* --- @p_free@ --- * + * + * Arguments: @phrase *p@ = pointer to phrase block + * + * Returns: --- + * + * Use: Frees a phrase block. + */ + +static void p_free(phrase *p) +{ + if (p->t) + sel_rmtimer(&p->timer); + xfree(p->tag); + l_free(&lm, p->p); + p->next->prev = p->prev; + p->prev->next = p->next; + DESTROY(p); +} + +/* --- @p_timer@ --- * + * + * Arguments: @struct timeval *tv@ = current time + * @void *p@ = pointer to phrase + * + * Returns: --- + * + * Use: Expires a passphrase. + */ + +static void p_timer(struct timeval *tv, void *p) +{ + phrase *pp = p; + if (verbose) + log("expiring passphrase `%s'", pp->tag); + p_free(pp); +} + +/* --- @p_alloc@ --- * + * + * Arguments: @size_t sz@ = amount of memory required + * + * Returns: Pointer to allocated memory, or null. + * + * Use: Allocates some locked memory, flushing old passphrases if + * there's not enough space. + */ + +static void *p_alloc(size_t sz) +{ + for (;;) { + char *p; + if ((p = l_alloc(&lm, sz)) != 0) + return (p); + if (P_ROOT->next == P_ROOT) + return (0); + if (verbose) { + log("flushing passphrase `%s' to free up needed space", + P_ROOT->next->tag); + } + p_free(P_ROOT->next); + } +} + +/* --- @p_find@ --- * + * + * Arguments: @const char *tag@ = pointer to tag to find + * + * Returns: Pointer to passphrase block, or null. + * + * Use: Finds a passphrase with a given tag. + */ + +static phrase *p_find(const char *tag) +{ + phrase *p; + + for (p = P_ROOT->next; p != P_ROOT; p = p->next) { + if (strcmp(p->tag, tag) == 0) { + if (p->t) { + struct timeval tv; + sel_rmtimer(&p->timer); + gettimeofday(&tv, 0); + tv.tv_sec += p->t; + sel_addtimer(&sel, &p->timer, &tv, p_timer, p); + } + p->next->prev = p->prev; + p->prev->next = p->next; + p->next = P_ROOT; + p->prev = P_ROOT->prev; + P_ROOT->prev->next = p; + P_ROOT->prev = p; + return (p); + } + } + return (0); +} + +/* --- @p_add@ --- * + * + * Arguments: @const char *tag@ = pointer to tag string + * @const char *p@ = pointer to passphrase + * @unsigned long t@ = expiry timeout + * + * Returns: Pointer to newly-added passphrase. + * + * Use: Adds a new passphrase. The tag must not already exist. + */ + +static phrase *p_add(const char *tag, const char *p, unsigned long t) +{ + size_t sz = strlen(p) + 1; + char *l = p_alloc(sz); + phrase *pp; + + /* --- Make sure the locked memory was allocated --- */ + + if (!l) + return (0); + + /* --- Fill in some other bits of the block --- */ + + pp = CREATE(phrase); + memcpy(l, p, sz); + pp->p = l; + pp->tag = xstrdup(tag); + pp->f = 0; + + /* --- Set the timer --- */ + + pp->t = t; + if (t) { + struct timeval tv; + gettimeofday(&tv, 0); + tv.tv_sec += t; + sel_addtimer(&sel, &pp->timer, &tv, p_timer, pp); + } + + /* --- Link the block into the chain --- */ + + pp->next = P_ROOT; + pp->prev = P_ROOT->prev; + P_ROOT->prev->next = pp; + P_ROOT->prev = pp; + return (pp); +} + +/* --- @p_flush@ --- * + * + * Arguments: @const char *tag@ = pointer to tag string, or zero for all + * + * Returns: --- + * + * Use: Immediately flushes either a single phrase or all of them. + */ + +static void p_flush(const char *tag) +{ + phrase *p; + + if (!tag && verbose > 1) + log("flushing all passphrases"); + p = P_ROOT->next; + while (p != P_ROOT) { + phrase *pp = p->next; + if (!tag) + p_free(p); + else if (strcmp(p->tag, tag) == 0) { + if (verbose > 1) + log("flushing passphrase `%s'", tag); + p_free(p); + break; + } + p = pp; + } +} + +/*----- Reading passphrases -----------------------------------------------*/ + +/* --- @p_request@ --- * + * + * Arguments: @const char *msg@ = message string + * @const char *tag@ = pointer to tag string + * @char *buf@ = pointer to (locked) buffer + * @size_t sz@ = size of buffer + * + * Returns: Zero if all went well, nonzero otherwise. + * + * Use: Requests a passphrase from the user. + */ + +static int p_request(const char *msg, const char *tag, char *buf, size_t sz) +{ + /* --- If there's a passphrase-fetching command, run it --- */ + + if (command) { + dstr d = DSTR_INIT; + const char *p; + int fd[2]; + pid_t kid; + int r; + int rc; + + /* --- Substitute the prompt string into the command --- */ + + p = command; + for (;;) { + const char *q = strchr(p, '%'); + if (!q || !q[1]) { + DPUTS(&d, p); + break; + } + DPUTM(&d, p, q - p); + p = q + 1; + switch (*p) { + case 'm': + DPUTS(&d, msg); + break; + case 't': + DPUTS(&d, tag); + break; + default: + DPUTC(&d, '%'); + DPUTC(&d, *p); + break; + } + p++; + } + DPUTZ(&d); + + /* --- Create a pipe and start a child process --- */ + + if (pipe(fd)) + goto fail_1; + if ((kid = fork()) < 0) + goto fail_2; + + /* --- Child process --- */ + + fflush(0); + if (kid == 0) { + if (dup2(fd[1], STDOUT_FILENO) < 0) + _exit(127); + close(fd[0]); + execl("/bin/sh", "sh", "-c", d.buf, (char *)0); + _exit(127); + } + + /* --- Read the data back into my buffer --- */ + + close(fd[1]); + if ((r = read(fd[0], buf, sz - 1)) >= 0) { + char *q = memchr(buf, '\n', r); + if (!q) + q = buf + r; + *q = 0; + } + close(fd[0]); + waitpid(kid, &rc, 0); + dstr_destroy(&d); + if (r < 0 || rc != 0) + goto fail_0; + goto ok; + + /* --- Tidy up when things go wrong --- */ + + fail_2: + close(fd[0]); + close(fd[1]); + fail_1: + dstr_destroy(&d); + fail_0: + return (-1); + } + + /* --- Read a passphrase from the terminal --- * + * + * Use the standard Catacomb passphrase-reading function, so it'll read the + * passphrase from a file descriptor or something if the appropriate + * environment variable is set. + */ + + { + dstr d = DSTR_INIT; + int rc; + dstr_putf(&d, "%s %s: ", msg, tag); + rc = pixie_getpass(d.buf, buf, sz); + dstr_destroy(&d); + if (rc) + return (rc); + goto ok; + } + + /* --- Sort out the buffer --- * + * + * Strip leading spaces. + */ + +ok: { + char *p = buf; + size_t len; + while (isspace((unsigned char)*p)) + p++; + len = strlen(p); + memmove(buf, p, len); + p[len] = 0; + } + + /* --- Done --- */ + + return (0); +} + +/* --- @p_get@ --- * + * + * Arguments: @const char **q@ = where to store the result + * @const char *tag@ = pointer to tag string + * @unsigned mode@ = reading mode (verify?) + * @time_t exp@ = expiry time suggestion + * + * Returns: Zero if successful, @-1@ on a read failure, or @+1@ if the + * passphrase is missing and there is no fetcher. (This will + * always happen if there is no fetcher and @mode@ is + * @PMODE_VERIFY@. + * + * Use: Reads a passphrase from somewhere. + */ + +static int p_get(const char **q, const char *tag, unsigned mode, time_t exp) +{ +#define LBUFSZ 1024 + + phrase *p; + char *pp = 0; + + /* --- Write a log message --- */ + + if (verbose > 1) + log("passphrase `%s' requested", tag); + + /* --- If there is no fetcher, life is simpler --- */ + + if (!(flags & F_FETCH)) { + if (mode == PMODE_VERIFY) + return (+1); + if ((p = p_find(tag)) == 0) + return (+1); + *q = p->p; + return (0); + } + + /* --- Try to find the phrase --- */ + + if (mode == PMODE_VERIFY) + p_flush(tag); + if (mode == PMODE_VERIFY || (p = p_find(tag)) == 0) { + if ((pp = p_alloc(LBUFSZ)) == 0) + goto fail; + if (p_request(mode == PMODE_READ ? "Passphrase" : "New passphrase", + tag, pp, LBUFSZ) < 0) + goto fail; + p = p_add(tag, pp, exp); + if (!p) + goto fail; + } + + /* --- If verification is requested, verify the passphrase --- */ + + if (mode == PMODE_VERIFY) { + if (!pp && (pp = p_alloc(LBUFSZ)) == 0) + goto fail; + if (p_request("Verify passphrase", tag, pp, LBUFSZ) < 0) + goto fail; + if (strcmp(pp, p->p) != 0) { + if (verbose) + log("passphrases for `%s' don't match", tag); + p_free(p); + goto fail; + } + } + + /* --- Tidy up and return the passphrase --- */ + + if (pp) { + memset(pp, 0, LBUFSZ); + l_free(&lm, pp); + } + *q = p->p; + return (0); + + /* --- Tidy up if things went wrong --- */ + +fail: + if (pp) { + memset(pp, 0, LBUFSZ); + l_free(&lm, pp); + } + return (-1); + +#undef LBUFSZ +} + +/*----- Server command parsing --------------------------------------------*/ + +/* --- Data structures --- */ + +typedef struct pixserv { + selbuf b; + int fd; + sel_timer timer; + unsigned f; +} pixserv; + +#define px_stdin 1u + +#define PIXSERV_TIMEOUT 30 + +/* --- @pixserv_expire@ --- * + * + * Arguments: @struct timeval *tv@ = pointer to current time + * @void *p@ = pointer to server block + * + * Returns: --- + * + * Use: Expires a pixie connection if the remote end decides he's not + * interested any more. + */ + +static void pixserv_expire(struct timeval *tv, void *p) +{ + pixserv *px = p; + if (px->fd != px->b.reader.fd) + close(px->fd); + selbuf_destroy(&px->b); + close(px->b.reader.fd); + DESTROY(px); +} + +/* --- @pixserv_write@ --- * + * + * Arguments: @pixserv *px@ = pointer to server block + * @const char *p@ = pointer to skeleton string + * @...@ = other arguments to fill in + * + * Returns: --- + * + * Use: Formats a string and emits it to the output file. + */ + +static void pixserv_write(pixserv *px, const char *p, ...) +{ + dstr d = DSTR_INIT; + va_list ap; + + va_start(ap, p); + dstr_vputf(&d, p, &ap); + write(px->fd, d.buf, d.len); + va_end(ap); + dstr_destroy(&d); +} + +/* --- @pixserv_timeout@ --- * + * + * Arguments: @const char *p@ = pointer to timeout string + * + * Returns: Timeout in seconds. + * + * Use: Translates a string to a timeout value in seconds. + */ + +static unsigned long pixserv_timeout(const char *p) +{ + unsigned long t; + char *q; + + if (!p) + return (timeout); + + t = strtoul(p, &q, 0); + switch (*q) { + case 'd': t *= 24; + case 'h': t *= 60; + case 'm': t *= 60; + case 's': if (q[1] != 0) + default: t = 0; + case 0: break; + } + return (t); +} + +/* --- @pixserv_line@ --- * + * + * Arguments: @char *s@ = pointer to the line read + * @size_t len@ = length of the line + * @void *p@ = pointer to server block + * + * Returns: --- + * + * Use: Handles a line read from the client. + */ + +static void pixserv_line(char *s, size_t len, void *p) +{ + pixserv *px = p; + char *q, *qq; + unsigned mode; + + /* --- Handle an end-of-file --- */ + + if (!(px->f & px_stdin)) + sel_rmtimer(&px->timer); + if (!s) { + if (px->fd != px->b.reader.fd) + close(px->fd); + selbuf_destroy(&px->b); + close(px->b.reader.fd); + return; + } + + /* --- Fiddle the timeout --- */ + + if (!(px->f & px_stdin)) { + struct timeval tv; + gettimeofday(&tv, 0); + tv.tv_sec += PIXSERV_TIMEOUT; + sel_addtimer(&sel, &px->timer, &tv, pixserv_expire, px); + } + + /* --- Scan out the first word --- */ + + if ((q = str_getword(&s)) == 0) + return; + for (qq = q; *qq; qq++) + *qq = tolower((unsigned char)*qq); + + /* --- Handle a help request --- */ + + if (strcmp(q, "help") == 0) { + pixserv_write(px, "\ +INFO Commands supported:\n\ +INFO HELP\n\ +INFO LIST\n\ +INFO PASS tag [expire]\n\ +INFO VERIFY tag [expire]\n\ +INFO FLUSH [tag]\n\ +INFO SET tag [expire] -- phrase\n\ +INFO QUIT\n\ +OK\n\ +"); + } + + /* --- List the passphrases --- */ + + else if (strcmp(q, "list") == 0) { + phrase *p; + + for (p = P_ROOT->next; p != P_ROOT; p = p->next) { + if (!p->t) + pixserv_write(px, "ITEM %s no-expire\n", p->tag); + else { + struct timeval tv; + gettimeofday(&tv, 0); + TV_SUB(&tv, &p->timer.tv, &tv); + pixserv_write(px, "ITEM %s %i\n", p->tag, tv.tv_sec); + } + } + pixserv_write(px, "OK\n"); + } + + /* --- Request a passphrase --- */ + + else if ((mode = PMODE_READ, strcmp(q, "pass") == 0) || + (mode = PMODE_VERIFY, strcmp(q, "verify") == 0)) { + unsigned long t; + const char *p; + int rc; + + if ((q = str_getword(&s)) == 0) + pixserv_write(px, "FAIL missing tag\n"); + else if ((t = pixserv_timeout(s)) == 0) + pixserv_write(px, "FAIL bad timeout\n"); + else { + rc = p_get(&p, q, mode, t > timeout ? timeout : t); + switch (rc) { + case 0: + pixserv_write(px, "OK %s\n", p); + break; + case -1: + pixserv_write(px, "FAIL error reading passphrase\n"); + break; + case +1: + pixserv_write(px, "MISSING\n"); + break; + } + } + } + + /* --- Flush existing passphrases --- */ + + else if (strcmp(q, "flush") == 0) { + q = str_getword(&s); + p_flush(q); + pixserv_write(px, "OK\n"); + } + + /* --- Set a passphrase --- */ + + else if (strcmp(q, "set") == 0) { + char *tag; + unsigned long t; + if ((tag = str_getword(&s)) == 0) + pixserv_write(px, "FAIL missing tag\n"); + else if ((q = str_getword(&s)) == 0) + pixserv_write(px, "FAIL no passphrase\n"); + else { + if (strcmp(q, "--") != 0) { + t = pixserv_timeout(q); + q = str_getword(&s); + } else + t = pixserv_timeout(0); + if (!q) + pixserv_write(px, "FAIL no passphrase\n"); + else if (strcmp(q, "--") != 0) + pixserv_write(px, "FAIL rubbish found before passphrase\n"); + else { + p_flush(tag); + p_add(tag, s, t); + pixserv_write(px, "OK\n"); + } + } + } + + /* --- Shut the server down --- */ + + else if (strcmp(q, "quit") == 0) { + if (verbose) + log("%s client requested shutdown", + px->f & px_stdin ? "local" : "remote"); + pixserv_write(px, "OK\n"); + exit(0); + } + + /* --- Report an error for other commands --- */ + + else + pixserv_write(px, "FAIL unknown command `%s'\n", q); +} + +/* --- @pixserv_create@ --- * + * + * Arguments: @int fd@ = file descriptor to read from + * @int ofd@ = file descriptor to write to + * + * Returns: Pointer to the new connection. + * + * Use: Creates a new Pixie server instance for a new connection. + */ + +static pixserv *pixserv_create(int fd, int ofd) +{ + pixserv *px = CREATE(pixserv); + struct timeval tv; + fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); + if (ofd != fd) + fdflags(ofd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); + px->fd = ofd; + selbuf_init(&px->b, &sel, fd, pixserv_line, px); + px->b.b.a = arena_secure; + selbuf_setsize(&px->b, 1024); + gettimeofday(&tv, 0); + tv.tv_sec += PIXSERV_TIMEOUT; + sel_addtimer(&sel, &px->timer, &tv, pixserv_expire, px); + px->f = 0; + return (px); +} + +/* --- @pixserv_accept@ --- * + * + * Arguments: @int fd@ = file descriptor + * @unsigned mode@ = what's happened + * @void *p@ = an uninteresting argument + * + * Returns: --- + * + * Use: Accepts a new connection. + */ + +static void pixserv_accept(int fd, unsigned mode, void *p) +{ + int nfd; + struct sockaddr_un sun; + size_t sunsz = sizeof(sun); + + if (mode != SEL_READ) + return; + if ((nfd = accept(fd, (struct sockaddr *)&sun, &sunsz)) < 0) { + if (verbose && errno != EAGAIN && errno != EWOULDBLOCK && + errno != ECONNABORTED && errno != EPROTO && errno != EINTR) + log("new connection failed: %s", strerror(errno)); + return; + } + pixserv_create(nfd, nfd); +} + +/*----- Setting up the server ---------------------------------------------*/ + +/* --- @unlinksocket@ --- * + * + * Arguments: --- + * + * Returns: --- + * + * Use: Tidies up the socket when it's finished with. + */ + +static char *sockpath; + +static void unlinksocket(void) +{ + unlink(sockpath); + l_purge(&lm); +} + +/* --- @pix_sigdie@ --- * + * + * Arguments: @int sig@ = signal number + * @void *p@ = uninteresting argument + * + * Returns: --- + * + * Use: Shuts down the program after a fatal signal. + */ + +static void pix_sigdie(int sig, void *p) +{ + if (verbose) { + char *p; + char buf[20]; + + switch (sig) { + case SIGTERM: p = "SIGTERM"; break; + case SIGINT: p = "SIGINT"; break; + default: + sprintf(buf, "signal %i", sig); + p = buf; + break; + } + log("shutting down on %s", p); + } + exit(0); +} + +/* --- @pix_sigflush@ --- * + * + * Arguments: @int sig@ = signal number + * @void *p@ = uninteresting argument + * + * Returns: --- + * + * Use: Flushes the passphrase cache on receipt of a signal. + */ + +static void pix_sigflush(int sig, void *p) +{ + if (verbose) { + char *p; + char buf[20]; + + switch (sig) { + case SIGHUP: p = "SIGHUP"; break; + case SIGQUIT: p = "SIGQUIT"; break; + default: + sprintf(buf, "signal %i", sig); + p = buf; + break; + } + log("received %s; flushing passphrases", p); + } + p_flush(0); +} + +/* --- @pix_setup@ --- * + * + * Arguments: @struct sockaddr_un *sun@ = pointer to address to use + * @size_t sz@ = size of socket address + * + * Returns: --- + * + * Use: Sets up the pixie's Unix-domain socket. + */ + +static void pix_setup(struct sockaddr_un *sun, size_t sz) +{ + int fd; + + /* --- Set up the parent directory --- */ + + { + char *p = sun->sun_path; + char *q = strrchr(p, '/'); + + if (q) { + dstr d = DSTR_INIT; + struct stat st; + + DPUTM(&d, p, q - p); + DPUTZ(&d); + + mkdir(d.buf, 0700); + if (stat(d.buf, &st)) + die(1, "couldn't stat `%s': %s", d.buf, strerror(errno)); + if (!S_ISDIR(st.st_mode)) + die(1, "object `%s' isn't a directory", d.buf); + if (st.st_mode & 0077) + die(1, "parent directory `%s' has group or world access", d.buf); + dstr_destroy(&d); + } + } + + /* --- Initialize the socket --- */ + + { + int n = 5; + int e; + + umask(0077); + again: + if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) + die(1, "couldn't create socket: %s", strerror(errno)); + if (bind(fd, (struct sockaddr *)sun, sz) < 0) { + e = errno; + if (errno != EADDRINUSE) + die(1, "couldn't bind to address: %s", strerror(e)); + if (!n) + die(1, "too many retries; giving up"); + n--; + if (connect(fd, (struct sockaddr *)sun, sz)) { + struct stat st; + if (errno != ECONNREFUSED) + die(1, "couldn't bind to address: %s", strerror(e)); + if (stat(sun->sun_path, &st)) + die(1, "couldn't stat `%s': %s", sun->sun_path, strerror(errno)); + if (!S_ISSOCK(st.st_mode)) + die(1, "object `%s' isn't a socket", sun->sun_path); + if (verbose) + log("stale socket found; removing it"); + unlink(sun->sun_path); + close(fd); + } else { + if (verbose) + log("server already running; shutting it down"); + write(fd, "QUIT\n", 5); + sleep(1); + close(fd); + } + goto again; + } + chmod(sun->sun_path, 0600); + fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); + if (listen(fd, 5)) + die(1, "couldn't listen on socket: %s", strerror(errno)); + } + + /* --- Set up the rest of the server --- */ + + { + static sel_file serv; + sockpath = sun->sun_path; + atexit(unlinksocket); + sel_initfile(&sel, &serv, fd, SEL_READ, pixserv_accept, 0); + sel_addfile(&serv); + } +} + +/*----- Client support code -----------------------------------------------*/ + +/* --- Variables --- */ + +static selbuf c_server, c_client; +static unsigned c_flags = 0; + +#define cf_uclose 1u +#define cf_sclose 2u +#define cf_cooked 4u + +/* --- Line handler functions --- */ + +static void c_uline(char *s, size_t len, void *p) +{ + if (!s) { + selbuf_destroy(&c_client); + shutdown(c_server.reader.fd, 1); + c_flags |= cf_uclose; + } else { + s[len++] = '\n'; + write(c_server.reader.fd, s, len); + } +} + +static void c_sline(char *s, size_t len, void *p) +{ + if (!s) { + selbuf_destroy(&c_server); + if (!(c_flags & cf_uclose)) { + moan("server closed the connection"); + selbuf_destroy(&c_client); + } + exit(0); + } + if (!(c_flags & cf_cooked)) + puts(s); + else { + char *q = str_getword(&s); + if (strcmp(q, "FAIL") == 0) + die(1, "%s", s); + else if (strcmp(q, "INFO") == 0 || + strcmp(q, "ITEM") == 0) + puts(s); + else if (strcmp(q, "OK") == 0) { + if (s && *s) puts(s); + } else if (strcmp(q, "MISSING") == 0) + ; + else + moan("unexpected output: %s %s", q, s); + } +} + +/* --- @pix_client@ --- * + * + * Arguments: @struct sockaddr_un *sun@ = pointer to socket address + * @size_t sz@ = size of socket address + * @char *argv[]@ = pointer to arguments to send + * + * Returns: --- + * + * Use: Performs client-side actions for the passphrase pixie. + */ + +static void pix_client(struct sockaddr_un *sun, size_t sz, char *argv[]) +{ + int fd; + + /* --- Dispose of locked memory --- */ + + l_destroy(&lm); + + /* --- Open the socket --- */ + + if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) + die(1, "couldn't create socket: %s", strerror(errno)); + if (connect(fd, (struct sockaddr *)sun, sz)) + die(1, "couldn't connect to server: %s", strerror(errno)); + selbuf_init(&c_server, &sel, fd, c_sline, 0); + + /* --- If there are any arguments, turn them into a string --- */ + + if (!*argv) + selbuf_init(&c_client, &sel, STDIN_FILENO, c_uline, 0); + else { + dstr d = DSTR_INIT; + DPUTS(&d, *argv++); + while (*argv) { + DPUTC(&d, ' '); + DPUTS(&d, *argv++); + } + DPUTC(&d, '\n'); + write(fd, d.buf, d.len); + shutdown(fd, 1); + c_flags |= cf_uclose | cf_cooked; + dstr_destroy(&d); + } + + /* --- And repeat --- */ + + for (;;) { + if (sel_select(&sel)) + die(EXIT_FAILURE, "select error: %s", strerror(errno)); + } +} + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @help@, @version@, @usage@ --- * + * + * Arguments: @FILE *fp@ = stream to write on + * + * Returns: --- + * + * Use: Emit helpful messages. + */ + +static void usage(FILE *fp) +{ + pquis(fp, "\ +Usage:\n\ + $ [-qvfidl] [-c COMMAND] [-t TIMEOUT] [-s SOCKET]\n\ + $ [-s SOCKET] -C [COMMAND ARGS...]\n\ + $ [-s SOCKET] -P[P] TAG\n\ +"); +} + +static void version(FILE *fp) +{ + pquis(fp, "$, Catacomb version " VERSION "\n"); +} + +static void help(FILE *fp) +{ + version(fp); + fputc('\n', fp); + usage(fp); + pquis(fp, "\n\ +The Catacomb passphrase pixie collects and caches passphrases used to\n\ +protect important keys. Options provided:\n\ +\n\ +-h, --help Show this help text.\n\ +-V, --version Show the program's version number.\n\ +-u, --usage Show a (very) terse usage summary.\n\ +\n\ +-C, --client Connect to a running pixie as a client.\n\ +-P, --passphrase Request passphrase TAG and print to stdout.\n\ +-PP, --verify-passphrase\n\ + Verify passphrase TAG and print to stdout.\n\ +\n\ +-q, --quiet Emit fewer log messages.\n\ +-v, --version Emit more log messages.\n\ +-s, --socket=FILE Name the pixie's socket.\n\ +-c, --command=COMMAND Shell command to read a passphrase.\n\ +-f, --fetch Fetch passphrases from the terminal.\n\ +-t, --timeout=TIMEOUT Length of time to retain a passphrase in memory.\n\ +-i, --interactive Allow commands to be typed interactively.\n\ +-d, --daemon Fork into the background after initialization.\n\ +-l, --syslog Emit log messages to the system log.\n\ +\n\ +The COMMAND may contain `%m' and `%t' markers which are replaced by a\n\ +prompt message and the passphrase tag respectively. The TIMEOUT is an\n\ +integer, optionally followed by `d', `h', `m' or `s' to specify units of\n\ +days, hours, minutes or seconds respectively.\n\ +\n\ +In client mode, if a command is specified on the command line, it is sent\n\ +to the running server; otherwise the program reads requests from stdin.\n\ +Responses from the pixie are written to stdout. Send a HELP request for\n\ +a quick summary of the pixie communication protocol.\n\ +"); +} + +/* --- @main@ --- * + * + * Arguments: @int argc@ = number of arguments + * @char *argv[]@ = vector of argument values + * + * Returns: Zero if OK. + * + * Use: Main program. Listens on a socket and responds with a PGP + * passphrase when asked. + */ + +int main(int argc, char *argv[]) +{ + char *path = 0; + struct sockaddr_un *sun; + size_t sz; + unsigned f = 0; + +#define f_bogus 1u +#define f_client 2u +#define f_stdin 4u +#define f_daemon 8u +#define f_syslog 16u +#define f_fetch 32u +#define f_verify 64u + + /* --- Initialize libraries --- */ + + ego(argv[0]); + sub_init(); + + /* --- Set up the locked memory area --- */ + + l_init(&lm, 16384); + setuid(getuid()); + + /* --- Parse command line arguments --- */ + + for (;;) { + static struct option opts[] = { + + /* --- Standard GNUy help options --- */ + + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { "usage", 0, 0, 'u' }, + + /* --- Other options --- */ + + { "quiet", 0, 0, 'q' }, + { "verbose", 0, 0, 'v' }, + { "client", 0, 0, 'C' }, + { "passphrase", 0, 0, 'P' }, + { "verify-passphrase", 0, 0, '+' }, + { "socket", OPTF_ARGREQ, 0, 's' }, + { "command", OPTF_ARGREQ, 0, 'c' }, + { "fetch", 0, 0, 'f' }, + { "timeout", OPTF_ARGREQ, 0, 't' }, + { "interactive", 0, 0, 'i' }, + { "stdin", 0, 0, 'i' }, + { "daemon", 0, 0, 'd' }, + { "log", 0, 0, 'l' }, + { "syslog", 0, 0, 'l' }, + + /* --- Magic terminator --- */ + + { 0, 0, 0, 0 } + }; + + int i = mdwopt(argc, argv, "hVuqvCPs:c:ft:idl", opts, 0, 0, 0); + if (i < 0) + break; + + switch (i) { + + /* --- GNUy help options --- */ + + case 'h': + help(stdout); + exit(0); + case 'V': + version(stdout); + exit(0); + case 'u': + usage(stdout); + exit(0); + + /* --- Other interesting things --- */ + + case 'q': + if (verbose) + verbose--; + break; + case 'v': + verbose++; + break; + case 'C': + f |= f_client; + f &= ~f_fetch; + break; + case 'P': + if (!(f & f_fetch)) + f |= f_fetch; + else + f |= f_verify; + break; + case '+': + f |= f_fetch | f_verify; + f &= ~f_client; + break; + case 's': + path = optarg; + break; + case 't': + if ((timeout = pixserv_timeout(optarg)) == 0) + die(1, "bad timeout `%s'", optarg); + break; + case 'c': + command = optarg; + flags |= F_FETCH; + break; + case 'f': + flags |= F_FETCH; + break; + case 'i': + f |= f_stdin; + break; + case 'd': + f |= f_daemon; + break; + case 'l': + f |= f_syslog; + break; + + /* --- Something else --- */ + + default: + f |= f_bogus; + break; + } + } + + if (f & f_bogus || + (optind < argc && !(f & (f_client|f_fetch))) || + ((f & f_fetch) && optind != argc - 1)) { + usage(stderr); + exit(1); + } + + /* --- Handle request for a passphrase --- */ + + if (f & f_fetch) { + char *buf = l_alloc(&lm, 1024); + passphrase_connect(path); + if (passphrase_read(argv[optind], + (f & f_verify) ? PMODE_VERIFY : PMODE_READ, + buf, 1024)) + die(1, "failed to read passphrase: %s", strerror(errno)); + puts(buf); + return (0); + } + + /* --- Set up the socket address --- */ + + sun = pixie_address(path, &sz); + + /* --- Initialize selectory --- */ + + sel_init(&sel); + signal(SIGPIPE, SIG_IGN); + + /* --- Be a client if a client's wanted --- */ + + if (f & f_client) + pix_client(sun, sz, argv + optind); + + /* --- Open the syslog if requested --- */ + + if (f & f_syslog) { + flags |= F_SYSLOG; + openlog(QUIS, 0, LOG_DAEMON); + } + + /* --- Check on the locked memory area --- */ + + { + dstr d = DSTR_INIT; + int rc = l_report(&lm, &d); + if (rc < 0) + die(EXIT_FAILURE, d.buf); + else if (rc && verbose) { + log(d.buf); + log("couldn't lock passphrase buffer"); + } + dstr_destroy(&d); + arena_setsecure(&lm.a); + } + + /* --- Set signal behaviours --- */ + + { + static sig sigint, sigterm, sigquit, sighup; + struct sigaction sa; + sig_init(&sel); + sigaction(SIGINT, 0, &sa); + if (sa.sa_handler != SIG_IGN) + sig_add(&sigint, SIGINT, pix_sigdie, 0); + sig_add(&sigterm, SIGTERM, pix_sigdie, 0); + sig_add(&sigquit, SIGQUIT, pix_sigflush, 0); + sig_add(&sighup, SIGHUP, pix_sigflush, 0); + } + + /* --- Set up the server --- */ + + pix_setup(sun, sz); + if (f & f_stdin) { + pixserv *px = pixserv_create(STDIN_FILENO, STDOUT_FILENO); + sel_rmtimer(&px->timer); + px->f |= px_stdin; + } + + /* --- Fork into the background if requested --- */ + + if (f & f_daemon) { + pid_t kid; + + if (((f & f_stdin) && + (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO))) || + (!command && (flags & F_FETCH))) + die(1, "can't become a daemon if terminal required"); + + if ((kid = fork()) < 0) + die(1, "fork failed: %s", strerror(errno)); + if (kid) + _exit(0); +#ifdef TIOCNOTTY + { + int fd; + if ((fd = open("/dev/tty", O_RDONLY)) >= 0) { + ioctl(fd, TIOCNOTTY); + close(fd); + } + } +#endif + chdir("/"); + setsid(); + + if (fork() != 0) + _exit(0); + } + + if (verbose) + log("initialized ok"); + + { + int selerr = 0; + for (;;) { + if (!sel_select(&sel)) + selerr = 0; + else if (errno != EINTR && errno != EAGAIN) { + log("error from select: %s", strerror(errno)); + selerr++; + if (selerr > 8) { + log("too many consecutive select errors: bailing out"); + exit(EXIT_FAILURE); + } + } + } + } + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/progs/rspit.c b/progs/rspit.c new file mode 100644 index 0000000..1819a61 --- /dev/null +++ b/progs/rspit.c @@ -0,0 +1,1400 @@ +/* -*-c-*- + * + * Spit out random numbers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef PORTABLE +# include +#endif + +#include +#include +#include +#include +#include +#include + +#include "fipstest.h" +#include "grand.h" +#include "maurer.h" +#include "key.h" + +#include "lcrand.h" +#include "fibrand.h" +#include "rand.h" +#include "noise.h" + +#include "bbs.h" +#include "mprand.h" + +#include "rc4.h" +#include "seal.h" + +#include "des-ofb.h" +#include "des3-ofb.h" +#include "rc2-ofb.h" +#include "rc5-ofb.h" +#include "mars-ofb.h" +#include "skipjack-ofb.h" +#include "tea-ofb.h" +#include "xtea-ofb.h" +#include "blowfish-ofb.h" +#include "twofish-ofb.h" +#include "idea-ofb.h" +#include "cast128-ofb.h" +#include "cast256-ofb.h" +#include "noekeon-ofb.h" +#include "rijndael-ofb.h" +#include "rijndael192-ofb.h" +#include "rijndael256-ofb.h" +#include "safer-ofb.h" +#include "safersk-ofb.h" +#include "square-ofb.h" +#include "serpent-ofb.h" + +#include "des-counter.h" +#include "des3-counter.h" +#include "rc2-counter.h" +#include "rc5-counter.h" +#include "mars-counter.h" +#include "skipjack-counter.h" +#include "tea-counter.h" +#include "xtea-counter.h" +#include "blowfish-counter.h" +#include "twofish-counter.h" +#include "idea-counter.h" +#include "cast128-counter.h" +#include "cast256-counter.h" +#include "noekeon-counter.h" +#include "rijndael-counter.h" +#include "rijndael192-counter.h" +#include "rijndael256-counter.h" +#include "safer-counter.h" +#include "safersk-counter.h" +#include "square-counter.h" +#include "serpent-counter.h" + +#include "md2-mgf.h" +#include "md4-mgf.h" +#include "md5-mgf.h" +#include "sha-mgf.h" +#include "tiger-mgf.h" +#include "rmd128-mgf.h" +#include "rmd160-mgf.h" +#include "rmd256-mgf.h" +#include "rmd320-mgf.h" + +#include "rmd160.h" + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct gen { + const char *name; + grand *(*seed)(unsigned /*i*/); + unsigned i; + const char *help; +} gen; + +extern gen generators[]; + +#define CIPHERS \ + E(DES, des) \ + E(DES3, des3) \ + E(RC2, rc2) \ + E(RC5, rc5) \ + E(MARS, mars) \ + E(SKIPJACK, skipjack) \ + E(TEA, tea) \ + E(XTEA, xtea) \ + E(BLOWFISH, blowfish) \ + E(TWOFISH, twofish) \ + E(IDEA, idea) \ + E(CAST128, cast128) \ + E(CAST256, cast256) \ + E(SQUARE, square) \ + E(SAFER, safer) \ + E(SAFERSK, safersk) \ + E(NOEKEON, noekeon) \ + E(RIJNDAEL, rijndael) \ + E(RIJNDAEL192, rijndael192) \ + E(RIJNDAEL256, rijndael256) \ + E(SERPENT, serpent) + +#define HASHES \ + E(MD2, md2) \ + E(MD4, md4) \ + E(MD5, md5) \ + E(SHA, sha) \ + E(TIGER, tiger) \ + E(RMD128, rmd128) \ + E(RMD160, rmd160) \ + E(RMD256, rmd256) \ + E(RMD320, rmd320) + +#define E(PRE, pre) CIPHER_##PRE, +enum { CIPHERS CIPHER__bogus }; +#undef E + +#define E(PRE, pre) HASH_##PRE, +enum { HASHES HASH__bogus }; +#undef E + +static struct { + const octet *keysz; + size_t blksz; + grand *(*ofb)(const void */*k*/, size_t /*sz*/); + grand *(*counter)(const void */*k*/, size_t /*sz*/); +} ciphertab[] = { +#define E(PRE, pre) \ + { pre##_keysz, PRE##_BLKSZ, pre##_ofbrand, pre##_counterrand }, + CIPHERS +#undef E +}; + +static struct { + const gchash *h; + const octet *keysz; + grand *(*mgf)(const void */*k*/, size_t /*sz*/); +} hashtab[] = { +#define E(PRE, pre) \ + { &pre, pre##_mgfkeysz, pre##_mgfrand }, + HASHES +#undef E +}; + +/*----- Miscellaneous static data -----------------------------------------*/ + +static FILE *outfp; +static size_t outsz = 0; +static unsigned maurer_lo = 5, maurer_hi = 8; + +static int argc; +static char **argv; + +static unsigned flags = 0; + +#define f_progress 1u +#define f_file 2u +#define f_fips 4u +#define f_maurer 8u +#define f_timer 16u +#define f_discard 32u + +/*----- Help options ------------------------------------------------------*/ + +static void usage(FILE *fp) +{ + pquis(fp, "Usage: $ generator [options]\n"); +} + +static void version(FILE *fp) +{ + pquis(fp, "$, Catacomb version " VERSION "\n"); +} + +static void help(FILE *fp) +{ + version(fp); + fputc('\n', fp); + usage(fp); + pquis(fp, "\n\ +Emits a stream of random bytes suitable for, well, all sorts of things.\n\ +The primary objective is to be able to generate streams of input for\n\ +statistical tests, such as Diehard.\n\ +\n\ +Options are specific to the particular generator, although there's a\n\ +common core set:\n\ +\n\ +-h, --help Display this help message.\n\ +-v, --version Display the program's version number.\n\ +-u, --usage Display a useless usage message.\n\ +\n\ +-l, --list Show a list of the supported generators, with\n\ + their options.\n\ +-f, --fipstest Run the FIPS 140-1 randomness test.\n\ +-m, --maurer[=LO-HI] Run Maurer's universal statistical test.\n\ +-o, --output FILE Write output to FILE, not stdout.\n\ +-z, --size SIZE Emit SIZE bytes, not an unlimited number.\n\ +-p, --progress Show a little progress meter (on stderr).\n\ +-T, --timer Keep track of the CPU time used by the generator.\n\ +-d, --discard Discard the generated output.\n\ +\n\ +(A SIZE may be followed by `g' for gigabytes, `m' for megabytes, or\n\ +`k' for kilobytes. If unqualified, an amount in bytes is assumed.)\n\ +"); +} + +/*----- Main options parser -----------------------------------------------*/ + +static struct option opts[] = { + + /* --- Standard GNU help options --- */ + + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "usage", 0, 0, 'u' }, + + /* --- Other useful things --- */ + + { "list", 0, 0, 'l' }, + { "fipstest", 0, 0, 'f' }, + { "maurer", OPTF_ARGOPT, 0, 'm' }, + { "output", OPTF_ARGREQ, 0, 'o' }, + { "size", OPTF_ARGREQ, 0, 'z' }, + { "progress", 0, 0, 'p' }, + { "timer", 0, 0, 'T' }, + { "discard", 0, 0, 'd' }, + + /* --- End of main table --- */ + + { 0, 0, 0, 0 } +}; + +static const char *sopts = "hvu lfm::o:z:pTd"; + +#ifndef OPTION_V + DA_DECL(option_v, struct option); +# define OPTION_V +#endif + +static option_v optv = DA_INIT; +static dstr optd = DSTR_INIT; + +/* --- @addopts@ --- * + * + * Arguments: @const char *s@ = pointer to short options + * @struct option *l@ = pointer to long options + * + * Returns: --- + * + * Use: Adds a collection of options to the table. + */ + +static void addopts(const char *s, struct option *l) +{ + dstr_puts(&optd, s); + if (DA_LEN(&optv)) + DA_SHRINK(&optv, 1); + while (l->name) + DA_PUSH(&optv, *l++); + DA_PUSH(&optv, *l); +} + +/* --- @opt@ --- * + * + * Arguments: --- + * + * Returns: Next option from argument array. + * + * Use: Fetches options, handling the standard ones. + */ + +static int opt(void) +{ + for (;;) { + int i = mdwopt(argc, argv, optd.buf, DA(&optv), 0, 0, 0); + switch (i) { + case 'h': + help(stdout); + exit(0); + case 'v': + version(stdout); + exit(0); + case 'u': + usage(stdout); + exit(0); + case 'l': { + gen *g; + puts("Generators supported:"); + for (g = generators; g->name; g++) + printf(" %s %s\n", g->name, g->help); + exit(0); + } break; + case 'f': + flags |= f_fips; + break; + case 'm': + flags |= f_maurer; + if (optarg) { + char *p; + unsigned long lo, hi; + lo = strtoul(optarg, &p, 0); + if (*p == '-' || *p == ',') + hi = strtoul(p + 1, &p, 0); + else + hi = lo; + if (*p != 0 || hi < lo || lo == 0) + die(EXIT_FAILURE, "bad bit range `%s'", optarg); + maurer_lo = lo; + maurer_hi = hi; + } + break; + case 'o': + if (flags & f_file) + die(EXIT_FAILURE, "already set an output file"); + if (strcmp(optarg, "-") == 0) + outfp = stdout; + else { + outfp = fopen(optarg, "w"); + if (!outfp) { + die(EXIT_FAILURE, "couldn't open output file `%s': %s", + optarg, strerror(errno)); + } + } + flags |= f_file; + break; + case 'z': { + char *p; + outsz = strtoul(optarg, &p, 0); + if (!outsz) + die(EXIT_FAILURE, "bad number `%s'", optarg); + switch (*p) { + case 'G': case 'g': outsz *= 1024; + case 'M': case 'm': outsz *= 1024; + case 'K': case 'k': outsz *= 1024; + case 0: + break; + default: + die(EXIT_FAILURE, "bad suffix `%s'", p); + break; + } + if (*p && p[1] != 0) + die(EXIT_FAILURE, "bad suffix `%s'", p); + } break; + case 'p': + flags |= f_progress; + break; + case 'T': + flags |= f_timer; + break; + case 'd': + flags |= f_discard; + break; + default: + return (i); + } + } +} + +/*----- Manglers for seed strings -----------------------------------------*/ + +/* --- @unhex@ --- * + * + * Arguments: @const char *p@ = pointer to input string + * @char **end@ = where the end goes + * @dstr *d@ = output buffer + * + * Returns: --- + * + * Use: Transforms a hex string into a chunk of binary data. + */ + +static void unhex(const char *p, char **end, dstr *d) +{ + while (p[0] && p[1]) { + int x = p[0], y = p[1]; + if ('0' <= x && x <= '9') x -= '0'; + else if ('A' <= x && x <= 'F') x -= 'A' - 10; + else if ('a' <= x && x <= 'f') x -= 'a' - 10; + else x = 0; + if ('0' <= y && y <= '9') y -= '0'; + else if ('A' <= y && y <= 'F') y -= 'A' - 10; + else if ('a' <= y && y <= 'f') y -= 'a' - 10; + else y = 0; + DPUTC(d, (x << 4) + y); + p += 2; + } + *end = (char *)p; +} + +/* --- Generate a key --- */ + +static void textkey(dstr *d, const char *p, const octet *ksz) +{ + size_t sz = strlen(p); + + if (!sz) + die(EXIT_FAILURE, "zero-length key string"); + if (keysz(sz, ksz) != sz) + DPUTM(d, p, sz); + else { + rmd160_mgfctx g; + rmd160_mgfinit(&g, p, sz); + sz = keysz(0, ksz); + dstr_ensure(d, sz); + rmd160_mgfencrypt(&g, 0, d->buf, sz); + d->len += sz; + } + assert(((void)"I can't seem to choose a good key size", + keysz(d->len, ksz) == d->len)); +} + +static void hexkey(dstr *d, const char *p, const octet *ksz) +{ + char *q; + unhex(optarg, &q, d); + if (*q) + die(EXIT_FAILURE, "bad hex key `%s'", p); + if (keysz(d->len, ksz) != d->len) + die(EXIT_FAILURE, "bad key length"); +} + +static void randkey(dstr *d, const octet *ksz) +{ + size_t sz = keysz(0, ksz); + dstr_ensure(d, sz); + rand_get(RAND_GLOBAL, d->buf, sz); + d->len += sz; +} + +/*----- Generators --------------------------------------------------------*/ + +/* --- Blum-Blum-Shub strong generator --- */ + +static grand *gen_bbs(unsigned i) +{ + /* --- Default modulus --- * + * + * The factors of this number are + * + * @p = 1229936431484295969649886203367009966370895964206162032259292413@ + * @7754313537966036459299022912838407755462506416274551744201653277@ + * @313130311731673973886822067@ + * + * @q = 9798171783943489959487301695884963889684294764514008432498259742@ + * @5374320073594018817245784145742769603334292182227671519041431067@ + * @61344781426317516045890159@ + * + * Both %$p$% and %$q$% are prime; %$(p - 1)/2$% and %$(q - 1)/2$% have no + * common factors. They were found using this program, with random + * starting points. + * + * I hope that, by publishing these factors, I'll dissuade people from + * actually using this modulus in an attempt to attain real security. The + * program is quite quick at finding Blum numbers, so there's no excuse for + * not generating your own. + */ + + const char *mt = + "12051128439013574251357214209433471144307319411973256935382082" + "84356405274180923922403660880355098909699130818163691602989614" + "90135716255689660470370755013177656905237112577648090277537209" + "93607817155427455344810369808478266925293635284364998010510985" + "0503830397166360721262431179505917248447259735253684659338653"; + + /* --- Other things --- */ + + grand *r; + const char *xt = 0; + unsigned bits = 1024; + mp *m, *x; + unsigned show = 0; + const char *kfile = 0, *id = 0, *ktype = 0; + + /* --- Parse options --- */ + + static struct option opts[] = { + { "modulus", OPTF_ARGREQ, 0, 'M' }, + { "generate", 0, 0, 'g' }, + { "seed", OPTF_ARGREQ, 0, 's' }, + { "bits", OPTF_ARGREQ, 0, 'b' }, + { "show", 0, 0, 'S' }, + { "keyring", OPTF_ARGREQ, 0, 'k' }, + { "id", OPTF_ARGREQ, 0, 'i' }, + { "type", OPTF_ARGREQ, 0, 't' }, + { 0, 0, 0, 0 } + }; + + addopts("M:gs:b:Sk:i:t:", opts); + + for (;;) { + int o = opt(); + if (o < 0) + break; + switch (o) { + case 'M': + mt = optarg; + break; + case 'g': + mt = 0; + break; + case 's': + xt = optarg; + break; + case 'b': + bits = strtoul(optarg, 0, 0); + if (bits == 0) + die(EXIT_FAILURE, "bad number of bits `%s'", optarg); + break; + case 'S': + show = 1; + break; + case 'k': + kfile = optarg; + mt = 0; + break; + case 'i': + id = optarg; + mt = 0; + break; + case 't': + ktype = optarg; + mt = 0; + break; + default: + return (0); + } + } + + /* --- Generate a modulus if one is requested --- */ + + if (mt) { + char *p; + m = mp_readstring(MP_NEW, mt, &p, 0); + if (!m || *p || (m->v[0] & 3) != 1) + die(EXIT_FAILURE, "bad modulus `%s'", mt); + /* Unfortunately I don't know how to test for a Blum integer */ + } else if (kfile || id || ktype) { + key_file kf; + key *kk; + key_data *kd; + + /* --- Open the key file --- */ + + if (!kfile) + kfile = "keyring"; + if (key_open(&kf, kfile, KOPEN_READ, key_moan, 0)) { + die(EXIT_FAILURE, "error opening key file `%s': %s", + kfile, strerror(errno)); + } + + /* --- Find the key --- */ + + if (id) { + if ((kk = key_bytag(&kf, id)) == 0) + die(EXIT_FAILURE, "key `%s' not found", id); + } else { + if (!ktype) + ktype = "bbs"; + if ((kk = key_bytype(&kf, ktype)) == 0) + die(EXIT_FAILURE, "no suitable key with type `%s' found", ktype); + } + + /* --- Read the key data --- */ + + if ((kk->k->e & KF_ENCMASK) != KENC_STRUCT) + die(EXIT_FAILURE, "key is not structured"); + if ((kd = key_structfind(kk->k, "n")) == 0) + die(EXIT_FAILURE, "key has no subkey `n'"); + if ((kd->e & KF_ENCMASK) != KENC_MP) + die(EXIT_FAILURE, "incompatible subkey encoding"); + m = MP_COPY(kd->u.m); + key_close(&kf); + } else { + bbs_priv bp; + + if (bbs_gen(&bp, bits, &rand_global, 0, + (flags & f_progress) ? pgen_ev : 0, 0)) + die(EXIT_FAILURE, "modulus generation failed"); + m = bp.n; + + if (show) { + fputs("p = ", stderr); + mp_writefile(bp.p, stderr, 10); + fputs("\nq = ", stderr); + mp_writefile(bp.q, stderr, 10); + fputs("\nn = ", stderr); + mp_writefile(bp.n, stderr, 10); + fputc('\n', stderr); + } + + mp_drop(bp.p); + mp_drop(bp.q); + } + + /* --- Set up a seed --- */ + + if (!xt) + x = mprand(MP_NEW, mp_bits(m) - 1, &rand_global, 1); + else { + char *p; + x = mp_readstring(MP_NEW, xt, &p, 0); + if (*p) + die(EXIT_FAILURE, "bad modulus `%s'", xt); + } + + /* --- Right --- */ + + r = bbs_rand(m, x); + + mp_drop(m); + mp_drop(x); + return (r); +} + +/* --- Catacomb's random number generator --- */ + +static grand *gen_rand(unsigned i) +{ + grand *r = rand_create(); + dstr d = DSTR_INIT; + + static struct option opts[] = { + { "key", OPTF_ARGREQ, 0, 'k' }, + { "text", OPTF_ARGREQ, 0, 't' }, + { "hex", OPTF_ARGREQ, 0, 'H' }, + { 0, 0, 0, 0 } + }; + + addopts("k:t:H:n", opts); + + r->ops->misc(r, RAND_NOISESRC, &noise_source); + r->ops->misc(r, RAND_SEED, 160); + + for (;;) { + int o = opt(); + if (o < 0) + break; + switch (o) { + case 'k': + DRESET(&d); + textkey(&d, optarg, rmd160_hmackeysz); + r->ops->misc(r, RAND_KEY, d.buf, d.len); + break; + case 't': + r->ops->misc(r, GRAND_SEEDBLOCK, optarg, strlen(optarg)); + break; + case 'H': + DRESET(&d); + hexkey(&d, optarg, rmd160_hmackeysz); + r->ops->misc(r, GRAND_SEEDBLOCK, d.buf, d.len); + break; + } + } + + dstr_destroy(&d); + return (r); +} + +/* --- RC4 output --- */ + +static grand *gen_rc4(unsigned i) +{ + grand *r; + dstr d = DSTR_INIT; + + static struct option opts[] = { + { "key", OPTF_ARGREQ, 0, 'k' }, + { "hex", OPTF_ARGREQ, 0, 'H' }, + { 0, 0, 0, 0 } + }; + + addopts("k:H:", opts); + + for (;;) { + int o = opt(); + if (o < 0) + break; + switch (o) { + case 'k': + DRESET(&d); + textkey(&d, optarg, rc4_keysz); + break; + case 'H': + DRESET(&d); + hexkey(&d, optarg, rc4_keysz); + break; + default: + return (0); + } + } + + if (!d.len) + randkey(&d, rc4_keysz); + r = rc4_rand(d.buf, d.len); + dstr_destroy(&d); + return (r); +} + +/* --- SEAL output --- */ + +static grand *gen_seal(unsigned i) +{ + grand *r; + dstr d = DSTR_INIT; + uint32 n = 0; + + static struct option opts[] = { + { "key", OPTF_ARGREQ, 0, 'k' }, + { "hex", OPTF_ARGREQ, 0, 'H' }, + { "sequence", OPTF_ARGREQ, 0, 'n' }, + { 0, 0, 0, 0 } + }; + + addopts("k:H:n:", opts); + + for (;;) { + int o = opt(); + if (o < 0) + break; + switch (o) { + case 'k': + DRESET(&d); + textkey(&d, optarg, seal_keysz); + break; + case 'H': + DRESET(&d); + hexkey(&d, optarg, seal_keysz); + break; + case 'n': { + char *p; + n = strtoul(optarg, &p, 0); + if (*p) + die(EXIT_FAILURE, "bad number `%s'", optarg); + } break; + default: + return (0); + } + } + + if (!d.len) + randkey(&d, seal_keysz); + r = seal_rand(d.buf, d.len, n); + dstr_destroy(&d); + return (r); +} + +/* --- Output feedback generators --- */ + +static grand *gen_ofb(unsigned i) +{ + grand *r; + dstr d = DSTR_INIT; + dstr iv = DSTR_INIT; + + static struct option opts[] = { + { "key", OPTF_ARGREQ, 0, 'k' }, + { "hex", OPTF_ARGREQ, 0, 'H' }, + { "iv", OPTF_ARGREQ, 0, 'i' }, + { 0, 0, 0, 0 } + }; + + addopts("k:H:i:", opts); + + for (;;) { + int o = opt(); + if (o < 0) + break; + switch (o) { + case 'k': + DRESET(&d); + textkey(&d, optarg, ciphertab[i].keysz); + break; + case 'H': + DRESET(&d); + hexkey(&d, optarg, ciphertab[i].keysz); + break; + case 'i': { + char *p; + unhex(optarg, &p, &iv); + if (*p) + die(EXIT_FAILURE, "bad hex IV `%s'", optarg); + } break; + default: + return (0); + } + } + + if (!d.len) + randkey(&d, ciphertab[i].keysz); + r = ciphertab[i].ofb(d.buf, d.len); + if (iv.len) { + if (iv.len != ciphertab[i].blksz) { + die(EXIT_FAILURE, "bad IV length %lu (must be %lu)", + (unsigned long)iv.len, (unsigned long)ciphertab[i].blksz); + } + r->ops->misc(r, GRAND_SEEDBLOCK, iv.buf); + } + + dstr_destroy(&d); + dstr_destroy(&iv); + return (r); +} + +/* --- Counter generators --- */ + +static grand *gen_counter(unsigned i) +{ + grand *r; + dstr d = DSTR_INIT; + dstr iv = DSTR_INIT; + + static struct option opts[] = { + { "key", OPTF_ARGREQ, 0, 'k' }, + { "hex", OPTF_ARGREQ, 0, 'H' }, + { "iv", OPTF_ARGREQ, 0, 'i' }, + { 0, 0, 0, 0 } + }; + + addopts("k:H:i:", opts); + + for (;;) { + int o = opt(); + if (o < 0) + break; + switch (o) { + case 'k': + DRESET(&d); + textkey(&d, optarg, ciphertab[i].keysz); + break; + case 'H': + DRESET(&d); + hexkey(&d, optarg, ciphertab[i].keysz); + break; + case 'i': { + char *p; + unhex(optarg, &p, &iv); + if (*p) + die(EXIT_FAILURE, "bad hex IV `%s'", optarg); + } break; + default: + return (0); + } + } + + if (!d.len) + randkey(&d, ciphertab[i].keysz); + r = ciphertab[i].counter(d.buf, d.len); + if (iv.len) { + if (iv.len != ciphertab[i].blksz) { + die(EXIT_FAILURE, "bad IV length %lu (must be %lu)", + (unsigned long)iv.len, (unsigned long)ciphertab[i].blksz); + } + r->ops->misc(r, GRAND_SEEDBLOCK, iv.buf); + } + + dstr_destroy(&d); + dstr_destroy(&iv); + return (r); +} + +/* --- Mask generators --- */ + +static grand *gen_mgf(unsigned i) +{ + grand *r; + dstr d = DSTR_INIT; + uint32 c = 0; + + static struct option opts[] = { + { "key", OPTF_ARGREQ, 0, 'k' }, + { "hex", OPTF_ARGREQ, 0, 'H' }, + { "index", OPTF_ARGREQ, 0, 'i' }, + { 0, 0, 0, 0 } + }; + + addopts("k:H:i:", opts); + + for (;;) { + int o = opt(); + if (o < 0) + break; + switch (o) { + case 'k': + DRESET(&d); + textkey(&d, optarg, hashtab[i].keysz); + break; + case 'H': + DRESET(&d); + hexkey(&d, optarg, hashtab[i].keysz); + break; + case 'i': { + char *p; + c = strtoul(optarg, &p, 0); + if (*p) + die(EXIT_FAILURE, "bad index `%s'", optarg); + } break; + default: + return (0); + } + } + + if (!d.len) + randkey(&d, hashtab[i].keysz); + + r = hashtab[i].mgf(d.buf, d.len); + if (c) + r->ops->misc(r, GRAND_SEEDUINT32, c); + + dstr_destroy(&d); + return (r); +} + +/* --- Fibonacci generator --- */ + +static grand *gen_fib(unsigned i) +{ + grand *r; + uint32 s = 0; + char *p; + unsigned set = 0; + + static struct option opts[] = { + { "seed", OPTF_ARGREQ, 0, 's' }, + { 0, 0, 0, 0 } + }; + + addopts("s:", opts); + + for (;;) { + int o = opt(); + if (o < 0) + break; + switch (o) { + case 's': + s = strtoul(optarg, &p, 0); + if (*p) + die(EXIT_FAILURE, "bad integer `%s'", optarg); + set = 1; + break; + default: + return (0); + } + } + r = fibrand_create(s); + if (!set) + r->ops->misc(r, GRAND_SEEDRAND, &rand_global); + return (r); +} + +/* --- LC generator --- */ + +static grand *gen_lc(unsigned i) +{ + uint32 s = 0; + char *p; + unsigned set = 0; + + static struct option opts[] = { + { "seed", OPTF_ARGREQ, 0, 's' }, + { 0, 0, 0, 0 } + }; + + addopts("s:", opts); + + for (;;) { + int o = opt(); + if (o < 0) + break; + switch (o) { + case 's': + s = strtoul(optarg, &p, 0); + if (*p) + die(EXIT_FAILURE, "bad integer `%s'", optarg); + set = 1; + break; + default: + return (0); + } + } + if (!set) { + do + s = rand_global.ops->range(&rand_global, LCRAND_P); + while (s == LCRAND_FIXEDPT); + } + return (lcrand_create(s)); +} + +/* --- Basic options parser -- can't generate output --- */ + +static grand *gen_opts(unsigned i) +{ + while (opt() >= 0) + ; + return (0); +} + +/*----- Generators table --------------------------------------------------*/ + +gen generators[] = { + { "fibonacci", gen_fib, 0, + "[-s SEED]" }, + { "lc", gen_lc, 0, + "[-s SEED]" }, +#define E(PRE, pre) \ + { #pre "-ofb", gen_ofb, CIPHER_##PRE, \ + "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" }, + CIPHERS +#undef E +#define E(PRE, pre) \ + { #pre "-counter", gen_counter, CIPHER_##PRE, \ + "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" }, + CIPHERS +#undef E +#define E(PRE, pre) \ + { #pre "-mgf", gen_mgf, HASH_##PRE, \ + "[-k KEY-PHRASE] [-H HEX-KEY] [-i INDEX]" }, + HASHES +#undef E + { "rc4", gen_rc4, 0, + "[-k KEY-PHRASE] [-H HEX-KEY]" }, + { "seal", gen_seal, 0, + "[-k KEY-PHRASE] [-H HEX-KEY] [-n SEQ]" }, + { "rand", gen_rand, 0, + "[-n] [-k KEY-PHRASE] [-t TEXT-BLOCK] [-H HEX-BLOCK]" }, + { "bbs", gen_bbs, 0, + "[-gS] [-s SEED] [-M MODULUS] [-b BITS] [-k KEYRING] [-i TAG] [-t TYPE]" + }, + { 0, 0, 0, 0 }, +}; + +static gen optsg = { "options", gen_opts, 0, + "This message shouldn't be printed." }; + +/*----- Random number generation ------------------------------------------*/ + +static int genfile(const void *buf, size_t sz, void *p) +{ + FILE *fp = p; + if (fwrite(buf, 1, sz, fp) != sz) + die(EXIT_FAILURE, "error writing to file: %s", strerror(errno)); + return (0); +} + +static int genbuf(const void *buf, size_t sz, void *p) +{ + octet **pp = p; + memcpy(*pp, buf, sz); + *pp += sz; + return (0); +} + +typedef struct genmaurer_ctx { + size_t n; + maurer_ctx *m; +} genmaurer_ctx; + +static int genmaurer(const void *buf, size_t sz, void *p) +{ + genmaurer_ctx *g = p; + size_t i; + + for (i = 0; i < g->n; i++) + maurer_test(&g->m[i], buf, sz); + return (0); +} + +static int generate(grand *r, size_t outsz, + int (*func)(const void *buf, size_t sz, void *p), + void *p) +{ + static char kmg[] = { ' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 0 }; + + unsigned percent = 0; + size_t kb = 0; + time_t last; + static char baton[] = "-\\|/"; + char *bp; + int rc; + clock_t clk = 0; + + /* --- Spit out random data --- */ + + last = time(0); + bp = baton; + if (flags & f_progress) { + char *errbuf = xmalloc(BUFSIZ); + setvbuf(stderr, errbuf, _IOLBF, BUFSIZ); + if (outsz) + fprintf(stderr, "[%*s] 0%% 0\r[/\b", 50, ""); + else + fputs("[ ] 0\r[/\b", stderr); + fflush(stderr); + } + +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif + + do { + octet buf[BUFSIZ]; + size_t sz = sizeof(buf); + clock_t c_start, c_stop; + + /* --- Emit a bufferful (or less) of data --- */ + + if (outsz) { + if (sz > outsz - kb) + sz = outsz - kb; + } + c_start = clock(); + r->ops->fill(r, buf, sz); + c_stop = clock(); + clk += c_stop - c_start; + if (func && (rc = func(buf, sz, p)) != 0) + return (rc); + kb += sz; + + /* --- Update the display --- */ + + if (flags & f_progress) { + time_t t = time(0); + unsigned up = 0; + + if (percent > 100) + up = 1; + + if (!outsz) { + if (difftime(t, last) > 1.0) { + up = 1; + } + if (up) + fputs(" ] ", stderr); + } else { + unsigned pc = kb * 100.0 / outsz; + if (pc > percent || percent > 100 || difftime(t, last) > 1.0) { + if (percent > 100) + percent = 0; + percent &= ~1; + for (; percent < (pc & ~1); percent += 2) + putc('.', stderr); + percent = pc; + for (; pc < 100; pc += 2) + putc(' ', stderr); + fprintf(stderr, "] %3i%% ", percent); + up = 1; + } + } + + if (up) { + size_t q = kb; + char *kk = kmg; + while (q > 8192 && kk[1]) { + q >>= 10; + kk++; + } + fprintf(stderr, "%4i%c\r[", q, *kk); + if (outsz) { + unsigned pc; + for (pc = 0; pc < (percent & ~1); pc += 2) + putc('.', stderr); + } + last = t; + } + + if (percent > 100) + percent = 0; + + if (percent < 100) { + putc(*bp++, stderr); + putc('\b', stderr); + if (!*bp) + bp = baton; + } + fflush(stderr); + } + + /* --- Terminate the loop --- */ + + } while (!outsz || kb < outsz); + + if (flags & f_progress) + fputc('\n', stderr); + if (flags & f_timer) { + fprintf(stderr, "generated %lu bytes ", (unsigned long)outsz); + if (!clk) + fputs("too quickly to measure\n", stderr); + else { + char *kk; + double sec = (double)clk/CLOCKS_PER_SEC; + double bps = (outsz << 3)/sec; + for (kk = kmg; bps > 1024 && kk[1]; kk++, bps /= 1024) + ; + fprintf(stderr, "in %g secs (%g %cb/s)\n", sec, bps, *kk); + } + } + return (0); +} + +/*----- Main code ---------------------------------------------------------*/ + +int main(int ac, char *av[]) +{ + gen *g = &optsg; + grand *r; + + /* --- Initialize mLib --- */ + + ego(av[0]); + sub_init(); + + /* --- Set up the main Catacomb generator --- */ + + rand_noisesrc(RAND_GLOBAL, &noise_source); + rand_seed(RAND_GLOBAL, 160); + + /* --- Initialize the options table --- */ + + addopts(sopts, opts); + argc = ac; + argv = av; + outfp = stdout; + + /* --- Read the generator out of the first argument --- */ + + if (argc > 1 && *argv[1] != '-') { + const char *arg = av[1]; + size_t sz = strlen(arg); + gen *gg; + + g = 0; + for (gg = generators; gg->name; gg++) { + if (strncmp(arg, gg->name, sz) == 0) { + if (gg->name[sz] == 0) { + g = gg; + break; + } else if (g) + die(EXIT_FAILURE, "ambiguous generator name `%s'", arg); + else + g = gg; + } + } + if (!g) + die(EXIT_FAILURE, "unknown generator name `%s'", arg); + argc--; + argv++; + } + + /* --- Get a generic random number generator --- */ + + r = g->seed(g->i); + if (!r || optind != ac - 1) { + usage(stderr); + exit(EXIT_FAILURE); + } + + /* --- Do the FIPS test --- */ + + if (flags & f_fips) { + octet buf[FIPSTEST_BUFSZ]; + unsigned rc; + octet *p = buf; + + generate(r, sizeof(buf), genbuf, &p); + rc = fipstest(buf); + if (rc & FIPSTEST_MONOBIT) + moan("failed monobit test"); + if (rc & FIPSTEST_POKER) + moan("failed poker test"); + if (rc & FIPSTEST_RUNS) + moan("failed runs test"); + if (rc & FIPSTEST_LONGRUNS) + moan("failed long runs test"); + if (!rc && (flags & f_progress)) + fputs("test passed\n", stderr); + return (rc ? EXIT_FAILURE : 0); + } + + /* --- Do Maurer's test --- */ + + if (flags & f_maurer) { + size_t bufsz; + unsigned i; + unsigned rc = 0; + genmaurer_ctx g; + + static struct { double x; const char *sig; } sigtab[] = { + { 3.2905, "1e-3" }, + { 3.0902, "2e-3" }, + { 2.8070, "5e-3" }, + { 2.5758, "1e-2" }, + { 0 , 0 } + }; + + g.n = maurer_hi - maurer_lo + 1; + g.m = xmalloc(g.n * sizeof(maurer_ctx)); + for (i = 0; i < g.n; i++) + maurer_init(&g.m[i], i + maurer_lo); + bufsz = (100 * maurer_hi) << maurer_hi; + + generate(r, bufsz, genmaurer, &g); + + for (i = maurer_lo; i <= maurer_hi; i++) { + double z = maurer_done(&g.m[i - maurer_lo]); + double zz = fabs(z); + unsigned j; + + for (j = 0; sigtab[j].sig; j++) { + if (zz > sigtab[j].x) { + rc = EXIT_FAILURE; + moan("failed, bits = %u, sig = %s, Z_u = %g", + i, sigtab[j].sig, z); + break; + } + } + if (flags & f_progress) + fprintf(stderr, "bits = %u, Z_u = %g\n", i, z); + } + + xfree(g.m); + return (rc); + } + + /* --- Discard --- */ + + if (flags & f_discard) { + generate(r, outsz, 0, 0); + return (0); + } + + /* --- Write to a file --- */ + +#ifndef PORTABLE + if (!(flags & f_file) && isatty(STDOUT_FILENO)) + die(EXIT_FAILURE, "writing output to a terminal is a bad idea"); +#endif + + generate(r, outsz, genfile, outfp); + + /* --- Done --- */ + + r->ops->destroy(r); + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/xpixie b/progs/xpixie similarity index 100% rename from xpixie rename to progs/xpixie diff --git a/pss.c b/pss.c deleted file mode 100644 index b4771db..0000000 --- a/pss.c +++ /dev/null @@ -1,188 +0,0 @@ -/* -*-c-*- - * - * $Id: pss.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Probabistic signature scheme - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include -#include -#include - -#include "gcipher.h" -#include "ghash.h" -#include "grand.h" -#include "rsa.h" - -/*----- Magic statics -----------------------------------------------------*/ - -static const octet z8[8] = { 0 }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @pss_encode@ --- * - * - * Arguments: @mp *d@ = where to put the answer - * @const void *m@ = pointer to the message hash - * @size_t msz@ = the size of the message hash - * @octet *b@ = scratch buffer - * @size_t sz@ = sizeo of the buffer (large enough) - * @unsigned long nbits@ = size in bits of @n@ - * @void *p@ = pointer to the PSS parameters - * - * Returns: Encoded message representative, or null on error. - * - * Use: Implements the operation @EMSA-PSS-ENCODE@, as defined in - * PKCS#1 v. 2.1 (RFC3447). - */ - -mp *pss_encode(mp *d, const void *m, size_t msz, octet *b, size_t sz, - unsigned long nbits, void *p) -{ - pss *pp = p; - octet *s, *r; - ghash *h; - gcipher *c; - unsigned mask; - size_t pssz, hsz = pp->ch->hashsz; - - /* --- Check the message length --- */ - - nbits--; - sz = (nbits + 7)/8; - mask = (1 << nbits%8) - 1; - if (!mask) mask = 0xff; - if (hsz + pp->ssz + 2 > sz) - return (0); - - /* --- Generate a random salt --- */ - - pssz = sz - pp->ssz - hsz - 2; - memset(b, 0, pssz); - b[pssz] = 0x01; - s = b + pssz + 1; - r = s + pp->ssz; - GR_FILL(pp->r, s, pp->ssz); - - /* --- Compute the salted hash --- */ - - h = GH_INIT(pp->ch); - GH_HASH(h, z8, 8); - GH_HASH(h, m, msz); - GH_HASH(h, s, pp->ssz); - GH_DONE(h, r); - r[hsz] = 0xbc; - - /* --- Do the masking --- */ - - c = GC_INIT(pp->cc, r, hsz); - GC_ENCRYPT(c, b, b, pssz + pp->ssz + 1); - GC_DESTROY(c); - b[0] &= mask; - return (mp_loadb(d, b, sz)); -} - -/* --- @pss_decode@ --- * - * - * Arguments: @mp *s@ = the message representative - * @const void *m@ = the original message - * @size_t msz@ = the message size - * @octet *b@ = a scratch buffer - * @size_t sz@ = size of the buffer (large enough) - * @unsigned long nbits@ = number of bits in @n@ - * @void *p@ = pointer to PKCS1 parameters - * - * Returns: The length of the output string if successful, negative on - * failure. - * - * Use: Implements the operation @EMSA_PSS_VERIFY@, as defined in - * PCSK#1 v. 2.1 (RFC3447). - */ - -int pss_decode(mp *mi, const void *m, size_t msz, octet *b, size_t sz, - unsigned long nbits, void *p) -{ - pss *pp = p; - octet *s, *r; - ghash *h; - gcipher *c; - unsigned mask; - size_t pssz, hsz = pp->ch->hashsz, i; - int rc; - - /* --- Check the message length --- */ - - nbits--; - sz = (nbits + 7)/8; - if (mp_octets(mi) > sz) - return (-1); - mask = (1 << nbits%8) - 1; - if (!mask) mask = 0xff; - if (hsz + pp->ssz + 2 > sz) - return (-1); - mp_storeb(mi, b, sz); - - /* --- Split up the buffer --- */ - - pssz = sz - hsz - pp->ssz - 2; - s = b + pssz + 1; - r = s + pp->ssz; - if (r[hsz] != 0xbc) - return (-1); - - /* --- Decode the seed --- */ - - if (b[0] & ~mask) - return (-1); - c = GC_INIT(pp->cc, r, hsz); - GC_DECRYPT(c, b, b, pssz + pp->ssz + 1); - GC_DESTROY(c); - b[0] &= mask; - for (i = 0; i < pssz; i++) - if (b[i]) return (-1); - if (b[pssz] != 0x01) - return (-1); - - /* --- Hash the message --- */ - - h = GH_INIT(pp->ch); - GH_HASH(h, z8, 8); - GH_HASH(h, m, msz); - GH_HASH(h, s, pp->ssz); - s = GH_DONE(h, 0); - rc = !memcmp(s, r, hsz); - GH_DESTROY(h); - if (!rc) return (-1); - - /* --- Done --- */ - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/ptab.h b/ptab.h deleted file mode 100644 index 1e9af6e..0000000 --- a/ptab.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*-c-*- - * - * $Id: ptab.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Table of standard prime groups - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_PTAB_H -#define CATACOMB_PTAB_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct pdata { - mp p; /* The modulus */ - mp q; /* The group order */ - mp g; /* The generator */ -} pdata; - -typedef struct pentry { - const char *name; - pdata *data; -} pentry; - -/*----- Global variables --------------------------------------------------*/ - -extern const pentry ptab[]; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/ptab.in b/ptab.in deleted file mode 100644 index 24151f9..0000000 --- a/ptab.in +++ /dev/null @@ -1,219 +0,0 @@ -# $Id$ -# -# Standard prime groups - -#----- Groups from Oakley (RFC2412) ----------------------------------------- - -group oakley768 - p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff - q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31d1b107fffffffffffffff - g 2 - -group oakley1024 - p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff - q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f67329c0ffffffffffffffff - g 2 - -group oakley1536 - p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff - q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba36046511b993ffffffffffffffff - g 2 - -#----- Groups from RFC3526 -------------------------------------------------- - -group oakley2048 - p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff - q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba36046511b993ffffffffffffffff - g 2 - -group oakley3072 - p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff - q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549d69657fffffffffffffff - g 2 - -group oakley4096 - p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff - q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f4e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f68fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49a0318ccffffffffffffffff - g 2 - -group oakley6144 - p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff - q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f4e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f68fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49a0142491b61fd5a693e381360ea6e593013236f64ba8f3b1edd1bdefc7fca0356cf298772ed9c17a09800d7583529f6c813ec188bcb93d8432d448c6d1f6df5e7cd8a76a267365d676a5d8dedbf8a23f36612a5999028a895ebd7a137dc7a009bc6695facc1e500e325c9767819750ae8b90e81fa416be7373a7f7b6aaf3817a34c06415ad42018c8058e4f2cf3e4bfdf63f47991d4bd3f1b66445f078ea2dbffac2d62a5ea03d915a0aa556647b6bf5fa470ec0a662f6907c01bf053cb8af7794df1940350eac5dbe2ed3b7aa8551ec50fdff8758ce658d189eaae6d2b64f617794b191c3ff46bb71e0234021f47b31fa43077095f96ad85ba3a6b734a7c8f36e620127fffffffffffffff - g 2 - -group oakley8192 - p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff - q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f4e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f68fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49a0142491b61fd5a693e381360ea6e593013236f64ba8f3b1edd1bdefc7fca0356cf298772ed9c17a09800d7583529f6c813ec188bcb93d8432d448c6d1f6df5e7cd8a76a267365d676a5d8dedbf8a23f36612a5999028a895ebd7a137dc7a009bc6695facc1e500e325c9767819750ae8b90e81fa416be7373a7f7b6aaf3817a34c06415ad42018c8058e4f2cf3e4bfdf63f47991d4bd3f1b66445f078ea2dbffac2d62a5ea03d915a0aa556647b6bf5fa470ec0a662f6907c01bf053cb8af7794df1940350eac5dbe2ed3b7aa8551ec50fdff8758ce658d189eaae6d2b64f617794b191c3ff46bb71e0234021f47b31fa43077095f96ad85ba3a6b734a7c8f36df08acba51c937897f72f21c3bbe5b54996fc66c5f626839dc98dd1de4195b46cee9803a0fd3dfc57e23f692bb7b49b5d212331d55b1ce2d727ab41a11da3a15f8e4bc11c78b65f1ceb296f1fedc5f7e42456c911117025201be0389f5abd40d11f8639a39fe3236751835a5e5e44317c1c2eefd4ea5bfd16043f43cb41981f6adee9d03159e7ad9d13c53369509fc1fa27c16ef9887703a55b51b22cbf44cd012aee0b2798e628423428efcd5a40caef6bf50d8ea885ebf73a6b9fd79b5e18f67d1341ac8237a75c3cfc92004a1c5a40e366bc44d00176af71c15e48c86d37e013723caac7223ab3bf4d54f1828713b2b4a6fe40fab74405cb738b064c06ecc76e9efffffffffffffffff - g 2 - -#----- Lim-Lee groups generated by hand ------------------------------------- -# -# I generated these using utils/genpgroups. It took a rather long time. - -# --- catacomb-ll-128-512 --- -# -# keyid = 3db35e07 -# seed = PbNeB774QFw0xJvLDEn3bUx6hJw= -# fingerprint = fb47344e-9bfcd0e-e986c772-48edc231-861cb5fb - -group catacomb-ll-128-512 - p 9749248307666198278625282069621029423614285873414870747628872221551255623823205551438908261067675576856742534707535779666498916029617598868013496631088223 - q 271499434142083095503643289076442321059 - g 572938290446952786361356734705597783874760982871814854106633812061613480394314443743197177265739535298268868306029572450131746639710824513310586144336987 -#:factor 271499434142083095503643289076442321059 -#:factor 251174382438405784142034780246853570853 -#:factor 259658226261043076610234546745792177763 -#:factor 275292752516630714214627215608643381611 - -# --- catacomb-ll-160-1024 --- -# -# keyid = 98f62cc8 -# seed = mPYsyKXF6PoNTkl5uZE64gKEf20= -# fingerprint = 6ab1f087-5614561c-5d388443-b1f02eac-38248fe6 - -group catacomb-ll-160-1024 - p 69775951038073580217048751187698556149910661999359201823421066000439190288124938297116840422332973903349265313226189724474672148172906743149961449018143681316055777549225333684417216672046201528908637006946721694566251047975893301628540057123962444434130461052652526277961662241061299058137499738575071867183 - q 741802303617786660769426556982216255271020758647 - g 24031880137812767104513348688448999056754549625670167617628008814539123937598464069755252337842705625768270002772600104095116713027947418314704258588569425678035630653993833866258334547988915311887541947589468379164053328339235797437698686107421712042993209960764868024283667188725341401853595169622553906137 -#:factor 741802303617786660769426556982216255271020758647 -#:factor 1436145082693042410533997633791272917636904431479 -#:factor 1053371763883815722032496338163704236230178616951 -#:factor 1215995718665420681503927009463070333378310191827 -#:factor 1448192360714741582009673893725822727433041298541 -#:factor 17654251325616983743094122151298023764308424678047987263690296014551 - -# --- catacomb-ll-192-1536 --- -# -# keyid = 7efe5c2c -# seed = fv5cLMXgGO2voYGTQ5K525Xtf9E= -# fingerprint = ae9d47b9-e303daa5-9677023d-764b338b-53f03c4e - -group catacomb-ll-192-1536 - p 271163844483056215974969265313967454661676256266511940924304321373021958106999031565631233996938091358447023677706317722695337026864685384345663120704730255257202847527192911265950638087504732115876440997750045081880863038141607482083211725689822517898206821836185159703555104632867971994304356879518337226475272092974597967943366038800089283400183985773753490774687966167193456249452974119129018696293050595073100284829925638444204379135326678813960293114732959 - q 3265942811645946563242629602041107481841853511350443184197 - g 216185318413290469366405581500018842001794769819261149347277739848511992115259660705539911431188902360038442052949313200461450240469139278699145891151900315976816130082310914969548643710915174155521909660265659882527478738966654443422798664706090262812802264667406360583964285545011889176706871228354070760597031811706100156760441692822039947686308668974200473374152063439445019790248156400822413220452383963514887723177708643429977392740800552485785350546387634 -#:factor 3265942811645946563242629602041107481841853511350443184197 -#:factor 4203281750074745560664516895168522022509720946720609480259 -#:factor 5008750505930402098755083797499946811957880698185704286517 -#:factor 5437815993255342021982036827752826453901545498474314278259 -#:factor 3856915640937851719940744630159301063173277801391043813291 -#:factor 6054082443893470116716978196535076127652382149483455623509 -#:factor 4527580176039500642864307604310793340910014541817043735439 -#:factor 3430016280837410693307976287901159907499384818919106315351 - -# --- catacomb-ll-224-2048 --- -# -# keyid = e2824699 -# seed = 4oJGmZFnxNgns4UExrPWJXJDQYY= -# fingerprint = 5b3631f1-f388bca-554c1df1-3774fee9-cd46747c - -group catacomb-ll-224-2048 - p 3113844893182469436423817481922802329154474934213986369565700235348098440269001480103560846535113493144522446351379349356211385191632945710341444495577638160076546999114567117877732507854868463110804063964212132228977417231690350182211790515961798314443291574015832300281633156990779527484905381392680532643288437519954295652416759988107781937077836044809781096660654460207183523575424301901443740349094152501352983589721328225459512044516684078781305909247963063040562914192132284695886353707336911126238203292592145886841905764429235683487108646920559740458905874135798982283901137307047131586817745416509850061963 - q 18749474022970964965792505501868745784157349746475161167020805104727 - g 1018599075350815414286530684646967825916370747779291600517646276513566802791874935821816063520500873842729343817973803895278528701892043836290994612088035311589900475691176610297248816678701309707300454643927577686742011376684351525767933769045470869869290385506108485669189456183746644562327923152628958690988304340204333382573235567919004822811151873260798098816157572583867825397056414990908538555039226503662448878536483457742053639607062687899859473980884756925814541061907505350254827583321961201313954703462583072253230646667723110441238195386606218014837851495231172030604130800244334912972408067680590879980 -#:factor 18749474022970964965792505501868745784157349746475161167020805104727 -#:factor 26459793266106143518700371316953986751950547842631163615799385478033 -#:factor 23385205652191135191327958583020476187937251160152256504448581299573 -#:factor 17287418736358368314036906794523064561326146990020019216549187737103 -#:factor 16800288948485454351848726052252844830400274721321174607061304165751 -#:factor 14817124042645057452868896146782513905071983176482538876644503596827 -#:factor 24089412810223523640445605527780074479098235298741910558499656689361 -#:factor 18919386933765812741111621380736732547216460099506859126765656541087 -#:factor 68423637472150676252123752731403397187923476268634988015857219241126016100451 - -# --- catacomb-ll-256-3072 --- -# -# keyid = e6a15ce1 -# seed = 5qFc4fL01gTjyvNMZH5BvwETZco= -# fingerprint = 904df4e7-74941baa-40d589c8-fecad932-2b3b7c8d - -group catacomb-ll-256-3072 - p 635937223373484887991140560420669529960468634418212194527199243018802509220923645480563049852948379631872315326364181219863391536284352632127476573990043945919830000350264391397346335414535975554209931971547284463207275833747975949070870172306582775948778222246682185331862354083029804303222690541851195763223409045953191584611635790362191424339883737168342809190665629632289528654983812904611647818546832860081714363504512892885600580448186423533085059295328609139522690627823102925150246378111221377628009667319528150747320084312110336288028683700603719073769314245952464113622780032073817850603131463761017417455806035107984621889773217138911836476354442521466189648565925624512100087534918369360007697883847802211797655614684090408428715299537509886614640500137409891381649298835563011151796284848165977247286439820050405175697064122759870661294968492275655767983096727976056361878300352234381528837008128941375285251387 - q 89271282791461757245617785540129155142212959423277129581512553253419075634703 - g 293025651734044707050351995205142657657141955131408425452312245943331353163428637443799381119408990271553007202915223601376791534187122912295000993316207089139736477148501917083144416322685925261624358336253378688806309805096283386698409139605996997308008266491782991490291726095895573563845937760385377670846794792328581579165150512160132493375389995617711312966986681865792948443127326586291576561351005982500369077653940283008076332825908419690031303502192009860824429031526378047535596212801179578879818504990773143072529887215206211778546705082334239130823956177702608427222251531070457604183947814624087379251368161182770323100074409926426428526795865215674068539423364010352920515052672366811052717283396264950182005583498061313136436293898863077084485762289185337928869086731032780517039420605615746259170222257438835029958473402842467194409561307509136616954789698181252705567549441508247668319257495617674881793988 -#:factor 89271282791461757245617785540129155142212959423277129581512553253419075634703 -#:factor 85831054040144766435760746678768685031101307134949905606966042252247846736739 -#:factor 106974241938861083915762659525277908624697359844432666343676471334975764276049 -#:factor 74188558205228235051388929541366735789893711666871143431413381703129034070571 -#:factor 64157908398727096384500697645883202842334928055247546726538359334678953374533 -#:factor 91888021786522811643506031866522514605588426773858897142365239694153824388723 -#:factor 86202112980065410413258705060295663522206392211838714986438313175672540034679 -#:factor 101718718485667336124248700072690338405530751717394437871691123315096947983183 -#:factor 86666452227843804499517643692692014159268339780015078349842908985056208435853 -#:factor 107755126504421076829573915729759110231793946298489260169446357640494497518059 -#:factor 106001951238340530179427922980522671485637210826387486585015951056665476348869 -#:factor 102183593360154313236939029184315018977616435836107396944951781361526011480879 - -# --- catacomb-ll-384-7680 --- -# -# keyid = 5269085d -# seed = UmkIXe0NUh9EHPOO8u8wF8mhLQE= -# fingerprint = 79071929-98fc59d-90b7743e-c5c2b654-9bb79c2f - -group catacomb-ll-384-7680 - p 216559231449171871041190135626382624797124950735238103903411263023444445882521628396323446917201544947387362748232352479621010825720892522010264595137021526116731147020276163999389935515909942333859243831227670403913428432731504427389273023004939424753052775358161721558889434984752937404659922107755872908503276779890720154023419646466364753857461405783464469564625360217138090672724105361675896756808274354930058114085554600822147968649870032508764648998263671769796991884663568970203225077040350146289614179408735323764473153776149414398483161820946251418283039309221276673125231280207218356527486085198155052448482264858753938528034551335541575510835605019724293894867922725429018142837363943168309374088743910487619039647758175469460668571266467909654776838430687432194443218576000354284573578578313918222270250431668826898042163427173702446261012188950489694384130788197898956349943432660613123480611964086340909829616693038723512697569973817087806925553170590595578662024721424212829104524679861074838515062614572669868082762235959143570965134389478420007029121452023331460602894158087970348076496609174310151629106271427215947168306439928345126945165118709319486831988505313790613950433545275492703644799196726129007271379101141097250063655345163597099147393517021524375283410477077887674889864364373504345856902602031627659096612965600880097793678105801528551273968273016116586602655943987294387646704481664853571904789295943497201543689680443816576374462034616478062083674538453821741357423160686683957869164976227205380757021506255070600142017516211729170052461889059117212201165174680435195480761191462787291840078314124775690821420091760461597315155088442641783854597704388729214697745034805817520117506496545607796864049406793174516710815917428415700817370248228453077064519820749224220930454265603643316849024708084260878037824529368824330161019279087245044637182254878850971615729695143996520927935652887799292993748602455597137301552603377186175439256163850872771856775561289081476860168359000521640192117573827877302113899996287468260783657370603418752653187994927154468272901154316379212588059218864942163650290968975838491996852452140839172227541162524444316754170785930872965059072588210184084993896704348797801907146398460530513820150529386362374102968643080903455218783795163739396580563 - q 33126499307317576797871833023217004335728314922050873541842362900543256622519036793987373377351818708943025119171013 - g 96859294361547047642162231787698695293269170366381491039992704638487946870512955047635144422727688206850890592577601738386271033615655069759857614095318767501569475658225621379418176050399654722867097565799361229947796756782330159878485797280010527792372818398073347477883450716624241650342576251700830368197267161507895940250335059430229713885285808307538641824823453590259949699610056770268667527819173674245700546468626735701216914339359142650715456068873883323510582206093162545301581421872580614739960541059105320799303366751068487975658774037067271201124075671594347915071804828018801863090776942278748696864666275555399479604564578677796647983816263014540144519577131864786690922226752900095101570448042330169808811588582992274222974333043374060077106932770817928804830739464113061207244668378493315384242428432594357567083170258903374723309088233501818385465347016865045003737737429798873421728939731524368763227995005635265743181878570394577251864081145075962862658667595276249717296728684048617249986325764929873684993115348889870151843083280953797610712542442651569528403369291638278579344023829005801861314384307223035852089456550106858884145475380292972702972023699980804060437666725813022897101316874650121913713231347979141680903702045096621935190730276560295174524297300767314797689155407477601193107232938299830541221417725759368288595613473097104008577963940594171976537149511040148774289702490489315160512871522386217608881824304091006999472822494018964857391111674528315676869116824677355671824612095554583261258648450847127015033139359148253652027620146044628375304786435643476708542206375787159378427699020092463186472971399347599749181816424274424067915825882710114752513444732397713670497772986582958901510359579133132479016445445133604454907255125008080844594331635493230874836372234145675198053154029087315214747182882002718722228763467363382722967777319004806095376893995711476881150741027724250087088999020456989167082293444606242846362570237792721708356293491203816603574491100293039203889820292140596922368098350519693304511861932465759110608906269402554390780611082681465359527185555358515709411662470414648813606479086286524570875988991968332315775966514438221552899748093614170849525785168229994381907745855683962639488177828929551456219770877454135407893035439949325975780350 -#:factor 33126499307317576797871833023217004335728314922050873541842362900543256622519036793987373377351818708943025119171013 -#:factor 39355538213779465581327905402419970362362827155309917911796788256581129259700838386618633466328785307910060598484089 -#:factor 24990988056514685939227489925894893740599480412356885556635114159485308445876939770393364881549529860169928180358751 -#:factor 29710393998736802825004025579677917729092552502321819764111039726208854433428942095508492913578932136133436765710137 -#:factor 30739990822741028562742164007270587796692423847729505877569973917995737943042778723217469119645159801429991709987411 -#:factor 38467104071408925475553899301420008676544897864238119086844380566779548268491996551153519861871328607592273248640063 -#:factor 26249202441547885968346939762119297860863007366370739789532392353072352597721946778221716140197625626869457398407943 -#:factor 35113510884533077462576668870689443131037411172656549819745724383911555364605887073198680214468558440325573744139273 -#:factor 22799521027155572453510717469170377645186972219918245680012037643676230864376926993221681405925996643835629140041553 -#:factor 35237903572957790995889936270089932531166269466107290813994448142778414605138387309936585467385466822473088271031989 -#:factor 27428052831286394078655137717030752972732374814011687175621160166365055343004612251793080304507732432129056200291727 -#:factor 20653805003557030567582482355924457431196786739428479408853799555350943953733271029133593962324338862058432369521581 -#:factor 20826184829221859923080357759745090302065026449606341016497732724141145977802307612276509411486570418197846062995143 -#:factor 26186565771074398017481590713676896769947111595943534554546789381717976098676902111563130714755073678247235508588839 -#:factor 25062273677906610062620640227124848504281876654137470308684277968100792708156285085199790540571827305085913619650939 -#:factor 28620246516918127020366359691491908359742867622666550018522929993024502416569436771205673472786682579926850748107811 -#:factor 37856943506407240881326721106883344091018942980536189030625919515240362253893275735656123073145875668656864714642553 -#:factor 22067087486134964177557541373312161142485654981859077450341811542291069526079170766664489890765256439946132722899891 -#:factor 23098926790257626751285008739153477597734517594763012574497649607286859624287080618144594023194033634778511868647877 -#:factor 29874082012645596638985309976826212131328113612069017684649166404247820505933961130580996098120522635385267888074961 - -# --- catacomb-ll-512-15360 --- -# -# keyid = eb8239f8 -# seed = 64I5+NMQg5J7WZeXPpo7dsXLiAs= -# fingerprint = c9addb82-dd632399-3dc1de81-40bf1c07-8ca10f5f - -group catacomb-ll-512-15360 - p 267737496760767722068079882470300794033605836807622482067410964171393411520919176256914869964612479175351332823409449521645606004586415623871847948375817498161847543702485018137658512658395575254789459353699345744602369381934625059696198589413369531883820496222659510755499199435844896264025524352060302680951373940575374076136832975200291005032514098640691398905405952695332479714616633295008654736506041813997134163987333741695846413097366684661344684616003601739167823328153896592432168889551779922529269033348086812310042261625165919052730860791202842844956446296689792441147970214424901342118997798159010536443797638756041327664696059380444566468860999953138675880647585649322318597258428498912095373426547986582540102395757192981849426353427220562438871461011279156327503538285028350335365137967747204548916792891345433172565689300894798309981237564346356082832141951952353587270953547648554401212070076679138112680602893278933373210074307452631417834131238872904464712762382727721405307974548332455937227001307804713345124421010621912271858653169426612004330651882144263970965845286327430353225544353979151213153918381850147302137013870443565447267408929820734324527586605299075224612369180273167439366180804630758969753426630886643792237194705165542753979443278245006454216061793688914453452033873682552924255069369382991399006219888447629091144761962816311838278453426744318329244891747907726689490072483441687762777514940810025483492250932938902924371182177616985098416863622505393245791898509271049937545780547703178646787153221220148776603371623990916784487761937997154509142207118563842540149656720890488789518041789234252783231203642923485126118874925205605743388337049290048102619379144553450612454492744292824661671019548713713568495220254740410669480812494122553523238166010275744321977341774600646768663036548131650974040647199495585196626323527740836162430085342052052727637724463434046775500298250476314587684591403987781101547180153540252142742428325763088665202774890061858211471865412555929191623058633649510807447665649697908545538433271811034260583364231115893882106660460362988412359863944207083315791203817813275002751650497247445133621959259165882426036642183903263726738720790482023621515505915532731458799675555130983697925269194130788271555917528320139537585237789448433361057472038619150612530155365282694361060208517945072413778375766282508764808188838406430261098030072276397680381934641479775177012533402001805227189560517281847643477431969193260714721511089510106902236389858739200666246366584470443084819740458839115330024642751710950508392249199171525940200641812690856715538273687610654143705053231753228288281925749573248819830807718047751291456635357252049651851428004843642993442708365926756086784864901619631645046021861362898457472437142021009316121209673296032419273205690055243737394068612057117222448137828274568145532165778912543711623225896980785464025683101674037519994362712933363700839222229325067956938417486554365785132752607665421070796369679950679278370647133471481601224482043380412158088958751348091674065435762606782309017939064656880665108380755999804750464216396676060064634049102602879726529064753147592949810279608808566906092860843406668537037778792512924649747927350781700804454803517161392276648064085521072720776995493746790698252658256127300427299712765912635964190588872362794322452414626926829451697570056145597909237733397993006318713907266282999209757835954408527578538863449022305050578740139814278853085620493082736691092281414370903171187358162080568284465302364244005694005210033241390491480461570699307912480038911233821105644446152512328525805707483171601688919032664561976430006629718308661207667153016502452884195148963125673969191706827403727809879672157011607257925720399770233625156155404482591336975116607711326594730647784392952199755924399936290034962258677008541859799419880022170446493041811273344503041707889648677394173861246482375736320283850849220544488123549088485079584855817373424359266678858651199243166073560382077730099987468377705636637242565948949985751205620857554830109239961545967537041510571588045286127240744618124771659845616409968497542978672000492769104999131872897737410994487787465125717465733543538344980281077012185860886320520255782307357238375948751409954873680258342250057671086544607706855079362474966284884466968233383764211808745671425930931575698296989086335739534025778159969392356967742191929914522690322438276604838230279525053780117636662663017876019549874233270026169569062088907790243918806941605480559016625665402398248013040463246716327424411605332836931485156524858341673845209004633198457099 - q 10571951456907669779892620647342646690819262609396359690524502534177633120229168340667942575812279188027386527234551758107216468763903236115143427787743501 - g 128598894907195188417229808251635947329739807715046258519185506584473330204570377688022234101083503575628247088869022751684161661116289139941422707052770784716284088672813457818076409289020116060576402861848262767893027233018967673188177319672220467630868456703363498829958429433052255385200803148036151824908127072135772477213206484282052574102804738136991255543544214210006836913841655431369354618035834267490750490209475650037611036969604510775085809840648347935149597993597050657382149424122551607765060905481452516927446598515527477247171478999535528834297030357374539135945862618225434749983777290822601640168801388457093291990583760394365529485898194260738109655976435021259260994433703250576566622543068851481307975157566559105117105696734982421364733215553702481282493676675415951561410801018648748202526310066348347675957920894052908634114299749835690825285958913309859395516637946391466247723186108045362984213928977339986546180336619120165000686737182828914686039307870836014970214762767616169050313307016785283407848979763838796901889533929991249262241241357085858440003100578599589303213283823231174826022087580289633445725655404503623057795603361275581688344479184031083934546255260431689248986625244613768138643274300512818504921212079442823382330541009102805040432664579664706843475903526712081265964789883073385412340566450530204050902742402634241295067292054198743776821135490852456571373786221834566840691504860631528594003016940806795952907191256706618335919348660172917691296581810487025804834121410117485699086165420315964836248122689453219355409068053887775439819365185836341867035959423656535221657069676936301160422526984733243805036094607065902991385803575050051402498313584896099087939918378394590246964040554542516556529955127714323667109459918696040305338316628605973670322139489914621903381403168134305230387553206034949296665589019458435333656497975595505186840554679289490725712215379119708936656398805481443817609780446044759428279250269061044353577054755809478942400511447476504959503019924384501854940670343756700595741830432409860516378561836547983052719529231317929703619794317736666240984610506873930809661048521360303804091987776920298335472932445807825891843426486417538296088228895526448505937443508396033850769937257926518277775854316505029339507246170910597358345642816471561799639718384521695469006324992746905242127842686811730217295508863843618253667094515294426385046337302700840651870607339402514793220932482394311605909804968180513732290422195401488734272875219573971965851758260974945420620612963750578280530090049561109078297429042230921153112538935821627493853510065306244811588574295137834903557863723543417221594934011392570967713979066781470665113263579679078346927299350593423807794432345965954214411279192997560913500420482135209761870894770590428753377060355446520714577823849327411455211803153798853005451969647921330963739815383804967938950844708859220970746343764387380686978388124365668599015606571832777646186264005031394838487124138566127931419400765659300590631175744824203747372760896426041038824093171455170878742081716134501047540584551546098074082811645710233649110893608312835114875022232159365133137870471783950558791394747886849817239478618258433146217414467845273035067690658728958244690182678308246002614307639728716544214919926387449699076757255860035522872191741413862595318802625699582434142963070125555096411118677017567085204173949296857347553686296332447084040218420742023614270285859547357310153777066869597179554114216347704995773693933927290606278271631839500986041846119745101489053876898923820486679517034985529967206488771012442386273647914758788794352696546007225147463040960836917540476556158171204978341050270842436674153236983839541594662370682859252061101201529771658391958638069866925173982823135401442054529882771497178435812973944610940759337374490667655762675502138898683030596178493879840530527200986100162672072577140966652435656059897085134772326082774218777784721364471952331014224241827859689552691557210912017591834455185827870287610792949837996937421382409243563221525985357912277040622211893182331275112628740300448802121194783069108322399073099060064264166221152635853834406853391568903009131371873111346754163371271208724745835028574196362705248110621990890004232459546556494832519339269358637289654972986665902221815201810894863582325166306449650465453223955176919686048223394344108072515484536428726902347665256053780647893633252440024422896973060032376625419596170725316577542832012274755089837231069989343909974684844834831911679673118788567527167638795212119760473587068197787346864147296908951760670987133395 -#:factor 10571951456907669779892620647342646690819262609396359690524502534177633120229168340667942575812279188027386527234551758107216468763903236115143427787743501 -#:factor 9012440645643314246834973626922261248430582884321541587438489180023988737512032104254581442848613136311423618140795155753411152808972231131191495364696113 -#:factor 11664407479888990184202139277551028676651013424643181979060212470678705307128063234525963058666093887020686441365922823734852909082402446828730382752979229 -#:factor 9087876611156307298284101521955646383324933273215705601366986444355710006473522774817841755272381080750837076062838195845188516807677339637355892566997161 -#:factor 7850875653648084112022472229380028253695299668265516016947697170686003077850514907765524197019907612330445487029463301633628025237963893050671557196181037 -#:factor 9811668747595937862696556986818901047696541620978343479470960055182987731849807766456487932153408355304918692734270804755894967739728440775732045253975867 -#:factor 6850528828310882434413759447618080765577150578105428774266564959349750426580886713871673166366380181300391220234049862529092166014652885149727426581950889 -#:factor 6821638102376526854453397172384749542254164092866952888824098621712040405559147454526516007481215285840029382069182522430838260284493396455708010177523951 -#:factor 9678671090017306504471193471606002503207329774194080688795341865275315066168913972420992866933767238945244749299859823721414058505077146271463652017042439 -#:factor 11393931156044806890317196442201195583808258792085050704419049073069764825659064050709401048990965128349659629815212528487569661791997378607235211682046767 -#:factor 9017010040179947675396805634091838536572796142622751259821087175550548949037522734269840576513891007984351108919567391192649737362028379518075599077332061 -#:factor 8471151817163912127252174076707115691748601873337141861143247343372659043906393812132481208054508793108003038614600545971718635646265794386795278691754067 -#:factor 13197493938382376428309109637837242582358905975783852842417135134626200360303237020546312789639222633029539785097700295596040150049781404432593082545583687 -#:factor 8575974070132361564362415034026161716899096825228901868850832979622821929082521380113628505749265007300639809003377137159593961387754096563405572654530453 -#:factor 10685309091824418682668636366538457951831463604934567645475353414106697701363236027779367582469465499678424648685247868794321185827903765405464064983847047 -#:factor 7832579167103862778682606390694147440819353518240318233355101493037014682039100415001767021498559727856779744520541030712369584582339760294936511514528613 -#:factor 11443136038500921044854720404653372565248054144656073888671297768218410197327711069816877279851418893039887799451033119855767890079711768713385653679344477 -#:factor 11688409215583921110956357044321797822832780718093563289058981511879157867538826225803418406379935887495839460956831051786990678735417867002006878510530001 -#:factor 8269373232168928931276034385529570570419130675409379232099124396037402056853784630410470739109999093193671624909979089535332341276117302614326085797220209 -#:factor 9186395703395988275207810642702730047142932136743815395858445937000755684133671310159954341948067614705752787518132853542049279332346920436340054839993081 -#:factor 6795425485592182949378541037739159131046423659599522629955532628051588695375698396588579193598504741404656736703919260744390720003440892800061391975968543 -#:factor 10396118888753141861444655191592919753341123585411878553552147287212817173935858961195926696707128865851883589958560492545922923504442555855283863684690883 -#:factor 9200414943820306382018413241324240995480578531923453792659897506893121059804164387167396258851931504929883516095987516319887977740512884087194394964391023 -#:factor 12530634260640146540037552613265173527563597551474945252217132553909981324169848692185513076985582524700624840690045385961239986165286808674599194021249909 -#:factor 11777196311833624813129143516165715650218942159782423895657055945748378658698548936802659687190537166673298770529607439929019151210938035218664232208577273 -#:factor 7348262210091125168844276092746402631926760996426639974638799774896265368458530624040379440531440039323922186709965290812433008147988187233036235954446539 -#:factor 7495895476596043082228459599736776072884975040533651752897223545444099013720437774241963953093854938504409948988231217421899198126781802901186687835439671 -#:factor 7552446094981741253426497231778914956993354256770700433779133501020398264257537810327407638749096379083785811976115762275583243733103646262540268854635459 -#:factor 11876032185719044257059947481606348236079583968867505900797840767914468036111126560459281957584518925180041310466390015937147792402479266081314053413722009 -#:factor 9583540052593144013269177059658457027998433819569867982260511279574493019496581755069425156501941108339618548765191994601041609651011729970172839875903479 - -#----- That's all, folks ---------------------------------------------------- diff --git a/pub/Makefile.am b/pub/Makefile.am new file mode 100644 index 0000000..d919edf --- /dev/null +++ b/pub/Makefile.am @@ -0,0 +1,101 @@ +### -*-makefile-*- +### +### Build script for public-key cryptography +### +### (c) 2013 Straylight/Edgeware +### + +###----- Licensing notice --------------------------------------------------- +### +### This file is part of Catacomb. +### +### Catacomb is free software; you can redistribute it and/or modify +### it under the terms of the GNU Library General Public License as +### published by the Free Software Foundation; either version 2 of the +### License, or (at your option) any later version. +### +### Catacomb is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU Library General Public License for more details. +### +### You should have received a copy of the GNU Library General Public +### License along with Catacomb; if not, write to the Free +### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +### MA 02111-1307, USA. + +include $(top_srcdir)/vars.am + +noinst_LTLIBRARIES = libpub.la +libpub_la_SOURCES = + +TEST_LIBS = libpub.la + +###-------------------------------------------------------------------------- +### Component files. + +## The Blum--Blum--Shub random-bit generator. +pkginclude_HEADERS += bbs.h +libpub_la_SOURCES += bbs-fetch.c +libpub_la_SOURCES += bbs-gen.c +libpub_la_SOURCES += bbs-jump.c +TESTS += bbs-jump.$t +libpub_la_SOURCES += bbs-rand.c +TESTS += bbs-rand.$t +EXTRA_DIST += t/bbs + +## Plain Diffie--Hellman, in Schorr groups. +pkginclude_HEADERS += dh.h +libpub_la_SOURCES += dh-check.c +libpub_la_SOURCES += dh-fetch.c +libpub_la_SOURCES += dh-gen.c +libpub_la_SOURCES += dh-kcdsa.c +libpub_la_SOURCES += dh-limlee.c +libpub_la_SOURCES += dh-param.c +TESTS += dh-param.$t + +## The National Security Agency's Digital Signature Algorithm. +pkginclude_HEADERS += dsa.h +libpub_la_SOURCES += dsa-gen.c +TESTS += dsa-gen.$t +libpub_la_SOURCES += dsa-misc.c +libpub_la_SOURCES += dsa-sign.c +TESTS += dsa-sign.$t +libpub_la_SOURCES += dsa-verify.c +TESTS += dsa-verify.$t +libpub_la_SOURCES += dsa-check.c +EXTRA_DIST += t/dsa + +## Generalization of DSA to arbitrary cyclic groups. +pkginclude_HEADERS += gdsa.h +libpub_la_SOURCES += gdsa.c +TESTS += gdsa.$t +EXTRA_DIST += t/gdsa + +## KISA `KCDSA', generalized to arbitrary cyclic groups. +pkginclude_HEADERS += gkcdsa.h +libpub_la_SOURCES += gkcdsa.c +TESTS += gkcdsa.$t +EXTRA_DIST += t/gkcdsa + +## General key validity checking machinery. +pkginclude_HEADERS += keycheck.h +libpub_la_SOURCES += keycheck.c +libpub_la_SOURCES += keycheck-mp.c +libpub_la_SOURCES += keycheck-report.c + +## The Rivest--Shamir--Adleman trapdoor one-way function. +pkginclude_HEADERS += rsa.h +libpub_la_SOURCES += rsa-fetch.c +libpub_la_SOURCES += rsa-gen.c +libpub_la_SOURCES += rsa-priv.c +libpub_la_SOURCES += rsa-pub.c +libpub_la_SOURCES += rsa-recover.c +libpub_la_SOURCES += oaep.c +libpub_la_SOURCES += pkcs1.c +libpub_la_SOURCES += pss.c +EXTRA_DIST += rsa-test.c +TESTS += rsa-test.$t +EXTRA_DIST += t/rsa + +###----- That's all, folks -------------------------------------------------- diff --git a/pub/bbs-fetch.c b/pub/bbs-fetch.c new file mode 100644 index 0000000..939aecb --- /dev/null +++ b/pub/bbs-fetch.c @@ -0,0 +1,73 @@ +/* -*-c-*- + * + * Key fetching for BBS public and private keys + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "bbs.h" +#include "key.h" + +/*----- Key fetching ------------------------------------------------------*/ + +const key_fetchdef bbs_pubfetch[] = { + { "n", offsetof(bbs_pub, n), KENC_MP, 0 }, + { 0, 0, 0, 0 } +}; + +static const key_fetchdef priv[] = { + { "p", offsetof(bbs_priv, p), KENC_MP, 0 }, + { "q", offsetof(bbs_priv, q), KENC_MP, 0 }, + { 0, 0, 0, 0 } +}; + +const key_fetchdef bbs_privfetch[] = { + { "n", offsetof(bbs_priv, n), KENC_MP, 0 }, + { "private", 0, KENC_STRUCT, priv }, + { 0, 0, 0, 0 } +}; + +/* --- @bbs_pubfree@, @bbs_privfree@ --- * + * + * Arguments: @bbs_pub *bp@, @bbs_priv *bp@ = pointer to key block + * + * Returns: --- + * + * Use: Frees an RSA key block. + */ + +void bbs_pubfree(bbs_pub *bp) +{ + mp_drop(bp->n); +} + +void bbs_privfree(bbs_priv *bp) +{ + mp_drop(bp->n); + mp_drop(bp->p); + mp_drop(bp->q); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/bbs-gen.c b/pub/bbs-gen.c new file mode 100644 index 0000000..e9e6922 --- /dev/null +++ b/pub/bbs-gen.c @@ -0,0 +1,124 @@ +/* -*-c-*- + * + * Generate Blum integers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include "bbs.h" +#include "mp.h" +#include "mprand.h" +#include "pgen.h" +#include "strongprime.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @bbs_gen@ --- * + * + * Arguments: @bbs_priv *bp@ = pointer to parameter block + * @unsigned nbits@ = number of bits in the modulus + * @grand *r@ = pointer to random number source + * @unsigned n@ = number of attempts to make + * @pgen_proc *event@ = event handler function + * @void *ectx@ = argument for event handler + * + * Returns: If it worked OK, @PGEN_DONE@, otherwise @PGEN_ABORT@. + * + * Use: Finds two prime numbers %$p'$% and %$q'$% such that both are + * congruent to %$3 \bmod 4$%, and $(p - 1)/2$% and + * %$(q - 1)/2$% have no common factors. The product %$n = pq$% + * is eminently suitable for use as a modulus in a Blum-Blum- + * Shub pseudorandom bit generator. + */ + +int bbs_gen(bbs_priv *bp, unsigned nbits, grand *r, unsigned n, + pgen_proc *event, void *ectx) +{ + rabin rb; + pfilt jp; + pgen_jumpctx j; + pgen_gcdstepctx g; + unsigned nb = nbits/2; + mp *x = MP_NEW; + + /* --- Generate @p@ --- */ + +again: + if ((x = strongprime_setup("p", x, &jp, nb, r, n, event, ectx)) == 0) + goto fail_x; + j.j = &jp; + bp->p = pgen("p", MP_NEW, x, event, ectx, n, pgen_jump, &j, + rabin_iters(nb), pgen_test, &rb); + pfilt_destroy(&jp); + if (!bp->p) { + if (n) + goto fail_p; + goto again; + } + + /* --- Generate @q@ --- */ + + nb = nbits - nb; + if ((x = strongprime_setup("q", x, &g.jp, nb, r, n, event, ectx)) == 0) + goto fail_q; + if ((x->v[0] & 3) != 3) + x = mp_add(x, x, g.jp.m); + pfilt_muladd(&g.jp, &g.jp, 2, 0); + g.r = mp_lsr(MP_NEW, bp->p, 1); + g.g = MP_NEW; + g.max = MP_ONE; + bp->q = pgen("q", MP_NEW, x, event, ectx, n, pgen_gcdstep, &g, + rabin_iters(nb), pgen_test, &rb); + pfilt_destroy(&g.jp); + mp_drop(g.r); + mp_drop(g.g); + if (!bp->q) { + if (n) + goto fail_q; + mp_drop(bp->p); + goto again; + } + + /* --- Compute @n@ --- */ + + bp->n = mp_mul(MP_NEW, bp->p, bp->q); + mp_drop(x); + return (PGEN_DONE); + + /* --- Tidy up if things went wrong --- */ + +fail_q: + mp_drop(bp->p); +fail_p: + mp_drop(x); +fail_x: + return (PGEN_ABORT); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/bbs-jump.c b/pub/bbs-jump.c new file mode 100644 index 0000000..dd41d6f --- /dev/null +++ b/pub/bbs-jump.c @@ -0,0 +1,294 @@ +/* -*-c-*- + * + * Jumping around a BBS sequence + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "bbs.h" +#include "mp.h" +#include "mpbarrett.h" +#include "mpcrt.h" +#include "mpint.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @jump@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator context + * @const bbs_priv *bp@ = pointer to BBS modulus factors + * @mp *n@ = number of steps to move + * @mp *px@ = exponent mod @p@ for a one-step jump + * @mp *qx@ = exponent mod @q@ for a one-step jump + * + * Returns: --- + * + * Use: Jumps a BBS context a certain number of places (assuming the + * arguments are right). + * + * Let the BBS modulus be %$n = pq$% and the current residue be + * %$x$%. Then the computations performed are: + * + * * Calculate %$x_p = x \bmod p$% and %$x_q = x \bmod q$%. + * + * * Determine %$e_p = px^n \bmod (p - 1)$% and similarly + * %$e_q = qx^n \bmod (p - 1)$%. + * + * * Calculate %$x_p' = x_p^{e_p} \bmod p$% and + * %$x_q' = x_q^{e_q} \bmod q$%. + * + * * Combine %$x_p'$% and %$x_q'$% using the Chinese Remainder + * Theorem. + * + * If you want to step the generator forwards, simply set + * %$px = qx = 2$%. If you want to step backwards, make + * %$px = (p + 1)/4$% and %$qx = (q + 1)/4$%. Note that, if + * %$x$% is a quadratic residue mod $%p$%, then + * + * %$(x^2) ^ {(p + 1)/4}$% + * %${} = x^{(p + 1)/2}$% + * %${} = x \cdot x^{(p - 1)/2}$% + * %${} = x$% + * + * Simple, no? (Note that the division works because + * %$p \equiv 3 \pmod 4$%.) + */ + +static void jump(bbs *b, const bbs_priv *bp, mp *n, + mp *px, mp *qx) +{ + mp *ep, *eq; + mp *v[2] = { MP_NEW, MP_NEW }; + + /* --- First work out the exponents --- */ + + { + mpbarrett mb; + mp *m; + + m = mp_sub(MP_NEW, bp->p, MP_ONE); + mpbarrett_create(&mb, m); + ep = mpbarrett_exp(&mb, MP_NEW, px, n); + mpbarrett_destroy(&mb); + if (qx == px) + eq = MP_COPY(ep); + else { + m = mp_sub(m, bp->q, MP_ONE); + mpbarrett_create(&mb, m); + eq = mpbarrett_exp(&mb, MP_NEW, qx, n); + mpbarrett_destroy(&mb); + } + + mp_drop(m); + } + + /* --- Now calculate the residues of @x@ --- */ + + mp_div(0, &v[0], b->x, bp->p); + mp_div(0, &v[1], b->x, bp->q); + + /* --- Exponentiate --- */ + + { + mpbarrett mb; + + mpbarrett_create(&mb, bp->p); + v[0] = mpbarrett_exp(&mb, v[0], v[0], ep); + mpbarrett_destroy(&mb); + + mpbarrett_create(&mb, bp->q); + v[1] = mpbarrett_exp(&mb, v[1], v[1], eq); + mpbarrett_destroy(&mb); + + mp_drop(ep); + mp_drop(eq); + } + + /* --- Sort out the result using the Chinese Remainder Theorem --- */ + + { + mpcrt_mod mv[2]; + mpcrt c; + int i; + + mv[0].m = MP_COPY(bp->p); + mv[1].m = MP_COPY(bp->q); + for (i = 0; i < 2; i++) + mv[i].n = mv[i].ni = mv[i].nni = MP_NEW; + mpcrt_create(&c, mv, 2, b->mb.m); + b->x = mpcrt_solve(&c, b->x, v); + mpcrt_destroy(&c); + } + + /* --- Tidy away --- */ + + mp_drop(v[0]); + mp_drop(v[1]); + b->r = b->x->v[0]; + b->b = b->k; +} + +/* --- @bbs_{ff,rew}{,n}@ --- * + * + * Arguments: @bbs *b@ = pointer to a BBS generator state + * @const bbs_priv *bp@ = pointer to BBS modulus factors + * @mp *n@, @unsigned long n@ = number of steps to make + * + * Returns: --- + * + * Use: `Fast-forwards' or rewinds a Blum-Blum-Shub generator by @n@ + * steps. The @...n@ versions take an @unsigned long@ argument; + * the non-@...n@ versions a multiprecision integer. If @n@ is + * negative then the generator is stepped in the reverse + * direction. + */ + +static void ff(bbs *b, const bbs_priv *bp, mp *n) + { jump(b, bp, n, MP_TWO, MP_TWO); } + +static void rew(bbs *b, const bbs_priv *bp, mp *n) +{ + mp *px = mp_lsr(MP_NEW, bp->p, 2); + mp *qx = mp_lsr(MP_NEW, bp->q, 2); + px = mp_add(px, px, MP_ONE); + qx = mp_add(qx, qx, MP_ONE); + jump(b, bp, n, px, qx); + mp_drop(px); + mp_drop(qx); +} + +void bbs_ff(bbs *b, const bbs_priv *bp, mp *n) +{ + if (!MP_NEGP(n)) + ff(b, bp, n); + else { + n = mp_neg(MP_NEW, n); + rew(b, bp, n); + mp_drop(n); + } +} + +void bbs_ffn(bbs *b, const bbs_priv *bp, unsigned long n) + { mp *nn = mp_fromulong(MP_NEW, n); ff(b, bp, nn); mp_drop(nn); } + +void bbs_rew(bbs *b, const bbs_priv *bp, mp *n) +{ + if (!MP_NEGP(n)) + rew(b, bp, n); + else { + n = mp_neg(MP_NEW, n); + ff(b, bp, n); + mp_drop(n); + } +} + +void bbs_rewn(bbs *b, const bbs_priv *bp, unsigned long n) + { mp *nn = mp_fromulong(MP_NEW, n); bbs_rew(b, bp, nn); mp_drop(nn); } + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int verify(dstr *v) +{ + bbs_priv bp; + bbs b; + mp *x; + unsigned long n; + int ok = 1; + uint32 p, q, r; + int i; + + bp.p = *(mp **)v[0].buf; + bp.q = *(mp **)v[1].buf; + bp.n = mp_mul(MP_NEW, bp.p, bp.q); + x = *(mp **)v[2].buf; + n = *(unsigned long *)v[3].buf; + + bbs_create(&b, bp.n, x); + p = bbs_bits(&b, 32); + + bbs_seed(&b, x); + for (i = 0; i < n; i++) + bbs_step(&b); + q = bbs_bits(&b, 32); + bbs_wrap(&b); + + bbs_rewn(&b, &bp, n + (32 + b.k - 1) / b.k); + r = bbs_bits(&b, 32); + + if (r != p) { + fputs("\n*** bbs rewind failure\n", stderr); + fputs("p = ", stderr); mp_writefile(bp.p, stderr, 10); fputc('\n', stderr); + fputs("q = ", stderr); mp_writefile(bp.q, stderr, 10); fputc('\n', stderr); + fputs("n = ", stderr); mp_writefile(bp.n, stderr, 10); fputc('\n', stderr); + fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr); + fprintf(stderr, "stepped %lu back\n", n + (32 + b.k - 1) / b.k); + fprintf(stderr, "expected output = %08lx, found %08lx\n", + (unsigned long)p, (unsigned long)r); + ok = 0; + } + + bbs_seed(&b, x); + bbs_ffn(&b, &bp, n); + r = bbs_bits(&b, 32); + + if (q != r) { + fputs("\n*** bbs fastforward failure\n", stderr); + fputs("p = ", stderr); mp_writefile(bp.p, stderr, 10); fputc('\n', stderr); + fputs("q = ", stderr); mp_writefile(bp.q, stderr, 10); fputc('\n', stderr); + fputs("n = ", stderr); mp_writefile(bp.n, stderr, 10); fputc('\n', stderr); + fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr); + fprintf(stderr, "stepped %lu back\n", n + (32 + b.k - 1) / b.k); + fprintf(stderr, "expected output = %08lx, found %08lx\n", + (unsigned long)q, (unsigned long)r); + ok = 0; + } + + bbs_destroy(&b); + mp_drop(bp.p); + mp_drop(bp.q); + mp_drop(bp.n); + mp_drop(x); + + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "bbs-jump", verify, { &type_mp, &type_mp, &type_mp, &type_ulong, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/bbs"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/bbs-rand.c b/pub/bbs-rand.c new file mode 100644 index 0000000..58b62b1 --- /dev/null +++ b/pub/bbs-rand.c @@ -0,0 +1,421 @@ +/* -*-c-*- + * + * Blum-Blum-Shub secure random number generator + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include +#include + +#include "arena.h" +#include "bbs.h" +#include "grand.h" +#include "mp.h" +#include "mpbarrett.h" +#include "mpint.h" +#include "mprand.h" +#include "paranoia.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @bbs_create@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state to initialize + * @mp *m@ = modulus (must be a Blum integer) + * @mp *x@ = initial seed for generator + * + * Returns: --- + * + * Use: Initializes a BBS generator. The generator is stepped once + * after initialization, as for @bbs_seed@. + */ + +void bbs_create(bbs *b, mp *m, mp *x) +{ + mpw kw; + mp k; + + mpbarrett_create(&b->mb, m); + kw = mp_bits(m) - 1; + mp_build(&k, &kw, &kw + 1); + b->k = mp_bits(&k) - 1; + b->x = 0; + bbs_seed(b, x); +} + +/* --- @bbs_destroy@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state + * + * Returns: --- + * + * Use: Destroys a generator state when it's no longer wanted. + */ + +void bbs_destroy(bbs *b) +{ + mp_drop(b->x); + mpbarrett_destroy(&b->mb); +} + +/* --- @bbs_step@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state + * + * Returns: --- + * + * Use: Steps the generator once. This isn't too useful in client + * code. + */ + +void bbs_step(bbs *b) +{ + mp *x = b->x; + x = mp_sqr(x, x); + x = mpbarrett_reduce(&b->mb, x, x); + b->x = x; + b->b = b->k; + b->r = b->x->v[0]; +} + +/* --- @bbs_set@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state + * @mp *x@ = new residue to set + * + * Returns: --- + * + * Use: Sets a new quadratic residue. The generator is stepped once. + */ + +void bbs_set(bbs *b, mp *x) +{ + mp_drop(b->x); + b->x = MP_COPY(x); + bbs_step(b); +} + +/* --- @bbs_seed@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state + * @mp *x@ = new seed to set + * + * Returns --- + * + * Use: Sets a new seed. The generator is stepped until the residue + * has clearly wrapped around. + */ + +void bbs_seed(bbs *b, mp *x) +{ + mp *y; + x = MP_COPY(x); + for (;;) { + y = mp_sqr(MP_NEW, x); + y = mpbarrett_reduce(&b->mb, y, y); + if (MP_CMP(y, <, x)) + break; + mp_drop(x); + x = y; + } + mp_drop(x); + bbs_set(b, y); + mp_drop(y); +} + +/* --- @bbs_bits@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state + * @unsigned bits@ = number of bits wanted + * + * Returns: Bits extracted from the BBS generator. + * + * Use: Extracts a requested number of bits from the BBS generator. + */ + +uint32 bbs_bits(bbs *b, unsigned bits) +{ + uint32 x = 0; + mpw m; + + /* --- Keep turning the handle until there's enough in the reservoir --- */ + + while (bits >= b->b) { + bits -= b->b; + m = (1 << b->b) - 1; + x |= (b->r & m) << bits; + bbs_step(b); + } + + /* --- Extract the last few bits needed --- */ + + if (bits) { + m = (1 << bits) - 1; + b->b -= bits; + x |= (b->r >> b->b) & m; + } + + /* --- Done --- */ + + return (x); +} + +/* --- @bbs_wrap@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state + * + * Returns: --- + * + * Use: Steps the generator if any of the reservoir bits are used. + * This can be used to `wrap up' after a Blum-Goldwasser + * encryption, for example, producing the final value to be sent + * along with the ciphertext. + * + * If a generator is seeded, %$b$% bits are extracted, and then + * @bbs_wrap@ is called, the generator will have been stepped + * %$\lceil b/k \rceil$% times. + */ + +void bbs_wrap(bbs *b) +{ + if (b->b < b->k) + bbs_step(b); +} + +/*----- Generic random number generator interface -------------------------*/ + +typedef struct gctx { + grand r; + bbs b; +} gctx; + +static void gdestroy(grand *r) +{ + gctx *g = (gctx *)r; + bbs_destroy(&g->b); + BURN(*g); + S_DESTROY(g); +} + +static int gmisc(grand *r, unsigned op, ...) +{ + gctx *g = (gctx *)r; + va_list ap; + int rc = 0; + va_start(ap, op); + + switch (op) { + case GRAND_CHECK: + switch (va_arg(ap, unsigned)) { + case GRAND_CHECK: + case GRAND_SEEDINT: + case GRAND_SEEDUINT32: + case GRAND_SEEDMP: + case GRAND_SEEDRAND: + case BBS_SET: + case BBS_STEP: + case BBS_STEPSZ: + case BBS_BITS: + case BBS_WRAP: + case BBS_FF: + case BBS_FFN: + case BBS_REW: + case BBS_REWN: + case BBS_MOD: + case BBS_STATE: + rc = 1; + break; + default: + rc = 0; + break; + } + break; + case GRAND_SEEDINT: { + mp *x = mp_fromuint(MP_NEW, va_arg(ap, unsigned)); + bbs_seed(&g->b, x); + mp_drop(x); + } break; + case GRAND_SEEDUINT32: { + mp *x = mp_fromuint32(MP_NEW, va_arg(ap, uint32)); + bbs_seed(&g->b, x); + mp_drop(x); + } break; + case GRAND_SEEDMP: + bbs_seed(&g->b, va_arg(ap, mp *)); + break; + case GRAND_SEEDRAND: { + grand *rr = va_arg(ap, grand *); + mp *m = mprand(MP_NEW, mp_bits(g->b.mb.m) - 1, rr, 0); + bbs_seed(&g->b, m); + mp_drop(m); + } break; + case BBS_SET: + bbs_set(&g->b, va_arg(ap, mp *)); + break; + case BBS_STEP: + bbs_step(&g->b); + break; + case BBS_STEPSZ: + rc = g->b.k; + break; + case BBS_BITS: { + unsigned nb = va_arg(ap, unsigned); + uint32 *w = va_arg(ap, uint32 *); + *w = bbs_bits(&g->b, nb); + } break; + case BBS_WRAP: + bbs_wrap(&g->b); + break; + case BBS_FF: { + const bbs_priv *bp = va_arg(ap, const bbs_priv *); + mp *n = va_arg(ap, mp *); + bbs_ff(&g->b, bp, n); + } break; + case BBS_FFN: { + const bbs_priv *bp = va_arg(ap, const bbs_priv *); + unsigned long n = va_arg(ap, unsigned long); + bbs_ffn(&g->b, bp, n); + } break; + case BBS_REW: { + const bbs_priv *bp = va_arg(ap, const bbs_priv *); + mp *n = va_arg(ap, mp *); + bbs_rew(&g->b, bp, n); + } break; + case BBS_REWN: { + const bbs_priv *bp = va_arg(ap, const bbs_priv *); + unsigned long n = va_arg(ap, unsigned long); + bbs_rewn(&g->b, bp, n); + } break; + case BBS_MOD: { + mp **n = va_arg(ap, mp **); + if (*n) MP_DROP(*n); + *n = MP_COPY(g->b.mb.m); + } break; + case BBS_STATE: { + mp **n = va_arg(ap, mp **); + if (*n) MP_DROP(*n); + *n = MP_COPY(g->b.x); + } break; + default: + GRAND_BADOP; + break; + } + + va_end(ap); + return (rc); +} + +static octet gbyte(grand *r) +{ + gctx *g = (gctx *)r; + return (bbs_bits(&g->b, 8)); +} + +static uint32 gword(grand *r) +{ + gctx *g = (gctx *)r; + return (bbs_bits(&g->b, 32)); +} + +static const grand_ops gops = { + "bbs", + GRAND_CRYPTO, 0, + gmisc, gdestroy, + gword, gbyte, gword, grand_range, grand_fill +}; + +/* --- @bbs_rand@ --- * + * + * Arguments: @mp *m@ = modulus + * @mp *x@ = initial seed + * + * Returns: Pointer to a generic generator. + * + * Use: Constructs a generic generator interface over a + * Blum-Blum-Shub generator. + */ + +grand *bbs_rand(mp *m, mp *x) +{ + gctx *g = S_CREATE(gctx); + g->r.ops = &gops; + bbs_create(&g->b, m, x); + return (&g->r); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int verify(dstr *v) +{ + mp *n = *(mp **)v[0].buf; + mp *x = *(mp **)v[1].buf; + grand *b = bbs_rand(n, x); + dstr d = DSTR_INIT; + int ok = 1; + + dstr_ensure(&d, v[2].len); + b->ops->fill(b, d.buf, v[2].len); + d.len = v[2].len; + if (memcmp(d.buf, v[2].buf, v[2].len) != 0) { + fputs("\n*** bbs failure\n", stderr); + fputs("n = ", stderr); mp_writefile(n, stderr, 10); fputc('\n', stderr); + fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr); + fputs("expected = ", stderr); type_hex.dump(&v[2], stderr); + fputc('\n', stderr); + fputs(" found = ", stderr); type_hex.dump(&d, stderr); + fputc('\n', stderr); + fprintf(stderr, "k = %u\n", ((gctx *)b)->b.k); + ok = 0; + } + b->ops->destroy(b); + mp_drop(x); + mp_drop(n); + dstr_destroy(&d); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "bbs", verify, { &type_mp, &type_mp, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/bbs"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/bbs.h b/pub/bbs.h new file mode 100644 index 0000000..4eb48d7 --- /dev/null +++ b/pub/bbs.h @@ -0,0 +1,294 @@ +/* -*-c-*- + * + * The Blum-Blum-Shub random bit generator + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the BBS generator ----------------------------------------* + * + * The Blum-Blum-Shub generator takes the least significant bits from the + * sequence %$x_i = x_{i - 1}^2 \bmod n$%, where %$n = pq$% is the product of + * two primes %$p$% and %$q$%, each of which are congruent to %$3 \bmod 4$%. + * For maximum period of the generator, %$(p - 1)/2$% and %$(q - 1)/1$% + * should be coprime. It is safe to use the least significant + * %$\log \log n$% bits of each step in the sequence -- an adversary must + * factor the modulus before being able to work forwards or backwards. The + * output of the generator cannot be distinguished from a (uniform, + * independent) random sequence of bits using any polynomial-time test. This + * is by far the strongest pseudorandom number generator provided in + * Catacomb, and by far the slowest too. For normal use, the standard + * Catacomb @rand@ generator should be more than adequate. + */ + +#ifndef CATACOMB_BBS_H +#define CATACOMB_BBS_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_KEY_H +# include "key.h" +#endif + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_MPBARRETT_H +# include "mpbarrett.h" +#endif + +#ifndef CATACOMB_PGEN_H +# include "pgen.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- Basic generator state --- */ + +typedef struct bbs { + mpbarrett mb; /* Barrett reduction context */ + mp *x; /* Current quadratic residue */ + unsigned k; /* Number of bits from each step */ + unsigned b; /* Number of bits in reservoir */ + mpw r; /* Reservoir of output bits */ +} bbs; + +/* --- Parameters --- */ + +typedef struct bbs_pub { + mp *n; +} bbs_pub; + +typedef struct bbs_priv { + mp *p, *q; /* Prime factors (3 mod 4) */ + mp *n; /* Product @pq@ -- a Blum integer */ +} bbs_priv; + +/*----- Key fetching ------------------------------------------------------*/ + +extern const key_fetchdef bbs_pubfetch[]; +#define BBS_PUBFETCHSZ 3 + +extern const key_fetchdef bbs_privfetch[]; +#define BBS_PRIVFETCHSZ 7 + +/* --- @bbs_pubfree@, @bbs_privfree@ --- * + * + * Arguments: @bbs_pub *bp@, @bbs_priv *bp@ = pointer to key block + * + * Returns: --- + * + * Use: Frees a BBS key block. + */ + +extern void bbs_pubfree(bbs_pub */*bp*/); +extern void bbs_privfree(bbs_priv */*bp*/); + +/*----- The basic generator -----------------------------------------------*/ + +/* --- @bbs_create@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state to initialize + * @mp *m@ = modulus (must be a Blum integer) + * @mp *x@ = initial seed for generator + * + * Returns: --- + * + * Use: Initializes a BBS generator. The generator is stepped once + * after initialization, as for @bbs_seed@. + */ + +extern void bbs_create(bbs */*b*/, mp */*m*/, mp */*x*/); + +/* --- @bbs_destroy@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state + * + * Returns: --- + * + * Use: Destroys a generator state when it's no longer wanted. + */ + +extern void bbs_destroy(bbs */*b*/); + +/* --- @bbs_step@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state + * + * Returns: --- + * + * Use: Steps the generator once. This isn't too useful in client + * code. + */ + +extern void bbs_step(bbs */*b*/); + +/* --- @bbs_set@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state + * @mp *x@ = new residue to set + * + * Returns: --- + * + * Use: Sets a new quadratic residue. The generator is stepped once. + */ + +extern void bbs_set(bbs */*b*/, mp */*x*/); + +/* --- @bbs_seed@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state + * @mp *x@ = new seed to set + * + * Returns --- + * + * Use: Sets a new seed. The generator is stepped until the residue + * has clearly wrapped around. + */ + +extern void bbs_seed(bbs */*b*/, mp */*x*/); + +/* --- @bbs_bits@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state + * @unsigned bits@ = number of bits wanted + * + * Returns: Bits extracted from the BBS generator. + * + * Use: Extracts a requested number of bits from the BBS generator. + */ + +extern uint32 bbs_bits(bbs */*b*/, unsigned /*bits*/); + +/* --- @bbs_wrap@ --- * + * + * Arguments: @bbs *b@ = pointer to BBS generator state + * + * Returns: --- + * + * Use: Steps the generator if any of the reservoir bits are used. + * This can be used to `wrap up' after a Blum-Goldwasser + * encryption, for example, producing the final value to be sent + * along with the ciphertext. + * + * If a generator is seeded, %$b$% bits are extracted, and then + * @bbs_wrap@ is called, the generator will have been stepped + * %$\lceil b/k \rceil$% times. + */ + +extern void bbs_wrap(bbs */*b*/); + +/*----- Large forwards and backwards jumps --------------------------------*/ + +/* --- @bbs_{ff,rew}{,n}@ --- * + * + * Arguments: @bbs *b@ = pointer to a BBS generator state + * @const bbs_priv *bp@ = pointer to BBS modulus factors + * @mp *n@, @unsigned long n@ = number of steps to make + * + * Returns: --- + * + * Use: `Fast-forwards' or rewinds a Blum-Blum-Shub generator by @n@ + * steps. The @...n@ versions take an @unsigned long@ argument; + * the non-@...n@ versions a multiprecision integer. If @n@ is + * negative then the generator is stepped in the reverse + * direction. + */ + +extern void bbs_ff(bbs */*b*/, const bbs_priv */*bp*/, mp */*n*/); +extern void bbs_ffn(bbs */*b*/, const bbs_priv */*bp*/, unsigned long /*n*/); +extern void bbs_rew(bbs */*b*/, const bbs_priv */*bp*/, mp */*n*/); +extern void bbs_rewn(bbs */*b*/, const bbs_priv */*bp*/, unsigned long /*n*/); + +/*----- Parameter generation ----------------------------------------------*/ + +/* --- @bbs_gen@ --- * + * + * Arguments: @bbs_priv *bp@ = pointer to parameter block + * @unsigned nbits@ = number of bits in the modulus + * @grand *r@ = pointer to random number source + * @unsigned n@ = number of attempts to make + * @pgen_proc *event@ = event handler function + * @void *ectx@ = argument for event handler + * + * Returns: If it worked OK, @PGEN_DONE@, otherwise @PGEN_ABORT@. + * + * Use: Finds two prime numbers %$p'$% and %$q'$% such that both are + * congruent to %$3 \bmod 4$%, and $(p - 1)/2$% and + * %$(q - 1)/2$% have no common factors. The product %$n = pq$% + * is eminently suitable for use as a modulus in a Blum-Blum- + * Shub pseudorandom bit generator. + */ + +extern int bbs_gen(bbs_priv */*bp*/, unsigned /*nbits*/, grand */*r*/, + unsigned /*n*/, pgen_proc */*event*/, void */*ectx*/); + +/*----- Generic random number generator interface -------------------------*/ + +/* --- @bbs_rand@ --- * + * + * Arguments: @mp *m@ = modulus + * @mp *x@ = initial seed + * + * Returns: Pointer to a generic generator. + * + * Use: Constructs a generic generator interface over a + * Blum-Blum-Shub generator. + */ + +extern grand *bbs_rand(mp */*m*/, mp */*x*/); + +/* --- Blum-Blum-Shub-specific misc op codes --- */ + +enum { + BBS_SET = GRAND_SPECIFIC('B'), /* @mp *x@ */ + BBS_STEP, /* @void@ */ + BBS_STEPSZ, /* @void@ */ + BBS_BITS, /* @unsigned bits, uint32 *w@ */ + BBS_WRAP, /* @void@ */ + BBS_FF, /* @bbs_priv *p, mp *n@ */ + BBS_FFN, /* @bbs_priv *p, unsigned long n@ */ + BBS_REW, /* @bbs_priv *p, mp *n@ */ + BBS_REWN, /* @bbs_priv *p, unsigned long n@ */ + BBS_MOD, /* @mp **n@ */ + BBS_STATE /* @mp **x@ */ +}; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/pub/dh-check.c b/pub/dh-check.c new file mode 100644 index 0000000..06f02ae --- /dev/null +++ b/pub/dh-check.c @@ -0,0 +1,170 @@ +/* -*-c-*- + * + * Checks Diffie-Hellman group parameters + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "dh.h" +#include "keycheck.h" +#include "mp.h" +#include "mpmont.h" +#include "mpmul.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @dh_checkparam@ --- * + * + * Arguments: @keycheck *kc@ = keycheck state + * @const dh_param *dp@ = pointer to the parameter set + * @mp **v@ = optional vector of factors + * @size_t n@ = size of vector + * + * Returns: Zero if all OK, or return status from function. + * + * Use: Checks a set of Diffie-Hellman parameters for consistency and + * security. + */ + +int dh_checkparam(keycheck *kc, const dh_param *dp, mp **v, size_t n) +{ + int rc = 0; + mpmont mm; + mp *pm1 = MP_NEW; + mp *q = MP_NEW; + mp *x; + mpmul mu; + size_t i; + + /* --- Check that the numbers which are supposed to be prime are --- */ + + if ((!v && keycheck_prime(kc, KCSEV_WARN, dp->q, "q")) || + keycheck_prime(kc, KCSEV_ERR, dp->p, "p")) + goto fail; + + /* --- Ensure that %$q$% is a sensible choice of number --- */ + + pm1 = mp_sub(pm1, dp->p, MP_ONE); + mp_div(0, &q, pm1, dp->q); + if (!mp_eq(q, MP_ZERO) && + keycheck_report(kc, KCSEV_ERR, "q not a factor of p - 1")) + goto fail; + + /* --- Check that %$g$% is actually right --- * + * + * This isn't perfect. If %$q$% is composite and we don't have the factors + * of %$p - 1$% then the order of %$g$% may be some factor of %$q$% which + * we can't find. (If we do have the factors, we check them all lower + * down.) We do strip out powers of two from %$q$% before testing, though. + */ + + if ((mp_eq(dp->g, MP_ONE) || mp_eq(dp->g, pm1)) && + keycheck_report(kc, KCSEV_ERR, "g is degenerate (+/-1 mod p)")) + goto fail; + q = mp_odd(q, dp->q, &i); + mpmont_create(&mm, dp->p); + x = mpmont_mul(&mm, MP_NEW, dp->g, mm.r2); + q = mpmont_expr(&mm, q, x, q); + mp_drop(x); + do { + if (mp_eq(q, mm.r) != !i) { + if (keycheck_report(kc, KCSEV_ERR, "order of g != q")) { + mpmont_destroy(&mm); + goto fail; + } + break; + } + if (i) { + q = mp_sqr(q, q); + q = mpmont_reduce(&mm, q, q); + } + } while (i--); + + /* --- Check Lim-Lee primes more carefully --- * + * + * In this case, we really can be sure whether the order of %$g$% is + * actually %$q$% as advertised. Also ensure that the individual primes + * are really prime, and that their product is correct. + */ + + if (!v) + mpmont_destroy(&mm); + else { + dstr d = DSTR_INIT; + mp *r = MP_NEW; + + mpmul_init(&mu); + for (i = 0; i < n; i++) { + DRESET(&d); + dstr_putf(&d, "factor f_%lu of p", (unsigned long)i); + if ((rc = keycheck_prime(kc, KCSEV_ERR, v[i], d.buf)) != 0) + break; + mp_div(&q, &r, dp->q, v[i]); + if (mp_eq(r, MP_ZERO) && !mp_eq(q, MP_ONE)) { + q = mpmont_exp(&mm, q, dp->g, q); + if (mp_eq(q, MP_ONE) && + (rc = keycheck_report(kc, KCSEV_ERR, + "order of g is proper divisor of q")) != 0) + break; + } + mpmul_add(&mu, v[i]); + } + mp_drop(q); + mp_drop(r); + q = mpmul_done(&mu); + mpmont_destroy(&mm); + dstr_destroy(&d); + if (rc) + goto fail; + q = mp_lsl(q, q, 1); + if (!mp_eq(q, pm1) && + keycheck_report(kc, KCSEV_ERR, "product of f_i != (p - 1)/2")) + goto fail; + } + + /* --- Finally, check the key sizes --- */ + + if ((mp_bits(dp->p) < 1024 && + keycheck_report(kc, KCSEV_WARN, + "p too small to resist index calculus attacks")) || + (mp_bits(dp->q) < 160 && + keycheck_report(kc, KCSEV_WARN, + "q too small to resist collision-finding attacks"))) + goto fail; + + /* --- Done --- */ + +tidy: + mp_drop(q); + mp_drop(pm1); + return (rc); +fail: + rc = -1; + goto tidy; +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/dh-fetch.c b/pub/dh-fetch.c new file mode 100644 index 0000000..ddb3ce2 --- /dev/null +++ b/pub/dh-fetch.c @@ -0,0 +1,98 @@ +/* -*-c-*- + * + * Key fetching for Diffie-Hellman public and private keys + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "dh.h" +#include "key.h" + +/*----- Key fetching ------------------------------------------------------*/ + +const key_fetchdef dh_paramfetch[] = { + { "p", offsetof(dh_param, p), KENC_MP, 0 }, + { "q", offsetof(dh_param, q), KENC_MP, 0 }, + { "g", offsetof(dh_param, g), KENC_MP, 0 }, + { 0, 0, 0, 0 } +}; + +const key_fetchdef dh_pubfetch[] = { + { "p", offsetof(dh_pub, dp.p), KENC_MP, 0 }, + { "q", offsetof(dh_pub, dp.q), KENC_MP, 0 }, + { "g", offsetof(dh_pub, dp.g), KENC_MP, 0 }, + { "y", offsetof(dh_pub, y), KENC_MP, 0 }, + { 0, 0, 0, 0 } +}; + +static const key_fetchdef priv[] = { + { "x", offsetof(dh_priv, x), KENC_MP, 0 }, + { 0, 0, 0, 0 } +}; + +const key_fetchdef dh_privfetch[] = { + { "p", offsetof(dh_priv, dp.p), KENC_MP, 0 }, + { "q", offsetof(dh_priv, dp.q), KENC_MP, 0 }, + { "g", offsetof(dh_priv, dp.g), KENC_MP, 0 }, + { "y", offsetof(dh_priv, y), KENC_MP, 0 }, + { "private", 0, KENC_STRUCT, priv }, + { 0, 0, 0, 0 } +}; + +/* --- @dh_paramfree@, @dh_pubfree@, @dh_privfree@ --- * + * + * Arguments: @dh_param *dp@, @dh_pub *dp@, @dh_priv *dp@ = pointer + * to key block to free + * + * Returns: --- + * + * Use: Frees a Diffie-Hellman key block. + */ + +void dh_paramfree(dh_param *dp) +{ + mp_drop(dp->p); + mp_drop(dp->q); + mp_drop(dp->g); +} + +void dh_pubfree(dh_pub *dp) +{ + mp_drop(dp->dp.p); + mp_drop(dp->dp.q); + mp_drop(dp->dp.g); + mp_drop(dp->y); +} + +void dh_privfree(dh_priv *dp) +{ + mp_drop(dp->dp.p); + mp_drop(dp->dp.q); + mp_drop(dp->dp.g); + mp_drop(dp->y); + mp_drop(dp->x); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/dh-gen.c b/pub/dh-gen.c new file mode 100644 index 0000000..17b34f6 --- /dev/null +++ b/pub/dh-gen.c @@ -0,0 +1,161 @@ +/* -*-c-*- + * + * Generate Diffie-Hellman parameters + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "dh.h" +#include "grand.h" +#include "mp.h" +#include "mpmont.h" +#include "mprand.h" +#include "pfilt.h" +#include "pgen.h" +#include "prim.h" +#include "rabin.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @dh_gen@ --- * + * + * Arguments: @dh_param *dp@ = pointer to output parameter block + * @unsigned ql@ = length of %$q$% in bits, or zero + * @unsigned pl@ = length of %$p$% in bits + * @unsigned steps@ = number of steps to go + * @grand *r@ = random number source + * @pgen_proc *event@ = event handler function + * @void *ectx@ = argument for the event handler + * + * Returns: @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't. + * + * Use: Generates Diffie-Hellman parameters. + * + * The parameters are a prime %$q$%, relatively small, and a + * large prime %$p = kq + 1$% for some %$k$%, together with a + * generator %$g$% of the cyclic subgroup of order %$q$%. These + * are actually the same as the DSA parameter set, but the + * generation algorithm is different. Also, if @ql@ is zero, + * this algorithm forces %$k = 2$%, and chooses %$g = 4$%. Make + * sure you have something interesting to do if you choose this + * option. + */ + +int dh_gen(dh_param *dp, unsigned ql, unsigned pl, unsigned steps, grand *r, + pgen_proc *event, void *ectx) +{ + /* --- If @ql@ is zero, do the time consuming safe-prime thing --- */ + + if (!ql) { + pgen_simulprime sp[2]; + pgen_simulctx ss; + + mp *m = mprand(MP_NEW, pl - 1, r, 1); + ss.step = MP_TWO; + sp[0].mul = MP_ONE; sp[0].add = MP_ZERO; sp[0].f = 0; + sp[1].mul = MP_TWO; sp[1].add = MP_ONE; sp[1].f = PGENF_KEEP; + ss.v = sp; ss.n = N(sp); + dp->q = pgen("p", MP_NEW, m, event, ectx, steps, pgen_simulstep, &ss, + rabin_iters(pl), pgen_simultest, &ss); + mp_drop(m); + if (!dp->q) { + mp_drop(sp[1].u.x); + return (PGEN_ABORT); + } + dp->p = sp[1].u.x; + dp->g = MP_FOUR; + return (PGEN_DONE); + } + + /* --- Otherwise the job is much simpler --- * + * + * But doesn't look it... + */ + + else { + pgen_filterctx c; + pgen_jumpctx j; + rabin rb; + prim_ctx p; + int i; + mp *m = MP_NEW; + mp *x, *y; + + /* --- Generate @q@ first --- */ + + c.step = 2; + m = mprand(MP_NEW, ql, r, 1); + dp->q = pgen("q", MP_NEW, m, event, ectx, steps, pgen_filter, &c, + rabin_iters(ql), pgen_test, &rb); + if (!dp->q) + goto fail_q; + + /* --- Now pick a suitable @p@ --- */ + + m = mp_lsl(m, dp->q, 1); + x = mprand(MP_NEW, pl, r, 0); + y = MP_NEW; mp_div(0, &y, x, m); + x = mp_sub(x, x, y); + x = mp_add(x, x, MP_ONE); + mp_drop(y); + pfilt_create(&c.f, m); + j.j = &c.f; + dp->p = pgen("p", MP_NEW, x, event, ectx, steps, pgen_jump, &j, + rabin_iters(pl), pgen_test, &rb); + pfilt_destroy(&c.f); + mp_drop(x); + if (!dp->p) + goto fail_p; + + /* --- And finally a suitable @g@ --- */ + + mpmont_create(&p.mm, dp->p); + mp_div(&m, 0, dp->p, dp->q); + i = 0; + p.exp = m; + p.n = 0; + dp->g = pgen("g", MP_NEW, MP_NEW, event, ectx, 0, prim_step, &i, + 1, prim_test, &p); + mpmont_destroy(&p.mm); + if (!dp->g) + goto fail_g; + mp_drop(m); + return (PGEN_DONE); + + /* --- Tidy up --- */ + + fail_g: + mp_drop(dp->q); + fail_q: + mp_drop(dp->p); + fail_p: + mp_drop(m); + return (PGEN_ABORT); + } +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/dh-kcdsa.c b/pub/dh-kcdsa.c new file mode 100644 index 0000000..e773309 --- /dev/null +++ b/pub/dh-kcdsa.c @@ -0,0 +1,123 @@ +/* -*-c-*- + * + * Generate KCDSA prime groups + * + * (c) 2006 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "dh.h" +#include "mprand.h" +#include "pgen.h" +#include "prim.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @dh_kcdsagen@ --- * + * + * Arguments: @dh_param *dp@ = pointer to output parameter block + * @unsigned ql@ = size of small factor of %$(p - 1)/2$% + * @unsigned pl@ = size of %$p$% in bits + * @unsigned flags@ = other generation flags + * @unsigned steps@ = number of steps to go + * @grand *r@ = random number source + * @pgen_proc *ev@ = event handler function + * @void *ec@ = context for the event handler + * + * Returns: @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it failed. + * + * Use: Generates a KCDSA prime group. That is, it chooses a prime + * %$p$%, such that $%p = 2 q v + 1$%, for primes %$q$% and + * %$v$%. The actual group of interest is the subgroup of order + * %$q$%. + */ + +int dh_kcdsagen(dh_param *dp, unsigned ql, unsigned pl, + unsigned flags, unsigned steps, grand *r, + pgen_proc *ev, void *ec) +{ + pgen_filterctx pf; + pgen_simulprime sp[2]; + pgen_simulctx ss; + prim_ctx pc; + rabin rb; + int rc = PGEN_ABORT; + int i; + mp *x; + + /* --- First trick: find %$q$% --- */ + + pf.step = 2; + x = mprand(MP_NEW, pl - ql, r, 1); + x = pgen("v", x, x, ev, ec, + steps, pgen_filter, &pf, + rabin_iters(pl - ql), pgen_test, &rb); + if (!x) + goto fail_0; + + /* --- Second trick: find %$p$% and %$v$% --- */ + + x = mp_lsl(x, x, 1); + sp[0].add = MP_ZERO; sp[0].mul = MP_ONE; sp[0].f = 0; + sp[1].add = MP_ONE; sp[1].mul = x; sp[1].f = PGENF_KEEP; + ss.step = MP_TWO; ss.v = sp; ss.n = N(sp); + x = mprand(MP_NEW, ql, r, 1); + dp->q = pgen("p", MP_NEW, x, ev, ec, + steps, pgen_simulstep, &ss, + rabin_iters(ql), pgen_simultest, &ss); + mp_drop(sp[0].mul); + if (!dp->q) + goto fail_1; + dp->p = sp[1].u.x; + + /* --- Third trick: find a generator --- */ + + mpmont_create(&pc.mm, dp->p); + mp_div(&x, 0, dp->p, dp->q); + i = 0; + pc.exp = x; + pc.n = 0; + dp->g = pgen("g", MP_NEW, MP_NEW, ev, ec, + 0, prim_step, &i, 1, prim_test, &pc); + mpmont_destroy(&pc.mm); + if (!dp->g) + goto fail_2; + + rc = PGEN_DONE; + goto done; + + /* --- Tidying up and going home --- */ + +fail_2: + mp_drop(dp->p); +fail_1: +fail_0: +done: + mp_drop(x); + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/dh-limlee.c b/pub/dh-limlee.c new file mode 100644 index 0000000..cdcebe2 --- /dev/null +++ b/pub/dh-limlee.c @@ -0,0 +1,138 @@ +/* -*-c-*- + * + * Generate Diffie-Hellman parameters from Lim-Lee primes + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "dh.h" +#include "limlee.h" +#include "mpmont.h" +#include "prim.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @dh_limlee@ --- * + * + * Arguments: @dh_param *dp@ = pointer to output parameter block + * @unsigned ql@ = length of smallest factor of %$(p - 1)/2$% + * @unsigned pl@ = length of %$p$% in bits + * @unsigned flags@ = other generation flags + * @unsigned steps@ = number of steps to go + * @grand *r@ = random number source + * @pgen_proc *oev@ = outer event handler function + * @void *oec@ = argument for the outer event handler + * @pgen_proc *iev@ = inner event handler function + * @void *iec@ = argument for the inner event handler + * @size_t *nf@, @mp ***f@ = output array for factors + * + * Returns: @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't. + * + * Use: Generates Diffie-Hellman parameters based on a Lim-Lee prime. + * + * The modulus is a large prime %$p = 2 \prod q_i + 1$%, @pl@ + * bits long, where the %$q_i$% are smaller primes each at least + * @ql@ bits long. It is safe to set @nf@ and @f@ to zero if + * you're not interested in the factor values. + * + * The returned %$g$% generates a subgroup of order %$q_0$% (the + * first factor, returned as @f[0]@), if the flag @DH_SUBGROUP@ + * is set on entry; otherwise %$g$% will have order + * %$(p - 1)/2$%. + */ + +int dh_limlee(dh_param *dp, unsigned ql, unsigned pl, + unsigned flags, unsigned steps, grand *r, + pgen_proc *oev, void *oec, pgen_proc *iev, + void *iec, size_t *nf, mp ***f) +{ + mp **ff; + size_t nff; + prim_ctx pc; + size_t i; + int j; + mp *pp; + + /* --- Generate the Lim-Lee prime --- */ + + if ((dp->p = limlee("p", MP_NEW, MP_NEW, ql, pl, + r, steps, oev, oec, iev, iec, &nff, &ff)) == 0) + return (PGEN_ABORT); + + /* --- Now find a primitive element --- */ + + mpmont_create(&pc.mm, dp->p); + pp = mp_sub(MP_NEW, dp->p, MP_ONE); + if (flags & DH_SUBGROUP) { + dp->q = mp_copy(ff[0]); + pc.exp = MP_NEW; + mp_div(&pc.exp, 0, pp, dp->q); + pc.n = 0; + pc.f = 0; + } else { + dp->q = mp_lsr(MP_NEW, dp->p, 1); + pc.exp = MP_TWO; + pc.n = nff; + pc.f = xmalloc(nff * sizeof(mp *)); + for (i = 0; i < nff; i++) { + pc.f[i] = MP_NEW; + mp_div(&pc.f[i], 0, pp, ff[i]); + } + } + + j = 0; + dp->g = pgen("g", MP_NEW, MP_NEW, oev, oec, + 0, prim_step, &j, 1, prim_test, &pc); + + mp_drop(pp); + if (pc.f) { + for (i = 0; i < pc.n; i++) + mp_drop(pc.f[i]); + xfree(pc.f); + } + mpmont_destroy(&pc.mm); + + /* --- Do something sensible with the list of primes --- */ + + if (dp->g && f) { + *f = ff; + *nf = nff; + } else { + for (i = 0; i < nff; i++) + mp_drop(ff[i]); + xfree(ff); + } + + /* --- Tidy up and return --- */ + + if (!dp->g) { + mp_drop(dp->p); + mp_drop(dp->q); + return (PGEN_ABORT); + } + return (PGEN_DONE); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/dh-param.c b/pub/dh-param.c new file mode 100644 index 0000000..b593fb8 --- /dev/null +++ b/pub/dh-param.c @@ -0,0 +1,170 @@ +/* -*-c-*- + * + * Reading Diffie-Hellman parameters + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "dh.h" +#include "ptab.h" +#include "bintab.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* ---- @dh_infofromdata@ --- * + * + * Arguments: @dh_param *dp@ = parameters to fill in + * @pdata *pd@ = packed data structure + * + * Returns: --- + * + * Use: Fills in a parameters structure from a packed data block. + */ + +void dh_infofromdata(dh_param *dp, pdata *pd) + { dp->p = &pd->p; dp->q = &pd->q; dp->g = &pd->g; } + +/* --- @dh_parse@, @dhbin_parse@ --- * + * + * Arguments: @qd_parse *qd@ = parser context + * @dh_param *dp@ = parameters to fill in + * + * Returns: Zero if OK, nonzero on error. + * + * Use: Parses a prime group string. This is either one of the + * standard group strings, or a %$p$%, %$q$%, %$g$% triple + * separated by commas. + */ + +static int parse(qd_parse *qd, gprime_param *dp) +{ + mp *p = MP_NEW, *q = MP_NEW, *g = MP_NEW; + + if ((p = qd_getmp(qd)) == 0) goto fail; + qd_delim(qd, ','); if ((q = qd_getmp(qd)) == 0) goto fail; + qd_delim(qd, ','); if ((g = qd_getmp(qd)) == 0) goto fail; + dp->p = p; dp->q = q; dp->g = g; + return (0); +fail: + mp_drop(p); mp_drop(q); mp_drop(g); + return (-1); +} + +int dh_parse(qd_parse *qd, dh_param *dp) +{ + const pentry *pe; + + for (pe = ptab; pe->name; pe++) { + if (qd_enum(qd, pe->name) >= 0) { + dh_infofromdata(dp, pe->data); + goto found; + } + } + if (parse(qd, dp)) + return (-1); +found: + return (0); +} + +int dhbin_parse(qd_parse *qd, gbin_param *gb) +{ + const binentry *be; + + for (be = bintab; be->name; be++) { + if (qd_enum(qd, be->name) >= 0) { + dh_infofromdata(gb, be->data); + goto found; + } + } + if (parse(qd, gb)) + return (-1); +found: + return (0); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include "fibrand.h" + +int main(int argc, char *argv[]) +{ + const pentry *pe; + const binentry *be; + const char *e; + int ok = 1, aok = 1; + grand *gr; + + gr = fibrand_create(0); + fputs("checking standard prime groups:", stdout); + fflush(stdout); + for (pe = ptab; pe->name; pe++) { + dh_param dp; + group *g; + dh_infofromdata(&dp, pe->data); + g = group_prime(&dp); + if (mp_bits(dp.p) > 2048 && + (!argv[1] || strcmp(argv[1], "keen") != 0)) { + printf(" [%s skipped]", pe->name); + fflush(stdout); + continue; + } + e = G_CHECK(g, gr); + G_DESTROYGROUP(g); + dh_paramfree(&dp); + if (e) { + printf(" [%s failed: %s]", pe->name, e); + ok = aok = 0; + } else + printf(" %s", pe->name); + fflush(stdout); + } + fputs(ok ? " ok\n" : " failed\n", stdout); + ok = 1; + fputs("checking standard binary groups:", stdout); + for (be = bintab; be->name; be++) { + gbin_param gb; + group *g; + dh_infofromdata(&gb, be->data); + g = group_binary(&gb); + e = G_CHECK(g, gr); + G_DESTROYGROUP(g); + dh_paramfree(&gb); + if (e) { + printf(" [%s failed: %s]", be->name, e); + ok = aok = 0; + } else + printf(" %s", be->name); + fflush(stdout); + } + fputs(ok ? " ok\n" : " failed\n", stdout); + gr->ops->destroy(gr); + return (!aok); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/dh.h b/pub/dh.h new file mode 100644 index 0000000..32ed522 --- /dev/null +++ b/pub/dh.h @@ -0,0 +1,240 @@ +/* -*-c-*- + * + * Diffie-Hellman and related public-key systems + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_DH_H +#define CATACOMB_DH_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GROUP_H +# include "group.h" +#endif + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_KEY_H +# include "key.h" +#endif + +#ifndef CATACOMB_KEYCHECK_H +# include "keycheck.h" +#endif + +#ifndef CATACOMB_PGEN_H +# include "pgen.h" +#endif + +#ifndef CATACOMB_QDPARSE_H +# include "qdparse.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef gprime_param dh_param; /* Group parameters */ + +typedef struct dh_pub { + dh_param dp; /* Shared parameters */ + mp *y; /* Public key */ +} dh_pub; + +typedef struct dh_priv { + dh_param dp; /* Shared parameters */ + mp *x; /* Private key */ + mp *y; /* %$y \equiv g^x \pmod{p}$% */ +} dh_priv; + +/*----- Key fetching ------------------------------------------------------*/ + +extern const key_fetchdef dh_paramfetch[]; +#define DH_PARAMFETCHSZ 5 + +extern const key_fetchdef dh_pubfetch[]; +#define DH_PUBFETCHSZ 6 + +extern const key_fetchdef dh_privfetch[]; +#define DH_PRIVFETCHSZ 9 + +/* --- @dh_paramfree@, @dh_pubfree@, @dh_privfree@ --- * + * + * Arguments: @dh_param *dp@, @dh_pub *dp@, @dh_priv *dp@ = pointer to + * key block to free + * + * Returns: --- + * + * Use: Frees a Diffie-Hellman key block. + */ + +extern void dh_paramfree(dh_param */*dp*/); +extern void dh_pubfree(dh_pub */*dp*/); +extern void dh_privfree(dh_priv */*dp*/); + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @dh_gen@ --- * + * + * Arguments: @dh_param *dp@ = pointer to output parameter block + * @unsigned ql@ = length of %$q$% in bits, or zero + * @unsigned pl@ = length of %$p$% in bits + * @unsigned steps@ = number of steps to go + * @grand *r@ = random number source + * @pgen_proc *event@ = event handler function + * @void *ectx@ = argument for the event handler + * + * Returns: @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't. + * + * Use: Generates Diffie-Hellman parameters. + * + * The parameters are a prime %$q$%, relatively small, and a + * large prime %$p = kq + 1$% for some %$k$%, together with a + * generator %$g$% of the cyclic subgroup of order %$q$%. These + * are actually the same as the DSA parameter set, but the + * generation algorithm is different. Also, if @ql@ is zero, + * this algorithm forces %$k = 2$%, and chooses %$g = 4$%. Make + * sure you have something interesting to do if you choose this + * option. + */ + +extern int dh_gen(dh_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/, + unsigned /*steps*/, grand */*r*/, pgen_proc */*event*/, + void */*ectx*/); + +/* --- @dh_limlee@ --- * + * + * Arguments: @dh_param *dp@ = pointer to output parameter block + * @unsigned ql@ = length of smallest factor of %$(p - 1)/2$% + * @unsigned pl@ = length of %$p$% in bits + * @unsigned flags@ = other generation flags + * @unsigned steps@ = number of steps to go + * @grand *r@ = random number source + * @pgen_proc *oev@ = outer event handler function + * @void *oec@ = argument for the outer event handler + * @pgen_proc *iev@ = inner event handler function + * @void *iec@ = argument for the inner event handler + * @size_t *nf@, @mp ***f@ = output array for factors + * + * Returns: @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't. + * + * Use: Generates Diffie-Hellman parameters based on a Lim-Lee prime. + * + * The modulus is a large prime %$p = 2 \prod q_i + 1$%, @pl@ + * bits long, where the %$q_i$% are smaller primes each at least + * @ql@ bits long. It is safe to set @nf@ and @f@ to zero if + * you're not interested in the factor values. + * + * The returned %$g$% generates a subgroup of order %$q_0$% (the + * first factor, returned as @f[0]@), if the flag @DH_SUBGROUP@ + * is set on entry; otherwise %$g$% will have order + * %$(p - 1)/2$%. + */ + +#define DH_SUBGROUP 1u + +extern int dh_limlee(dh_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/, + unsigned /*flags*/, unsigned /*steps*/, grand */*r*/, + pgen_proc */*oev*/, void */*oec*/, pgen_proc */*iev*/, + void */*iec*/, size_t */*nf*/, mp ***/*f*/); + +/* --- @dh_kcdsagen@ --- * + * + * Arguments: @dh_param *dp@ = pointer to output parameter block + * @unsigned ql@ = size of small factor of %$(p - 1)/2$% + * @unsigned pl@ = size of %$p$% in bits + * @unsigned flags@ = other generation flags (none defined) + * @unsigned steps@ = number of steps to go + * @grand *r@ = random number source + * @pgen_proc *ev@ = event handler function + * @void *ec@ = context for the event handler + * + * Returns: @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it failed. + * + * Use: Generates a KCDSA prime group. That is, it chooses a prime + * %$p$%, such that $%p = 2 q v + 1$%, for primes %$q$% and + * %$v$%. The actual group of interest is the subgroup of order + * %$q$%. + */ + +extern int dh_kcdsagen(dh_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/, + unsigned /*flags*/, unsigned /*steps*/, grand */*r*/, + pgen_proc */*ev*/, void */*ec*/); + +/* --- @dh_checkparam@ --- * + * + * Arguments: @keycheck *kc@ = keycheck state + * @const dh_param *dp@ = pointer to the parameter set + * @mp **v@ = optional vector of factors + * @size_t n@ = size of vector + * + * Returns: Zero if all OK, or return status from function. + * + * Use: Checks a set of Diffie-Hellman parameters for consistency and + * security. + */ + +extern int dh_checkparam(keycheck */*kc*/, const dh_param */*dp*/, + mp **/*v*/, size_t /*n*/); + +/* ---- @dh_infofromdata@ --- * + * + * Arguments: @dh_param *dp@ = parameters to fill in + * @pdata *pd@ = packed data structure + * + * Returns: --- + * + * Use: Fills in a parameters structure from a packed data block. + */ + +struct pdata; +extern void dh_infofromdata(dh_param */*dp*/, struct pdata */*pd*/); + +/* --- @dh_parse@, @dhbin_parse@ --- * + * + * Arguments: @qd_parse *qd@ = parser context + * @dh_param *dp@ = parameters to fill in + * + * Returns: Zero if OK, nonzero on error. + * + * Use: Parses a prime/binary group string. This is either one of + * the standard group strings, or a %$p$%, %$q$%, %$g$% triple + * separated by commas. + */ + +extern int dh_parse(qd_parse */*qd*/, dh_param */*dp*/); +extern int dhbin_parse(qd_parse */*qd*/, gbin_param */*gb*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/pub/dsa-check.c b/pub/dsa-check.c new file mode 100644 index 0000000..4d42ff2 --- /dev/null +++ b/pub/dsa-check.c @@ -0,0 +1,87 @@ +/* -*-c-*- + * + * Consistency checking for DSA keys + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "dh.h" +#include "dsa.h" +#include "dsarand.h" +#include "grand.h" +#include "keycheck.h" +#include "mp.h" +#include "mprand.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @dsa_checkparam@ --- * + * + * Arguments: @keycheck *kc@ = keycheck state + * @const dsa_param *dp@ = pointer to the parameter set + * @const dsa_seed *ds@ = pointer to seed information + * + * Returns: Zero if all OK, or return status from function. + * + * Use: Checks a set of DSA parameters for consistency and security. + */ + +int dsa_checkparam(keycheck *kc, const dsa_param *dp, const dsa_seed *ds) +{ + if (ds) { + grand *r = dsarand_create(ds->p, ds->sz); + mp *p = MP_NEW, *q = MP_NEW; + int rc = 0; + unsigned i; + unsigned long n; + + r->ops->misc(r, DSARAND_PASSES, 2); + q = mprand(q, mp_bits(dp->q), r, 1); + if (!mp_eq(q, dp->q) && + keycheck_report(kc, KCSEV_ERR, "q doesn't match seed provided")) + rc = -1; + else { + n = mp_bits(dp->p); + r->ops->misc(r, DSARAND_PASSES, 1); + for (i = 0; i <= ds->count; i++) + p = mprand(p, n, r, 0); + q = mp_lsl(q, q, 1); + mp_div(0, &q, p, q); + p = mp_sub(p, p, q); + p->v[0] |= 1; + if (!mp_eq(p, dp->p) && + keycheck_report(kc, KCSEV_ERR, "p doesn't match seed provided")) + rc = -1; + } + mp_drop(p); + mp_drop(q); + r->ops->destroy(r); + if (rc) + return (rc); + } + return (dh_checkparam(kc, dp, 0, 0)); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/dsa-gen.c b/pub/dsa-gen.c new file mode 100644 index 0000000..7c6c3ba --- /dev/null +++ b/pub/dsa-gen.c @@ -0,0 +1,299 @@ +/* -*-c-*- + * + * Generate DSA shared parameters + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include "dsa.h" +#include "dsarand.h" +#include "fibrand.h" +#include "mp.h" +#include "mprand.h" +#include "pgen.h" +#include "prim.h" +#include "sha.h" + +/*----- The DSA stepper ---------------------------------------------------*/ + +/* --- @next@ --- * + * + * Arguments: @pgen_event *ev@ = pointer to event block + * @dsa_stepctx *d@ = pointer to stepping context + * + * Returns: A @PGEN@ result code. + * + * Use: Steps the generator once, reads the result, and tests it. + */ + +static int next(pgen_event *ev, dsa_stepctx *d) +{ + mp *m; + int rc; + + /* --- Load the new candidate --- */ + + if (d->seedbuf) + d->r->ops->misc(d->r, DSARAND_GETSEED, d->seedbuf); + m = mprand(ev->m, d->bits, d->r, 0); + + /* --- Force to be a multiple of @q@ --- */ + + if (d->q) { + mp *r = MP_NEW; + mp_div(0, &r, m, d->q); + m = mp_sub(m, m, r); + mp_drop(r); + } + m->v[0] |= d->or; + ev->m = m; + + /* --- Do the trial division --- */ + + rc = pfilt_smallfactor(m); + d->count++; + + /* --- Return the result --- */ + + return (rc); +} + +/* --- @dsa_step@ --- */ + +int dsa_step(int rq, pgen_event *ev, void *p) +{ + dsa_stepctx *d = p; + + switch (rq) { + case PGEN_BEGIN: + case PGEN_TRY: + return (next(ev, d)); + case PGEN_DONE: + return (PGEN_DONE); + } + return (PGEN_ABORT); +} + +/*----- Glue code ---------------------------------------------------------*/ + +/* --- @dsa_gen@ --- * + * + * Arguments: @dsa_param *dp@ = where to store parameters + * @unsigned ql@ = length of @q@ in bits + * @unsigned pl@ = length of @p@ in bits + * @unsigned steps@ = number of steps to find @q@ + * @const void *k@ = pointer to key material + * @size_t sz@ = size of key material + * @dsa_seed *ds@ = optional pointer for output seed information + * @pgen_proc *event@ = event handler function + * @void *ectx@ = argument for event handler + * + * Returns: @PGEN_DONE@ if everything worked ok; @PGEN_ABORT@ otherwise. + * + * Use: Generates the DSA shared parameters from a given seed value. + * + * The parameters are a prime %$q$%, relatively small, and a + * large prime %$p = kq + 1$% for some %$k$%, together with a + * generator %$g$% of the cyclic subgroup of order %$q$%. These + * are actually the same as the Diffie-Hellman parameter set, + * but the generation algorithm is different. + * + * The algorithm used is a compatible extension of the method + * described in the DSA standard, FIPS 186. The standard + * requires that %$q$% be 160 bits in size (i.e., @ql == 160@) + * and that the length of %$p$% be %$L = 512 + 64l$% for some + * %$l$%. Neither limitation applies to this implementation. + */ + +int dsa_gen(dsa_param *dp, unsigned ql, unsigned pl, unsigned steps, + const void *k, size_t sz, dsa_seed *ds, + pgen_proc *event, void *ectx) +{ + dsa_stepctx s; + prim_ctx p; + int i; + rabin r; + mp *qc; + + /* --- Initialize the stepping context --- */ + + s.r = dsarand_create(k, sz); + + /* --- Find @q@ --- */ + + s.q = 0; + s.r->ops->misc(s.r, DSARAND_PASSES, 2); + s.bits = ql; + s.count = 0; + s.or = 1; + if (!ds) + s.seedbuf = 0; + else { + ds->sz = sz; + ds->p = s.seedbuf = xmalloc(sz); + } + if ((dp->q = pgen("q", MP_NEW, MP_NEW, event, ectx, steps, dsa_step, &s, + rabin_iters(ql), pgen_test, &r)) == 0) + goto fail_q; + + /* --- Find @p@ --- */ + + s.count = ~0; + s.q = mp_lsl(MP_NEW, dp->q, 1); + s.r->ops->misc(s.r, DSARAND_PASSES, 1); + s.bits = pl; + s.seedbuf = 0; + if ((dp->p = pgen("p", MP_NEW, MP_NEW, event, ectx, 4096, dsa_step, &s, + rabin_iters(pl), pgen_test, &r)) == 0) + goto fail_p; + mp_drop(s.q); + if (ds) + ds->count = s.count; + + /* --- Find @g@ --- * + * + * The division returns remainder 1. This doesn't matter. + */ + + mpmont_create(&p.mm, dp->p); + qc = MP_NEW; mp_div(&qc, 0, dp->p, dp->q); + i = 0; + p.exp = qc; + p.n = 0; + if ((dp->g = pgen("g", MP_NEW, MP_NEW, event, ectx, 0, prim_step, &i, + 1, prim_test, &p)) == 0) + goto fail_g; + + /* --- Done --- */ + + mp_drop(qc); + mpmont_destroy(&p.mm); + s.r->ops->destroy(s.r); + return (PGEN_DONE); + + /* --- Tidy up when things go wrong --- */ + +fail_g: + mp_drop(qc); + mpmont_destroy(&p.mm); +fail_p: + mp_drop(dp->q); + mp_drop(s.q); +fail_q: + s.r->ops->destroy(s.r); + if (ds) + xfree(ds->p); + return (PGEN_ABORT); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static int verify(dstr *v) +{ + mp *q = *(mp **)v[4].buf; + mp *p = *(mp **)v[5].buf; + mp *g = *(mp **)v[6].buf; + dsa_param dp; + dsa_seed ds; + unsigned long l = *(unsigned long *)v[1].buf; + unsigned long n = *(unsigned long *)v[3].buf; + int ok = 1; + int rc; + keycheck kc; + keycheck_reportctx kcr; + + rc = dsa_gen(&dp, 160, l, 16, v[0].buf, v[0].len, &ds, pgen_evspin, 0); + if (rc || ds.count != n || ds.sz != v[2].len || + memcmp(ds.p, v[2].buf, v[2].len) != 0 || + !MP_EQ(q, dp.q) || !MP_EQ(p, dp.p) || !MP_EQ(g, dp.g)) { + fputs("\n*** gen failed", stderr); + fputs("\nseed_in = ", stderr); type_hex.dump(&v[0], stderr); + fprintf(stderr, "\nl = %lu", l); + fputs("\nseed_out = ", stderr); type_hex.dump(&v[2], stderr); + fprintf(stderr, "\ncount = %lu", n); + fputs("\n q = ", stderr); mp_writefile(q, stderr, 16); + fputs("\n p = ", stderr); mp_writefile(p, stderr, 16); + fputs("\n g = ", stderr); mp_writefile(g, stderr, 16); + if (!rc) { + dstr d; + d.buf = ds.p; d.len = ds.sz; + fputs("\nds.seed = ", stderr); type_hex.dump(&d, stderr); + fprintf(stderr, "\nds.count = %u", ds.count); + fputs("\ndp.q = ", stderr); mp_writefile(dp.q, stderr, 16); + fputs("\ndp.p = ", stderr); mp_writefile(dp.p, stderr, 16); + fputs("\ndp.g = ", stderr); mp_writefile(dp.g, stderr, 16); + } + fputc('\n', stderr); + ok = 0; + } + + kcr.fp = stderr; + kcr.sev = KCSEV_ERR; + keycheck_init(&kc, keycheck_stdreport, &kcr); + if (!rc) + dsa_checkparam(&kc, &dp, &ds); + if (!keycheck_allclear(&kc, KCSEV_ERR)) { + fputs("\n*** gen failed check", stderr); + fputs("\nseed_in = ", stderr); type_hex.dump(&v[0], stderr); + fprintf(stderr, "\nl = %lu", l); + fputs("\nseed_out = ", stderr); type_hex.dump(&v[2], stderr); + fprintf(stderr, "\ncount = %lu", n); + fputs("\n q = ", stderr); mp_writefile(q, stderr, 16); + fputs("\n p = ", stderr); mp_writefile(p, stderr, 16); + fputs("\n g = ", stderr); mp_writefile(g, stderr, 16); + fputc('\n', stderr); + ok = 0; + } + + mp_drop(q); mp_drop(p); mp_drop(g); + if (!rc) { + mp_drop(dp.q); mp_drop(dp.p); mp_drop(dp.g); xfree(ds.p); + } + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "gen", verify, + { &type_hex, &type_ulong, &type_hex, &type_ulong, + &type_mp, &type_mp, &type_mp, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/dsa"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/dsa-misc.c b/pub/dsa-misc.c similarity index 100% rename from dsa-misc.c rename to pub/dsa-misc.c diff --git a/pub/dsa-sign.c b/pub/dsa-sign.c new file mode 100644 index 0000000..23bbf7f --- /dev/null +++ b/pub/dsa-sign.c @@ -0,0 +1,198 @@ +/* -*-c-*- + * + * DSA signing operation + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "dsa.h" +#include "mp.h" +#include "mpbarrett.h" +#include "mpmont.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @dsa_mksig@ --- * + * + * Arguments: @const dsa_param *dp@ = pointer to DSA parameters + * @mp *a@ = secret signing key + * @mp *m@ = message to be signed + * @mp *k@ = random data + * @mp **rr, **ss@ = where to put output parameters + * + * Returns: --- + * + * Use: Computes a DSA signature of a message. + */ + +void dsa_mksig(const dsa_param *dp, mp *a, mp *m, mp *k, mp **rr, mp **ss) +{ + mpmont pm; + mpbarrett qb; + mp *k1, *r; + mp *ar; + + /* --- Compute %$r = (g^k \bmod p) \bmod q$% --- */ + + mpmont_create(&pm, dp->p); + r = mpmont_exp(&pm, MP_NEW, dp->g, k); + mpmont_destroy(&pm); + mp_div(0, &r, r, dp->q); + + /* --- Compute %$k^{-1} \bmod q$% --- */ + + k1 = mp_modinv(MP_NEW, k, dp->q); + + /* --- Now for %$k^{-1}(m + ar)$% --- */ + + mpbarrett_create(&qb, dp->q); + ar = mp_mul(MP_NEW, a, r); + ar = mp_add(ar, ar, m); + ar = mpbarrett_reduce(&qb, ar, ar); + ar = mp_mul(ar, ar, k1); + ar = mpbarrett_reduce(&qb, ar, ar); + mpbarrett_destroy(&qb); + MP_DROP(k1); + if (*rr) MP_DROP(*rr); + if (*ss) MP_DROP(*ss); + *rr = r; + *ss = ar; +} + +/* --- @dsa_sign@ --- * + * + * Arguments: @dsa_param *dp@ = pointer to DSA parameters + * @mp *a@ = pointer to secret signing key + * @const void *m@ = pointer to message + * @size_t msz@ = size of the message + * @const void *k@ = secret random data for securing signature + * @size_t ksz@ = size of secret data + * @void *r@ = pointer to output space for @r@ + * @size_t rsz@ = size of output space for @r@ + * @void *s@ = pointer to output space for @s@ + * @size_t ssz@ = size of output space for @s@ + * + * Returns: --- + * + * Use: Signs a message, storing the results in a big-endian binary + * form. + */ + +void dsa_sign(dsa_param *dp, mp *a, + const void *m, size_t msz, const void *k, size_t ksz, + void *r, size_t rsz, void *s, size_t ssz) +{ + mp *mm = dsa_h2n(MP_NEW, dp->q, m, msz); + mp *km = mp_loadb(MP_NEW, k, ksz); + mp *rm = MP_NEW, *sm = MP_NEW; + dsa_mksig(dp, a, mm, km, &rm, &sm); + mp_storeb(rm, r, rsz); + mp_storeb(sm, s, ssz); + mp_drop(mm); mp_drop(km); + mp_drop(rm); mp_drop(sm); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +#include "sha.h" + +static int verify(dstr *v) +{ + dsa_param dp; + mp *x; + sha_ctx c; + octet hash[SHA_HASHSZ]; + dsa_sig s; + int ok = 1; + + dp.q = *(mp **)v[0].buf; + dp.p = *(mp **)v[1].buf; + dp.g = *(mp **)v[2].buf; + x = *(mp **)v[3].buf; + + sha_init(&c); + sha_hash(&c, v[4].buf, v[4].len); + sha_done(&c, hash); + + dsa_sign(&dp, x, hash, sizeof(hash), v[5].buf, v[5].len, + s.r, sizeof(s.r), s.s, sizeof(s.s)); + + if (v[6].len != sizeof(s.r) || v[7].len != sizeof(s.s) || + memcmp(s.r, v[6].buf, sizeof(s.r)) != 0 || + memcmp(s.s, v[7].buf, sizeof(s.s)) != 0) { + fputs("\n*** signature failed", stderr); + fputs("\nq = ", stderr); mp_writefile(dp.q, stderr, 16); + fputs("\np = ", stderr); mp_writefile(dp.p, stderr, 16); + fputs("\ng = ", stderr); mp_writefile(dp.g, stderr, 16); + fputs("\nx = ", stderr); mp_writefile(x, stderr, 16); + fprintf(stderr, "\nmessage = `%s'", v[4].buf); + fputs("\nk = ", stderr); type_hex.dump(&v[5], stderr); + fputs("\nR = ", stderr); type_hex.dump(&v[6], stderr); + fputs("\nS = ", stderr); type_hex.dump(&v[7], stderr); + + { + mp *m = MP_NEW; + m = mp_loadb(m, hash, sizeof(hash)); + fputs("\nm = ", stderr); mp_writefile(m, stderr, 16); + m = mp_loadb(m, s.r, sizeof(s.r)); + fputs("\nr = ", stderr); mp_writefile(m, stderr, 16); + m = mp_loadb(m, s.s, sizeof(s.s)); + fputs("\ns = ", stderr); mp_writefile(m, stderr, 16); + mp_drop(m); + } + + fputc('\n', stderr); + ok = 0; + } + + mp_drop(dp.p); + mp_drop(dp.q); + mp_drop(dp.g); + mp_drop(x); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static test_chunk tests[] = { + { "sign", verify, + { &type_mp, &type_mp, &type_mp, &type_mp, + &type_string, &type_hex, &type_hex, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/dsa"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/dsa-verify.c b/pub/dsa-verify.c new file mode 100644 index 0000000..5a6bd4e --- /dev/null +++ b/pub/dsa-verify.c @@ -0,0 +1,205 @@ +/* -*-c-*- + * + * DSA signature verification + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "dsa.h" +#include "mp.h" +#include "mpmont.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @dsa_vrfy@ --- * + * + * Arguments: @const dsa_param *dp@ = pointer to DSA parameters + * @mp *y@ = public verification key + * @mp *m@ = message which was signed + * @mp *r, *s@ = the signature + * + * Returns: Zero if the signature is a forgery, nonzero if it's valid. + * + * Use: Verifies a DSA digital signature. + */ + +int dsa_vrfy(const dsa_param *dp, mp *y, mp *m, mp *r, mp *s) +{ + mpmont pm, qm; + mp *w; + mp_expfactor f[2]; + int ok; + + /* --- Ensure that all of the signature bits are in range --- */ + + if ((r->f | s->f) & MP_NEG) + return (0); + if (MP_CMP(r, >=, dp->q) || MP_CMP(s, >=, dp->q)) + return (0); + + /* --- Set up Montgomery contexts --- */ + + mpmont_create(&pm, dp->p); + mpmont_create(&qm, dp->q); + + /* --- Compute %$w = s^{-1} \bmod q$% --- */ + + { + mp *z = mp_modinv(MP_NEW, s, dp->q); + w = mpmont_mul(&qm, MP_NEW, z, qm.r2); + mp_drop(z); + } + + /* --- Compute %$wr$% and %$wm$% --- */ + + f[0].exp = mpmont_mul(&qm, MP_NEW, w, m); + f[1].exp = mpmont_mul(&qm, MP_NEW, w, r); + mp_drop(w); + mpmont_destroy(&qm); + + /* --- Do the exponentiation and take residue mod @q@ --- */ + + f[0].base = dp->g; + f[1].base = y; + w = mpmont_mexp(&pm, MP_NEW, f, 2); + mp_div(0, &w, w, dp->q); + ok = MP_EQ(w, r); + + /* --- Tidy up --- */ + + mp_drop(w); + mp_drop(f[0].exp); + mp_drop(f[1].exp); + mpmont_destroy(&pm); + return (ok); +} + +/* --- @dsa_verify@ --- * + * + * Arguments: @const dsa_param *dp@ = pointer to DSA parameters + * @mp *y@ = public verification key + * @const void *m@ = pointer to message block + * @size_t msz@ = size of message block + * @const void *r@ = pointer to @r@ signature half + * @size_t rsz@ = size of @r@ + * @const void *s@ = pointer to @s@ signature half + * @size_t ssz@ = size of @s@ + * + * Returns: Zero if the signature is a forgery, nonzero if it's valid. + * + * Use: Verifies a DSA digital signature. + */ + +int dsa_verify(const dsa_param *dp, mp *y, + const void *m, size_t msz, + const void *r, size_t rsz, + const void *s, size_t ssz) +{ + mp *mm = dsa_h2n(MP_NEW, dp->q, m, msz); + mp *rm = mp_loadb(MP_NEW, r, rsz); + mp *sm = mp_loadb(MP_NEW, s, ssz); + int ok = dsa_vrfy(dp, y, mm, rm, sm); + mp_drop(mm); + mp_drop(rm); + mp_drop(sm); + return (ok); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +#include "sha.h" + +static int verify(int good, dstr *v) +{ + dsa_param dp; + mp *y; + sha_ctx c; + octet hash[SHA_HASHSZ]; + int ok = 1; + int rc; + + dp.q = *(mp **)v[0].buf; + dp.p = *(mp **)v[1].buf; + dp.g = *(mp **)v[2].buf; + y = *(mp **)v[3].buf; + + sha_init(&c); + sha_hash(&c, v[4].buf, v[4].len); + sha_done(&c, hash); + + rc = dsa_verify(&dp, y, hash, sizeof(hash), + v[5].buf, v[5].len, v[6].buf, v[6].len); + + if (!rc != !good) { + if (good) + fputs("\n*** verification failed", stderr); + else + fputs("\n*** verification succeeded", stderr); + fputs("\nq = ", stderr); mp_writefile(dp.q, stderr, 16); + fputs("\np = ", stderr); mp_writefile(dp.p, stderr, 16); + fputs("\ng = ", stderr); mp_writefile(dp.g, stderr, 16); + fputs("\ny = ", stderr); mp_writefile(y, stderr, 16); + fprintf(stderr, "\nmessage = `%s'", v[4].buf); + fputs("\nr = ", stderr); type_hex.dump(&v[5], stderr); + fputs("\ns = ", stderr); type_hex.dump(&v[6], stderr); + fputc('\n', stderr); + ok = 0; + } + + mp_drop(dp.p); + mp_drop(dp.q); + mp_drop(dp.g); + mp_drop(y); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int vgood(dstr *v) { return verify(1, v); } +static int vbad(dstr *v) { return verify(0, v); } + +static test_chunk tests[] = { + { "verify-good", vgood, + { &type_mp, &type_mp, &type_mp, &type_mp, + &type_string, &type_hex, &type_hex, 0 } }, + { "verify-bad", vbad, + { &type_mp, &type_mp, &type_mp, &type_mp, + &type_string, &type_hex, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/dsa"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/dsa.h b/pub/dsa.h new file mode 100644 index 0000000..3b93d93 --- /dev/null +++ b/pub/dsa.h @@ -0,0 +1,277 @@ +/* -*-c-*- + * + * Digital Signature Algorithm + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_DSA_H +#define CATACOMB_DSA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Notes on the Digital Signature Algorithm --------------------------* + * + * The Digital Signature Algorithm was designed by the NSA for US Government + * use. It's defined in FIPS 186-1. Whether it's covered by patents is + * under dispute, although it looks relatively clear. It produces compact + * signatures, and is relatively easy to compute. It seems strong, if + * appropriate parameters are chosen. + */ + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_DH_H +# include "dh.h" +#endif + +#ifndef CATACOMB_KEY_H +# include "key.h" +#endif + +#ifndef CATACOMB_KEYCHECK_H +# include "keycheck.h" +#endif + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_PGEN_H +# include "pgen.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- The parameters and keys are the same as for Diffie-Hellman --- */ + +typedef dh_param dsa_param; +typedef dh_pub dsa_pub; +typedef dh_priv dsa_priv; + +/* --- DSA key seed structure --- */ + +typedef struct dsa_seed { + void *p; /* Pointer to seed material */ + size_t sz; /* Size of seed material */ + unsigned count; /* Iterations to find @p@ */ +} dsa_seed; + +/* --- DSA signature structure --- * + * + * This is the recommended structure for a DSA signature. The actual signing + * function can cope with arbitrary-sized objects given appropriate + * parameters, however. + */ + +#define DSA_SIGLEN 20 + +typedef struct dsa_sig { + octet r[DSA_SIGLEN]; /* 160-bit @r@ value */ + octet s[DSA_SIGLEN]; /* 160-bit @s@ value */ +} dsa_sig; + +/*----- Key fetching ------------------------------------------------------*/ + +#define dsa_paramfetch dh_paramfetch +#define dsa_pubfetch dh_pubfetch +#define dsa_privfetch dh_privfetch + +#define DSA_PARAMFETCHSZ DH_PARAMFETCHSZ +#define DSA_PUBFETCHSZ DH_PUBFETCHSZ +#define DSA_PRIVFETCHSZ DH_PRIVFETCHSZ + +#define dsa_paramfree dh_paramfree +#define dsa_pubfree dh_pubfree +#define dsa_privfree dh_privfree + +/*----- DSA stepper -------------------------------------------------------*/ + +typedef struct dsa_stepctx { + + /* --- To be initialized by the client --- */ + + grand *r; /* Random number generator */ + mp *q; /* Force @p@ to be a multiple */ + size_t bits; /* Number of bits in the result */ + unsigned or; /* OR mask for low order bits */ + unsigned count; /* Counts the number of steps made */ + void *seedbuf; /* Pointer to seed buffer */ +} dsa_stepctx; + +/* --- @dsa_step@ --- * + * + * The stepper chooses random integers, ensures that they are a multiple of + * @q@ (if specified), sets the low-order bits, and then tests for + * divisibility by small primes. + */ + +extern pgen_proc dsa_step; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @dsa_gen@ --- * + * + * Arguments: @dsa_param *dp@ = where to store parameters + * @unsigned ql@ = length of @q@ in bits + * @unsigned pl@ = length of @p@ in bits + * @unsigned steps@ = number of steps to find @q@ + * @const void *k@ = pointer to key material + * @size_t sz@ = size of key material + * @dsa_seed *sd@ = optional pointer for output seed information + * @pgen_proc *event@ = event handler function + * @void *ectx@ = argument for event handler + * + * Returns: @PGEN_DONE@ if everything worked ok; @PGEN_ABORT@ otherwise. + * + * Use: Generates the DSA shared parameters from a given seed value. + * This can take quite a long time. + * + * The algorithm used is a compatible extension of the method + * described in the DSA standard, FIPS 186. The standard + * requires that %$q$% be 160 bits in size (i.e., @ql == 160@) + * and that the length of %$p$% be %$L = 512 + 64l$% for some + * %$l$%. Neither limitation applies to this implementation. + */ + +extern int dsa_gen(dsa_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/, + unsigned /*steps*/, const void */*k*/, size_t /*sz*/, + dsa_seed */*sd*/, pgen_proc */*event*/, void */*ectx*/); + +/* --- @dsa_checkparam@ --- * + * + * Arguments: @keycheck *kc@ = keycheck state + * @const dsa_param *dp@ = pointer to the parameter set + * @const dsa_seed *ds@ = pointer to seed information + * + * Returns: Zero if all OK, or return status from function. + * + * Use: Checks a set of DSA parameters for consistency and security. + */ + +extern int dsa_checkparam(keycheck */*kc*/, const dsa_param */*dp*/, + const dsa_seed */*ds*/); + +/* --- @dsa_h2n@ --- * + * + * Arguments: @mp *d@ = destination integer + * @mp *r@ = order of the DSA group + * @const void *h@ = pointer to message hash + * @size_t hsz@ = size (in bytes) of the hash output + * + * Returns: Resulting integer. + * + * Use: Converts a hash to an integer in the demented way necessary + * for DSA/ECDSA. This is, of course, completely insane, but + * there you go. + */ + +extern mp *dsa_h2n(mp */*d*/, mp */*r*/, const void */*h*/, size_t /*hsz*/); + +/* --- @dsa_mksig@ --- * + * + * Arguments: @const dsa_param *dp@ = pointer to DSA parameters + * @mp *a@ = secret signing key + * @mp *m@ = message to be signed + * @mp *k@ = random data + * @mp **rr, **ss@ = where to put output parameters + * + * Returns: --- + * + * Use: Computes a DSA signature of a message. + */ + +extern void dsa_mksig(const dsa_param */*dp*/, mp */*a*/, + mp */*m*/, mp */*k*/, + mp **/*rr*/, mp **/*ss*/); + +/* --- @dsa_sign@ --- * + * + * Arguments: @dsa_param *dp@ = pointer to DSA parameters + * @mp *a@ = pointer to secret signing key + * @const void *m@ = pointer to message + * @size_t msz@ = size of the message + * @const void *k@ = secret random data for securing signature + * @size_t ksz@ = size of secret data + * @void *r@ = pointer to output space for @r@ + * @size_t rsz@ = size of output space for @r@ + * @void *s@ = pointer to output space for @s@ + * @size_t ssz@ = size of output space for @s@ + * + * Returns: --- + * + * Use: Signs a message, storing the results in a big-endian binary + * form. + */ + +extern void dsa_sign(dsa_param */*dp*/, mp */*a*/, + const void */*m*/, size_t /*msz*/, + const void */*k*/, size_t /*ksz*/, + void */*r*/, size_t /*rsz*/, + void */*s*/, size_t /*ssz*/); + +/* --- @dsa_vrfy@ --- * + * + * Arguments: @const dsa_param *dp@ = pointer to DSA parameters + * @mp *y@ = public verification key + * @mp *m@ = message which was signed + * @mp *r, *s@ = the signature + * + * Returns: Zero if the signature is a forgery, nonzero if it's valid. + * + * Use: Verifies a DSA digital signature. + */ + +extern int dsa_vrfy(const dsa_param */*dp*/, mp */*y*/, + mp */*m*/, mp */*r*/, mp */*s*/); + +/* --- @dsa_verify@ --- * + * + * Arguments: @const dsa_param *dp@ = pointer to DSA parameters + * @mp *y@ = public verification key + * @const void *m@ = pointer to message block + * @size_t msz@ = size of message block + * @const void *r@ = pointer to @r@ signature half + * @size_t rsz@ = size of @r@ + * @const void *s@ = pointer to @s@ signature half + * @size_t ssz@ = size of @s@ + * + * Returns: Zero if the signature is a forgery, nonzero if it's valid. + * + * Use: Verifies a DSA digital signature. + */ + +extern int dsa_verify(const dsa_param */*dp*/, mp */*y*/, + const void */*m*/, size_t /*msz*/, + const void */*r*/, size_t /*rsz*/, + const void */*s*/, size_t /*ssz*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/pub/gdsa.c b/pub/gdsa.c new file mode 100644 index 0000000..6fea5f4 --- /dev/null +++ b/pub/gdsa.c @@ -0,0 +1,255 @@ +/* -*-c-*- + * + * Generalized version of DSA + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "dsa.h" +#include "gdsa.h" +#include "group.h" +#include "ghash.h" +#include "mpbarrett.h" +#include "mprand.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gdsa_beginhash@ --- * + * + * Arguments: @const gdsa *c@ = pointer to the context structure + * + * Returns: A hashing context for you to hash the message. + * + * Use: Initializes a hash function correctly for you to hash a + * message. Requires @h@. + */ + +ghash *gdsa_beginhash(const gdsa *c) { return (GH_INIT(c->h)); } + +/* --- @gdsa_endhash@ --- * + * + * Arguments: @const gdsa *c@ = pointer to the context structure + * @ghash *h@ = the hashing context + * + * Returns: --- + * + * Use: Does any final thing that DSA wants to do when hashing a + * message. (Actually, there's nothing.) The hashing context + * isn't finalized. + */ + +void gdsa_endhash(const gdsa *c, ghash *h) { ; } + +/* --- @gdsa_sign@ --- * + * + * Arguments: @const gdsa *c@ = my context structure + * @gdsa_sig *s@ = where to put the signature (initialized) + * @const void *m@ = pointer to message hash + * @mp *k@ = random exponent for this message or null + * + * Returns: --- + * + * Use: Signs a message. Requires @g@, @u@, @h@, and @r@ if @k@ is + * null. This is a better idea than inventing @k@ yourself. + */ + +void gdsa_sign(const gdsa *c, gdsa_sig *s, const void *m, mp *k) +{ + group *g = c->g; + mp *mr = dsa_h2n(MP_NEW, g->r, m, c->h->hashsz); + ge *z = G_CREATE(g); + mp *sr = s->r, *ss = s->s; + mpbarrett b; + + if (k) { MP_COPY(k); goto have_k; } +new_k: + k = mprand_range(k, g->r, c->r, 0); +have_k: + if (MP_ZEROP(k)) goto new_k; + G_EXP(g, z, g->g, k); + sr = G_TOINT(g, sr, z); assert(sr); + if (MP_ZEROP(sr)) goto new_k; + + mp_div(0, &sr, sr, g->r); + mpbarrett_create(&b, g->r); + ss = mp_mul(ss, sr, c->u); ss = mpbarrett_reduce(&b, ss, ss); + ss = mp_add(ss, ss, mr); mp_div(0, &ss, ss, g->r); + k = mp_modinv(k, k, g->r); + ss = mp_mul(ss, ss, k); ss = mpbarrett_reduce(&b, ss, ss); + s->r = sr; s->s = ss; + mp_drop(k); mp_drop(mr); mpbarrett_destroy(&b); G_DESTROY(g, z); +} + +/* --- @gdsa_verify@ --- * + * + * Arguments: @const gdsa *c@ = my context structure + * @const gdsa_sig *s@ = the signature to verify + * @const void *m@ = pointer to message hash + * + * Returns: Zero if OK, negative on failure. + * + * Use: Checks a signature on a message, Requires @g@, @p@ and @h@. + */ + +int gdsa_verify(const gdsa *c, const gdsa_sig *s, const void *m) +{ + group *g = c->g; + group_expfactor e[2]; + mpbarrett b; + mp *h, *t; + ge *w; + int rc = -1; + + if (MP_CMP(s->r, <, MP_ONE) || MP_CMP(s->r, >=, g->r) || + MP_CMP(s->s, <, MP_ONE) || MP_CMP(s->s, >=, g->r)) + return (-1); + mpbarrett_create(&b, g->r); h = mp_modinv(MP_NEW, s->s, g->r); + e[0].base = g->g; e[1].base = c->p; + t = dsa_h2n(MP_NEW, g->r, m, c->h->hashsz); mp_div(0, &t, t, g->r); + t = mp_mul(t, t, h); e[0].exp = t = mpbarrett_reduce(&b, t, t); + h = mp_mul(h, s->r, h); e[1].exp = h = mpbarrett_reduce(&b, h, h); + w = G_CREATE(g); G_MEXP(g, w, e, 2); + t = G_TOINT(g, t, w); if (!t) goto done; + mp_div(0, &t, t, g->r); if (MP_EQ(t, s->r)) rc = 0; +done: + G_DESTROY(g, w); mp_drop(t); mp_drop(h); mpbarrett_destroy(&b); + return (rc); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static group *getgroup(const char *p) { + group *g; qd_parse qd; + qd.p = p; qd.e = 0; g = group_parse(&qd); + if (g && !qd_eofp(&qd)) { G_DESTROYGROUP(g); g = 0; qd.e = "junk at eof"; } + if (!g) { fprintf(stderr, "bad group string `%.*s|%s': %s\n", qd.p - p, + p, qd.p, qd.e); exit(1); } + return (g); +} + +static ge *getge(group *g, const char *p) { + ge *x = G_CREATE(g); + if (group_readstring(g, x, p, 0)) { + fprintf(stderr, "bad group element `%s'\n", p); + exit(1); + } + return (x); +} + +static void showge(group *g, const char *p, ge *x) { + fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr); + putc('\n', stderr); +} + +static void showmp(const char *p, mp *x, int r) { + fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r); + putc('\n', stderr); +} + +static int tsign(dstr *v) +{ + gdsa c; + gdsa_sig s, ss = GDSA_SIG_INIT; + ghash *h; + mp *k; + int ok = 1; + + c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf); + c.u = *(mp **)v[2].buf; k = *(mp **)v[4].buf; + s.r = *(mp **)v[5].buf; s.s = *(mp **)v[6].buf; + + h = gdsa_beginhash(&c); + GH_HASH(h, v[3].buf, v[3].len); + gdsa_endhash(&c, h); + gdsa_sign(&c, &ss, GH_DONE(h, 0), k); + if (!MP_EQ(s.r, ss.r) || !MP_EQ(s.s, ss.s)) { + ok = 0; + fprintf(stderr, "*** sign failed!\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + fprintf(stderr, "*** hash: %s\n", c.h->name); + showmp("private key", c.u, 16); + fprintf(stderr, "*** message: `%s'\n", v[3].buf); + showmp("computed r", ss.r, 16); showmp("computed s", ss.s, 16); + showmp("expected r", s.r, 16); showmp("expected s", s.s, 16); + } + mp_drop(s.r); mp_drop(s.s); mp_drop(ss.r); mp_drop(ss.s); + mp_drop(k); mp_drop(c.u); G_DESTROYGROUP(c.g); GH_DESTROY(h); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tverify(dstr *v) +{ + gdsa c; + gdsa_sig s; + ghash *h; + int rc, erc; + int ok = 1; + + c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf); + c.p = getge(c.g, v[2].buf); + s.r = *(mp **)v[4].buf; s.s = *(mp **)v[5].buf; + erc = *(int *)v[6].buf; + + h = gdsa_beginhash(&c); + GH_HASH(h, v[3].buf, v[3].len); + gdsa_endhash(&c, h); + rc = gdsa_verify(&c, &s, GH_DONE(h, 0)); + if (!rc != !erc) { + ok = 0; + fprintf(stderr, "*** verify failed!\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + fprintf(stderr, "*** hash: %s\n", c.h->name); + showge(c.g, "public key", c.p); + fprintf(stderr, "*** message: `%s'\n", v[3].buf); + showmp("sig r", s.r, 16); showmp("sig s", s.s, 16); + fprintf(stderr, "*** expected %s\n", !erc ? "pass" : "fail"); + } + mp_drop(s.r); mp_drop(s.s); G_DESTROY(c.g, c.p); G_DESTROYGROUP(c.g); + GH_DESTROY(h); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static const test_chunk tests[] = { + { "sign", tsign, { &type_string, &type_string, &type_mp, &type_string, + &type_mp, &type_mp, &type_mp } }, + { "verify", tverify, { &type_string, &type_string, &type_string, + &type_string, &type_mp, &type_mp, &type_int } }, + { 0 } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/gdsa"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/gdsa.h b/pub/gdsa.h new file mode 100644 index 0000000..df41632 --- /dev/null +++ b/pub/gdsa.h @@ -0,0 +1,130 @@ +/* -*-c-*- + * + * Generalized version of DSA + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GDSA_H +#define CATACOMB_GDSA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +#ifndef CATACOMB_GROUP_H +# include "group.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- GDSA context --- * + * + * You don't need to fill in all of this stuff. See the description of the + * function you want to use to find out what members are needed. + */ + +typedef struct gdsa { + group *g; /* The group we work in */ + mp *u; /* Private key, for signing */ + ge *p; /* Public key, for verifying */ + grand *r; /* Random number source */ + const gchash *h; /* Hash function */ +} gdsa; + +/* --- GDSA signatures --- */ + +typedef struct gdsa_sig { mp *r, *s; } gdsa_sig; +#define GDSA_SIG_INIT { MP_NEW, MP_NEW } + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @gdsa_beginhash@ --- * + * + * Arguments: @const gdsa *c@ = pointer to the context structure + * + * Returns: A hashing context for you to hash the message. + * + * Use: Initializes a hash function correctly for you to hash a + * message. Requires @h@. + */ + +extern ghash *gdsa_beginhash(const gdsa */*c*/); + +/* --- @gdsa_endhash@ --- * + * + * Arguments: @const gdsa *c@ = pointer to the context structure + * @ghash *h@ = the hashing context + * + * Returns: --- + * + * Use: Does any final thing that DSA wants to do when hashing a + * message. (Actually, there's nothing.) The hashing context + * isn't finalized. + */ + +extern void gdsa_endhash(const gdsa */*c*/, ghash */*h*/); + +/* --- @gdsa_sign@ --- * + * + * Arguments: @const gdsa *c@ = my context structure + * @gdsa_sig *s@ = where to put the signature (initialized) + * @const void *m@ = pointer to message hash + * @mp *k@ = random exponent for this message or null + * + * Returns: --- + * + * Use: Signs a message. Requires @g@, @u@, @h@, and @r@ if @k@ is + * null. This is a better idea than inventing @k@ yourself. + */ + +extern void gdsa_sign(const gdsa */*c*/, gdsa_sig */*s*/, + const void */*m*/, mp */*k*/); + +/* --- @gdsa_verify@ --- * + * + * Arguments: @const gdsa *c@ = my context structure + * @const gdsa_sig *s@ = the signature to verify + * @const void *m@ = pointer to message hash + * + * Returns: Zero if OK, negative on failure. + * + * Use: Checks a signature on a message, Requires @g@, @p@, @h@. + */ + +extern int gdsa_verify(const gdsa */*c*/, const gdsa_sig */*s*/, + const void */*m*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/pub/gkcdsa.c b/pub/gkcdsa.c new file mode 100644 index 0000000..eb5a3de --- /dev/null +++ b/pub/gkcdsa.c @@ -0,0 +1,309 @@ +/* -*-c-*- + * + * Generalized version of KCDSA + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "gkcdsa.h" +#include "group.h" +#include "ghash.h" +#include "mpbarrett.h" +#include "mprand.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gkcdsa_beginhash@ --- * + * + * Arguments: @const gkcdsa *c@ = pointer to the context structure + * + * Returns: A hashing context for you to hash the message. + * + * Use: Initializes a hash function correctly for you to hash a + * message. Requires @h@, @g@ and @p@. + */ + +ghash *gkcdsa_beginhash(const gkcdsa *c) +{ + ghash *h = GH_INIT(c->h); + mp *v = G_TOINT(c->g, MP_NEW, c->p); + size_t sz = c->h->bufsz; + void *p = xmalloc(sz); + if (/*ouch*/ !v) memset(p, 0, sz); + else mp_storeb(v, p, sz); + GH_HASH(h, p, sz); + mp_drop(v); xfree(p); + return (h); +} + +/* --- @gkcdsa_endhash@ --- * + * + * Arguments: @const gkcdsa *c@ = pointer to the context structure + * @ghash *h@ = the hashing context + * + * Returns: --- + * + * Use: Does any final thing that KCDSA wants to do when hashing a + * message. (Actually, there's nothing.) The hashing context + * isn't finalized. + */ + +void gkcdsa_endhash(const gkcdsa *c, ghash *h) { ; } + +/* --- @hashge@ --- * + * + * Arguments: @group *g@ = abstract group + * @const gchash *hc@ = hash class + * @ge *w@ = a group element + * + * Returns: A hash context, with the hash of @w@ in it. + */ + +static ghash *hashge(group *g, const gchash *hc, ge *w) +{ + ghash *h; + size_t sz; + void *p; + buf b; + int rc; + + sz = hc->hashsz; + if (sz < g->noctets) + sz = g->noctets; + p = xmalloc(sz); + buf_init(&b, p, sz); + rc = G_TORAW(g, &b, w); + assert(rc == 0); + h = GH_INIT(hc); + GH_HASH(h, BBASE(&b), BLEN(&b)); + xfree(p); + return (h); +} + +/* --- @gkcdsa_sign@ --- * + * + * Arguments: @const gkcdsa *c@ = my context structure + * @gkcdsa_sig *s@ = where to put the signature (initialized) + * @const void *m@ = pointer to message hash + * @mp *k@ = random exponent for this message or null + * + * Returns: --- + * + * Use: Signs a message. Requires @g@, @u@, @h@, and @r@ if @k@ is + * null. This is a better idea than inventing @k@ yourself. + */ + +void gkcdsa_sign(const gkcdsa *c, gkcdsa_sig *s, const void *m, mp *k) +{ + group *g = c->g; + mp *x, *y; + ge *z = G_CREATE(g); + size_t hsz = c->h->hashsz; + ghash *h; + + if (k) { MP_COPY(k); goto have_k; } +new_k: + k = mprand_range(k, g->r, c->r, 0); +have_k: + if (MP_ZEROP(k)) goto new_k; + G_EXP(g, z, g->g, k); + if (!s->r) s->r = xmalloc(hsz); + h = hashge(g, c->h, z); GH_DONE(h, s->r); + + x = mp_loadb(s->s, m, hsz); + y = mp_loadb(MP_NEW, s->r, hsz); + x = mp_xor(x, x, y); + mp_div(0, &x, x, g->r); + x = mp_sub(x, g->r, x); + x = mp_add(x, x, k); + if (MP_CMP(x, >=, g->r)) x = mp_sub(x, x, g->r); + x = mp_mul(x, x, c->u); mp_div(0, &x, x, g->r); + s->s = x; + mp_drop(k); mp_drop(y); GH_DESTROY(h); G_DESTROY(g, z); +} + +/* --- @gkcdsa_verify@ --- * + * + * Arguments: @const gkcdsa *c@ = my context structure + * @const gkcdsa_sig *s@ = the signature to verify + * @const void *m@ = pointer to message hash + * + * Returns: Zero if OK, negative on failure. + * + * Use: Checks a signature on a message, Requires @g@, @p@, @h@. + */ + +int gkcdsa_verify(const gkcdsa *c, const gkcdsa_sig *s, const void *m) +{ + group *g = c->g; + size_t hsz = c->h->hashsz; + group_expfactor e[2]; + mp *x, *y; + ghash *h; + ge *z; + octet *p; + int rc = -1; + + if (MP_CMP(s->s, <, MP_ONE) || MP_CMP(s->s, >=, g->r)) + return (-1); + x = mp_loadb(MP_NEW, m, hsz); y = mp_loadb(MP_NEW, s->r, hsz); + x = mp_xor(x, x, y); mp_div(0, &x, x, g->r); + e[0].base = c->p; e[0].exp = s->s; + e[1].base = g->g; e[1].exp = x; + z = G_CREATE(g); G_MEXP(g, z, e, 2); + h = hashge(g, c->h, z); p = GH_DONE(h, 0); + if (memcmp(p, s->r, hsz) == 0) rc = 0; + mp_drop(x); mp_drop(y); G_DESTROY(g, z); GH_DESTROY(h); + return (rc); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static group *getgroup(const char *p) { + group *g; qd_parse qd; + qd.p = p; qd.e = 0; g = group_parse(&qd); + if (g && !qd_eofp(&qd)) { G_DESTROYGROUP(g); g = 0; qd.e = "junk at eof"; } + if (!g) { fprintf(stderr, "bad group string `%.*s|%s': %s\n", qd.p - p, + p, qd.p, qd.e); exit(1); } + return (g); +} + +static ge *getge(group *g, const char *p) { + ge *x = G_CREATE(g); + if (group_readstring(g, x, p, 0)) { + fprintf(stderr, "bad group element `%s'\n", p); + exit(1); + } + return (x); +} + +static void showge(group *g, const char *p, ge *x) { + fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr); + putc('\n', stderr); +} + +static void showmp(const char *p, mp *x, int r) { + fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r); + putc('\n', stderr); +} + +static int tsign(dstr *v) +{ + gdsa c; + gkcdsa_sig s, ss = GKCDSA_SIG_INIT; + ghash *h; + mp *k; + dstr d = DSTR_INIT; + mp *x; + int ok = 1; + + c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf); + c.u = *(mp **)v[2].buf; k = *(mp **)v[4].buf; + s.r = (octet *)v[5].buf; s.s = *(mp **)v[6].buf; + DENSURE(&d, c.h->hashsz); d.len = c.h->hashsz; memset(d.buf, 0, d.len); + ss.r = (octet *)d.buf; + + x = mp_modinv(MP_NEW, c.u, c.g->r); + c.p = G_CREATE(c.g); G_EXP(c.g, c.p, c.g->g, x); + h = gkcdsa_beginhash(&c); + GH_HASH(h, v[3].buf, v[3].len); + gkcdsa_endhash(&c, h); + gkcdsa_sign(&c, &ss, GH_DONE(h, 0), k); + if (memcmp(s.r, ss.r, c.h->hashsz) || !MP_EQ(s.s, ss.s)) { + ok = 0; + fprintf(stderr, "*** sign failed!\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + fprintf(stderr, "*** hash: %s\n", c.h->name); + showmp("private key", c.u, 16); + showge(c.g, "public key", c.p); + fprintf(stderr, "*** message: `%s'\n", v[3].buf); + fprintf(stderr, "*** computed r = "); + type_hex.dump(&d, stderr); putc('\n', stderr); + showmp("computed s", ss.s, 16); + fprintf(stderr, "*** computed r = "); + type_hex.dump(&v[5], stderr); putc('\n', stderr); + showmp("expected s", s.s, 16); + } + mp_drop(s.s); dstr_destroy(&d); mp_drop(ss.s); mp_drop(x); mp_drop(k); + mp_drop(c.u); G_DESTROY(c.g, c.p); G_DESTROYGROUP(c.g); GH_DESTROY(h); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tverify(dstr *v) +{ + gkcdsa c; + gkcdsa_sig s; + ghash *h; + int rc, erc; + int ok = 1; + + c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf); + c.p = getge(c.g, v[2].buf); + s.r = (octet *)v[4].buf; s.s = *(mp **)v[5].buf; + erc = *(int *)v[6].buf; + + h = gkcdsa_beginhash(&c); + GH_HASH(h, v[3].buf, v[3].len); + gkcdsa_endhash(&c, h); + rc = gkcdsa_verify(&c, &s, GH_DONE(h, 0)); + if (!rc != !erc) { + ok = 0; + fprintf(stderr, "*** verify failed!\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + fprintf(stderr, "*** hash: %s\n", c.h->name); + showge(c.g, "public key", c.p); + fprintf(stderr, "*** message: `%s'\n", v[3].buf); + fprintf(stderr, "*** sig r = "); + type_hex.dump(&v[4], stderr); putc('\n', stderr); + showmp("sig s", s.s, 16); + fprintf(stderr, "*** expected %s\n", !erc ? "pass" : "fail"); + } + mp_drop(s.s); G_DESTROY(c.g, c.p); G_DESTROYGROUP(c.g); + GH_DESTROY(h); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static const test_chunk tests[] = { + { "sign", tsign, { &type_string, &type_string, &type_mp, &type_string, + &type_mp, &type_hex, &type_mp } }, + { "verify", tverify, { &type_string, &type_string, &type_string, + &type_string, &type_hex, &type_mp, &type_int } }, + { 0 } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/t/gkcdsa"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/gkcdsa.h b/pub/gkcdsa.h new file mode 100644 index 0000000..d8e44c3 --- /dev/null +++ b/pub/gkcdsa.h @@ -0,0 +1,130 @@ +/* -*-c-*- + * + * Generalized version of KCDSA + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GKCDSA_H +#define CATACOMB_GKCDSA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GROUP_H +# include "group.h" +#endif + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +#ifndef CATACOMB_GDSA_H +# include "gdsa.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- Careful! --- * + * + * These structures are the same as for DSA. However, the private key @u@ is + * the %$\emph{inverse}$% of the exponent. Do this wrong and the maths will + * fail hopelessly. + */ + +typedef gdsa gkcdsa; + +typedef struct gkcdsa_sig { + octet *r; /* Null means @xmalloc@ me */ + mp *s; +} gkcdsa_sig; +#define GKCDSA_SIG_INIT { 0, 0 } + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @gkcdsa_beginhash@ --- * + * + * Arguments: @const gkcdsa *c@ = pointer to the context structure + * + * Returns: A hashing context for you to hash the message. + * + * Use: Initializes a hash function correctly for you to hash a + * message. Requires @h@, @g@ and @p@. + */ + +extern ghash *gkcdsa_beginhash(const gkcdsa */*c*/); + +/* --- @gkcdsa_endhash@ --- * + * + * Arguments: @const gkcdsa *c@ = pointer to the context structure + * @ghash *h@ = the hashing context + * + * Returns: --- + * + * Use: Does any final thing that KCDSA wants to do when hashing a + * message. (Actually, there's nothing.) The hashing context + * isn't finalized. + */ + +extern void gkcdsa_endhash(const gkcdsa */*c*/, ghash */*h*/); + +/* --- @gkcdsa_sign@ --- * + * + * Arguments: @const gkcdsa *c@ = my context structure + * @gkcdsa_sig *s@ = where to put the signature (initialized) + * @const void *m@ = pointer to message hash + * @mp *k@ = random exponent for this message or null + * + * Returns: --- + * + * Use: Signs a message. Requires @g@, @u@, @h@, and @r@ if @k@ is + * null. This is a better idea than inventing @k@ yourself. + */ + +extern void gkcdsa_sign(const gkcdsa */*c*/, gkcdsa_sig */*s*/, + const void */*m*/, mp */*k*/); + +/* --- @gkcdsa_verify@ --- * + * + * Arguments: @const gkcdsa *c@ = my context structure + * @const gkcdsa_sig *s@ = the signature to verify + * @const void *m@ = pointer to message hash + * + * Returns: Zero if OK, negative on failure. + * + * Use: Checks a signature on a message, Requires @g@, @p@, @h@. + */ + +extern int gkcdsa_verify(const gkcdsa */*c*/, const gkcdsa_sig */*s*/, + const void */*m*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/pub/keycheck-mp.c b/pub/keycheck-mp.c new file mode 100644 index 0000000..c5779a4 --- /dev/null +++ b/pub/keycheck-mp.c @@ -0,0 +1,86 @@ +/* -*-c-*- + * + * Key consistency checking tools for large integers + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "fibrand.h" +#include "grand.h" +#include "keycheck.h" +#include "mp.h" +#include "mprand.h" +#include "pfilt.h" +#include "pgen.h" +#include "rabin.h" +#include "rand.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @keycheck_prime@ --- * + * + * Arguments: @keycheck *kc@ = keycheck state + * @unsigned sev@ = severity if not prime + * @mp *m@ = a number to check for primality + * @const char *name@ = name of this number + * + * Returns: Zero if OK, or return status from function. + * + * Use: Checks that a number is prime. + */ + +int keycheck_prime(keycheck *kc, unsigned sev, mp *m, const char *name) +{ + int rc; + + rc = pfilt_smallfactor(m); + if (rc == PGEN_TRY) { + rabin rn; + grand *r = fibrand_create(0); + unsigned n; + mp *x = MP_NEW; + + r->ops->misc(r, GRAND_SEEDRAND, &rand_global); + n = rabin_iters(mp_bits(m)); + rabin_create(&rn, m); + do { + x = mprand_range(x, m, r, 0); + rc = rabin_test(&rn, x); + n--; + } while (n && rc == PGEN_PASS); + rabin_destroy(&rn); + mp_drop(x); + r->ops->destroy(r); + } + if (rc != PGEN_FAIL) + rc = 0; + else + rc = keycheck_report(kc, sev, "%s not prime", name); + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/keycheck-report.c b/pub/keycheck-report.c new file mode 100644 index 0000000..4270cfc --- /dev/null +++ b/pub/keycheck-report.c @@ -0,0 +1,59 @@ +/* -*-c-*- + * + * A standard reporter function + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "keycheck.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @keycheck_stdreport@ --- * + * + * Arguments: @unsigned sev@ = problem severity + * @const char *msg@ = message to report + * @void *p@ = an uninteresting pointer + * + * Returns: Zero. + * + * Use: Reports a message to stderr. + */ + +int keycheck_stdreport(unsigned sev, const char *msg, void *p) +{ + static const char *const sevtab[] = { + "informational", "warning", "error" + }; + keycheck_reportctx *r = p; + if (r && sev < r->sev) + return (0); + fprintf(r ? r->fp : stderr, "keycheck: %s: %s\n", sevtab[sev], msg); + return (0); +} + +/*----- that's all, folks -------------------------------------------------*/ diff --git a/pub/keycheck.c b/pub/keycheck.c new file mode 100644 index 0000000..2624c0b --- /dev/null +++ b/pub/keycheck.c @@ -0,0 +1,108 @@ +/* -*-c-*- + * + * Framework for checking consistency of keys + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#include "keycheck.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @keycheck_report@ --- * + * + * Arguments: @keycheck *kc@ = keycheck state + * @unsigned sev@ = severity of this report + * @const char *msg@ = message to send along + * @...@ = things to fill the message in with + * + * Returns: Zero to continue, or nonzero to stop and give up. + * + * Use: Reports a message to the user function. + */ + +int keycheck_report(keycheck *kc, unsigned sev, const char *msg, ...) +{ + int rc; + va_list ap; + dstr d = DSTR_INIT; + + kc->sev[sev]++; + va_start(ap, msg); + dstr_vputf(&d, msg, &ap); + va_end(ap); + rc = kc->func ? kc->func(sev, d.buf, kc->p) : 0; + dstr_destroy(&d); + return (rc); +} + +/* --- @keycheck_init@ --- * + * + * Arguments: @keycheck *kc@ = pointer to block to initialize + * @int (*func)(unsigned sev, const char *msg, void *p)@ = + * handler function for problems + * @void *p@ = pointer to give to handler + * + * Returns: --- + * + * Use: Initializes a key checking context. + */ + +void keycheck_init(keycheck *kc, + int (*func)(unsigned /*sev*/, + const char */*msg*/, + void */*p*/), + void *p) +{ + unsigned i; + kc->func = func; + kc->p = p; + for (i = 0; i < KCSEV_MAX; i++) + kc->sev[i] = 0; +} + +/* --- @keycheck_allclear@ --- * + * + * Arguments: @keycheck *kc@ = pointer to keycheck context + * @unsigned sev@ = minimum severity to care about + * + * Returns: Nonzero if no problems of @sev@ or above were noticed. + */ + +int keycheck_allclear(keycheck *kc, unsigned sev) +{ + while (sev < KCSEV_MAX) { + if (kc->sev[sev]) + return (0); + sev++; + } + return (1); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/keycheck.h b/pub/keycheck.h new file mode 100644 index 0000000..f6b3388 --- /dev/null +++ b/pub/keycheck.h @@ -0,0 +1,146 @@ +/* -*-c-*- + * + * Framework for checking consistency of keys + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_KEYCHECK_H +#define CATACOMB_KEYCHECK_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +enum { + KCSEV_ALL, + KCSEV_INFO = KCSEV_ALL, + KCSEV_WARN, + KCSEV_ERR, + KCSEV_MAX +}; + +typedef struct keycheck { + unsigned sev[KCSEV_MAX]; + int (*func)(unsigned /*sev*/, const char */*msg*/, void */*p*/); + void *p; +} keycheck; + +typedef struct keycheck_reportctx { + FILE *fp; + unsigned sev; +} keycheck_reportctx; + +/*----- Generic functions -------------------------------------------------*/ + +/* --- @keycheck_report@ --- * + * + * Arguments: @keycheck *kc@ = keycheck state + * @unsigned sev@ = severity of this report + * @const char *msg@ = message to send along + * @...@ = things to fill the message in with + * + * Returns: Zero to continue, or nonzero to stop and give up. + * + * Use: Reports a message to the user function. + */ + +extern int keycheck_report(keycheck */*kc*/, unsigned /*sev*/, + const char */*msg*/, ...); + +/* --- @keycheck_init@ --- * + * + * Arguments: @keycheck *kc@ = pointer to block to initialize + * @int (*func)(unsigned sev, const char *msg, void *p)@ = + * handler function for problems + * @void *p@ = pointer to give to handler + * + * Returns: --- + * + * Use: Initializes a key checking context. + */ + +extern void keycheck_init(keycheck */*kc*/, + int (*/*func*/)(unsigned /*sev*/, + const char */*msg*/, + void */*p*/), + void */*p*/); + +/* --- @keycheck_allclear@ --- * + * + * Arguments: @keycheck *kc@ = pointer to keycheck context + * @unsigned sev@ = minimum severity to care about + * + * Returns: Nonzero if no problems of @sev@ or above were noticed. + */ + +extern int keycheck_allclear(keycheck */*kc*/, unsigned /*sev*/); + +/*----- A standard report function ----------------------------------------*/ + +/* --- @keycheck_stdreport@ --- * + * + * Arguments: @unsigned sev@ = problem severity + * @const char *msg@ = message to report + * @void *p@ = pointer to a @keycheck_reportctx@ structure + * + * Returns: Zero. + * + * Use: Reports a message to stderr. + */ + +extern int keycheck_stdreport(unsigned /*sev*/, + const char */*msg*/, void */*p*/); + +/*----- Special support functions for large integers ----------------------*/ + +/* --- @keycheck_prime@ --- * + * + * Arguments: @keycheck *kc@ = keycheck state + * @unsigned sev@ = severity if not prime + * @mp *m@ = a number to check for primality + * @const char *name@ = name of this number + * + * Returns: Zero if OK, or return status from function. + * + * Use: Checks that a number is prime. + */ + +extern int keycheck_prime(keycheck */*kc*/, unsigned /*sev*/, + mp */*m*/, const char */*name*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/pub/oaep.c b/pub/oaep.c new file mode 100644 index 0000000..7c83416 --- /dev/null +++ b/pub/oaep.c @@ -0,0 +1,182 @@ +/* -*-c-*- + * + * Optimal asymmetric encryption packing + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include +#include +#include + +#include "ct.h" +#include "gcipher.h" +#include "ghash.h" +#include "grand.h" +#include "rsa.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @oaep_encode@ --- * + * + * Arguments: @mp *d@ = where to put the answer + * @const void *m@ = pointer to message data + * @size_t msz@ = size of message data + * @octet *b@ = spare buffer + * @size_t sz@ = size of the buffer (big enough) + * @unsigned long nbits@ = length of bits of @n@ + * @void *p@ = pointer to OAEP parameter block + * + * Returns: The encoded plaintext, or null on failure. + * + * Use: Implements the operation @EME-OAEP-ENCODE@, as defined in + * PKCS#1 v. 2.0 (RFC2437). + */ + +mp *oaep_encode(mp *d, const void *m, size_t msz, octet *b, size_t sz, + unsigned long nbits, void *p) +{ + oaep *o = p; + size_t hsz = o->ch->hashsz; + ghash *h; + octet *q, *mq; + octet *pp; + gcipher *c; + size_t n; + + /* --- Ensure that everything is sensibly sized --- */ + + if (2 * hsz + 2 + msz > sz) + return (0); + + /* --- Make the `seed' value --- */ + + q = b; + *q++ = 0; sz--; + mq = q + hsz; + GR_FILL(o->r, q, hsz); + + /* --- Fill in the rest of the buffer --- */ + + h = GH_INIT(o->ch); + GH_HASH(h, o->ep, o->epsz); + GH_DONE(h, mq); + GH_DESTROY(h); + pp = mq + hsz; + n = sz - 2 * hsz - msz - 1; + memset(pp, 0, n); + pp += n; + *pp++ = 1; + memcpy(pp, m, msz); + + /* --- Do the packing --- */ + + n = sz - hsz; + c = GC_INIT(o->cc, q, hsz); + GC_ENCRYPT(c, mq, mq, n); + GC_DESTROY(c); + + c = GC_INIT(o->cc, mq, n); + GC_ENCRYPT(c, q, q, hsz); + GC_DESTROY(c); + + /* --- Done --- */ + + return (mp_loadb(d, b, sz + 1)); +} + +/* --- @oaep_decode@ --- * + * + * Arguments: @mp *m@ = the decrypted message + * @octet *b@ = pointer to a buffer to work in + * @size_t sz@ = the size of the buffer (big enough) + * @unsigned long nbits@ = the number of bits in @n@ + * @void *p@ = pointer to OAEP parameter block + * + * Returns: The length of the output string if successful, negative on + * failure. + * + * Use: Implements the operation @EME-OAEP-DECODE@, as defined in + * PKCS#1 v. 2.0 (RFC2437). + */ + +int oaep_decode(mp *m, octet *b, size_t sz, unsigned long nbits, void *p) +{ + oaep *o = p; + gcipher *c; + ghash *h; + octet *q, *mq, *qq; + octet *pp; + uint32 goodp = 1; + size_t n; + size_t hsz = o->ch->hashsz; + + /* --- Ensure that the block is large enough --- */ + + if (sz < 2 * hsz) /* Doesn't depend on ciphertext */ + return (-1); + + /* --- Decrypt the message --- */ + + mp_storeb(m, b, sz); + q = b; + goodp &= ct_inteq(*q, 0); + q++; sz--; + mq = q + hsz; + qq = q + sz; + n = sz - hsz; + c = GC_INIT(o->cc, mq, n); + GC_DECRYPT(c, q, q, hsz); + GC_DESTROY(c); + + c = GC_INIT(o->cc, q, hsz); + GC_DECRYPT(c, mq, mq, n); + GC_DESTROY(c); + q--; + + /* --- Check the hash on the encoding parameters --- */ + + h = GH_INIT(o->ch); + GH_HASH(h, o->ep, o->epsz); + GH_DONE(h, q); + GH_DESTROY(h); + goodp &= ct_memeq(q, mq, hsz); + + /* --- Now find the start of the actual message --- */ + + pp = mq + hsz; + while (*pp == 0 && pp < qq) + pp++; + goodp &= ~ct_intle(qq - b, pp - b); + goodp &= ct_inteq(*pp, 1); + pp++; + n = qq - pp; + memmove(q, pp, n); + return (goodp ? n : -1); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/pkcs1.c b/pub/pkcs1.c new file mode 100644 index 0000000..590c05e --- /dev/null +++ b/pub/pkcs1.c @@ -0,0 +1,259 @@ +/* -*-c-*- + * + * PKCS#1 1.5 packing + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include +#include + +#include "ct.h" +#include "grand.h" +#include "rsa.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @pkcs1_cryptencode@ --- * + * + * Arguments: @mp *d@ = where to put the answer + * @const void *m@ = pointer to message data + * @size_t msz@ = size of message data + * @octet *b@ = spare buffer + * @size_t sz@ = size of the buffer (big enough) + * @unsigned long nbits@ = length of bits of @n@ + * @void *p@ = pointer to PKCS1 parameter block + * + * Returns: The encoded result, or null. + * + * Use: Implements the operation @EME-PKCS1-V1_5-ENCODE@, as defined + * in PKCS#1 v. 2.0 (RFC2437). + */ + +mp *pkcs1_cryptencode(mp *d, const void *m, size_t msz, octet *b, size_t sz, + unsigned long nbits, void *p) +{ + pkcs1 *pp = p; + grand *r = pp->r; + octet *q; + size_t i, n; + + /* --- Ensure that the buffer is sensibly sized --- */ + + if (pp->epsz + msz + 11 > sz) + return (0); + + /* --- Allocate the buffer and fill it in --- */ + + q = b; + *q++ = 0x00; + *q++ = 0x02; + n = sz - msz - pp->epsz - 3; + GR_FILL(r, q, n); + for (i = 0; i < n; i++) { + if (*q == 0) + *q = r->ops->range(r, 255) + 1; + q++; + } + *q++ = 0; + if (pp->ep) { + memcpy(q, pp->ep, pp->epsz); + q += pp->epsz; + } + memcpy(q, m, msz); + q += msz; + assert(q == b + sz); + + /* --- Collect the result --- */ + + return (mp_loadb(d, b, sz)); +} + +/* --- @pkcs1_cryptdecode@ --- * + * + * Arguments: @mp *m@ = the decrypted message + * @octet *b@ = pointer to a buffer to work in + * @size_t sz@ = the size of the buffer (big enough) + * @unsigned long nbits@ = the number of bits in @n@ + * @void *p@ = pointer to PKCS1 parameter block + * + * Returns: The length of the output string if successful, negative on + * failure. + * + * Use: Implements the operation @EME-PKCS1-V1_5-DECODE@, as defined + * in PKCS#1 v. 2.0 (RFC2437). + */ + +int pkcs1_cryptdecode(mp *m, octet *b, size_t sz, + unsigned long nbits, void *p) +{ + pkcs1 *pp = p; + const octet *q, *qq; + size_t n, i; + uint32 goodp = 1; + + /* --- Check the size of the block looks sane --- */ + + if (pp->epsz + 11 > sz) /* OK: independent of ciphertext */ + return (-1); + mp_storeb(m, b, sz); + q = b; + qq = q + sz; + + /* --- Ensure that the block looks OK --- */ + + goodp &= ct_inteq(*q++, 0); + goodp &= ct_inteq(*q++, 2); + + /* --- Check the nonzero padding --- */ + + i = 0; + while (*q != 0 && q < qq) + i++, q++; + goodp &= ct_intle(8, i); + goodp &= ~ct_intle(qq - q, pp->epsz + 1); + q++; + + /* --- Check the encoding parameters --- */ + + if (pp->ep) + goodp &= ct_memeq(b + ct_pick(goodp, 0, q - b), pp->ep, pp->epsz); + q += pp->epsz; + + /* --- Done --- */ + + n = qq - q; + memmove(b, b + ct_pick(goodp, 1, q - b), n); + return (goodp ? n : -1); +} + +/* --- @pkcs1_sigencode@ --- * + * + * Arguments: @mp *d@ = where to put the answer + * @const void *m@ = pointer to message data + * @size_t msz@ = size of message data + * @octet *b@ = spare buffer + * @size_t sz@ = size of the buffer (big enough) + * @unsigned long nbits@ = length of bits of @n@ + * @void *p@ = pointer to PKCS1 parameter block + * + * Returns: The encoded message representative, or null. + * + * Use: Implements the operation @EMSA-PKCS1-V1_5-ENCODE@, as defined + * in PKCS#1 v. 2.0 (RFC2437). + */ + +mp *pkcs1_sigencode(mp *d, const void *m, size_t msz, octet *b, size_t sz, + unsigned long nbits, void *p) +{ + pkcs1 *pp = p; + octet *q; + size_t n; + + /* --- Ensure that the buffer is sensibly sized --- */ + + if (pp->epsz + msz + 11 > sz) + return (0); + + /* --- Fill in the buffer --- */ + + q = b; + *q++ = 0x00; + *q++ = 0x01; + n = sz - msz - pp->epsz - 3; + memset(q, 0xff, n); + q += n; + *q++ = 0; + if (pp->ep) { + memcpy(q, pp->ep, pp->epsz); + q += pp->epsz; + } + memcpy(q, m, msz); + q += msz; + assert(q == b + sz); + return (mp_loadb(d, b, sz)); +} + +/* --- @pkcs1_sigdecode@ --- * + * + * Arguments: @mp *s@ = the message representative + * @const void *m@ = the original message, or null (ignored) + * @size_t msz@ = the message size (ignored) + * @octet *b@ = a scratch buffer + * @size_t sz@ = size of the buffer (large enough) + * @unsigned long nbits@ = number of bits in @n@ + * @void *p@ = pointer to PKCS1 parameters + * + * Returns: The length of the output string if successful, negative on + * failure. + * + * Use: Implements the operation @EMSA-PKCS1-V1_5-DECODE@, as defined + * in PKCS#1 v. 2.0 (RFC2437). + */ + +int pkcs1_sigdecode(mp *s, const void *m, size_t msz, octet *b, size_t sz, + unsigned long nbits, void *p) +{ + pkcs1 *pp = p; + const octet *q, *qq; + size_t i, n; + + /* --- Check the size of the block looks sane --- */ + + if (pp->epsz + 10 > sz) + return (-1); + mp_storeb(s, b, sz); + q = b; + qq = q + sz; + + /* --- Ensure that the block looks OK --- */ + + if (*q++ != 0x00 || *q++ != 0x01) + return (-1); + + /* --- Check the padding --- */ + + i = 0; + while (*q == 0xff && q < qq) + i++, q++; + if (i < 8 || qq - q < pp->epsz + 1 || *q++ != 0) + return (-1); + + /* --- Check the encoding parameters --- */ + + if (pp->ep && memcmp(q, pp->ep, pp->epsz) != 0) + return (-1); + q += pp->epsz; + + /* --- Done --- */ + + n = qq - q; + memmove(b, q, n); + return (n); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/pss.c b/pub/pss.c new file mode 100644 index 0000000..8e77b78 --- /dev/null +++ b/pub/pss.c @@ -0,0 +1,186 @@ +/* -*-c-*- + * + * Probabistic signature scheme + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include +#include +#include + +#include "gcipher.h" +#include "ghash.h" +#include "grand.h" +#include "rsa.h" + +/*----- Magic statics -----------------------------------------------------*/ + +static const octet z8[8] = { 0 }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @pss_encode@ --- * + * + * Arguments: @mp *d@ = where to put the answer + * @const void *m@ = pointer to the message hash + * @size_t msz@ = the size of the message hash + * @octet *b@ = scratch buffer + * @size_t sz@ = sizeo of the buffer (large enough) + * @unsigned long nbits@ = size in bits of @n@ + * @void *p@ = pointer to the PSS parameters + * + * Returns: Encoded message representative, or null on error. + * + * Use: Implements the operation @EMSA-PSS-ENCODE@, as defined in + * PKCS#1 v. 2.1 (RFC3447). + */ + +mp *pss_encode(mp *d, const void *m, size_t msz, octet *b, size_t sz, + unsigned long nbits, void *p) +{ + pss *pp = p; + octet *s, *r; + ghash *h; + gcipher *c; + unsigned mask; + size_t pssz, hsz = pp->ch->hashsz; + + /* --- Check the message length --- */ + + nbits--; + sz = (nbits + 7)/8; + mask = (1 << nbits%8) - 1; + if (!mask) mask = 0xff; + if (hsz + pp->ssz + 2 > sz) + return (0); + + /* --- Generate a random salt --- */ + + pssz = sz - pp->ssz - hsz - 2; + memset(b, 0, pssz); + b[pssz] = 0x01; + s = b + pssz + 1; + r = s + pp->ssz; + GR_FILL(pp->r, s, pp->ssz); + + /* --- Compute the salted hash --- */ + + h = GH_INIT(pp->ch); + GH_HASH(h, z8, 8); + GH_HASH(h, m, msz); + GH_HASH(h, s, pp->ssz); + GH_DONE(h, r); + r[hsz] = 0xbc; + + /* --- Do the masking --- */ + + c = GC_INIT(pp->cc, r, hsz); + GC_ENCRYPT(c, b, b, pssz + pp->ssz + 1); + GC_DESTROY(c); + b[0] &= mask; + return (mp_loadb(d, b, sz)); +} + +/* --- @pss_decode@ --- * + * + * Arguments: @mp *s@ = the message representative + * @const void *m@ = the original message + * @size_t msz@ = the message size + * @octet *b@ = a scratch buffer + * @size_t sz@ = size of the buffer (large enough) + * @unsigned long nbits@ = number of bits in @n@ + * @void *p@ = pointer to PKCS1 parameters + * + * Returns: The length of the output string if successful, negative on + * failure. + * + * Use: Implements the operation @EMSA_PSS_VERIFY@, as defined in + * PCSK#1 v. 2.1 (RFC3447). + */ + +int pss_decode(mp *mi, const void *m, size_t msz, octet *b, size_t sz, + unsigned long nbits, void *p) +{ + pss *pp = p; + octet *s, *r; + ghash *h; + gcipher *c; + unsigned mask; + size_t pssz, hsz = pp->ch->hashsz, i; + int rc; + + /* --- Check the message length --- */ + + nbits--; + sz = (nbits + 7)/8; + if (mp_octets(mi) > sz) + return (-1); + mask = (1 << nbits%8) - 1; + if (!mask) mask = 0xff; + if (hsz + pp->ssz + 2 > sz) + return (-1); + mp_storeb(mi, b, sz); + + /* --- Split up the buffer --- */ + + pssz = sz - hsz - pp->ssz - 2; + s = b + pssz + 1; + r = s + pp->ssz; + if (r[hsz] != 0xbc) + return (-1); + + /* --- Decode the seed --- */ + + if (b[0] & ~mask) + return (-1); + c = GC_INIT(pp->cc, r, hsz); + GC_DECRYPT(c, b, b, pssz + pp->ssz + 1); + GC_DESTROY(c); + b[0] &= mask; + for (i = 0; i < pssz; i++) + if (b[i]) return (-1); + if (b[pssz] != 0x01) + return (-1); + + /* --- Hash the message --- */ + + h = GH_INIT(pp->ch); + GH_HASH(h, z8, 8); + GH_HASH(h, m, msz); + GH_HASH(h, s, pp->ssz); + s = GH_DONE(h, 0); + rc = !memcmp(s, r, hsz); + GH_DESTROY(h); + if (!rc) return (-1); + + /* --- Done --- */ + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/rsa-fetch.c b/pub/rsa-fetch.c new file mode 100644 index 0000000..85356b4 --- /dev/null +++ b/pub/rsa-fetch.c @@ -0,0 +1,85 @@ +/* -*-c-*- + * + * Key fetching for RSA public and private keys + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "key.h" +#include "rsa.h" + +/*----- Key fetching ------------------------------------------------------*/ + +const key_fetchdef rsa_pubfetch[] = { + { "n", offsetof(rsa_pub, n), KENC_MP, 0 }, + { "e", offsetof(rsa_pub, e), KENC_MP, 0 }, + { 0, 0, 0, 0 } +}; + +static const key_fetchdef priv[] = { + { "p", offsetof(rsa_priv, p), KENC_MP, 0 }, + { "q", offsetof(rsa_priv, q), KENC_MP, 0 }, + { "q-inv", offsetof(rsa_priv, q_inv), KENC_MP, 0 }, + { "d", offsetof(rsa_priv, d), KENC_MP, 0 }, + { "d-mod-p", offsetof(rsa_priv, dp), KENC_MP, 0 }, + { "d-mod-q", offsetof(rsa_priv, dq), KENC_MP, 0 }, + { 0, 0, 0, 0 } +}; + +const key_fetchdef rsa_privfetch[] = { + { "n", offsetof(rsa_priv, n), KENC_MP, 0 }, + { "e", offsetof(rsa_priv, e), KENC_MP, 0 }, + { "private", 0, KENC_STRUCT, priv }, + { 0, 0, 0, 0 } +}; + +/* --- @rsa_pubfree@, @rsa_privfree@ --- * + * + * Arguments: @rsa_pub *rp@, @rsa_priv *rp@ = pointer to key block + * + * Returns: --- + * + * Use: Frees an RSA key block. + */ + +void rsa_pubfree(rsa_pub *rp) +{ + mp_drop(rp->n); + mp_drop(rp->e); +} + +void rsa_privfree(rsa_priv *rp) +{ + mp_drop(rp->n); + mp_drop(rp->e); + mp_drop(rp->p); + mp_drop(rp->q); + mp_drop(rp->q_inv); + mp_drop(rp->d); + mp_drop(rp->dp); + mp_drop(rp->dq); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/rsa-gen.c b/pub/rsa-gen.c new file mode 100644 index 0000000..a7a2ca4 --- /dev/null +++ b/pub/rsa-gen.c @@ -0,0 +1,189 @@ +/* -*-c-*- + * + * RSA parameter generation + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "grand.h" +#include "mp.h" +#include "mpint.h" +#include "pgen.h" +#include "rsa.h" +#include "strongprime.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rsa_gen@ --- * + * + * Arguments: @rsa_priv *rp@ = pointer to block to be filled in + * @unsigned nbits@ = required modulus size in bits + * @grand *r@ = random number source + * @unsigned n@ = number of attempts to make + * @pgen_proc *event@ = event handler function + * @void *ectx@ = argument for the event handler + * + * Returns: Zero if all went well, nonzero otherwise. + * + * Use: Constructs a pair of strong RSA primes and other useful RSA + * parameters. A small encryption exponent is chosen if + * possible. + */ + +int rsa_gen(rsa_priv *rp, unsigned nbits, grand *r, unsigned n, + pgen_proc *event, void *ectx) +{ + pgen_gcdstepctx g; + mp *phi = MP_NEW; + + /* --- Bits of initialization --- */ + + rp->e = mp_fromulong(MP_NEW, 0x10001); + rp->d = MP_NEW; + + /* --- Generate strong primes %$p$% and %$q$% --- * + * + * Constrain the GCD of @q@ to ensure that overly small private exponents + * are impossible. Current results suggest that if %$d < n^{0.29}$% then + * it can be guessed fairly easily. This implementation is rather more + * conservative about that sort of thing. + */ + +again: + if ((rp->p = strongprime("p", MP_NEWSEC, nbits/2, r, n, event, ectx)) == 0) + goto fail_p; + + /* --- Do painful fiddling with GCD steppers --- */ + + { + mp *q; + rabin rb; + + if ((q = strongprime_setup("q", MP_NEWSEC, &g.jp, nbits / 2, + r, n, event, ectx)) == 0) + goto fail_q; + g.r = mp_lsr(MP_NEW, rp->p, 1); + g.g = MP_NEW; + g.max = MP_256; + q = pgen("q", q, q, event, ectx, n, pgen_gcdstep, &g, + rabin_iters(nbits/2), pgen_test, &rb); + pfilt_destroy(&g.jp); + mp_drop(g.r); + if (!q) { + mp_drop(g.g); + if (n) + goto fail_q; + mp_drop(rp->p); + goto again; + } + rp->q = q; + } + + /* --- Ensure that %$p > q$% --- * + * + * Also ensure that %$p$% and %$q$% are sufficiently different to deter + * square-root-based factoring methods. + */ + + phi = mp_sub(phi, rp->p, rp->q); + if (MP_LEN(phi) * 4 < MP_LEN(rp->p) * 3 || + MP_LEN(phi) * 4 < MP_LEN(rp->q) * 3) { + mp_drop(rp->p); + mp_drop(g.g); + if (n) + goto fail_q; + mp_drop(rp->q); + goto again; + } + + if (MP_NEGP(phi)) { + mp *z = rp->p; + rp->p = rp->q; + rp->q = z; + } + + /* --- Work out the modulus and the CRT coefficient --- */ + + rp->n = mp_mul(MP_NEW, rp->p, rp->q); + rp->q_inv = mp_modinv(MP_NEW, rp->q, rp->p); + + /* --- Work out %$\varphi(n) = (p - 1)(q - 1)$% --- * + * + * Save on further multiplications by noting that %$n = pq$% is known and + * that %$(p - 1)(q - 1) = pq - p - q + 1$%. To minimize the size of @d@ + * (useful for performance reasons, although not very because an overly + * small @d@ will be rejected for security reasons) this is then divided by + * %$\gcd(p - 1, q - 1)$%. + */ + + phi = mp_sub(phi, rp->n, rp->p); + phi = mp_sub(phi, phi, rp->q); + phi = mp_add(phi, phi, MP_ONE); + phi = mp_lsr(phi, phi, 1); + mp_div(&phi, 0, phi, g.g); + + /* --- Decide on a public exponent --- * + * + * Simultaneously compute the private exponent. + */ + + mp_gcd(&g.g, 0, &rp->d, phi, rp->e); + if (!MP_EQ(g.g, MP_ONE) && MP_LEN(rp->d) * 4 > MP_LEN(rp->n) * 3) + goto fail_e; + + /* --- Work out exponent residues --- */ + + rp->dp = MP_NEW; phi = mp_sub(phi, rp->p, MP_ONE); + mp_div(0, &rp->dp, rp->d, phi); + + rp->dq = MP_NEW; phi = mp_sub(phi, rp->q, MP_ONE); + mp_div(0, &rp->dq, rp->d, phi); + + /* --- Done --- */ + + mp_drop(phi); + mp_drop(g.g); + return (0); + + /* --- Tidy up when something goes wrong --- */ + +fail_e: + mp_drop(g.g); + mp_drop(phi); + mp_drop(rp->n); + mp_drop(rp->q_inv); + mp_drop(rp->q); +fail_q: + mp_drop(rp->p); +fail_p: + mp_drop(rp->e); + if (rp->d) + mp_drop(rp->d); + return (-1); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/rsa-priv.c b/pub/rsa-priv.c new file mode 100644 index 0000000..08a8982 --- /dev/null +++ b/pub/rsa-priv.c @@ -0,0 +1,260 @@ +/* -*-c-*- + * + * RSA private-key operations + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include "mp.h" +#include "mpmont.h" +#include "mprand.h" +#include "rsa.h" + +/*----- Public key operations ---------------------------------------------*/ + +/* --- @rsa_privcreate@ --- * + * + * Arguments: @rsa_privctx *rd@ = pointer to an RSA private key context + * @rsa_priv *rp@ = pointer to RSA private key + * @grand *r@ = pointer to random number source for blinding + * + * Returns: --- + * + * Use: Initializes an RSA private-key context. Keeping a context + * for several decryption or signing operations provides a minor + * performance benefit. + * + * The random number source may be null if blinding is not + * desired. This improves decryption speed, at the risk of + * permitting timing attacks. + */ + +void rsa_privcreate(rsa_privctx *rd, rsa_priv *rp, grand *r) +{ + rd->rp = rp; + rd->r = r; + if (r) + mpmont_create(&rd->nm, rp->n); + mpmont_create(&rd->pm, rp->p); + mpmont_create(&rd->qm, rp->q); +} + +/* --- @rsa_privdestroy@ --- * + * + * Arguments: @rsa_privctx *rd@ = pointer to an RSA decryption context + * + * Returns: --- + * + * Use: Destroys an RSA decryption context. + */ + +void rsa_privdestroy(rsa_privctx *rd) +{ + if (rd->r) + mpmont_destroy(&rd->nm); + mpmont_destroy(&rd->pm); + mpmont_destroy(&rd->qm); +} + +/* --- @rsa_privop@ --- * + * + * Arguments: @rsa_privctx *rd@ = pointer to RSA private key context + * @mp *d@ = destination + * @mp *c@ = input message + * + * Returns: The transformed output message. + * + * Use: Performs an RSA private key operation. This function takes + * advantage of knowledge of the key factors in order to speed + * up decryption. It also blinds the ciphertext prior to + * decryption and unblinds it afterwards to thwart timing + * attacks. + */ + +mp *rsa_privop(rsa_privctx *rd, mp *d, mp *c) +{ + mp *ki = MP_NEW; + rsa_priv *rp = rd->rp; + + /* --- If so desired, set up a blinding constant --- * + * + * Choose a constant %$k$% relatively prime to the modulus %$m$%. Compute + * %$c' = c k^e \bmod n$%, and %$k^{-1} \bmod n$%. Don't bother with the + * CRT stuff here because %$e$% is chosen to be small. + */ + + c = MP_COPY(c); + if (rd->r) { + mp *k = MP_NEWSEC, *g = MP_NEW; + + do { + k = mprand_range(k, rp->n, rd->r, 0); + mp_gcd(&g, 0, &ki, rp->n, k); + } while (!MP_EQ(g, MP_ONE)); + k = mpmont_mul(&rd->nm, k, k, rd->nm.r2); + k = mpmont_expr(&rd->nm, k, k, rp->e); + c = mpmont_mul(&rd->nm, c, c, k); + mp_drop(k); + mp_drop(g); + } + + /* --- Do the actual modular exponentiation --- * + * + * Use a slightly hacked version of the Chinese Remainder Theorem stuff. + * + * Let %$q' = q^{-1} \bmod p$%. Then note that + * %$c^d \equiv q (q'(c_p^{d_p} - c_q^{d_q}) \bmod p) + c_q^{d_q} \pmod n$% + */ + + { + mp *cp = MP_NEW, *cq = MP_NEW; + + /* --- Work out the two halves of the result --- */ + + mp_div(0, &cp, c, rp->p); + cp = mpmont_exp(&rd->pm, cp, cp, rp->dp); + + mp_div(0, &cq, c, rp->q); + cq = mpmont_exp(&rd->qm, cq, cq, rp->dq); + + /* --- Combine the halves using the result above --- */ + + d = mp_sub(d, cp, cq); + mp_div(0, &d, d, rp->p); + d = mpmont_mul(&rd->pm, d, d, rp->q_inv); + d = mpmont_mul(&rd->pm, d, d, rd->pm.r2); + + d = mp_mul(d, d, rp->q); + d = mp_add(d, d, cq); + if (MP_CMP(d, >=, rp->n)) + d = mp_sub(d, d, rp->n); + + /* --- Tidy away temporary variables --- */ + + mp_drop(cp); + mp_drop(cq); + } + + /* --- Finally, possibly remove the blinding factor --- */ + + if (ki) { + d = mpmont_mul(&rd->nm, d, d, ki); + d = mpmont_mul(&rd->nm, d, d, rd->nm.r2); + mp_drop(ki); + } + + /* --- Done --- */ + + mp_drop(c); + return (d); +} + +/* --- @rsa_qprivop@ --- * + * + * Arguments: @rsa_priv *rp@ = pointer to RSA parameters + * @mp *d@ = destination + * @mp *c@ = input message + * @grand *r@ = pointer to random number source for blinding + * + * Returns: Correctly transformed output message + * + * Use: Performs an RSA private key operation, very carefully. + */ + +mp *rsa_qprivop(rsa_priv *rp, mp *d, mp *c, grand *r) +{ + rsa_privctx rd; + rsa_privcreate(&rd, rp, r); + d = rsa_privop(&rd, d, c); + rsa_privdestroy(&rd); + return (d); +} + +/*----- Operations with padding -------------------------------------------*/ + +/* --- @rsa_sign@ --- * + * + * Arguments: @rsa_privctx *rp@ = pointer to an RSA private key context + * @mp *d@ = where to put the result + * @const void *m@ = pointer to input message + * @size_t msz@ = size of input message + * @rsa_pad *e@ = encoding procedure + * @void *earg@ = argument pointer for encoding procedure + * + * Returns: The signature, as a multiprecision integer, or null on + * failure. + * + * Use: Computes an RSA digital signature. + */ + +mp *rsa_sign(rsa_privctx *rp, mp *d, const void *m, size_t msz, + rsa_pad *e, void *earg) +{ + octet *p; + unsigned long nb = mp_bits(rp->rp->n); + size_t n = (nb + 7)/8; + arena *a = d && d->a ? d->a->a : arena_global; + + p = x_alloc(a, n); + d = e(d, m, msz, p, n, nb, earg); + x_free(a, p); + return (d ? rsa_privop(rp, d, d) : 0); +} + +/* --- @rsa_decrypt@ --- * + * + * Arguments: @rsa_privctx *rp@ = pointer to an RSA private key context + * @mp *m@ = encrypted message, as a multiprecision integer + * @dstr *d@ = pointer to output string + * @rsa_decunpad *e@ = decoding procedure + * @void *earg@ = argument pointer for decoding procedure + * + * Returns: The length of the output string if successful, negative on + * failure. + * + * Use: Does RSA decryption. + */ + +int rsa_decrypt(rsa_privctx *rp, mp *m, dstr *d, + rsa_decunpad *e, void *earg) +{ + mp *p = rsa_privop(rp, MP_NEW, m); + unsigned long nb = mp_bits(rp->rp->n); + size_t n = (nb + 7)/8; + int rc; + + dstr_ensure(d, n); + rc = e(p, (octet *)d->buf + d->len, n, nb, earg); + if (rc >= 0) + d->len += rc; + mp_drop(p); + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/rsa-pub.c b/pub/rsa-pub.c new file mode 100644 index 0000000..78793a9 --- /dev/null +++ b/pub/rsa-pub.c @@ -0,0 +1,190 @@ +/* -*-c-*- + * + * [RSA encryption with padding * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include "mp.h" +#include "mpmont.h" +#include "rsa.h" + +/*----- Public key operations ---------------------------------------------*/ + +/* --- @rsa_pubcreate@ --- * + * + * Arguments: @rsa_pubctx *rd@ = pointer to an RSA public key context + * @rsa_pub *rp@ = pointer to RSA public key + * + * Returns: --- + * + * Use: Initializes an RSA public-key context. + */ + +void rsa_pubcreate(rsa_pubctx *rd, rsa_pub *rp) +{ + rd->rp = rp; + mpmont_create(&rd->mm, rp->n); +} + +/* --- @rsa_pubdestroy@ --- * + * + * Arguments: @rsa_pubctx *rd@ = pointer to an RSA public key context + * + * Returns: --- + * + * Use: Destroys an RSA public-key context. + */ + +void rsa_pubdestroy(rsa_pubctx *rd) +{ + mpmont_destroy(&rd->mm); +} + +/* --- @rsa_pubop@ --- * + * + * Arguments: @rsa_pubctx *rd@ = pointer to an RSA public key context + * @mp *d@ = destination + * @mp *p@ = input message + * + * Returns: The transformed output message. + * + * Use: Performs an RSA public key operation. + */ + +mp *rsa_pubop(rsa_pubctx *rd, mp *d, mp *p) +{ + return (mpmont_exp(&rd->mm, d, p, rd->rp->e)); +} + +/* --- @rsa_qpubop@ --- * + * + * Arguments: @rsa_pub *rp@ = pointer to RSA parameters + * @mp *d@ = destination + * @mp *p@ = input message + * + * Returns: Correctly transformed output message. + * + * Use: Performs an RSA public key operation. + */ + +mp *rsa_qpubop(rsa_pub *rp, mp *d, mp *c) +{ + rsa_pubctx rd; + rsa_pubcreate(&rd, rp); + d = rsa_pubop(&rd, d, c); + rsa_pubdestroy(&rd); + return (d); +} + +/*----- Operations with padding -------------------------------------------*/ + +/* --- @rsa_encrypt@ --- * + * + * Arguments: @rsa_pubctx *rp@ = pointer to an RSA public key context + * @mp *d@ = proposed destination integer + * @const void *m@ = pointer to input message + * @size_t msz@ = size of input message + * @rsa_pad *e@ = encoding procedure + * @void *earg@ = argument pointer for encoding procedure + * + * Returns: The encrypted message, as a multiprecision integer, or null + * on failure. + * + * Use: Does RSA encryption. + */ + +mp *rsa_encrypt(rsa_pubctx *rp, mp *d, const void *m, size_t msz, + rsa_pad *e, void *earg) +{ + octet *p; + unsigned long nb = mp_bits(rp->rp->n); + size_t n = (nb + 7)/8; + arena *a = d && d->a ? d->a->a : arena_global; + + p = x_alloc(a, n); + d = e(d, m, msz, p, n, nb, earg); + x_free(a, p); + return (d ? rsa_pubop(rp, d, d) : 0); +} + +/* --- @rsa_verify@ --- * + * + * Arguments: @rsa_pubctx *rp@ = pointer to an RSA public key contxt + * @mp *s@ = the signature, as a multiprecision integer + * @const void *m@ = pointer to message to verify, or null + * @size_t msz@ = size of input message + * @dstr *d@ = pointer to output string, or null + * @rsa_vfrunpad *e@ = decoding procedure + * @void *earg@ = argument pointer for decoding procedure + * + * Returns: The length of the output string if successful (0 if no output + * was wanted); negative on failure. + * + * Use: Does RSA signature verification. To use a signature scheme + * with recovery, pass in @m == 0@ and @d != 0@: the recovered + * message should appear in @d@. To use a signature scheme with + * appendix, provide @m != 0@ and @d == 0@; the result should be + * zero for success. + */ + +int rsa_verify(rsa_pubctx *rp, mp *s, const void *m, size_t msz, + dstr *d, rsa_vrfunpad *e, void *earg) +{ + mp *p = rsa_pubop(rp, MP_NEW, s); + unsigned long nb = mp_bits(rp->rp->n); + size_t n = (nb + 7)/8; + dstr dd = DSTR_INIT; + int rc; + + /* --- Decoder protocol --- * + * + * We deal with two kinds of decoders: ones with message recovery and ones + * with appendix. A decoder with recovery will leave a message in the + * buffer and exit nonzero: we'll check that against @m@ if provided and + * just leave it otherwise. A decoder with appendix will inspect @m@ and + * return zero or @-1@ itself. + */ + + if (!d) d = ⅆ + dstr_ensure(d, n); + rc = e(p, m, msz, (octet *)d->buf + d->len, n, nb, earg); + if (rc > 0 && m) { + if (rc != msz || memcmp(d->buf + d->len, m, msz) != 0) + rc = -1; + else + rc = 0; + } + if (rc > 0) + d->len += rc; + mp_drop(p); + dstr_destroy(&dd); + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/rsa-recover.c b/pub/rsa-recover.c new file mode 100644 index 0000000..1a7c460 --- /dev/null +++ b/pub/rsa-recover.c @@ -0,0 +1,240 @@ +/* -*-c-*- + * + * Recover RSA parameters + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mp.h" +#include "mpmont.h" +#include "rsa.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rsa_recover@ --- * + * + * Arguments: @rsa_priv *rp@ = pointer to parameter block + * + * Returns: Zero if all went well, nonzero if the parameters make no + * sense. + * + * Use: Derives the full set of RSA parameters given a minimal set. + */ + +int rsa_recover(rsa_priv *rp) +{ + /* --- If there is no modulus, calculate it --- */ + + if (!rp->n) { + if (!rp->p || !rp->q) + return (-1); + rp->n = mp_mul(MP_NEW, rp->p, rp->q); + } + + /* --- If there are no factors, compute them --- */ + + else if (!rp->p || !rp->q) { + + /* --- If one is missing, use simple division to recover the other --- */ + + if (rp->p || rp->q) { + mp *r = MP_NEW; + if (rp->p) + mp_div(&rp->q, &r, rp->n, rp->p); + else + mp_div(&rp->p, &r, rp->n, rp->q); + if (!MP_EQ(r, MP_ZERO)) { + mp_drop(r); + return (-1); + } + mp_drop(r); + } + + /* --- Otherwise use the public and private moduli --- */ + + else if (!rp->e || !rp->d) + return (-1); + else { + mp *t; + size_t s; + mp a; mpw aw; + mp *m1; + mpmont mm; + int i; + mp *z = MP_NEW; + + /* --- Work out the appropriate exponent --- * + * + * I need to compute %$s$% and %$t$% such that %$2^s t = e d - 1$%, and + * %$t$% is odd. + */ + + t = mp_mul(MP_NEW, rp->e, rp->d); + t = mp_sub(t, t, MP_ONE); + t = mp_odd(t, t, &s); + + /* --- Set up for the exponentiation --- */ + + mpmont_create(&mm, rp->n); + m1 = mp_sub(MP_NEW, rp->n, mm.r); + + /* --- Now for the main loop --- * + * + * Choose candidate integers and attempt to factor the modulus. + */ + + mp_build(&a, &aw, &aw + 1); + i = 0; + for (;;) { + again: + + /* --- Choose a random %$a$% and calculate %$z = a^t \bmod n$% --- * + * + * If %$z \equiv 1$% or %$z \equiv -1 \pmod n$% then this iteration + * is a failure. + */ + + aw = primetab[i++]; + z = mpmont_mul(&mm, z, &a, mm.r2); + z = mpmont_expr(&mm, z, z, t); + if (MP_EQ(z, mm.r) || MP_EQ(z, m1)) + continue; + + /* --- Now square until something interesting happens --- * + * + * Compute %$z^{2i} \bmod n$%. Eventually, I'll either get %$-1$% or + * %$1$%. If the former, the number is uninteresting, and I need to + * restart. If the latter, the previous number minus 1 has a common + * factor with %$n$%. + */ + + for (;;) { + mp *zz = mp_sqr(MP_NEW, z); + zz = mpmont_reduce(&mm, zz, zz); + if (MP_EQ(zz, mm.r)) { + mp_drop(zz); + goto done; + } else if (MP_EQ(zz, m1)) { + mp_drop(zz); + goto again; + } + mp_drop(z); + z = zz; + } + } + + /* --- Do the factoring --- * + * + * Here's how it actually works. I've found an interesting square + * root of %$1 \pmod n$%. Any square root of 1 must be congruent to + * %$\pm 1$% modulo both %$p$% and %$q$%. Both congruent to %$1$% is + * boring, as is both congruent to %$-1$%. Subtracting one from the + * result makes it congruent to %$0$% modulo %$p$% or %$q$% (and + * nobody cares which), and hence can be extracted by a GCD + * operation. + */ + + done: + z = mpmont_reduce(&mm, z, z); + z = mp_sub(z, z, MP_ONE); + rp->p = MP_NEW; + mp_gcd(&rp->p, 0, 0, rp->n, z); + rp->q = MP_NEW; + mp_div(&rp->q, 0, rp->n, rp->p); + mp_drop(z); + mp_drop(t); + mp_drop(m1); + if (MP_CMP(rp->p, <, rp->q)) { + z = rp->p; + rp->p = rp->q; + rp->q = z; + } + mpmont_destroy(&mm); + } + } + + /* --- If %$e$% or %$d$% is missing, recalculate it --- */ + + if (!rp->e || !rp->d) { + mp *phi; + mp *g = MP_NEW; + mp *p1, *q1; + + /* --- Compute %$\varphi(n)$% --- */ + + phi = mp_sub(MP_NEW, rp->n, rp->p); + phi = mp_sub(phi, phi, rp->q); + phi = mp_add(phi, phi, MP_ONE); + p1 = mp_sub(MP_NEW, rp->p, MP_ONE); + q1 = mp_sub(MP_NEW, rp->q, MP_ONE); + mp_gcd(&g, 0, 0, p1, q1); + mp_div(&phi, 0, phi, g); + mp_drop(p1); + mp_drop(q1); + + /* --- Recover the other exponent --- */ + + if (rp->e) + mp_gcd(&g, 0, &rp->d, phi, rp->e); + else if (rp->d) + mp_gcd(&g, 0, &rp->e, phi, rp->d); + else { + mp_drop(phi); + mp_drop(g); + return (-1); + } + + mp_drop(phi); + if (!MP_EQ(g, MP_ONE)) { + mp_drop(g); + return (-1); + } + mp_drop(g); + } + + /* --- Compute %$q^{-1} \bmod p$% --- */ + + if (!rp->q_inv) + mp_gcd(0, 0, &rp->q_inv, rp->p, rp->q); + + /* --- Compute %$d \bmod (p - 1)$% and %$d \bmod (q - 1)$% --- */ + + if (!rp->dp) { + mp *p1 = mp_sub(MP_NEW, rp->p, MP_ONE); + mp_div(0, &rp->dp, rp->d, p1); + mp_drop(p1); + } + if (!rp->dq) { + mp *q1 = mp_sub(MP_NEW, rp->q, MP_ONE); + mp_div(0, &rp->dq, rp->d, q1); + mp_drop(q1); + } + + /* --- Done --- */ + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/rsa-test.c b/pub/rsa-test.c new file mode 100644 index 0000000..34b2a1f --- /dev/null +++ b/pub/rsa-test.c @@ -0,0 +1,512 @@ +/* -*-c-*- + * + * Testing RSA padding operations + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "fibrand.h" +#include "rsa.h" + +/*----- Main code ---------------------------------------------------------*/ + +static int tencpad(int nbits, + dstr *p, int rc, mp *c, + const char *ename, dstr *eparam, rsa_pad *e, void *earg) +{ + size_t n = (nbits + 7)/8; + void *q = xmalloc(n); + mp *d; + int ok = 1; + + d = e(MP_NEW, p->buf, p->len, q, n, nbits, earg); + if (!d == !rc || (!rc && !MP_EQ(d, c))) { + ok = 0; + fprintf(stderr, "*** %s padding failed!\n", ename); + fprintf(stderr, "*** padding bits = %d\n", nbits); + if (eparam) { + fprintf(stderr, "*** encoding parameters = "); + type_hex.dump(eparam, stderr); + fputc('\n', stderr); + } + fprintf(stderr, "*** input message = "); type_hex.dump(p, stderr); + if (rc) + fprintf(stderr, "\n*** expected failure\n"); + else { + MP_EPRINTX("\n*** expected", c); + MP_EPRINTX("*** computed", d); + } + } + mp_drop(d); + mp_drop(c); + xfree(q); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +#define tsigpad tencpad + +#define DSTR_EQ(x, y) \ + ((x)->len == (y)->len && !memcmp((x)->buf, (y)->buf, (x)->len)) + +static int tdecpad(int nbits, + mp *c, int rc, dstr *p, + const char *ename, dstr *eparam, + rsa_decunpad *e, void *earg) +{ + dstr d = DSTR_INIT; + int n = (nbits + 7)/8; + int ok = 1; + + dstr_ensure(&d, n); + n = e(c, (octet *)d.buf, n, nbits, earg); + if (n >= 0) + d.len += n; + if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) { + ok = 0; + fprintf(stderr, "*** %s encryption unpadding failed!\n", ename); + fprintf(stderr, "*** padding bits = %d\n", nbits); + if (eparam) { + fprintf(stderr, "*** encoding parameters = "); + type_hex.dump(eparam, stderr); + fputc('\n', stderr); + } + MP_EPRINTX("*** input", c); + if (rc < 0) + fprintf(stderr, "*** expected failure\n"); + else { + fprintf(stderr, "*** expected: %d = ", rc); type_hex.dump(p, stderr); + fprintf(stderr, "\n*** computed: %d = ", n); type_hex.dump(&d, stderr); + fprintf(stderr, "\n"); + } + } + mp_drop(c); + dstr_destroy(&d); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tvrfpad(int nbits, + mp *c, dstr *m, int rc, dstr *p, + const char *ename, dstr *eparam, + rsa_vrfunpad *e, void *earg) +{ + dstr d = DSTR_INIT; + int n = (nbits + 7)/8; + int ok = 1; + + dstr_ensure(&d, n); + n = e(c, m->len ? (octet *)m->buf : 0, m->len, + (octet *)d.buf, n, nbits, earg); + if (n >= 0) + d.len += n; + if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) { + ok = 0; + fprintf(stderr, "*** %s signature unpadding failed!\n", ename); + fprintf(stderr, "*** padding bits = %d\n", nbits); + MP_EPRINTX("*** input", c); + if (eparam) { + fprintf(stderr, "*** encoding parameters = "); + type_hex.dump(eparam, stderr); + fputc('\n', stderr); + } + fprintf(stderr, "*** message = "); type_hex.dump(m, stderr); + if (rc < 0) + fprintf(stderr, "\n*** expected failure\n"); + else { + fprintf(stderr, "\n*** expected = %d: ", rc); type_hex.dump(p, stderr); + fprintf(stderr, "\n*** computed = %d: ", n); type_hex.dump(&d, stderr); + fprintf(stderr, "\n"); + } + } + mp_drop(c); + dstr_destroy(&d); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tencpub(rsa_pub *rp, + dstr *p, int rc, mp *c, + const char *ename, dstr *eparam, rsa_pad *e, void *earg) +{ + mp *d; + rsa_pubctx rpc; + int ok = 1; + + rsa_pubcreate(&rpc, rp); + d = rsa_encrypt(&rpc, MP_NEW, p->buf, p->len, e, earg); + if (!d == !rc || (!rc && !MP_EQ(d, c))) { + ok = 0; + fprintf(stderr, "*** encrypt with %s padding failed!\n", ename); + MP_EPRINTX("*** key.n", rp->n); + MP_EPRINTX("*** key.e", rp->e); + if (eparam) { + fprintf(stderr, "*** encoding parameters = "); + type_hex.dump(eparam, stderr); + fputc('\n', stderr); + } + fprintf(stderr, "*** input message = "); type_hex.dump(p, stderr); + if (rc) + fprintf(stderr, "\n*** expected failure\n"); + else { + MP_EPRINTX("\n*** expected", c); + MP_EPRINTX("*** computed", d); + } + } + rsa_pubdestroy(&rpc); + rsa_pubfree(rp); + mp_drop(d); + mp_drop(c); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tsigpriv(rsa_priv *rp, + dstr *p, int rc, mp *c, + const char *ename, dstr *eparam, rsa_pad *e, void *earg) +{ + mp *d; + grand *r = fibrand_create(0); + rsa_privctx rpc; + int ok = 1; + + rsa_privcreate(&rpc, rp, r); + d = rsa_sign(&rpc, MP_NEW, p->buf, p->len, e, earg); + if (!d == !rc || (!rc && !MP_EQ(d, c))) { + ok = 0; + fprintf(stderr, "*** sign with %s padding failed!\n", ename); + MP_EPRINTX("*** key.n", rp->n); + MP_EPRINTX("*** key.d", rp->d); + MP_EPRINTX("*** key.e", rp->e); + if (eparam) { + fprintf(stderr, "*** encoding parameters = "); + type_hex.dump(eparam, stderr); + fputc('\n', stderr); + } + fprintf(stderr, "*** input message = "); type_hex.dump(p, stderr); + if (rc) + fprintf(stderr, "\n*** expected failure\n"); + else { + MP_EPRINTX("\n*** expected", c); + MP_EPRINTX("\n*** computed", d); + } + } + rsa_privdestroy(&rpc); + rsa_privfree(rp); + mp_drop(d); + mp_drop(c); + GR_DESTROY(r); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tdecpriv(rsa_priv *rp, + mp *c, int rc, dstr *p, + const char *ename, dstr *eparam, + rsa_decunpad *e, void *earg) +{ + rsa_privctx rpc; + dstr d = DSTR_INIT; + grand *r = fibrand_create(0); + int n; + int ok = 1; + + rsa_privcreate(&rpc, rp, r); + n = rsa_decrypt(&rpc, c, &d, e, earg); + if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) { + ok = 0; + fprintf(stderr, "*** decryption with %s padding failed!\n", ename); + MP_EPRINTX("*** key.n", rp->n); + MP_EPRINTX("*** key.d", rp->d); + MP_EPRINTX("*** key.e", rp->e); + if (eparam) { + fprintf(stderr, "*** encoding parameters = "); + type_hex.dump(eparam, stderr); + fputc('\n', stderr); + } + MP_EPRINTX("*** input", c); + if (rc < 0) + fprintf(stderr, "*** expected failure\n"); + else { + fprintf(stderr, "*** expected = %d: ", rc); type_hex.dump(p, stderr); + fprintf(stderr, "\n*** computed = %d: ", n); type_hex.dump(&d, stderr); + fprintf(stderr, "\n"); + } + } + rsa_privdestroy(&rpc); + rsa_privfree(rp); + mp_drop(c); + dstr_destroy(&d); + GR_DESTROY(r); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tvrfpub(rsa_pub *rp, + mp *c, dstr *m, int rc, dstr *p, + const char *ename, dstr *eparam, + rsa_vrfunpad *e, void *earg) +{ + rsa_pubctx rpc; + dstr d = DSTR_INIT; + int n; + int ok = 1; + + rsa_pubcreate(&rpc, rp); + n = rsa_verify(&rpc, c, m->len ? m->buf : 0, m->len, &d, e, earg); + if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) { + ok = 0; + fprintf(stderr, "*** verification with %s padding failed!\n", ename); + MP_EPRINTX("*** key.n", rp->n); + MP_EPRINTX("*** key.e", rp->e); + if (eparam) { + fprintf(stderr, "*** encoding parameters = "); + type_hex.dump(eparam, stderr); + fputc('\n', stderr); + } + MP_EPRINTX("*** input", c); + fprintf(stderr, "*** message = "); type_hex.dump(m, stderr); + if (rc < 0) + fprintf(stderr, "\n*** expected failure\n"); + else { + fprintf(stderr, "\n*** expected = %d: ", rc); type_hex.dump(p, stderr); + fprintf(stderr, "\n*** computed = %d: ", n); type_hex.dump(&d, stderr); + fprintf(stderr, "\n"); + } + } + rsa_pubdestroy(&rpc); + rsa_pubfree(rp); + mp_drop(c); + dstr_destroy(&d); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +/*----- Deep magic --------------------------------------------------------* + * + * Wahey! Whacko macro programming on curry and lager. There's nothing like + * it. + */ + +#define DECL_priv \ + rsa_priv rp = { 0 }; +#define FUNC_priv \ + rp.n = *(mp **)v++->buf; \ + rp.e = *(mp **)v++->buf; \ + rp.d = *(mp **)v++->buf; \ + rsa_recover(&rp); +#define ARG_priv \ + &rp, +#define TAB_priv \ + &type_mp, &type_mp, &type_mp, + +#define DECL_pub \ + rsa_pub rp; +#define FUNC_pub \ + rp.n = *(mp **)v++->buf; \ + rp.e = *(mp **)v++->buf; +#define ARG_pub \ + &rp, +#define TAB_pub \ + &type_mp, &type_mp, + +#define DECL_pad \ + int nbits; +#define FUNC_pad \ + nbits = *(int *)v++->buf; +#define ARG_pad \ + nbits, +#define TAB_pad \ + &type_int, + +#define DECL_enc \ + dstr *p; \ + int rc; \ + mp *c; +#define FUNC_enc \ + p = v++; \ + rc = *(int *)v++->buf; \ + c = *(mp **)v++->buf; +#define ARG_enc \ + p, rc, c, +#define TAB_enc \ + &type_hex, &type_int, &type_mp, + +#define DECL_sig DECL_enc +#define FUNC_sig FUNC_enc +#define ARG_sig ARG_enc +#define TAB_sig TAB_enc + +#define DECL_dec \ + mp *c; \ + int rc; \ + dstr *p; +#define FUNC_dec \ + c = *(mp **)v++->buf; \ + rc = *(int *)v++->buf; \ + p = v++; +#define ARG_dec \ + c, rc, p, +#define TAB_dec \ + &type_mp, &type_int, &type_hex, + +#define DECL_vrf \ + mp *c; \ + dstr *m; \ + int rc; \ + dstr *p; +#define FUNC_vrf \ + c = *(mp **)v++->buf; \ + m = v++; \ + rc = *(int *)v++->buf; \ + p = v++; +#define ARG_vrf \ + c, m, rc, p, +#define TAB_vrf \ + &type_mp, &type_hex, &type_int, &type_hex, + +#define DECL_p1enc \ + pkcs1 p1; \ + dstr *ep; +#define FUNC_p1enc \ + p1.r = fib; \ + ep = v++; \ + p1.ep = ep->buf; \ + p1.epsz = ep->len; +#define ARG_p1enc \ + "pkcs1", ep, pkcs1_cryptencode, &p1 +#define TAB_p1enc \ + &type_hex + +#define DECL_p1sig DECL_p1enc +#define FUNC_p1sig FUNC_p1enc +#define ARG_p1sig \ + "pkcs1", ep, pkcs1_sigencode, &p1 +#define TAB_p1sig TAB_p1enc + +#define DECL_p1dec DECL_p1enc +#define FUNC_p1dec FUNC_p1enc +#define ARG_p1dec \ + "pkcs1", ep, pkcs1_cryptdecode, &p1 +#define TAB_p1dec TAB_p1enc + +#define DECL_p1vrf DECL_p1enc +#define FUNC_p1vrf FUNC_p1enc +#define ARG_p1vrf \ + "pkcs1", ep, pkcs1_sigdecode, &p1 +#define TAB_p1vrf TAB_p1enc + +#define DECL_oaepenc \ + oaep o; \ + dstr *ep; +#define FUNC_oaepenc \ + o.r = fib; \ + o.cc = gcipher_byname(v++->buf); \ + o.ch = ghash_byname(v++->buf); \ + ep = v++; \ + o.ep = ep->buf; \ + o.epsz = ep->len; +#define ARG_oaepenc \ + "oaep", ep, oaep_encode, &o +#define TAB_oaepenc \ + &type_string, &type_string, &type_hex + +#define DECL_oaepdec DECL_oaepenc +#define FUNC_oaepdec FUNC_oaepenc +#define ARG_oaepdec \ + "oaep", ep, oaep_decode, &o +#define TAB_oaepdec TAB_oaepenc + +#define DECL_psssig \ + pss pp; +#define FUNC_psssig \ + pp.r = fib; \ + pp.cc = gcipher_byname(v++->buf); \ + pp.ch = ghash_byname(v++->buf); \ + pp.ssz = *(int *)v++->buf; +#define ARG_psssig \ + "pss", 0, pss_encode, &pp +#define TAB_psssig \ + &type_string, &type_string, &type_int + +#define DECL_pssvrf DECL_psssig +#define FUNC_pssvrf FUNC_psssig +#define ARG_pssvrf \ + "pss", 0, pss_decode, &pp +#define TAB_pssvrf TAB_psssig + +#define TESTS(DO) \ + DO(pad, enc, p1enc) \ + DO(pad, dec, p1dec) \ + DO(pad, sig, p1sig) \ + DO(pad, vrf, p1vrf) \ + DO(pub, enc, p1enc) \ + DO(priv, dec, p1dec) \ + DO(priv, sig, p1sig) \ + DO(pub, vrf, p1vrf) \ + DO(pad, enc, oaepenc) \ + DO(pad, dec, oaepdec) \ + DO(pub, enc, oaepenc) \ + DO(priv, dec, oaepdec) \ + DO(pad, sig, psssig) \ + DO(pad, vrf, pssvrf) \ + DO(priv, sig, psssig) \ + DO(pub, vrf, pssvrf) + +#define FUNCS(key, op, enc) \ + int t_##key##_##enc(dstr *v) \ + { \ + DECL_##key \ + DECL_##op \ + DECL_##enc \ + fib->ops->misc(fib, GRAND_SEEDINT, 14); \ + FUNC_##key \ + FUNC_##op \ + FUNC_##enc \ + return (t##op##key(ARG_##key ARG_##op ARG_##enc)); \ + } + +#define TAB(key, op, enc) \ + { #enc "-" #key, t_##key##_##enc, { TAB_##key TAB_##op TAB_##enc } }, + +static grand *fib; + +TESTS(FUNCS) + +static const test_chunk tests[] = { + TESTS(TAB) + { 0 } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + fib = fibrand_create(0); + test_run(argc, argv, tests, SRCDIR "/t/rsa"); + GR_DESTROY(fib); + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/pub/rsa.h b/pub/rsa.h new file mode 100644 index 0000000..2fb767d --- /dev/null +++ b/pub/rsa.h @@ -0,0 +1,402 @@ +/* -*-c-*- + * + * The RSA public-key cryptosystem + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_RSA_H +#define CATACOMB_RSA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +#ifndef CATACOMB_KEY_H +# include "key.h" +#endif + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_PGEN_H +# include "pgen.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- RSA private and public keys --- */ + +typedef struct rsa_pub { + mp *n; + mp *e; +} rsa_pub; + +typedef struct rsa_priv { + mp *n, *p, *q, *q_inv; + mp *e, *d, *dp, *dq; +} rsa_priv; + +/* --- RSA private and public key contexts --- * + * + * These are used to store information about `active' keys which will speed + * up the various operations. + */ + +typedef struct rsa_privctx { + rsa_priv *rp; + grand *r; + mpmont nm, pm, qm; +} rsa_privctx; + +typedef struct rsa_pubctx { + mpmont mm; + rsa_pub *rp; +} rsa_pubctx; + +/* --- Encoding and decoding function schemas --- * + * + * See `oaep.h' and `pkcs1.h' for appropriate encoding functions. + */ + +typedef mp *rsa_pad(mp */*d*/, const void */*m*/, size_t /*msz*/, + octet */*b*/, size_t /*sz*/, + unsigned long /*nbits*/, void */*p*/); + +typedef int rsa_decunpad(mp */*m*/, octet */*b*/, size_t /*sz*/, + unsigned long /*nbits*/, void */*p*/); + +typedef int rsa_vrfunpad(mp */*s*/, const void */*m*/, size_t /*msz*/, + octet */*b*/, size_t /*sz*/, + unsigned long /*nbits*/, void */*p*/); + +/*----- Key fetching ------------------------------------------------------*/ + +extern const key_fetchdef rsa_pubfetch[]; +#define RSA_PUBFETCHSZ 4 + +extern const key_fetchdef rsa_privfetch[]; +#define RSA_PRIVFETCHSZ 12 + +/* --- @rsa_pubfree@, @rsa_privfree@ --- * + * + * Arguments: @rsa_pub *rp@, @rsa_priv *rp@ = pointer to key block + * + * Returns: --- + * + * Use: Frees an RSA key block. + */ + +extern void rsa_pubfree(rsa_pub */*rp*/); +extern void rsa_privfree(rsa_priv */*rp*/); + +/*----- RSA private key operations ----------------------------------------*/ + +/* --- @rsa_privcreate@ --- * + * + * Arguments: @rsa_privctx *rd@ = pointer to an RSA private key context + * @rsa_priv *rp@ = pointer to RSA private key + * @grand *r@ = pointer to random number source for blinding + * + * Returns: --- + * + * Use: Initializes an RSA private-key context. Keeping a context + * for several decryption or signing operations provides a minor + * performance benefit. + * + * The random number source may be null if blinding is not + * desired. This improves decryption speed, at the risk of + * permitting timing attacks. + */ + +extern void rsa_privcreate(rsa_privctx */*rd*/, rsa_priv */*rp*/, + grand */*r*/); + +/* --- @rsa_privdestroy@ --- * + * + * Arguments: @rsa_privctx *rd@ = pointer to an RSA decryption context + * + * Returns: --- + * + * Use: Destroys an RSA decryption context. + */ + +extern void rsa_privdestroy(rsa_privctx */*rd*/); + +/* --- @rsa_privop@ --- * + * + * Arguments: @rsa_privctx *rd@ = pointer to RSA private key context + * @mp *d@ = destination + * @mp *c@ = input message + * + * Returns: The transformed output message. + * + * Use: Performs an RSA private key operation. This function takes + * advantage of knowledge of the key factors in order to speed + * up decryption. It also blinds the ciphertext prior to + * decryption and unblinds it afterwards to thwart timing + * attacks. + */ + +extern mp *rsa_privop(rsa_privctx */*rd*/, mp */*d*/, mp */*c*/); + +/* --- @rsa_qprivop@ --- * + * + * Arguments: @rsa_priv *rp@ = pointer to RSA parameters + * @mp *d@ = destination + * @mp *c@ = input message + * @grand *r@ = pointer to random number source for blinding + * + * Returns: Correctly transformed output message + * + * Use: Performs an RSA private key operation, very carefully. + */ + +extern mp *rsa_qprivop(rsa_priv */*rp*/, mp */*d*/, mp */*c*/, grand */*r*/); + +/* --- @rsa_sign@ --- * + * + * Arguments: @rsa_privctx *rp@ = pointer to an RSA private key context + * @mp *d@ = where to put the result + * @const void *m@ = pointer to input message + * @size_t msz@ = size of input message + * @rsa_pad *e@ = encoding procedure + * @void *earg@ = argument pointer for encoding procedure + * + * Returns: The signature, as a multiprecision integer, or null on + * failure. + * + * Use: Computes an RSA digital signature. + */ + +extern mp *rsa_sign(rsa_privctx */*rp*/, mp */*d*/, + const void */*m*/, size_t /*msz*/, + rsa_pad */*e*/, void */*earg*/); + +/* --- @rsa_decrypt@ --- * + * + * Arguments: @rsa_privctx *rp@ = pointer to an RSA private key context + * @mp *m@ = encrypted message, as a multiprecision integer + * @dstr *d@ = pointer to output string + * @rsa_decunpad *e@ = decoding procedure + * @void *earg@ = argument pointer for decoding procedure + * + * Returns: The length of the output string if successful, negative on + * failure. + * + * Use: Does RSA decryption. + */ + +extern int rsa_decrypt(rsa_privctx */*rp*/, mp */*m*/, + dstr */*d*/, rsa_decunpad */*e*/, void */*earg*/); + +/*----- RSA public key operations -----------------------------------------*/ + +/* --- @rsa_pubcreate@ --- * + * + * Arguments: @rsa_pubctx *rd@ = pointer to an RSA public key context + * @rsa_pub *rp@ = pointer to RSA public key + * + * Returns: --- + * + * Use: Initializes an RSA public-key context. + */ + +extern void rsa_pubcreate(rsa_pubctx */*rd*/, rsa_pub */*rp*/); + +/* --- @rsa_pubdestroy@ --- * + * + * Arguments: @rsa_pubctx *rd@ = pointer to an RSA public key context + * + * Returns: --- + * + * Use: Destroys an RSA public-key context. + */ + +extern void rsa_pubdestroy(rsa_pubctx */*rd*/); + +/* --- @rsa_pubop@ --- * + * + * Arguments: @rsa_pubctx *rd@ = pointer to an RSA public key context + * @mp *d@ = destination + * @mp *p@ = input message + * + * Returns: The transformed output message. + * + * Use: Performs an RSA public key operation. + */ + +extern mp *rsa_pubop(rsa_pubctx */*rd*/, mp */*d*/, mp */*p*/); + +/* --- @rsa_qpubop@ --- * + * + * Arguments: @rsa_pub *rp@ = pointer to RSA parameters + * @mp *d@ = destination + * @mp *p@ = input message + * + * Returns: Correctly transformed output message. + * + * Use: Performs an RSA public key operation. + */ + +extern mp *rsa_qpubop(rsa_pub */*rp*/, mp */*d*/, mp */*c*/); + +/* --- @rsa_encrypt@ --- * + * + * Arguments: @rsa_pubctx *rp@ = pointer to an RSA public key context + * @mp *d@ = proposed destination integer + * @const void *m@ = pointer to input message + * @size_t msz@ = size of input message + * @rsa_pad *e@ = encoding procedure + * @void *earg@ = argument pointer for encoding procedure + * + * Returns: The encrypted message, as a multiprecision integer, or null + * on failure. + * + * Use: Does RSA encryption. + */ + +extern mp *rsa_encrypt(rsa_pubctx */*rp*/, mp */*d*/, + const void */*m*/, size_t /*msz*/, + rsa_pad */*e*/, void */*earg*/); + +/* --- @rsa_verify@ --- * + * + * Arguments: @rsa_pubctx *rp@ = pointer to an RSA public key contxt + * @mp *s@ = the signature, as a multiprecision integer + * @const void *m@ = pointer to message to verify, or null + * @size_t sz@ = size of input message + * @dstr *d@ = pointer to output string, or null + * @rsa_vfrunpad *e@ = decoding procedure + * @void *earg@ = argument pointer for decoding procedure + * + * Returns: The length of the output string if successful (0 if no output + * was wanted); negative on failure. + * + * Use: Does RSA signature verification. To use a signature scheme + * with recovery, pass in @m == 0@ and @d != 0@: the recovered + * message should appear in @d@. To use a signature scheme with + * appendix, provide @m != 0@ and @d == 0@; the result should be + * zero for success. + */ + +extern int rsa_verify(rsa_pubctx */*rp*/, mp */*s*/, + const void */*m*/, size_t /*sz*/, dstr */*d*/, + rsa_vrfunpad */*e*/, void */*earg*/); + +/*----- Miscellaneous operations ------------------------------------------*/ + +/* --- @rsa_gen@ --- * + * + * Arguments: @rsa_priv *rp@ = pointer to block to be filled in + * @unsigned nbits@ = required modulus size in bits + * @grand *r@ = random number source + * @unsigned n@ = number of attempts to make + * @pgen_proc *event@ = event handler function + * @void *ectx@ = argument for the event handler + * + * Returns: Zero if all went well, nonzero otherwise. + * + * Use: Constructs a pair of strong RSA primes and other useful RSA + * parameters. A small encryption exponent is chosen if + * possible. + */ + +extern int rsa_gen(rsa_priv */*rp*/, unsigned /*nbits*/, + grand */*r*/, unsigned /*n*/, + pgen_proc */*event*/, void */*ectx*/); + +/* --- @rsa_recover@ --- * + * + * Arguments: @rsa_priv *rp@ = pointer to parameter block + * + * Returns: Zero if all went well, nonzero if the parameters make no + * sense. + * + * Use: Derives the full set of RSA parameters given a minimal set. + */ + +extern int rsa_recover(rsa_priv */*rp*/); + +/*----- Padding schemes ---------------------------------------------------*/ + +/* --- PKCS1 padding --- */ + +typedef struct pkcs1 { + grand *r; /* Random number source */ + const void *ep; /* Encoding parameters block */ + size_t epsz; /* Size of the parameter block */ +} pkcs1; + +extern rsa_pad pkcs1_cryptencode; +extern rsa_decunpad pkcs1_cryptdecode; +extern rsa_pad pkcs1_sigencode; +extern rsa_vrfunpad pkcs1_sigdecode; + +/* --- OAEP --- */ + +typedef struct oaep { + const gccipher *cc; /* Cipher class for masking */ + const gchash *ch; /* Hash class for parameter block */ + grand *r; /* Random number source */ + const void *ep; /* Encoding parameters block */ + size_t epsz; /* Size of the parameter block */ +} oaep; + +extern rsa_pad oaep_encode; +extern rsa_decunpad oaep_decode; + +/* --- PSS --- */ + +typedef struct pss { + const gccipher *cc; /* Cipher class for masking */ + const gchash *ch; /* Hash class for choosing a seed */ + grand *r; /* Random number source */ + size_t ssz; /* Requested salt size */ +} pss; + +extern rsa_pad pss_encode; +extern rsa_vrfunpad pss_decode; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/pub/t/bbs b/pub/t/bbs new file mode 100644 index 0000000..65bbe2c --- /dev/null +++ b/pub/t/bbs @@ -0,0 +1,14 @@ +# Test vectors for Blum-Blum-Shub generator + +bbs { + 58618255351802153154518076227263324405595169368832105733339611861073310668957206153928098662820028322143309562326246028101842658621324089654810023510552099428926874474919949521150122806716423750640359105584279946965449493907636556236204117444242840921432253645386399913807490661488722966090824347967771475377 + 2 + 4a488784b0b74c53fe820e3416f67fb7f238898f711a8b5d3f3ea70b0ec264120b7bfaef30f841a979cb76ca9e9c6b01415e7618b5d6c4cc30db539852ca86d23b3527d566a76910d43ed9ba2b83596f3411354ae37c53cf0c2eab7e7e13ac7c58de83cbfd8b0a6b7cdcb7bcef92bf96a48e18124c2c21e7964a9b701b5ea4ab; +} + +bbs-jump { + 10300002644323831640029548502577413794096963710947992849414516873746495715149677373680896096678934650462228369293905743592335562158905193518665447759028003 + 8901308291494485065585437130459769427950766447948540080704500059827922533698081294071192603392538957644021072601596274962775430269633339980725226130767879 + 15 + 250; +} diff --git a/pub/t/dsa b/pub/t/dsa new file mode 100644 index 0000000..f263901 --- /dev/null +++ b/pub/t/dsa @@ -0,0 +1,119 @@ +# Test vectors for DSA + +# --- About the tests --- +# +# There's only one test vector from FIPS-186. The others I've made up. The +# tests themselves are split into parameter generation, signature generation, +# and verification. + +gen { + # --- One that I made up --- + + bbac0ab63411435cb72f1f95b16ab94c92c34211 256 + bbac0ab63411435cb72f1f95b16ab94c92c34221 10 + 0x84d192cd06ae59691897fa409da6198d5269325d + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5 + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e; + + # --- FIPS-186 test vector --- + + d5014e4b60ef2ba8b6211b4062ba3224e0427dd3 512 + d5014e4b60ef2ba8b6211b4062ba3224e0427dd3 105 + 0xc773218c737ec8ee993b4f2ded30f48edace915f + 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 + 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802; + + # --- And a full-sized vector --- + + d1a29e27dfe4d60124cc41a59e012ae690408acfc3266d07f4eaeefdc9f8c70d2d2a338d + 1024 + d1a29e27dfe4d60124cc41a59e012ae690408acfc3266d07f4eaeefdc9f8c70d2d2a338d + 66 + 0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9 + 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7 + 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014; +} + +sign { + # --- Quick simple test --- + + 0x84d192cd06ae59691897fa409da6198d5269325d + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5 + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + 0x1234 "An example message" + 649b1058e0fe7ee849d3cb00b8ec3053ad0793b8 + 2718bf488b981992b164e664224dd00ca1ed4e1c + 5c085679fbfa9ee806781bdbd86a67dbf14df640; + + # --- The FIPS-186 test vector --- + + 0xc773218c737ec8ee993b4f2ded30f48edace915f + 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 + 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 + 0x2070b3223dba372fde1c0ffc7b2e3b498b260614 + "abc" + 358dad571462710f50e254cf1a376b2bdeaadfbf + 8bac1ab66410435cb7181f95b16ab97c92b341c0 + 41e2345f1f56df2458f426d155b4ba2db6dcd8c8; + + # --- 1024-bit modulus test --- + + 0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9 + 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7 + 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 + 0x23a252f60bae4907a8ed5b6203e2b1da32848cd9 + "A message signed with a 1024-bit DSA key." + 12ccb231683a3d9c13dca6fe882349537eebfd03 + 2a301061ac185440fbf595f8f7d894158b8d1897 + 51aedaa73cb8d47e07281d14dda5ea8c0ddf7503; +} + +verify-good { + # --- Simple test ---- + + 0x84d192cd06ae59691897fa409da6198d5269325d + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5 + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 + "An example message" + 2718bf488b981992b164e664224dd00ca1ed4e1c + 5c085679fbfa9ee806781bdbd86a67dbf14df640; + + # --- The FIPS-186 test vector --- + + 0xc773218c737ec8ee993b4f2ded30f48edace915f + 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 + 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 + 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 + "abc" + 8bac1ab66410435cb7181f95b16ab97c92b341c0 + 41e2345f1f56df2458f426d155b4ba2db6dcd8c8; + + # --- 1024-bit modulus test --- + + 0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9 + 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7 + 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 + 0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074 + "A message signed with a 1024-bit DSA key." + 2a301061ac185440fbf595f8f7d894158b8d1897 + 51aedaa73cb8d47e07281d14dda5ea8c0ddf7503; +} + +verify-bad { + 0xc773218c737ec8ee993b4f2ded30f48edace915f + 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 + 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 + 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 + "abd" + 8bac1ab66410435cb7181f95b16ab97c92b341c0 + 41e2345f1f56df2458f426d155b4ba2db6dcd8c8; + + 0xc773218c737ec8ee993b4f2ded30f48edace915f + 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 + 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 + 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 + "abc" + 18bac1ab66410435cb7181f95b16ab97c92b341c0 + 41e2345f1f56df2458f426d155b4ba2db6dcd8c8; +} diff --git a/pub/t/gdsa b/pub/t/gdsa new file mode 100644 index 0000000..9eeb4e0 --- /dev/null +++ b/pub/t/gdsa @@ -0,0 +1,240 @@ +# Tests for abstract-group implementation of DSA + +sign { + # --- A simple and small test --- + + "prime { + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, + 0x84d192cd06ae59691897fa409da6198d5269325d, + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + }" + sha + 0x1234 + "An example message" + 0x649b1058e0fe7ee849d3cb00b8ec3053ad0793b8 + 0x2718bf488b981992b164e664224dd00ca1ed4e1c + 0x5c085679fbfa9ee806781bdbd86a67dbf14df640; + + # --- The FIPS186-1 test vector --- + + "prime { + 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291, + 0xc773218c737ec8ee993b4f2ded30f48edace915f, + 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 + }" + sha + 0x2070b3223dba372fde1c0ffc7b2e3b498b260614 + "abc" + 0x358dad571462710f50e254cf1a376b2bdeaadfbf + 0x8bac1ab66410435cb7181f95b16ab97c92b341c0 + 0x41e2345f1f56df2458f426d155b4ba2db6dcd8c8; + + # --- A test I made up --- + + "prime { + 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7, + 0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9, + 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 + }" + sha + 0x23a252f60bae4907a8ed5b6203e2b1da32848cd9 + "A message signed with a 1024-bit DSA key." + 0x12ccb231683a3d9c13dca6fe882349537eebfd03 + 0x2a301061ac185440fbf595f8f7d894158b8d1897 + 0x51aedaa73cb8d47e07281d14dda5ea8c0ddf7503; + + # --- Elliptic curve test vectors --- + + "ec { nist-b163 }" sha 0x1234 + "An example message" + 0x649b1058e0fe7ee849d3cb00b8ec3053ad0793b8 + 0x12e2f4e865bf6e034712b4f2ba6f3c825452d6419 + 0x30e0d918fde3a33781f984b877f8501356b6fbae9; + + "ec { secp160r1 }" sha + 0xaa374ffc3ce144e6b073307972cb6d57b2a4e982 + "abc" + 0x7b012db7681a3f28b9185c8b2ac5d528decd52da + 0xce2873e5be449563391feb47ddcba2dc16379191 + 0x3480ec1371a091a464b31ce47df0cb8aa2d98b54; + + "ec { sect163k1 }" sha + 0x3a41434aa99c2ef40c8495b2ed9739cb2155a1e0d + "abc" + 0xa40b301cc315c257d51d442234f5aff8189d2b6c + 0x994d2c41aa30e52952aea8462370471b2b0a34ac + 0x152f95ca15da1997a8c449e00cd2aa2accb988d7f; + + ## This one's from P1363: + ## http://grouper.ieee.org/groups/1363/P1363/testvector.txt + "ec { ansi-c2tnb191v1 }" sha + 0x340562e1dda332f9d2aec168249b5696ee39d0ed4d03760f + "abc" + 0x3eeace72b4919d991738d521879f787cb590aff8189d2b69 + 0x038e5a11fb55e4c65471dcd4998452b1e02d8af7099bb930 + 0x0c9a08c34468c244b4e5d6b21b3c68362807416020328b6e; + + "ec { nist-p256 }" sha256 + 0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa + "An example message" + 0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c + 0xb30f954bfb624041e56f09ece884c17c74f866c24149bba0712303a9530142a6 + 0x1076bd32f298aaffa8c6242d881d928b1c4e0f5ad7e8ce3c4d815fe348a9666a; + + # --- Test for over-long hash --- + + "ec { sect131r1 }" sha + 0x85bd9fd28a7e7f915891208fbb2b05c0 + "An example message" + 0xee98d38c001731403af6fbf77356f8ea + 0x1cba36e768c0247d537a744b7ea62e3b9 + 0x216e5d02a0b1fb11d6d2fc4b383dcb168; +} + +verify { + # --- A simple and small test --- + + "prime { + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, + 0x84d192cd06ae59691897fa409da6198d5269325d, + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + }" + sha + 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 + "An example message" + 0x2718bf488b981992b164e664224dd00ca1ed4e1c + 0x5c085679fbfa9ee806781bdbd86a67dbf14df640 + 0; + + "prime { + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, + 0x84d192cd06ae59691897fa409da6198d5269325d, + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + }" + sha + 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 + "An example messag" + 0x2718bf488b981992b164e664224dd00ca1ed4e1c + 0x5c085679fbfa9ee806781bdbd86a67dbf14df640 + -1; + + "prime { + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, + 0x84d192cd06ae59691897fa409da6198d5269325d, + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + }" + sha + 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 + "An example message" + 0x2718bf488b981992b164e664224dd00ca1ed4e1c + 0x5c085679fbfa9ee806781bdbd86a67dbf14df641 + -1; + + "prime { + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, + 0x84d192cd06ae59691897fa409da6198d5269325d, + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + }" + sha + 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 + "An example message" + 0x2718bf488b981992b164e664224dd00ca1ed4e1c + 0xe0d9e94702a8f8511f10161c7610816943b7289d + -1; + + # --- The FIPS186-1 test vector --- + + "prime { + 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291, + 0xc773218c737ec8ee993b4f2ded30f48edace915f, + 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 + }" + sha + 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 + "abc" + 0x8bac1ab66410435cb7181f95b16ab97c92b341c0 + 0x41e2345f1f56df2458f426d155b4ba2db6dcd8c8 + 0; + + # --- A test I made up --- + + "prime { + 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7, + 0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9, + 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 + }" + sha + 0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074 + "A message signed with a 1024-bit DSA key." + 0x2a301061ac185440fbf595f8f7d894158b8d1897 + 0x51aedaa73cb8d47e07281d14dda5ea8c0ddf7503 + 0; + + # --- Elliptic curve test vectors --- + + "ec { nist-b163 }" sha + "0x1e7d847d0331a794852ded2b96c71d82e61f9bb4c, + 0x1a2370ab2e63f5aa8f348fbe83c0415a7d8ee207b" + "An example message" + 0x12e2f4e865bf6e034712b4f2ba6f3c825452d6419 + 0x30e0d918fde3a33781f984b877f8501356b6fbae9 + 0; + + "ec { secp160r1 }" sha + "0x51b4496fecc406ed0e75a24a3c03206251419dc0, + 0xc28dcb4b73a514b468d793894f381ccc1756aa6c" + "abc" + 0xce2873e5be449563391feb47ddcba2dc16379191 + 0x3480ec1371a091a464b31ce47df0cb8aa2d98b54 + 0; + + "ec { sect163k1 }" sha + "0x037d529fa37e42195f10111127ffb2bb38644806bc, + 0x0447026eee8b34157f3eb51be5185d2be0249ed776" + "abc" + 0x994d2c41aa30e52952aea8462370471b2b0a34ac + 0x152f95ca15da1997a8c449e00cd2aa2accb988d7f + 0; + + ## This one's from P1363: + ## http://grouper.ieee.org/groups/1363/P1363/testvector.txt + "ec { ansi-c2tnb191v1 }" sha + "0x5de37e756bd55d72e3768cb396ffeb962614dea4ce28a2e7, + 0x55c0e0e02f5fb132caf416ef85b229bbb8e1352003125ba1" + "abc" + 0x038e5a11fb55e4c65471dcd4998452b1e02d8af7099bb930 + 0x0c9a08c34468c244b4e5d6b21b3c68362807416020328b6e + 0; + + "ec { nist-p256 }" sha256 + "0xcc2aecbc5c5f6d72cd7b937279d72a732abcf880ea47e012ebec77ddbca6ed40, + 0x90f99cd799abc0ea571d0e02bad80f8323050b1adbdbff50060b6e1e6ebd8611" + "An example message" + 0xb30f954bfb624041e56f09ece884c17c74f866c24149bba0712303a9530142a6 + 0x1076bd32f298aaffa8c6242d881d928b1c4e0f5ad7e8ce3c4d815fe348a9666a + 0; + + # --- Test for over-long hash --- + + "ec { sect131r1 }" sha + "0x2218ba2b57a7821be97c0015b797d82fe, 0x666aed14fd7a2abf867c6fa222ab26fcc" + "An example message" + 0x1cba36e768c0247d537a744b7ea62e3b9 + 0x216e5d02a0b1fb11d6d2fc4b383dcb168 + 0; + + "ec { sect131r1 }" sha + "0x2218ba2b57a7821be97c0015b797d82fe, 0x666aed14fd7a2abf867c6fa222ab26fcc" + "An example messag" + 0x1cba36e768c0247d537a744b7ea62e3b9 + 0x216e5d02a0b1fb11d6d2fc4b383dcb168 + -1; + + "ec { nist-b163 }" sha512 + "0x385a32536d1cb46d10cf3034a3dd39eb25e4f5123, + 0x29ee1edfa37d0f306c4da17b8d883f01ce3be4d46" + "qpwmoeqpofaosdaspdpqoweopdoagnqornifnasd" + 0x0231b6a807f6af1aee0598768b3fabb863d14a7f8d + 0x01c2f638e9dffe03b562e48ca4e1a380cf8c3055f1 + 0; +} diff --git a/pub/t/gkcdsa b/pub/t/gkcdsa new file mode 100644 index 0000000..0835f83 --- /dev/null +++ b/pub/t/gkcdsa @@ -0,0 +1,57 @@ +# Tests for KCDSA + +sign { + "prime { + 0xd7b9afc104f4d53f737db88d6bf77e12cd7ec3d71cbe3cb74cd224bff348154afba6bfed797044dfc655dcc20c952c0ec43a97e1ad67e687d10729caf622845d162afca8f0248cc412b3596c4c5d3384f7e25ee644ba87bb09b164fb465477b87fdba5eaa400ffa0925714ae19464ffacead3a9750d121948ab2d8d65c82379f, + 0xc3ddd3717bf05b8f8dd725c162f0b9432c6f77fb, + 0x50e414c7a56892d1ad633e42d5cd8346f2c09808111c772cc30b0c544102c27e7b5f9bec57b9df2a153128919d795e46652b2a072e1f2517f2a3afff5815253aaefe35724cfa1af6afce3a6b41e3d0e13bed0eff54383c4665e69b47ba79bbc3339f86b9be2b58894a18b201afc41fe3a0d93d3125efda79bc50dbbb2c3ab639 + }" + has160 + 0x068c4ef355d8b6f53eff1df6f243f98563896c58 + "This is a test message for KCDSA usage!" + 0x4b037e4b573bb7e334cad0a70bed6b5881df9e8e + 8f996a98eda57cc8d88aa6ffdfaea22f39d7fa8a + 0x541f7dc4f92c65eb7f63b6b4f22177f1ee2cf339; + + "ec { nist-p256 }" sha256 + 0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa + "Testing elliptic curves with KCDSA" + 0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c + e3f05cea444ec44d508b3af5b8d2d8eb2bcbff680e83684e3e630ec5b07393c0 + 0x42e307f5fa0a4e01906b067965f6253f1a7919a566cf3d73ddd9a35a17b38617; +} + +verify { + "prime { + 0xd7b9afc104f4d53f737db88d6bf77e12cd7ec3d71cbe3cb74cd224bff348154afba6bfed797044dfc655dcc20c952c0ec43a97e1ad67e687d10729caf622845d162afca8f0248cc412b3596c4c5d3384f7e25ee644ba87bb09b164fb465477b87fdba5eaa400ffa0925714ae19464ffacead3a9750d121948ab2d8d65c82379f, + 0xc3ddd3717bf05b8f8dd725c162f0b9432c6f77fb, + 0x50e414c7a56892d1ad633e42d5cd8346f2c09808111c772cc30b0c544102c27e7b5f9bec57b9df2a153128919d795e46652b2a072e1f2517f2a3afff5815253aaefe35724cfa1af6afce3a6b41e3d0e13bed0eff54383c4665e69b47ba79bbc3339f86b9be2b58894a18b201afc41fe3a0d93d3125efda79bc50dbbb2c3ab639 + }" + has160 + 0x96dce0e7b2f170093d9b51d2ba78202733b62c406d3769758b3e0cbba1ff6c78727a35703cb6bc2476c3c293743dfee94aa4b9efa9a17fa6bf790ac25a82c61523f50abaac7b64647eb15c957b07f5ed7d467243089f74695cd58fbf57920cc0c05d45829c0a8161b943f18451845760ed096540e78aa9750b03d02448cbf8de + "This is a test message for KCDSA usage!" + 8f996a98eda57cc8d88aa6ffdfaea22f39d7fa8a + 0x541f7dc4f92c65eb7f63b6b4f22177f1ee2cf339 + 0; + + "prime { + 0xd7b9afc104f4d53f737db88d6bf77e12cd7ec3d71cbe3cb74cd224bff348154afba6bfed797044dfc655dcc20c952c0ec43a97e1ad67e687d10729caf622845d162afca8f0248cc412b3596c4c5d3384f7e25ee644ba87bb09b164fb465477b87fdba5eaa400ffa0925714ae19464ffacead3a9750d121948ab2d8d65c82379f, + 0xc3ddd3717bf05b8f8dd725c162f0b9432c6f77fb, + 0x50e414c7a56892d1ad633e42d5cd8346f2c09808111c772cc30b0c544102c27e7b5f9bec57b9df2a153128919d795e46652b2a072e1f2517f2a3afff5815253aaefe35724cfa1af6afce3a6b41e3d0e13bed0eff54383c4665e69b47ba79bbc3339f86b9be2b58894a18b201afc41fe3a0d93d3125efda79bc50dbbb2c3ab639 + }" + has160 + 0x96dce0e7b2f170093d9b51d2ba78202733b62c406d3769758b3e0cbba1ff6c78727a35703cb6bc2476c3c293743dfee94aa4b9efa9a17fa6bf790ac25a82c61523f50abaac7b64647eb15c957b07f5ed7d467243089f74695cd58fbf57920cc0c05d45829c0a8161b943f18451845760ed096540e78aa9750b03d02448cbf8de + "This is a test message for KCDSA usage?" + 8f996a98eda57cc8d88aa6ffdfaea22f39d7fa8a + 0x541f7dc4f92c65eb7f63b6b4f22177f1ee2cf339 + -1; + + "ec { nist-p256 }" sha256 + "0x5068f177ccebee933a27457707f6879eb5c4c59d58483766caf9aabcc367c0d1, + 0x4869c59dceadad93f1ed306b3ed544356c119996cc78708b9557c7ca5901da4a" + "Testing elliptic curves with KCDSA" + e3f05cea444ec44d508b3af5b8d2d8eb2bcbff680e83684e3e630ec5b07393c0 + 0x42e307f5fa0a4e01906b067965f6253f1a7919a566cf3d73ddd9a35a17b38617 + 0; +} + diff --git a/pub/t/rsa b/pub/t/rsa new file mode 100644 index 0000000..2b2b27a --- /dev/null +++ b/pub/t/rsa @@ -0,0 +1,391 @@ +# Test vectors for the completely mad RSA infrastructure tests + +p1sig-pad { + # nbits msg rc result eparam + 256 "616263" 0 + 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263 + "cc22cc"; + 129 "616263" 0 0x0001ffffffffffffffff00cc22cc616263 "cc22cc"; + 128 "616263" -1 0 "cc22cc"; +} + +p1sig-priv { + # n e d msg rc result eparam + 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 + 0x10001 + 0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9 + "616263" 0 + 0xc484642d0e4dc4a4424d22410456dbdd9275b5c157d6974a66bee9aa02501c26 + "cc22cc"; + + 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff + 0x10001 + 0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81 + "a9993e364706816aba3e25717850c26c9cd0d89d" 0 + 0x0f642606b7aaf99ff4bb5853c51e31a02c58d8c1c33f3c584d4edc58b08a16d5dc8064b6e198edcc4dc06666171a113619d7da16dfd96cebfdb5cc5050af6fab3d9f2ca8b8d6ece1d513fabc98a11fe37892fcf0827ea2e792427a69b3523504f46c55ed8af9a1c59687ca73c4baad7235a1a3faedec14f95ddfa8d0554739a8 + "3021300906052b0e03021a05000414"; +} + +p1vrf-pad { + # nbits sig msg rc result eparam + 256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263 + "" 3 "616263" "cc22cc"; + 256 0x0101ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263 + "" -1 "" "cc22cc"; + 256 0x0002ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263 + "" -1 "" "cc22cc"; + 256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff01cc22cc616263 + "" -1 "" "cc22cc"; + 256 0x0001ffffffffffffffff00cc22ccffffffffffffffffffffff00cc22cc616263 + "" 18 "ffffffffffffffffffffff00cc22cc616263" "cc22cc"; + 256 0x0001ffffffffffffff00cc22ccffffffffffffffffffffffff00cc22cc616263 + "" -1 "" "cc22cc"; + 256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc21cc616263 + "" -1 "" "cc22cc"; + 256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616262 + "" 3 "616262" "cc22cc"; + 129 0x0001ffffffffffffffff00cc22cc616263 "" 3 "616263" "cc22cc"; + 128 0x0001ffffffffffffff00cc22cc616263 "" -1 "" "cc22cc"; +} + +p1vrf-pub { + # n e sig msg rc result eparam + 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 + 0x10001 + 0xc484642d0e4dc4a4424d22410456dbdd9275b5c157d6974a66bee9aa02501c26 + "" 3 "616263" "cc22cc"; + 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 + 0x10001 + 0xc484642d0e4dc4a4424d22410456dbdd9275b5c157d6974a66bee9aa02501c26 + "616263" 0 "" "cc22cc"; + 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 + 0x10001 + 0x27654c24f4ffefffc3bef7be8ae469db3069407702391eeb551ce9544621b63a + "" 18 "ffffffffffffffffffffff00cc22cc616263" "cc22cc"; + 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 + 0x10001 + 0xd980f3047ab74bc4e7bb99eeb17fcc657f50ee26146b7f2a9f982ef2f44cba + "" -1 "" "cc22cc"; + + 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff + 0x10001 + 0x0f642606b7aaf99ff4bb5853c51e31a02c58d8c1c33f3c584d4edc58b08a16d5dc8064b6e198edcc4dc06666171a113619d7da16dfd96cebfdb5cc5050af6fab3d9f2ca8b8d6ece1d513fabc98a11fe37892fcf0827ea2e792427a69b3523504f46c55ed8af9a1c59687ca73c4baad7235a1a3faedec14f95ddfa8d0554739a8 + "" 20 "a9993e364706816aba3e25717850c26c9cd0d89d" + "3021300906052b0e03021a05000414"; +} + +p1enc-pad { + # nbits msg rc ct eparam + 256 "616263" 0 + 0x0002efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263 ""; + 105 "616263" 0 + 0x0002efbd98524ad6419b00616263 ""; + 104 "616263" -1 0 ""; +} + +p1enc-pub { + # n e msg rc ct eparam + 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 + 0x10001 "616263" 0 + 0x8f20a0fc778b7c55567f41c344d39bfcdaca04fd475f2290dc05c236585a68ca ""; + + 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff + 0x10001 + "616263" + 0 + 0xaf91f5abf4766348eaaff1e8e5561b10bc1e3b15b6dff221869389a70d371d649b6cf78c5444f5d03a9feac12d5741cbc340e09d112063b1486568fca7c59b4c90604f0b6243eccc18901afa9001fc5f669108ebc75d6713e28d4a081723184332d4fb2ca391e3247a76c85323e66352d60c0a6ce8240af6f0583058820b1e32 + ""; +} + +p1dec-pad { + # nbits msg rc pt eparam + 256 0x0002efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263 + 3 "616263" ""; + 105 0x0002efbd98524ad6419b00616263 + 3 "616263" ""; + 104 0x0002efbd98524ad64100616263 + -1 "" ""; + 256 0x0002efbdfc524ad6419b00537a59b42a4662918436d6e0e4804b6b1000616263 + 21 "537a59b42a4662918436d6e0e4804b6b1000616263" ""; + 256 0x0002efbdfc524ad6419b00537a59b42a4662918436d6e0e4804b6b1000616263 + 3 "616263" "537a59b42a4662918436d6e0e4804b6b1000"; + 256 0x0102efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263 + -1 "" ""; + 256 0x0001efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263 + -1 "" ""; + 256 0x0002efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263 + 3 "616263" ""; + 256 0x0002efbdfc524ad6410065537a59b42a4662918436d6e0e4804b6b1000616263 + -1 "" ""; +} + +p1dec-priv { + # p e d msg rc pt eparam + 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 + 0x10001 + 0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9 + 0x8f20a0fc778b7c55567f41c344d39bfcdaca04fd475f2290dc05c236585a68ca + 3 "616263" ""; + 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 + 0x10001 + 0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9 + 0x19d6408010f0c2722b44cd4d5e006b6ffaa634aa225d727fa37c7c6ec29c5155 + 21 "537a59b42a4662918436d6e0e4804b6b1000616263" ""; + 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 + 0x10001 + 0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9~ + 0x952aa4893cd2620e4942f449529ea2f7105b9d67e041a676259fb986bc507b7d + -1 "" ""; + + 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff + 0x10001 + 0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81 + 0xaf91f5abf4766348eaaff1e8e5561b10bc1e3b15b6dff221869389a70d371d649b6cf78c5444f5d03a9feac12d5741cbc340e09d112063b1486568fca7c59b4c90604f0b6243eccc18901afa9001fc5f669108ebc75d6713e28d4a081723184332d4fb2ca391e3247a76c85323e66352d60c0a6ce8240af6f0583058820b1e32 + 3 "616263" ""; +} + +oaepenc-pad { + # nbits msg rc ct mgf hash eparam + 1024 "616263" 0 + 0x151709bd895ba510b5b3de3293c6de93adbb20cb065dcfbe3b2ca60aa39e458b30d14406eba05f0e479ddff40f554aba11da533c6d98df0321164c986807e8019c6918896817f37700a46c7fd71741a7692fcbd443952b67c32b838a576332b3bc1bab002fe3c941e9150d08b539908ef7f1901ac1246065c8520ac1beffed + sha-mgf sha ""; +} + +oaepdec-pad { + # nbits msg rc pt mgf hash eparam + 1024 + 0x151709bd895ba510b5b3de3293c6de93adbb20cb065dcfbe3b2ca60aa39e458b30d14406eba05f0e479ddff40f554aba11da533c6d98df0321164c986807e8019c6918896817f37700a46c7fd71741a7692fcbd443952b67c32b838a576332b3bc1bab002fe3c941e9150d08b539908ef7f1901ac1246065c8520ac1beffed + 3 "616263" sha-mgf sha ""; + 1024 + 0x151709bd895ba510b5b3de3293c6de93adbb20cb065dcfbe3b2ca60aa39e458b30d14406eba05f0e479ddff40f554aba11da533c6d98df0321164c986807e8019c6918896817f37700a46c7fd71741a7692fcbd443952b67c32b838a576332b3bc1bab002fe3c941e9150d08b539908ef7f1901ac1246065c8520ac1beffec + -1 "" sha-mgf sha ""; +} + +oaepenc-pub { + # n e msg rc ct mgf hash eparam + 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff + 0x10001 + "616263" + 0 + 0xa5c94083e56aeff3490a4abd63251b332a26cca0e521815af5d2915b2422fbc7e672c8e67c3dea8c355e0b999a1f8acc905cc4437a6ddc5a7d6f54489436bd24922f83d75629d2cb92a7963d010727ef8981c3c01971962f454e42d54996e74617022d7513505fef7b1f7d5dbdeccc4673594d01f943236e4439b3175c3f801b + sha-mgf sha ""; +} + +oaepdec-priv { + # n e d msg rc pt mgf hash eparam + 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff + 0x10001 + 0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81 + 0x6ae9901c7c40104b38e10097bd42212afd437867ee4c72e7e81d7486b8721aeab493be40e3bd4335bef05c76bba1a2e30795e76fe04517d5f8fa87d16756002b061674594cb85c32b96c3a690e135d64923bd7551c45b6b89ebb89941377ce02d5c801feb33c20ebacf8dd6d6bd44d4f29bc2ff4dca35db52da545ef97733955 + 3 "616263" sha-mgf sha ""; + 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff + 0x10001 + 0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81 + 0x6ae9901c7c40104b38e10097bd42212afd437867ee4c72e7e81d7486b8721aeab493be40e3bd4335bef05c76bba1a2e30795e76fe04517d5f8fa87d16756002b061674594cb85c32b96c3a690e135d64923bd7551c45b6b89ebb89941377ce02d5c801feb33c20ebacf8dd6d6bd44d4f29bc2ff4dca35db52da545ef97733954 + -1 "" sha-mgf sha ""; +} + +psssig-pad { + # nbits msg rc result mgf hash saltsz + 256 "a9993e364706816aba3e25717850c26c9cd0d89d" 0 + 0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc + sha-mgf sha 10; + 256 "a9993e364706816aba3e25717850c26c9cd0d89d" -1 + 0 sha-mgf sha 20; + 273 "a9993e364706816aba3e25717850c26c9cd0d89d" 0 + 0xb5c91e4c0c00aaaffba7d581011366f0477cf42d9b98fddf692f3d14f9b8a168e4bc + sha-mgf sha 10; + + 1024 "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0 + 0x2d22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc + sha-mgf sha 20; + 1025 "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0 + 0xad22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc + sha-mgf sha 20; + 1024 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 + 0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + sha256-mgf sha256 32; + 1025 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 + 0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + sha256-mgf sha256 32; + 1026 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 + 0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + sha256-mgf sha256 32; + 1027 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 + 0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + sha256-mgf sha256 32; + 1028 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 + 0x559bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + sha256-mgf sha256 32; + 1029 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 + 0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + sha256-mgf sha256 32; + 1030 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 + 0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + sha256-mgf sha256 32; + 1031 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 + 0x2d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + sha256-mgf sha256 32; + 1032 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 + 0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + sha256-mgf sha256 32; + + 2048 "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884" 0 + 0x106373ce481fe7e268a5a66f8b281e17719e23e1fa5f9d6bdfb2da5451a3fe7afab07969d8acdb904c723830280f78124717e87edf05a58626e191281b9c82edeceb02d1fc8dfab7d3e941ef3a13ea27ea51609e47dd727a784f66dc189fb8527093060ee5f982f7072e3f8a5fac4edcadd9ff107d6c8a99e9b52680a046b6f984c323afbb194e94bf2ab014804e791af59b254c164ef24af7c726b314a127febc4d026c700cbe08076d4e63be94581f6b353adbd3c754864d314f0039b3c7cae177c8be11a426358d523a1f0c97a0626aa9d565751229d488d96e168e7305cdc3d256401e6b865c246d686f0d8a673603038c464a60753dcd2b0f2a552514bc + sha256-mgf sha256 32; +} + +pssvrf-pad { + # nbits sig msg rc result mgf hash saltsz + 256 + 0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc + "a9993e364706816aba3e25717850c26c9cd0d89d" 0 "" sha-mgf sha 10; + 256 + 0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc + "a9993e364706816aba3e25717850c26c9cd0d89e" -1 "" sha-mgf sha 10; + 256 + 0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bd + "a9993e364706816aba3e25717850c26c9cd0d89d" -1 "" sha-mgf sha 10; + 256 + 0x3526a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc + "a9993e364706816aba3e25717850c26c9cd0d89d" -1 "" sha-mgf sha 10; + + 1024 + 0x2d22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc + "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0 "" + sha-mgf sha 20; + 1025 + 0xad22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc + "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0 "" + sha-mgf sha 20; + 1024 + 0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" + sha256-mgf sha256 32; + 1025 + 0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" + sha256-mgf sha256 32; + 1026 + 0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" + sha256-mgf sha256 32; + 1027 + 0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" + sha256-mgf sha256 32; + 1028 + 0x559bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" + sha256-mgf sha256 32; + 1029 + 0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" + sha256-mgf sha256 32; + 1030 + 0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" + sha256-mgf sha256 32; + 1031 + 0x2d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" + sha256-mgf sha256 32; + 1032 + 0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc + "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" + sha256-mgf sha256 32; + + 768 + 0x3314e642649adf696651f34108408fab0e770a617a3f7d44d981add5ca88841dc57d531bb885075f150b93e96f6e7580e18b98e1ece12826bbfe4d92dec1bc05c2e95ea362e08dd4cbf162b4abff6a9ed26b822d986ec32bdd698d162262abbc + "2923be84e16cd6ae529049f1f1bbe9ebb3a6db3c" 0 "" + sha-mgf sha 20; + 1024 + 0x29d14565cf1ad3966ad25ff10aa825c2adeb31cc431a9a388ee53afef2ea2bc3c40b54523fd6bec5d7eabbea2b969e25d1bd62086834ccc48f256d876a4065214ac4343dfba87091563921299adee851e9d0dfba8db14ae6972cc8ce569f32c01db77d291279a82c30220faa16d83b1740cb535aa7f594905d7c91122f67ffbc + "1cdbae32209a50ee407836fd124932f69e7d49dc" 0 "" + sha-mgf sha 20; + 768 + 0x1de4193d961d4c2f5737656c910d9d5262b09d463a0b8c7c426f92f91ea8db83be870d68ab125af488bef0596b15fb2416b2836c08bc6af31ee3c215c817c9c17ee84d813dc712676c86d4c41e69074eb1646fdc80c8a59e4bad819af27104bc + "b2eac9cc53bf67d6bf14d67e2ddc8e6683ef574961ff698f61cdd11e9d9c1672" 0 "" + sha256-mgf sha256 32; + 1024 + 0xb9317ad66af4a49e3d2e987c340e776ed3b7496d311813fd6374e743fd5156630453541fc82733b4c0fd44a869e8c541ede9692ea6deb7cd52dbb4fb66b0f5a9a07e84e886ee5520faadf4fc7d646f1987bf19ad3d669dd9df57eec3de510148a6d349b8626c20ffb6d95f09c0af54b276626da745502e9c2bb5496e1a29bc + "0515073b33821f187092da6454ceb1853e6915f8466a0496730ed9162f6768d4" 0 "" + sha256-mgf sha256 32; + 1025 + 0x0a9228b191158744e277bd223ada3c227429e5d64884007a748d74abca2d55358c1bb21cdf2666589ffd6cdfd458c877620009ebace86e7fc88c6d0acb99e5432f1af5705908e332e1a071e3700f0a0310b531589e79fd40922f0780b239cdd489816be7fdee9f6353f7f9f182abf873eb32e83586011fce20ae957bc66728bc + "a90b87978c2ff1151d9a95c19be1c07ee9a89aa786c2b554bf9ae7d923d15590" 0 "" + sha256-mgf sha256 32; + 1026 + 0x016ecc969a03557d5fb257119251316ec4d8630d66bd6c18e93bc5c69a3a1d68431cd298f92db41a5f017874f05054224da5d75c012855febdf801c77145c8067c714c5c218f555b1e335a73f3ca6228a9723fa074173c7941200526c3a8ad81bb25427c84bdf82052021590cb5fd6aa44d052734b9112d1063276995572300ebc + "cbc2033f4107840f1405651b2861c9c5e72c8e463608dcf3a88dfebef2eb71ff" 0 "" + sha256-mgf sha256 32; + 1027 + 0x031a071405323cf4ef20cc186ca5edc492fa2a7158565275d1d7cce302dcb10853625822b6887ab61c0713c332eb188b708690dee268ecc1e8b07f34106a1437246034347340bb65f39d8f002fe6ad5d826cce3c44d121924ba2a2fe265200523940b2f60918202839190fd4c50960be706863daf99b34cf7a152f720cbd9a2bbc + "6653330bcba1105e4cec034c73e605b4310eaaadcfd5b0ca27ffd89d144df479" 0 "" + sha256-mgf sha256 32; + 1028 + 0x032e267380b21f98eb301bfd28c95af795a29864dfd801146c6878d9755669a6a8ef0090c574d5e7b716e4bf32128787db838c1df23fa418406e124fe4c031e706e31e27982810561d0c77d391b7718a2dd12b583987fe1c3c07436d457e039c3f4a6bbc2b6e765670762138ec2f22c3b1ce84ff422c08479f90abeb39986abdbc + "d5cfd3a195ce5abe65272af607ada1be65a6b4c9c0693234092c4d018f1756c6" 0 "" + sha256-mgf sha256 32; + 1029 + 0x034a4f060407d55bea14998785fef3dc09240b2145350d7aaa8e7b0114ba531209e8a5d9cfa1f8c364f21a94d302968a0ba7905ac188da019da0b68c27e42bf513bde915eaf96a91f300a32bbd723cdf66510f1ecb964ed807679dacf7ada3903e7234167bd3dc49e8b59749a396dcdc3f06d3751d0b58216d1ea3760fface17bc + "608f6e3c7bf45b628a8a8f275cf7e5874a3b329b614084c6c3b1a7304a10ee75" 0 "" + sha256-mgf sha256 32; + 1030 + 0x0aab7297cc92ae458f1d4d3b275eab7b2c65af1a7ab4fde8f5ff78b21474751b3b245f9b32b3c7d22ca677ccc882957cfdf3583372a8038918c27e9efd9743e6673d935ade4d3a4c3029c81c56d9a900e3f403de752d816d2e224621db32baf716b7625598aae00a336df65970076a2421e82925b9496b45e889f3b91ff5c100bc + "0d2bb614ecbbb82f73e2517e7d1dd884d31f01be506b16d6432183191518982b" 0 "" + sha256-mgf sha256 32; + 1031 + 0x0a1a81c6c71b542db6ce4aac600e96d5280f31dc6d91d201a0a83f3c2fb9a1baebf0d77b5aadd2358de635eca6f802a3adfe33c4e32e321276e102bb74dbb23aafcd8ca3806abd496a55c88223478a21ce0ee9946b93d0f94dcff307f0f33e41b3ab282016b7cda40bd8a3b1a909fb9396afff909f9bb6e44a3d70240e9ec9eabc + "f25b81a07f5ccb1d36e949740255d2ac1a0bf7a92623405ba333b9358868ade1" 0 "" + sha256-mgf sha256 32; + +# This one's WRONG! +# 1024 +# 0x696c23c434d74b91841724d0cca8318938551593969a8c31468377335252f2e18cbc11902b09ea494297ac729872b459d852018bc0634e95f9a1e80f09b55b321a1cc3b5f5f8c66a6bc91f42f154c6b4406606f3e9dda02eefe343cd80436a09e013a6e6b1190d222279e6f790223c315f367f3a212ff6f1c838c728c7fafabc +# "29d7a859cc0dea26ed554e8084d92bf837b8edd57aa05c4efa9f21fc3c36858e81b07dbfeeb1e485e912078bc6ec66e2" 0 "" +# sha384-mgf sha384 48; + + 2048 + 0x7a14b3a1fbf3371d6a607e3a401b43937f77d1f0960f0caee52c3a962d097cbcf7659ee7a26d7da421bfdf650c02a275f7c839eccdb77eb8bd73e807f251a9b8dcf6c7bbde426e1cd2b05f5e0ca53d4a2e7487f56bde022384d581208489a835b0e4f23aa713497d7ad0b1ba3a0d3fdf1798e40f5add1ab96c1ca17006138941b87fa1bc7bdb93c49befa6e2e4cdf6a144e55525d14f995ebbc452f8dd31ee07ddee8935454e5d484132e3799978eeb15f66444e342e425ca456c4ed13e3504e1dfef8d29de9086e027958a0ab7975f642f8d061c94b379b2ddf8b5f5540f2c94a9f50ce509d9bc7f21c8e5cbca7c783c78b2a8235f4ec536b129e6f105d3bbc + "a744b33e02b80487b63022dde456dd617b6e3d8c5ce7c467bc2ff2ffc9cc0f1390a924111ead4b41e592283f62f5b8aefda9492b3151ca80ec2e451a3935aabe" 0 "" + sha512-mgf sha512 64; + + 2048 + 0x106373ce481fe7e268a5a66f8b281e17719e23e1fa5f9d6bdfb2da5451a3fe7afab07969d8acdb904c723830280f78124717e87edf05a58626e191281b9c82edeceb02d1fc8dfab7d3e941ef3a13ea27ea51609e47dd727a784f66dc189fb8527093060ee5f982f7072e3f8a5fac4edcadd9ff107d6c8a99e9b52680a046b6f984c323afbb194e94bf2ab014804e791af59b254c164ef24af7c726b314a127febc4d026c700cbe08076d4e63be94581f6b353adbd3c754864d314f0039b3c7cae177c8be11a426358d523a1f0c97a0626aa9d565751229d488d96e168e7305cdc3d256401e6b865c246d686f0d8a673603038c464a60753dcd2b0f2a552514bc + "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884" 0 "" + sha256-mgf sha256 32; +} + +psssig-priv { + # n e d msg rc sig mgf hash saltsz + 0x6af87c8c97ae0c7668bc361ff1c358198309c80cd8a74a6d9d9cc846ea63ede9 + 0x10001 + 0x30ec4a0a5854d733a5ddc3e3584469f0a7d4b1f0cb38b8cfb04483c68b77a01 + "a9993e364706816aba3e25717850c26c9cd0d89d" 0 + 0x2b484543397da31ca7aaf774c4b19acd69eb8bc230b6d98a2ae10798793bd53f + sha-mgf sha 10; + + 0x560e64d28a2352ab7930aeb78fede05837b4fb868f0e6920d3108bcd57c8fe019d20d5df7ccc1ba15b5b0f850282739f3c76f0f592e2120573551c0146c3cd6d165cfd3bedfdc131bed468f0b36a7f07d47caf5ec83c0790354fba9f5027394618fa1a342b752a028addc86765061ca680d748190befe34d0f4032ad5639b148d033c3b3914f0b4ef9a1a7e167bdfe22a7954a8542286f562c226c393d48a91a1b7843831f8133e7214d65a5874954ecd8b10002dfe9847f5e8061cfb77d2b5defc6ce63d553aa79d1fe75e90fab2fdb78f55d8348063717a6335367d8316070a44847a49ba53be57f44bc6d6108aecbe0efbf81a2b51cbe98407166d89e89a9 + 0x10001 + 0x27f0e74fa6a8ad5a83d59a09fd85f10dd0d131baaad40bec1dba3cc0d24129cf72efc60443e671de8ac9b162d11eddee26c0a7a6bb052d4b155407baf9eeaffe351674bc6781d2b4b576ddbbf5f1f4429c974047f4149488148e4c365c1bd063ddfcdac3a2f5eec91e4dc091689c95189c8d0edbfd23da722e25643ffa58ad94ec06f6ab21fc8805b09066ffe3849e2d5536cf8a7385e62526989605c9fefbd9092ddb51bd887ee71cababab3a150b34d7de54d01c19987438bef4672208418e51bf49cdbe1825f16e2764c58aab339afbb4f673914646d2a191fec4f7a503e512841a2cccdc8852c0f348b8aedea3123747d20c3c580c38b438ef5fde3608bf + "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884" + 0 + 0x35fcbf7c5a69bd892dbf2ee88e53e40fe58ecddb4cf7c8885b228bfa9c24730ac554e20c65d82fc98d67a7805343450b1712a5f8c5ed6970c4310e06f65a9758d33e1c9dedec7178507da977a5ab76635d9f824b136abb855210caf851700bb57eb3aef7de61b217ae79ee4d6ad7c1a94279d9f8a425e06a0e4024d4c5b709ce1af6d09a26ce346f0a7eb36675fdbe1367f3d040ab7e18235b8090f91c355ee07425e3f4adf302e741be55959ac0f31075ccf1beef20e2f90693a82a30a48969c5ef32bc779ce84961b6a8d3ae0228cc520e2c644067bae96f14d90ceda2c8d00c97de3895d434a001d3cca244777fba4e0f5b5ed01c103842652c6402d2525b + sha256-mgf sha256 32; +} + +pssvrf-pub { + # n e sig msg rc result mgf hash saltsz + 0x6af87c8c97ae0c7668bc361ff1c358198309c80cd8a74a6d9d9cc846ea63ede9 + 0x10001 + 0x2b484543397da31ca7aaf774c4b19acd69eb8bc230b6d98a2ae10798793bd53f + "a9993e364706816aba3e25717850c26c9cd0d89d" 0 "" sha-mgf sha 10; + + 0x560e64d28a2352ab7930aeb78fede05837b4fb868f0e6920d3108bcd57c8fe019d20d5df7ccc1ba15b5b0f850282739f3c76f0f592e2120573551c0146c3cd6d165cfd3bedfdc131bed468f0b36a7f07d47caf5ec83c0790354fba9f5027394618fa1a342b752a028addc86765061ca680d748190befe34d0f4032ad5639b148d033c3b3914f0b4ef9a1a7e167bdfe22a7954a8542286f562c226c393d48a91a1b7843831f8133e7214d65a5874954ecd8b10002dfe9847f5e8061cfb77d2b5defc6ce63d553aa79d1fe75e90fab2fdb78f55d8348063717a6335367d8316070a44847a49ba53be57f44bc6d6108aecbe0efbf81a2b51cbe98407166d89e89a9 + 0x10001 + 0x35fcbf7c5a69bd892dbf2ee88e53e40fe58ecddb4cf7c8885b228bfa9c24730ac554e20c65d82fc98d67a7805343450b1712a5f8c5ed6970c4310e06f65a9758d33e1c9dedec7178507da977a5ab76635d9f824b136abb855210caf851700bb57eb3aef7de61b217ae79ee4d6ad7c1a94279d9f8a425e06a0e4024d4c5b709ce1af6d09a26ce346f0a7eb36675fdbe1367f3d040ab7e18235b8090f91c355ee07425e3f4adf302e741be55959ac0f31075ccf1beef20e2f90693a82a30a48969c5ef32bc779ce84961b6a8d3ae0228cc520e2c644067bae96f14d90ceda2c8d00c97de3895d434a001d3cca244777fba4e0f5b5ed01c103842652c6402d2525b + "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884" + 0 "" + sha256-mgf sha256 32; +} diff --git a/qdparse.c b/qdparse.c deleted file mode 100644 index 9615bb5..0000000 --- a/qdparse.c +++ /dev/null @@ -1,143 +0,0 @@ -/* -*-c-*- - * - * $Id: qdparse.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Quick-and-dirty parser - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include "qdparse.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @qd_skipspc@ --- * - * - * Arguments: @qd_parse *qd@ = context - * - * Returns: --- - * - * Use: Skips spaces in the string. No errors. - */ - -void qd_skipspc(qd_parse *qd) -{ - while (isspace((unsigned char)*qd->p)) - qd->p++; -} - -/* --- @qd_delim@ --- * - * - * Arguments: @qd_parse *qd@ = context - * @int ch@ = character to compare with - * - * Returns: Nonzero if it was, zero if it wasn't. - * - * Use: Checks the next (non-whitespace) character is what we - * expect. If it is, the character is eaten; otherwise it's no - * big deal. - */ - -int qd_delim(qd_parse *qd, int ch) -{ - qd_skipspc(qd); - if (*qd->p != ch) - return (0); - qd->p++; - return (1); -} - -/* --- @qd_enum@ --- * - * - * Arguments: @qd_parse *qd@ = context - * @const char *e@ = list of enum strings, space separated - * - * Returns: Index of the string matched, or @-1@. - * - * Use: Matches a keyword. - */ - -int qd_enum(qd_parse *qd, const char *e) -{ - size_t n; - int i = 0; - - qd_skipspc(qd); - for (;;) { - e += strspn(e, ", "); - if (!*e) break; - n = strcspn(e, ", "); - if (strncmp(qd->p, e, n) == 0 && !isalnum((unsigned char)qd->p[n])) { - qd->p += n; - return (i); - } - i++; e += n; - } - qd->e = "unrecognized keyword"; - return (-1); -} - -/* --- @qd_getmp@ --- * - * - * Arguments: @qd_parse *qd@ = context - * - * Returns: The integer extracted, or null. - * - * Use: Parses a multiprecision integer from a string. - */ - -mp *qd_getmp(qd_parse *qd) -{ - char *q; - mp *m; - - qd_skipspc(qd); - m = mp_readstring(MP_NEW, qd->p, &q, 0); - if (m && !isalnum((unsigned char)*q)) - qd->p = q; - else { - mp_drop(m); - qd->e = "bad number"; - } - return (m); -} - -/* --- @qd_eofp@ --- * - * - * Arguments: @qd_parse *qd@ = context - * - * Returns: Nonzero if at EOF, zero otherwise. - */ - -int qd_eofp(qd_parse *qd) -{ - qd_skipspc(qd); - return (!*qd->p); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/qdparse.h b/qdparse.h deleted file mode 100644 index f6696e4..0000000 --- a/qdparse.h +++ /dev/null @@ -1,115 +0,0 @@ -/* -*-c-*- - * - * $Id: qdparse.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Quick-and-dirty parser - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_QDPARSE_H -#define CATACOMB_QDPARSE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct qd_parse { - const char *p; /* Where we are right now */ - const char *e; /* Error string (output) */ -} qd_parse; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @qd_skipspc@ --- * - * - * Arguments: @qd_parse *qd@ = context - * - * Returns: --- - * - * Use: Skips spaces in the string. No errors. - */ - -extern void qd_skipspc(qd_parse */*qd*/); - -/* --- @qd_delim@ --- * - * - * Arguments: @qd_parse *qd@ = context - * @int ch@ = character to compare with - * - * Returns: Nonzero if it was, zero if it wasn't. - * - * Use: Checks the next (non-whitespace) character is what we - * expect. If it is, the character is eaten; otherwise it's no - * big deal. - */ - -extern int qd_delim(qd_parse */*qd*/, int /*ch*/); - -/* --- @qd_enum@ --- * - * - * Arguments: @qd_parse *qd@ = context - * @const char *e@ = list of enum strings, space separated - * - * Returns: Index of the string matched, or @-1@. - * - * Use: Matches a keyword. - */ - -extern int qd_enum(qd_parse */*qd*/, const char */*e*/); - -/* --- @qd_getmp@ --- * - * - * Arguments: @qd_parse *qd@ = context - * - * Returns: The integer extracted, or null. - * - * Use: Parses a multiprecision integer from a string. - */ - -extern mp *qd_getmp(qd_parse */*qd*/); - -/* --- @qd_eofp@ --- * - * - * Arguments: @qd_parse *qd@ = context - * - * Returns: Nonzero if at EOF, zero otherwise. - */ - -extern int qd_eofp(qd_parse */*qd*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rabin.c b/rabin.c deleted file mode 100644 index 1b1130b..0000000 --- a/rabin.c +++ /dev/null @@ -1,199 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Miller-Rabin primality test - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpbarrett.h" -#include "mpmont.h" -#include "pgen.h" -#include "rabin.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rabin_create@ --- * - * - * Arguments: @rabin *r@ = pointer to Rabin-Miller context - * @mp *m@ = pointer to number to test - * - * Returns: Zero on success, nonzero on failure. - * - * Use: Precomputes some useful values for performing the - * Miller-Rabin probabilistic primality test. - */ - -int rabin_create(rabin *r, mp *m) -{ - mp *m1 = mp_sub(MP_NEW, m, MP_ONE); - if (mpmont_create(&r->mm, m)) { - MP_DROP(m1); - return (-1); - } - r->r = mp_odd(MP_NEW, m1, &r->s); - r->m1 = mp_sub(MP_NEW, m, r->mm.r); - mp_drop(m1); - return (0); -} - -/* --- @rabin_destroy@ --- * - * - * Arguments: @rabin *r@ = pointer to Rabin-Miller context - * - * Returns: --- - * - * Use: Disposes of a Rabin-Miller context when it's no longer - * needed. - */ - -void rabin_destroy(rabin *r) -{ - mp_drop(r->r); - mp_drop(r->m1); - mpmont_destroy(&r->mm); -} - -/* --- @rabin_test@, @rabin_rtest@ --- * - * - * Arguments: @rabin *r@ = pointer to Rabin-Miller context - * @mp *g@ = base to test the number against - * - * Returns: Either @PGEN_FAIL@ if the test failed, or @PGEN_PASS@ - * if it succeeded. - * - * Use: Performs a single iteration of the Rabin-Miller primality - * test. The @rtest@ variant assumes that %$g$% is either - * already in Montgomery representation, or you don't care. - */ - -int rabin_rtest(rabin *r, mp *g) -{ - mp *y; - mp *dd, *spare = MP_NEW; - size_t j; - int rc = PGEN_FAIL; - - /* --- Calculate %$y R = g^r R \bmod m$% --- * - * - * If %$y = 1$% or %$y = m - 1$% then %$m$% is prime. If course, note that - * @y@ here has an extra factor of %$R$%. - */ - - y = mpmont_expr(&r->mm, MP_NEW, g, r->r); - if (MP_EQ(y, r->mm.r) || MP_EQ(y, r->m1)) { - rc = PGEN_PASS; - goto done; - } - - /* --- Now for the main loop --- * - * - * If %$y^{2^j} \ne m - 1$% for any %$0 \le j < s$% then %$m$% is - * composite. Of course, %$j = 0$% has already been tested. - */ - - for (j = 1; j < r->s; j++) { - dd = mp_sqr(spare, y); - dd = mpmont_reduce(&r->mm, dd, dd); - spare = y; y = dd; - if (MP_EQ(y, r->mm.r)) - break; - if (MP_EQ(y, r->m1)) { - rc = PGEN_PASS; - break; - } - } - - /* --- Done --- */ - -done: - if (spare != MP_NEW) - MP_DROP(spare); - MP_DROP(y); - return (rc); -} - -int rabin_test(rabin *r, mp *g) -{ - int rc; - g = mpmont_mul(&r->mm, MP_NEW, g, r->mm.r2); - rc = rabin_rtest(r, g); - mp_drop(g); - return (rc); -} - -/* --- @rabin_iters@ --- * - * - * Arguments: @unsigned len@ = number of bits in value - * - * Returns: Number of iterations recommended. - * - * Use: Returns the recommended number of iterations to ensure that a - * number with @len@ bits is really prime. - */ - -int rabin_iters(unsigned len) -{ - static const struct { - unsigned b; - int i; - } *p, *q, tab[] = { - { 100, 27 }, - { 150, 18 }, - { 200, 15 }, - { 250, 12 }, - { 300, 9 }, - { 350, 8 }, - { 400, 7 }, - { 450, 6 }, - { 550, 5 }, - { 650, 4 }, - { 850, 3 }, - { 1300, 2 } - }; - - unsigned i; - - /* --- Binary search through the table --- */ - - p = tab; - q = tab + (sizeof(tab)/sizeof(tab[0])); - for (;;) { - i = (q - p) / 2; - if (!i) - break; - if (len >= p[i].b && len < p[i + 1].b) - break; - if (len > p[i].b) - p = p + i; - else - q = p + i; - } - return (p[i].i); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rabin.h b/rabin.h deleted file mode 100644 index a491625..0000000 --- a/rabin.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Miller-Rabin primality test - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_RABIN_H -#define CATACOMB_RABIN_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_MPMONT_H -# include "mpmont.h" -#endif - -#ifndef CATACOMB_PFILT_H -# include "pfilt.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct rabin { - mpmont mm; /* Montgomery arithmetic context */ - size_t s; /* %$m = 2^s r + 1$% */ - mp *r; /* %$m = 2^s r + 1$% */ - mp *m1; /* %$(m - 1)R \bmod m$% */ -} rabin; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @rabin_create@ --- * - * - * Arguments: @rabin *r@ = pointer to Rabin-Miller context - * @mp *m@ = pointer to number to test - * - * Returns: Zero on success, nonzero for failure. - * - * Use: Precomputes some useful values for performing the - * Miller-Rabin probabilistic primality test. - */ - -extern int rabin_create(rabin */*r*/, mp */*m*/); - -/* --- @rabin_destroy@ --- * - * - * Arguments: @rabin *r@ = pointer to Rabin-Miller context - * - * Returns: --- - * - * Use: Disposes of a Rabin-Miller context when it's no longer - * needed. - */ - -extern void rabin_destroy(rabin */*r*/); - -/* --- @rabin_test@, @rabin_rtest@ --- * - * - * Arguments: @rabin *r@ = pointer to Rabin-Miller context - * @mp *g@ = base to test the number against - * - * Returns: Either @PGEN_FAIL@ if the test failed, or @PGEN_PASS@ - * if it succeeded. - * - * Use: Performs a single iteration of the Rabin-Miller primality - * test. The @rtest@ variant assumes that %$g$% is either - * already in Montgomery representation, or you don't care. - */ - -extern int rabin_rtest(rabin */*r*/, mp */*g*/); -extern int rabin_test(rabin */*r*/, mp */*g*/); - -/* --- @rabin_iters@ --- * - * - * Arguments: @unsigned len@ = number of bits in value - * - * Returns: Number of iterations recommended. - * - * Use: Returns the recommended number of iterations to ensure that a - * number with @len@ bits is really prime. - */ - -extern int rabin_iters(unsigned /*len*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rand.c b/rand.c deleted file mode 100644 index b004b3f..0000000 --- a/rand.c +++ /dev/null @@ -1,586 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Secure random number generator - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include -#include - -#include "arena.h" -#include "blowfish-cbc.h" -#include "paranoia.h" -#include "rand.h" -#include "rmd160.h" -#include "rmd160-hmac.h" - -/*----- Static variables --------------------------------------------------*/ - -static const grand_ops gops; - -typedef struct gctx { - grand r; - rand_pool p; -} gctx; - -static gctx *pool = 0; /* Default random pool */ - -/*----- Macros ------------------------------------------------------------*/ - -#define RAND_RESOLVE(r) do { \ - if ((r) == RAND_GLOBAL) { \ - if (!pool) \ - pool = (gctx *)rand_create(); \ - (r) = &pool->p; \ - } \ -} while (0) - -#define TIMER(r) do { \ - if ((r)->s && (r)->s->timer) \ - (r)->s->timer(r); \ -} while (0) - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rand_init@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: --- - * - * Use: Initializes a randomness pool. The pool doesn't start out - * very random: that's your job to sort out. A good suggestion - * would be to attach an appropriate noise source and call - * @rand_seed@. - */ - -void rand_init(rand_pool *r) -{ - RAND_RESOLVE(r); - memset(r->pool, 0, sizeof(r->pool)); - memset(r->buf, 0, sizeof(r->buf)); - r->i = 0; - r->irot = 0; - r->ibits = r->obits = 0; - r->o = RAND_SECSZ; - r->s = 0; - rmd160_hmacinit(&r->k, 0, 0); - rand_gate(r); -} - -/* --- @rand_noisesrc@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @const rand_source *s@ = pointer to source definition - * - * Returns: --- - * - * Use: Sets a noise source for a randomness pool. When the pool's - * estimate of good random bits falls to zero, the @getnoise@ - * function is called, passing the pool handle as an argument. - * It is expected to increase the number of good bits by at - * least one, because it'll be called over and over again until - * there are enough bits to satisfy the caller. The @timer@ - * function is called frequently throughout the generator's - * operation. - */ - -void rand_noisesrc(rand_pool *r, const rand_source *s) -{ - RAND_RESOLVE(r); - r->s = s; -} - -/* --- @rand_seed@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @unsigned bits@ = number of bits to ensure - * - * Returns: --- - * - * Use: Ensures that there are at least @bits@ good bits of entropy - * in the pool. It is recommended that you call this after - * initializing a new pool. Requesting @bits > RAND_IBITS@ is - * doomed to failure (and is an error). - */ - -void rand_seed(rand_pool *r, unsigned bits) -{ - RAND_RESOLVE(r); - - assert(((void)"bits pointlessly large in rand_seed", bits <= RAND_IBITS)); - assert(((void)"no noise source in rand_seed", r->s)); - - while (r->ibits < bits) - r->s->getnoise(r); - rand_gate(r); -} - -/* --- @rand_key@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @const void *k@ = pointer to key data - * @size_t sz@ = size of key data - * - * Returns: --- - * - * Use: Sets the secret key for a randomness pool. The key is used - * when mixing in new random bits. - */ - -void rand_key(rand_pool *r, const void *k, size_t sz) -{ - RAND_RESOLVE(r); - rmd160_hmacinit(&r->k, k, sz); -} - -/* --- @rand_add@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @const void *p@ = pointer a buffer of data to add - * @size_t sz@ = size of the data buffer - * @unsigned goodbits@ = number of good bits estimated in buffer - * - * Returns: --- - * - * Use: Mixes the data in the buffer with the contents of the - * pool. The estimate of the number of good bits is added to - * the pool's own count. The mixing operation is not - * cryptographically strong. However, data in the input pool - * isn't output directly, only through the one-way gating - * operation, so that shouldn't matter. - */ - -void rand_add(rand_pool *r, const void *p, size_t sz, unsigned goodbits) -{ - const octet *c = p; - int i, rot; - -#if RAND_POOLSZ != 128 -# error Polynomial in rand_add is out of date. Fix it. -#endif - - RAND_RESOLVE(r); - - i = r->i; rot = r->irot; - - while (sz) { - octet o = *c++; - r->pool[i] ^= (ROL8(o, rot) ^ - r->pool[(i + 1) % RAND_POOLSZ] ^ - r->pool[(i + 2) % RAND_POOLSZ] ^ - r->pool[(i + 7) % RAND_POOLSZ]); - rot = (rot + 5) & 7; - i++; if (i >= RAND_POOLSZ) i -= RAND_POOLSZ; - sz--; - } - - r->i = i; - r->irot = rot; - r->ibits += goodbits; - if (r->ibits > RAND_IBITS) - r->ibits = RAND_IBITS; -} - -/* --- @rand_goodbits@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: Estimate of the number of good bits remaining in the pool. - */ - -unsigned rand_goodbits(rand_pool *r) -{ - RAND_RESOLVE(r); - return (r->ibits + r->obits); -} - -/* --- @rand_gate@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: --- - * - * Use: Mixes up the entire state of the generator in a nonreversible - * way. - */ - -void rand_gate(rand_pool *r) -{ - octet mac[RMD160_HASHSZ]; - - RAND_RESOLVE(r); - TIMER(r); - - /* --- Hash up all the data in the pool --- */ - - { - rmd160_macctx mc; - - rmd160_macinit(&mc, &r->k); - rmd160_machash(&mc, r->pool, sizeof(r->pool)); - rmd160_machash(&mc, r->buf, sizeof(r->buf)); - rmd160_macdone(&mc, mac); - BURN(mc); - } - - /* --- Now mangle all of the data based on the hash --- */ - - { - blowfish_cbcctx bc; - - blowfish_cbcinit(&bc, mac, sizeof(mac), 0); - blowfish_cbcencrypt(&bc, r->pool, r->pool, sizeof(r->pool)); - blowfish_cbcencrypt(&bc, r->buf, r->buf, sizeof(r->buf)); - BURN(bc); - } - - /* --- Reset the various state variables --- */ - - r->o = RAND_SECSZ; - r->obits += r->ibits; - if (r->obits > RAND_OBITS) { - r->ibits = r->obits - r->ibits; - r->obits = RAND_OBITS; - } else - r->ibits = 0; - TIMER(r); -} - -/* --- @rand_stretch@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: --- - * - * Use: Stretches the contents of the output buffer by transforming - * it in a nonreversible way. This doesn't add any entropy - * worth speaking about, but it works well enough when the - * caller doesn't care about that sort of thing. - */ - -void rand_stretch(rand_pool *r) -{ - octet mac[RMD160_HASHSZ]; - - RAND_RESOLVE(r); - TIMER(r); - - /* --- Hash up all the data in the buffer --- */ - - { - rmd160_macctx mc; - - rmd160_macinit(&mc, &r->k); - rmd160_machash(&mc, r->pool, sizeof(r->pool)); - rmd160_machash(&mc, r->buf, sizeof(r->buf)); - rmd160_macdone(&mc, mac); - BURN(mc); - } - - /* --- Now mangle the buffer based on that hash --- */ - - { - blowfish_cbcctx bc; - - blowfish_cbcinit(&bc, mac, sizeof(mac), 0); - blowfish_cbcencrypt(&bc, r->buf, r->buf, sizeof(r->buf)); - BURN(bc); - } - - /* --- Reset the various state variables --- */ - - r->o = RAND_SECSZ; - TIMER(r); -} - -/* --- @rand_get@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @void *p@ = pointer to output buffer - * @size_t sz@ = size of output buffer - * - * Returns: --- - * - * Use: Gets random data from the pool. The pool's contents can't be - * determined from the output of this function; nor can the - * output data be determined from a knowledge of the data input - * to the pool wihtout also having knowledge of the secret key. - * The good bits counter is decremented, although no special - * action is taken if it reaches zero. - */ - -void rand_get(rand_pool *r, void *p, size_t sz) -{ - octet *o = p; - - RAND_RESOLVE(r); - TIMER(r); - - if (!sz) - return; - for (;;) { - if (r->o + sz <= RAND_BUFSZ) { - memcpy(o, r->buf + r->o, sz); - r->o += sz; - break; - } else { - size_t chunk = RAND_BUFSZ - r->o; - if (chunk) { - memcpy(o, r->buf + r->o, chunk); - sz -= chunk; - o += chunk; - } - rand_stretch(r); - } - } - - if (r->obits > sz * 8) - r->obits -= sz * 8; - else - r->obits = 0; -} - -/* --- @rand_getgood@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @void *p@ = pointer to output buffer - * @size_t sz@ = size of output buffer - * - * Returns: --- - * - * Use: Gets random data from the pool, ensuring that there are - * enough good bits. This interface isn't recommended: it makes - * the generator slow, and doesn't provide much more security - * than @rand_get@, assuming you've previously done a - * @rand_seed@. - */ - -void rand_getgood(rand_pool *r, void *p, size_t sz) -{ - octet *o = p; - - RAND_RESOLVE(r); - - if (!sz) - return; - if (!r->s || !r->s->getnoise) { - rand_get(r, p, sz); - return; - } - TIMER(r); - - while (sz) { - size_t chunk = sz; - - if (chunk * 8 > r->obits) { - if (chunk * 8 > r->ibits + r->obits) - do r->s->getnoise(r); while (r->ibits + r->obits < 256); - rand_gate(r); - if (chunk * 8 > r->obits) - chunk = r->obits / 8; - } - - if (chunk + r->o > RAND_BUFSZ) - chunk = RAND_BUFSZ - r->o; - - memcpy(o, r->buf + r->o, chunk); - r->o += chunk; - r->obits -= chunk * 8; - o += chunk; - sz -= chunk; - } -} - -/*----- Generic random number generator interface -------------------------*/ - -#define GRESOLVE(g, r) do { \ - if (r != &rand_global) \ - g = (gctx *)r; \ - else { \ - if (!pool) \ - pool = (gctx *)rand_create(); \ - g = pool; \ - } \ -} while (0) - -static void gdestroy(grand *r) -{ - gctx *g; - GRESOLVE(g, r); - if (g != pool) { - BURN(*g); - S_DESTROY(g); - } -} - -static int gmisc(grand *r, unsigned op, ...) -{ - gctx *g; - va_list ap; - int rc = 0; - va_start(ap, op); - - GRESOLVE(g, r); - switch (op) { - case GRAND_CHECK: - switch (va_arg(ap, unsigned)) { - case GRAND_CHECK: - case GRAND_SEEDINT: - case GRAND_SEEDUINT32: - case GRAND_SEEDBLOCK: - case GRAND_SEEDRAND: - case RAND_GATE: - case RAND_STRETCH: - case RAND_KEY: - case RAND_NOISESRC: - case RAND_SEED: - case RAND_TIMER: - case RAND_GOODBITS: - case RAND_ADD: - rc = 1; - break; - default: - rc = 0; - break; - } - break; - case GRAND_SEEDINT: { - unsigned u = va_arg(ap, unsigned); - rand_add(&g->p, &u, sizeof(u), sizeof(u)); - } break; - case GRAND_SEEDUINT32: { - uint32 i = va_arg(ap, uint32); - rand_add(&g->p, &i, sizeof(i), 4); - } break; - case GRAND_SEEDBLOCK: { - const void *p = va_arg(ap, const void *); - size_t sz = va_arg(ap, size_t); - rand_add(&g->p, p, sz, sz); - } break; - case GRAND_SEEDRAND: { - grand *rr = va_arg(ap, grand *); - octet buf[16]; - rr->ops->fill(rr, buf, sizeof(buf)); - rand_add(&g->p, buf, sizeof(buf), 8); - } break; - case RAND_GATE: - rand_gate(&g->p); - break; - case RAND_STRETCH: - rand_stretch(&g->p); - break; - case RAND_KEY: { - const void *k = va_arg(ap, const void *); - size_t sz = va_arg(ap, size_t); - rand_key(&g->p, k, sz); - } break; - case RAND_NOISESRC: - rand_noisesrc(&g->p, va_arg(ap, const rand_source *)); - break; - case RAND_SEED: - rand_seed(&g->p, va_arg(ap, unsigned)); - break; - case RAND_TIMER: - TIMER(&g->p); - break; - case RAND_GOODBITS: - rc = rand_goodbits(&g->p); - break; - case RAND_ADD: { - const void *p = va_arg(ap, const void *); - size_t sz = va_arg(ap, size_t); - unsigned goodbits = va_arg(ap, unsigned); - rand_add(&g->p, p, sz, goodbits); - } break; - default: - GRAND_BADOP; - break; - } - - va_end(ap); - return (rc); -} - -static octet gbyte(grand *r) -{ - gctx *g; - octet o; - GRESOLVE(g, r); - rand_getgood(&g->p, &o, 1); - return (o); -} - -static uint32 gword(grand *r) -{ - gctx *g; - octet b[4]; - GRESOLVE(g, r); - rand_getgood(&g->p, &b, sizeof(b)); - return (LOAD32(b)); -} - -static void gfill(grand *r, void *p, size_t sz) -{ - gctx *g; - GRESOLVE(g, r); - rand_get(&g->p, p, sz); -} - -static const grand_ops gops = { - "rand", - GRAND_CRYPTO, 0, - gmisc, gdestroy, - gword, gbyte, gword, grand_range, gfill -}; - -grand rand_global = { &gops }; - -/* --- @rand_create@ --- * - * - * Arguments: --- - * - * Returns: Pointer to a generic generator. - * - * Use: Constructs a generic generator interface over a Catacomb - * entropy pool generator. - */ - -grand *rand_create(void) -{ - gctx *g = S_CREATE(gctx); - g->r.ops = &gops; - rand_init(&g->p); - return (&g->r); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rand.h b/rand.h deleted file mode 100644 index 5d542b8..0000000 --- a/rand.h +++ /dev/null @@ -1,315 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Secure random number generator - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the random number generator ------------------------------* - * - * The algorithm is one of the author's own devising. It may therefore be - * worth a certain amount of skepticism. However, I've thought about this - * method for over a year before actually considering it worth implementing. - * With a little bit of luck, it should have received some peer review by the - * time this code is actually properly released, and it'll be worth a bit - * more confidence. My earlier generator was very similar in structure to - * the Linux /dev/random device. This generator is intended to address - * concerns I expressed about the Linux generator in a Usenet article to - * sci.crypt. - * - * The generator is divided into two parts: an input pool and an output - * buffer. New random data is placed into the pool in the way described - * below, which is shamelessly stolen from the Linux /dev/random generator. - * The only interaction that the pool has on the output buffer is through the - * keyed `gating' operation, which mixes up and redistributes all of the - * generator's state in an irreversible manner. Random bytes, when - * requested, are extracted from the output buffer in a linear fashion. - * - * The input pool is best seen as being eight shift registers in parallel. - * Data is added to the pool one octet at a time. Each bit of a new octet is - * added to a different shift register, by adding it (mod 2) with other bits - * according to the coefficients of a primitive polynomial. Each new byte is - * rotated before being added into the pool, in a half-hearted attempt to - * protect against biases in the input data (e.g., top bits being clear on - * ASCII text). - * - * The gating operation takes a keyed hash of the entire generator state, - * uses it as the key for a symmetric cipher, and encrypts the state. The - * key is then discarded. The result is that every ouptut bit of the - * operation depends in a complex way on every input bit, but the operation - * cannot be reversed. - * - * As an added wrinkle, 160 bits of the output buffer are never actually - * output. They are used in the gating operation only, as an extra item that - * an adversary has to guess before predicting generator output. - */ - -#ifndef CATACOMB_RAND_H -#define CATACOMB_RAND_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -#ifndef CATACOMB_RMD160_HMAC_H -# include "rmd160-hmac.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define RAND_POOLSZ 128 /* Input pool size in bytes */ -#define RAND_BUFSZ 512 /* Output buffer size in bytes */ -#define RAND_SECSZ 20 /* Secret octets in output buffer */ - -#define RAND_IBITS (RAND_POOLSZ * 8) -#define RAND_OBITS (RAND_BUFSZ * 8) - -/*----- Data structures ---------------------------------------------------*/ - -/* --- A random number generator pool --- */ - -typedef struct rand_pool { - octet pool[RAND_POOLSZ]; /* Actual contents of the pool */ - unsigned i; /* Current index into pool */ - unsigned irot; /* Current rotation applied */ - unsigned ibits; /* Number of good bits in pool */ - octet buf[RAND_BUFSZ]; /* Random octet output buffer */ - unsigned o; /* Current index into buffer */ - unsigned obits; /* Number of good bits in buffer */ - rmd160_mackey k; /* Secret key for this pool */ - const struct rand_source *s; /* System-specific noise source */ -} rand_pool; - -#define RAND_GLOBAL ((rand_pool *)0) /* The global randomness pool */ - -/* --- A noise source --- */ - -typedef struct rand_source { - void (*getnoise)(rand_pool */*r*/); /* Acquire more noise */ - int (*timer)(rand_pool */*r*/); /* Get noise from current time */ -} rand_source; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @rand_init@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: --- - * - * Use: Initializes a randomness pool. The pool doesn't start out - * very random: that's your job to sort out. - */ - -extern void rand_init(rand_pool */*r*/); - -/* --- @rand_noisesrc@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @const rand_source *s@ = pointer to source definition - * - * Returns: --- - * - * Use: Sets a noise source for a randomness pool. When the pool's - * estimate of good random bits falls to zero, the @getnoise@ - * function is called, passing the pool handle as an argument. - * It is expected to increase the number of good bits by at - * least one, because it'll be called over and over again until - * there are enough bits to satisfy the caller. The @timer@ - * function is called frequently throughout the generator's - * operation. - */ - -extern void rand_noisesrc(rand_pool */*r*/, const rand_source */*s*/); - -/* --- @rand_seed@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @unsigned bits@ = number of bits to ensure - * - * Returns: --- - * - * Use: Ensures that there are at least @bits@ good bits of entropy - * in the pool. It is recommended that you call this after - * initializing a new pool. Requesting @bits > RAND_IBITS@ is - * doomed to failure (and is an error). - */ - -extern void rand_seed(rand_pool */*r*/, unsigned /*bits*/); - -/* --- @rand_key@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @const void *k@ = pointer to key data - * @size_t sz@ = size of key data - * - * Returns: --- - * - * Use: Sets the secret key for a randomness pool. The key is used - * when mixing in new random bits. - */ - -extern void rand_key(rand_pool */*r*/, const void */*k*/, size_t /*sz*/); - -/* --- @rand_add@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @const void *p@ = pointer a buffer of data to add - * @size_t sz@ = size of the data buffer - * @unsigned goodbits@ = number of good bits estimated in buffer - * - * Returns: --- - * - * Use: Mixes the data in the buffer with the contents of the - * pool. The estimate of the number of good bits is added to - * the pool's own count. The mixing operation is not - * cryptographically strong. However, data in the input pool - * isn't output directly, only through the one-way gating - * operation, so that shouldn't matter. - */ - -extern void rand_add(rand_pool */*r*/, - const void */*p*/, size_t /*sz*/, - unsigned /*goodbits*/); - -/* --- @rand_goodbits@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: Estimate of the number of good bits remaining in the pool. - */ - -extern unsigned rand_goodbits(rand_pool */*r*/); - -/* --- @rand_gate@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: --- - * - * Use: Mixes up the entire state of the generator in a nonreversible - * way. - */ - -extern void rand_gate(rand_pool */*r*/); - -/* --- @rand_stretch@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * - * Returns: --- - * - * Use: Stretches the contents of the output buffer by transforming - * it in a nonreversible way. This doesn't add any entropy - * worth speaking about, but it works well enough when the - * caller doesn't care about that sort of thing. - */ - -extern void rand_stretch(rand_pool */*r*/); - -/* --- @rand_get@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @void *p@ = pointer to output buffer - * @size_t sz@ = size of output buffer - * - * Returns: --- - * - * Use: Gets random data from the pool. The pool's contents can't be - * determined from the output of this function; nor can the - * output data be determined from a knowledge of the data input - * to the pool without also having knowledge of the secret key. - * The good bits counter is decremented, although no special - * action is taken if it reaches zero. - */ - -extern void rand_get(rand_pool */*r*/, void */*p*/, size_t /*sz*/); - -/* --- @rand_getgood@ --- * - * - * Arguments: @rand_pool *r@ = pointer to a randomness pool - * @void *p@ = pointer to output buffer - * @size_t sz@ = size of output buffer - * - * Returns: --- - * - * Use: Gets random data from the pool. The pool's contents can't be - * determined from the output of this function; nor can the - * output data be determined from a knowledge of the data input - * to the pool wihtout also having knowledge of the secret key. - * If a noise source is attached to the pool in question, it is - * called to replenish the supply of good bits in the pool; - * otherwise this call is equivalent to @rand_get@. - */ - -extern void rand_getgood(rand_pool */*r*/, void */*p*/, size_t /*sz*/); - -/*----- Generic random number generator interface -------------------------*/ - -/* --- Miscellaneous operations --- */ - -enum { - RAND_GATE = GRAND_SPECIFIC('R'), /* No args */ - RAND_STRETCH, /* No args */ - RAND_KEY, /* @const void *k, size_t sz@ */ - RAND_NOISESRC, /* @const rand_source *s@ */ - RAND_SEED, /* @unsigned bits@ */ - RAND_TIMER, /* No args */ - RAND_GOODBITS, /* No args */ - RAND_ADD /* @const void *p, size_t sz,@ - * @unsigned goodbits */ -}; - -/* --- Default random number generator --- */ - -extern grand rand_global; - -/* --- @rand_create@ --- * - * - * Arguments: --- - * - * Returns: Pointer to a generic generator. - * - * Use: Constructs a generic generator interface over a Catacomb - * entropy pool generator. - */ - -extern grand *rand_create(void); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rand/Makefile.am b/rand/Makefile.am new file mode 100644 index 0000000..3934131 --- /dev/null +++ b/rand/Makefile.am @@ -0,0 +1,83 @@ +### -*-makefile-*- +### +### Build script for random number generators +### +### (c) 2013 Straylight/Edgeware +### + +###----- Licensing notice --------------------------------------------------- +### +### This file is part of Catacomb. +### +### Catacomb is free software; you can redistribute it and/or modify +### it under the terms of the GNU Library General Public License as +### published by the Free Software Foundation; either version 2 of the +### License, or (at your option) any later version. +### +### Catacomb is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU Library General Public License for more details. +### +### You should have received a copy of the GNU Library General Public +### License along with Catacomb; if not, write to the Free +### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +### MA 02111-1307, USA. + +include $(top_srcdir)/vars.am + +noinst_LTLIBRARIES = librand.la +librand_la_SOURCES = + +TEST_LIBS = librand.la + +###-------------------------------------------------------------------------- +### Component files. + +## The FIPS186 generator used to generate DSA domain parameters. +pkginclude_HEADERS += dsarand.h +librand_la_SOURCES += dsarand.c + +## Knuth's lagged-Fibonacci generator. +pkginclude_HEADERS += fibrand.h +librand_la_SOURCES += fibrand.c + +## The FIPS 140--2 random number generator tests. +pkginclude_HEADERS += fipstest.h +librand_la_SOURCES += fipstest.c + +## Interface for generic random number sources. +pkginclude_HEADERS += grand.h +librand_la_SOURCES += grand.c + +## A simple linear-congruential generator. +pkginclude_HEADERS += lcrand.h +librand_la_SOURCES += lcrand.c +TESTS += lcrand.$t +EXTRA_DIST += t/lcrand + +## Maurer's universal statistical test. +pkginclude_HEADERS += maurer.h +librand_la_SOURCES += maurer.c + +## System-specific noise acquisition. +pkginclude_HEADERS += noise.h +librand_la_SOURCES += noise.c + +## Cryptographic laundering for true random data generation. +pkginclude_HEADERS += rand.h +librand_la_SOURCES += rand.c + +## The SSL v3 pseudorandom function. +pkginclude_HEADERS += sslprf.h +librand_la_SOURCES += sslprf.c +TESTS += sslprf.$t +EXTRA_DIST += t/sslprf + +## The TLS v1 pseudorandom function. +pkginclude_HEADERS += tlsprf.h +librand_la_SOURCES += tlsprf.c +TESTS += tlsprf.$t +EXTRA_DIST += t/tlsprf + +###----- That's all, folks -------------------------------------------------- diff --git a/rand/dsarand.c b/rand/dsarand.c new file mode 100644 index 0000000..9b18ab0 --- /dev/null +++ b/rand/dsarand.c @@ -0,0 +1,335 @@ +/* -*-c-*- + * + * Random number generator for DSA + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include +#include +#include + +#include "dsarand.h" +#include "grand.h" +#include "sha.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @STEP@ --- * + * + * Arguments: @dsarand *d@ = pointer to context + * + * Use: Increments the buffer by one, interpreting it as a big-endian + * integer. Carries outside the integer are discarded. + */ + +#define STEP(d) do { \ + dsarand *_d = (d); \ + octet *_p = _d->p; \ + octet *_q = _p + _d->sz; \ + unsigned _c = 1; \ + while (_c && _q > _p) { \ + _c += *--_q; \ + *_q = U8(_c); \ + _c >>= 8; \ + } \ +} while (0) + +/* --- @dsarand_init@ --- * + * + * Arguments: @dsarand *d@ = pointer to context + * @const void *p@ = pointer to seed buffer + * @size_t sz@ = size of the buffer + * + * Returns: --- + * + * Use: Initializes a DSA random number generator. + */ + +void dsarand_init(dsarand *d, const void *p, size_t sz) +{ + d->p = xmalloc(sz); + d->sz = sz; + d->passes = 1; + if (p) + memcpy(d->p, p, sz); +} + +/* --- @dsarand_reseed@ --- * + * + * Arguments: @dsarand *d@ = pointer to context + * @const void *p@ = pointer to seed buffer + * @size_t sz@ = size of the buffer + * + * Returns: --- + * + * Use: Initializes a DSA random number generator. + */ + +void dsarand_reseed(dsarand *d, const void *p, size_t sz) +{ + xfree(d->p); + d->p = xmalloc(sz); + d->sz = sz; + d->passes = 1; + if (p) + memcpy(d->p, p, sz); +} + +/* --- @dsarand_destroy@ --- * + * + * Arguments: @dsarand *d@ = pointer to context + * + * Returns: --- + * + * Use: Disposes of a DSA random number generation context. + */ + +void dsarand_destroy(dsarand *d) +{ + xfree(d->p); +} + +/* --- @dsarand_fill@ --- * + * + * Arguments: @dsarand *d@ = pointer to context + * @void *p@ = pointer to output buffer + * @size_t sz@ = size of output buffer + * + * Returns: --- + * + * Use: Fills an output buffer with pseudorandom data. + * + * Let %$p$% be the numerical value of the input buffer, and let + * %$b$% be the number of bytes required. Let + * %$z = \lceil b / 20 \rceil$% be the number of SHA outputs + * required. Then the output of pass %$n$% is + * + * %$P_n = \sum_{0 \le i < z} 2^{160i} SHA(p + nz + i)$% + * %${} \bmod 2^{8b}$% + * + * and the actual result in the output buffer is the XOR of all + * of the output passes. + * + * The DSA procedure for choosing @q@ involves two passes with + * %$z = 1$%; the procedure for choosing @p@ involves one pass + * with larger %$z$%. This generalization of the DSA generation + * procedure is my own invention but it seems relatively sound. + */ + +void dsarand_fill(dsarand *d, void *p, size_t sz) +{ + octet *q = p; + unsigned n = d->passes; + + /* --- Write out the first pass --- * + * + * This can write directly to the output buffer, so it's done differently + * from the latter passes. + */ + + { + size_t o = sz; + + while (o) { + sha_ctx h; + + /* --- Hash the input buffer --- */ + + sha_init(&h); + sha_hash(&h, d->p, d->sz); + + /* --- If enough space, extract the hash output directly --- */ + + if (o >= SHA_HASHSZ) { + o -= SHA_HASHSZ; + sha_done(&h, q + o); + } + + /* --- Otherwise take the hash result out of line and copy it --- */ + + else { + octet hash[SHA_HASHSZ]; + sha_done(&h, hash); + memcpy(q, hash + (SHA_HASHSZ - o), o); + o = 0; + } + + /* --- Step the input buffer --- */ + + STEP(d); + } + + /* --- Another pass has been done --- */ + + n--; + } + + /* --- Write out subsequent passes --- * + * + * The hash output has to be done offline, so this is slightly easier. + */ + + while (n) { + size_t o = sz; + + while (o) { + sha_ctx h; + octet hash[SHA_HASHSZ]; + size_t n; + octet *pp, *qq; + + /* --- Hash the input buffer --- */ + + sha_init(&h); + sha_hash(&h, d->p, d->sz); + sha_done(&h, hash); + + /* --- Work out how much output is wanted --- */ + + n = SHA_HASHSZ; + if (n > o) + n = o; + o -= n; + + /* --- XOR the data out --- */ + + for (pp = hash + (SHA_HASHSZ - n), qq = q + o; + pp < hash + SHA_HASHSZ; pp++, qq++) + *qq ^= *pp; + + /* --- Step the input buffer --- */ + + STEP(d); + } + + /* --- Another pass is done --- */ + + n--; + } +} + +/*----- Generic pseudorandom-number generator interface -------------------*/ + +static const grand_ops gops; + +typedef struct gctx { + grand r; + dsarand d; +} gctx; + +static void gdestroy(grand *r) +{ + gctx *g = (gctx *)r; + dsarand_destroy(&g->d); + DESTROY(g); +} + +static int gmisc(grand *r, unsigned op, ...) +{ + gctx *g = (gctx *)r; + va_list ap; + int rc = 0; + va_start(ap, op); + + switch (op) { + case GRAND_CHECK: + switch (va_arg(ap, unsigned)) { + case GRAND_CHECK: + case GRAND_SEEDBLOCK: + case GRAND_SEEDRAND: + case DSARAND_PASSES: + case DSARAND_SEEDSZ: + case DSARAND_GETSEED: + rc = 1; + break; + default: + rc = 0; + break; + } + break; + case GRAND_SEEDBLOCK: { + const void *p = va_arg(ap, const void *); + size_t sz = va_arg(ap, size_t); + dsarand_reseed(&g->d, p, sz); + } break; + case GRAND_SEEDRAND: { + grand *rr = va_arg(ap, grand *); + rr->ops->fill(rr, g->d.p, g->d.sz); + } break; + case DSARAND_PASSES: + g->d.passes = va_arg(ap, unsigned); + break; + case DSARAND_SEEDSZ: + rc = g->d.sz; + break; + case DSARAND_GETSEED: + memcpy(va_arg(ap, void *), g->d.p, g->d.sz); + break; + default: + GRAND_BADOP; + break; + } + + va_end(ap); + return (rc); +} + +static void gfill(grand *r, void *p, size_t sz) +{ + gctx *g = (gctx *)r; + dsarand_fill(&g->d, p, sz); +} + +static const grand_ops gops = { + "dsarand", + 0, 0, + gmisc, gdestroy, + grand_word, grand_byte, grand_word, grand_range, gfill +}; + +/* --- @dsarand_create@ --- * + * + * Arguments: @const void *p@ = pointer to seed buffer + * @size_t sz@ = size of seed buffer + * + * Returns: Pointer to a generic generator. + * + * Use: Constructs a generic generator interface over a Catacomb + * entropy pool generator. + */ + +grand *dsarand_create(const void *p, size_t sz) +{ + gctx *g = CREATE(gctx); + g->r.ops = &gops; + dsarand_init(&g->d, p, sz); + return (&g->r); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/rand/dsarand.h b/rand/dsarand.h new file mode 100644 index 0000000..04254aa --- /dev/null +++ b/rand/dsarand.h @@ -0,0 +1,151 @@ +/* -*-c-*- + * + * Random number generator for DSA + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_DSARAND_H +#define CATACOMB_DSARAND_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_SHA_H +# include "sha.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct dsarand { + octet *p; /* Pointer to seed (modified) */ + size_t sz; /* Size of the seed buffer */ + unsigned passes; /* Number of passes to make */ +} dsarand; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @dsarand_init@ --- * + * + * Arguments: @dsarand *d@ = pointer to context + * @const void *p@ = pointer to seed buffer + * @size_t sz@ = size of the buffer + * + * Returns: --- + * + * Use: Initializes a DSA random number generator. + */ + +extern void dsarand_init(dsarand */*d*/, const void */*p*/, size_t /*sz*/); + +/* --- @dsarand_reseed@ --- * + * + * Arguments: @dsarand *d@ = pointer to context + * @const void *p@ = pointer to seed buffer + * @size_t sz@ = size of the buffer + * + * Returns: --- + * + * Use: Initializes a DSA random number generator. + */ + +extern void dsarand_reseed(dsarand */*d*/, const void */*p*/, size_t /*sz*/); + +/* --- @dsarand_destroy@ --- * + * + * Arguments: @dsarand *d@ = pointer to context + * + * Returns: --- + * + * Use: Disposes of a DSA random number generation context. + */ + +extern void dsarand_destroy(dsarand */*d*/); + +/* --- @dsarand_fill@ --- * + * + * Arguments: @dsarand *d@ = pointer to context + * @void *p@ = pointer to output buffer + * @size_t sz@ = size of output buffer + * + * Returns: --- + * + * Use: Fills an output buffer with pseudorandom data. + * + * Let %$p$% be the numerical value of the input buffer, and let + * %$b$% be the number of bytes required. Let + * %$z = \lceil b / 20 \rceil$% be the number of SHA outputs + * required. Then the output of pass %$n$% is + * + * %$P_n = \sum_{0 \le i < z} 2^{160i} SHA(p + nz + i)$% + * %${} \bmod 2^{8b}$% + * + * and the actual result in the output buffer is the XOR of all + * of the output passes. + * + * The DSA procedure for choosing @q@ involves two passes with + * %$z = 1$%; the procedure for choosing @p@ involves one pass + * with larger %$z$%. This generalization of the DSA generation + * procedure is my own invention but it seems relatively sound. + */ + +extern void dsarand_fill(dsarand */*d*/, void */*p*/, size_t /*sz*/); + +/*----- Generic pseudorandom-number generator interface -------------------*/ + +/* --- Miscellaneous operations --- */ + +enum { + DSARAND_PASSES = GRAND_SPECIFIC('D'), /* @unsigned n@ */ + DSARAND_SEEDSZ, /* No args */ + DSARAND_GETSEED /* @void *buf@ */ +}; + +/* --- @dsarand_create@ --- * + * + * Arguments: @const void *p@ = pointer to seed buffer + * @size_t sz@ = size of seed buffer + * + * Returns: Pointer to a generic generator. + * + * Use: Constructs a generic generator interface to a DSA generator. + */ + +extern grand *dsarand_create(const void */*p*/, size_t /*sz*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/rand/fibrand.c b/rand/fibrand.c new file mode 100644 index 0000000..bc9afd8 --- /dev/null +++ b/rand/fibrand.c @@ -0,0 +1,247 @@ +/* -*-c-*- + * + * Fibonacci generator + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include +#include + +#include "fibrand.h" +#include "grand.h" +#include "lcrand.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @fibrand_step@ --- * + * + * Arguments: @fibrand *f@ = pointer to Fibonacci generator context + * + * Returns: Next output from generator. + * + * Use: Steps the generator. Returns + * %$x_{i - 24} + x_{i - 55} \bmod 2^{32}$%. + */ + +uint32 fibrand_step(fibrand *f) +{ + unsigned i = f->i; + unsigned j = i + (FIB_SZ - FIB_TAP); + uint32 x; + if (j >= FIB_SZ) + j -= FIB_SZ; + x = f->x[i] = U32(f->x[i] + f->x[j]); + i++; + if (i >= FIB_SZ) + i = 0; + f->i = i; + return (x); +} + +/* --- @fibrand_seed@ --- * + * + * Arguments: @fibrand *f@ = pointer to Fibonacci generator context + * @grand *r@ = random number generator to extract words from + * + * Returns: --- + * + * Use: Initializes a Fibonacci generator using word outputs from the + * given random number source @r@. + */ + +void fibrand_seed(fibrand *f, grand *r) +{ + int i; + unsigned p = 0; + + for (i = 0; i < FIB_SZ; i++) + p |= f->x[i] = r->ops->word(r); + if (!(p & 1)) { + i = r->ops->range(r, FIB_SZ); + f->x[i] |= 1; + } + f->i = 0; +} + +/* --- @fibrand_lcseed@ --- * + * + * Arguments: @fibrand *f@ = pointer to Fibonacci generator context + * @uint32 seed@ = seed value + * + * Returns: --- + * + * Use: Initializes a Fibonacci generator using outputs from the + * @lcrand@ generator seeded from @seed@. This is faster than + * using a generic @lcrand@-based generator and @fibrand_rseed@ + * because it uses raw outputs rather than uniformly distributed + * 32-bit words. + */ + +void fibrand_lcseed(fibrand *f, uint32 seed) +{ + int i; + unsigned p = 0; + + for (i = 0; i < FIB_SZ; i++) + p |= f->x[i] = seed = lcrand(seed); + if (!(p & 1)) { + i = lcrand_range(&seed, FIB_SZ); + f->x[i] |= 1; + } + f->i = 0; +} + +/* --- @fibrand_range@ --- * + * + * Arguments: @fibrand *f@ = pointer to Fibonacci generator context + * @uint32 m@ = limit + * + * Returns: A uniformly distributed pseudorandom integer in the interval + * %$[0, m)$%. + */ + +uint32 fibrand_range(fibrand *f, uint32 m) +{ + uint32 r = 0xffffffff - (0xffffffff % m); + uint32 x; + + /* --- Now generate numbers until a good one comes along --- */ + + do x = fibrand_step(f); while (x >= r); + return (x % m); +} + +/*----- Generic interface -------------------------------------------------*/ + +typedef struct gctx { + grand r; + fibrand f; +} gctx; + +static void gdestroy(grand *r) +{ + gctx *g = (gctx *)r; + DESTROY(g); +} + +static int gmisc(grand *r, unsigned op, ...) +{ + gctx *g = (gctx *)r; + va_list ap; + int rc = 0; + va_start(ap, op); + + switch (op) { + case GRAND_CHECK: + switch (va_arg(ap, unsigned)) { + case GRAND_CHECK: + case GRAND_SEEDINT: + case GRAND_SEEDUINT32: + case GRAND_SEEDRAND: + rc = 1; + break; + default: + rc = 0; + break; + } + break; + case GRAND_SEEDINT: + fibrand_lcseed(&g->f, va_arg(ap, unsigned)); + break; + case GRAND_SEEDUINT32: + fibrand_lcseed(&g->f, va_arg(ap, uint32)); + break; + case GRAND_SEEDRAND: + fibrand_seed(&g->f, va_arg(ap, grand *)); + break; + default: + GRAND_BADOP; + break; + } + + va_end(ap); + return (rc); +} + +static octet gbyte(grand *r) +{ + gctx *g = (gctx *)r; + return (U8(fibrand_step(&g->f))); +} + +static uint32 gword(grand *r) +{ + gctx *g = (gctx *)r; + return (fibrand_step(&g->f)); +} + +static uint32 grange(grand *r, uint32 l) +{ + gctx *g = (gctx *)r; + return (fibrand_range(&g->f, l)); +} + +static void gfill(grand *r, void *p, size_t sz) +{ + gctx *g = (gctx *)r; + octet *q = p; + while (sz) { + *q++ = U8(fibrand_step(&g->f)); + sz--; + } +} + +static const grand_ops gops = { + "fibrand", + 0, 0, + gmisc, gdestroy, + gword, gbyte, gword, grange, gfill +}; + +/* --- @fibrand_create@ --- * + * + * Arguments: @uint32 seed@ = initial seed + * + * Returns: Pointer to a generic generator. + * + * Use: Constructs a generic generator interface over a Fibonacci + * generator. The generator is seeded using @fibrand_lcseed@. + */ + +grand *fibrand_create(uint32 seed) +{ + gctx *g = CREATE(gctx); + g->r.ops = &gops; + fibrand_lcseed(&g->f, seed); + return (&g->r); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/rand/fibrand.h b/rand/fibrand.h new file mode 100644 index 0000000..bdef40b --- /dev/null +++ b/rand/fibrand.h @@ -0,0 +1,137 @@ +/* -*-c-*- + * + * Fibonacci generator + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the Fibonacci generator ----------------------------------* + * + * The generator was originally suggested by G. J. Mitchell and D. P. Moore + * in 1957, and publicized by D. E. Knuth as Algorithm 3.2.2A in volume 2 of + * his work `The Art of Computer Programming'. The generator is simple: at + * each stage it emits %$x_n = (x_{n - 55} + x_{n - 24}) \bmod 2^{32}$%. The + * period is proven to be greater than %$2^{55}$%, and statistical properties + * appear to be good. + */ + +#ifndef CATACOMB_FIBRAND_H +#define CATACOMB_FIBRAND_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +/*----- Magic constants ---------------------------------------------------*/ + +#define FIB_SZ 55 +#define FIB_TAP 24 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct fibrand { + unsigned i; + uint32 x[FIB_SZ]; +} fibrand; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @fibrand_step@ --- * + * + * Arguments: @fibrand *f@ = pointer to Fibonacci generator context + * + * Returns: Next output from generator. + * + * Use: Steps the generator. Returns + * %$x_{i - 24} + x_{i - 55} \bmod 2^{32}$%. + */ + +extern uint32 fibrand_step(fibrand */*f*/); + +/* --- @fibrand_seed@ --- * + * + * Arguments: @fibrand *f@ = pointer to Fibonacci generator context + * @grand *r@ = random number generator to extract words from + * + * Returns: --- + * + * Use: Initializes a Fibonacci generator using word outputs from the + * given random number source @r@. + */ + +extern void fibrand_seed(fibrand */*f*/, grand */*r*/); + +/* --- @fibrand_lcseed@ --- * + * + * Arguments: @fibrand *f@ = pointer to Fibonacci generator context + * @uint32 seed@ = seed value + * + * Returns: --- + * + * Use: Initializes a Fibonacci generator using outputs from the + * @lcrand@ generator seeded from @seed@. This is faster than + * using a generic @lcrand@-based generator and @fibrand_rseed@ + * because it uses raw outputs rather than uniformly distributed + * 32-bit words. + */ + +extern void fibrand_lcseed(fibrand */*f*/, uint32 /*seed*/); + +/* --- @fibrand_range@ --- * + * + * Arguments: @fibrand *f@ = pointer to Fibonacci generator context + * @uint32 m@ = limit + * + * Returns: A uniformly distributed pseudorandom integer in the interval + * %$[0, m)$%. + */ + +extern uint32 fibrand_range(fibrand */*f*/, uint32 /*m*/); + +/* --- @fibrand_create@ --- * + * + * Arguments: @uint32 seed@ = initial seed + * + * Returns: Pointer to a generic generator. + * + * Use: Constructs a generic generator interface over a Fibonacci + * generator. The generator is seeded using @fibrand_lcseed@. + */ + +extern grand *fibrand_create(uint32 /*seed*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/rand/fipstest.c b/rand/fipstest.c new file mode 100644 index 0000000..4bc9625 --- /dev/null +++ b/rand/fipstest.c @@ -0,0 +1,189 @@ +/* -*-c-*- + * + * FIPS140 randomness tests + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "fipstest.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @monobit@ --- * + * + * Arguments: @const octet *p@ = pointer to buffer + * + * Returns: Zero if OK, @FIPSTEST_MONOBIT@ on failure. + * + * Use: Performs the monobit test on a buffer of data. If %$n_1$% is + * the number of 1 bits in the buffer, then the monobit test is + * passed when %$9654 < n_1 < 10346$%. + */ + +static unsigned monobit(const octet *p) +{ + unsigned n1 = 0; + unsigned i, j; + + for (i = 0; i < FIPSTEST_BUFSZ; i++) { + octet x = p[i]; + for (j = 0; j < 8; j++) { + if (x & 1) + n1++; + x >>= 1; + } + } + + if (9725 >= n1 || n1 >= 10275) + return (FIPSTEST_MONOBIT); + return (0); +} + +/* --- @poker@ --- * + * + * Arguments: @const octet *p@ = pointer to buffer + * + * Returns: Zero if OK, @FIPSTEST_POKER@ on failure. + * + * Use: Performs the poker test on a buffer of data. The buffer is + * divided into 4-bit nibbles %$x_i$%. If + * %$f(x) = \sum_{x_i = x} 1$% is the frequency of each nibble, + * then the test is passed if + * %$2.16 < 16/5000 \sum_i f(i)^2 - 5000 < 46.17$%. + */ + +static unsigned poker(const octet *p) +{ + unsigned long f[16] = { 0 }; + unsigned i; + unsigned long q = 0; + + /* --- Compute the frequencies --- */ + + for (i = 0; i < FIPSTEST_BUFSZ; i++) { + octet x = p[i]; + f[x & 0xf]++; + f[(x >> 4) & 0xf]++; + } + + /* --- Now do the comparison --- * + * + * This can be simplified. Multiply through the inequality by 5000 and + * we get %$5150 < 16 \sum_i f(i)^2 - 5000^2 < 287000$%. + */ + + for (i = 0; i < 16; i++) + q += f[i] * f[i]; + q <<= 4; + q -= 5000ul * 5000ul; + + if (10800 >= q || q >= 230850) + return (FIPSTEST_POKER); + return (0); +} + +/* --- @runs@ --- * + * + * Arguments: @const octet *p@ = pointer to buffer + * + * Returns: Zero for success, @FIPSTEST_RUNS@ or @FIPSTEST_LONGRUNS@ on + * failure. + * + * Use: Performs the runs and long runs tests. The frequency of each + * `run', or sequence of equal bits, is counted and tested. + */ + +static unsigned runs(const octet *p) +{ + unsigned rc = 0; + unsigned i, j; + unsigned r = 0; + unsigned bb = 0; + unsigned f[2][6] = { { 0 } }; + + /* --- Count the run lengths --- */ + + for (i = 0; i < FIPSTEST_BUFSZ; i++) { + octet x = p[i]; + for (j = 0; j < 8; j++) { + unsigned b = x & 1; + x >>= 1; + if (b == bb) + r++; + else { + if (r) { + if (r >= 34) + rc |= FIPSTEST_LONGRUNS; + if (r > 6) + r = 6; + f[bb][r - 1]++; + } + r = 1; + bb = b; + } + } + } + + if (r >= 26) + rc |= FIPSTEST_LONGRUNS; + if (r > 6) + r = 6; + f[bb][r - 1]++; + + /* --- Check the results --- */ + + if (2343 > f[0][0] || f[0][0] > 2657 || 2343 > f[1][0] || f[1][0] > 2657 || + 1135 > f[0][1] || f[0][1] > 1365 || 1135 > f[1][1] || f[1][1] > 1365 || + 542 > f[0][2] || f[0][2] > 708 || 542 > f[1][2] || f[1][2] > 708 || + 251 > f[0][3] || f[0][3] > 373 || 251 > f[1][3] || f[1][3] > 373 || + 111 > f[0][4] || f[0][4] > 201 || 111 > f[1][4] || f[1][4] > 201 || + 111 > f[0][5] || f[0][5] > 201 || 111 > f[1][5] || f[1][5] > 201) + rc |= FIPSTEST_RUNS; + + return (rc); +} + +/* --- @fipstest@ --- * + * + * Arguments: @const octet *p@ = pointer to a buffer of @FIPSTEST_BUFSZ@ + * bytes + * + * Returns: Zero if OK, or a bitmask of failed tests. + * + * Use: Performs the FIPS140 randomness tests on a block of data. + */ + +unsigned fipstest(const octet *p) +{ + unsigned rc = 0; + rc |= monobit(p); + rc |= poker(p); + rc |= runs(p); + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/rand/fipstest.h b/rand/fipstest.h new file mode 100644 index 0000000..91facb2 --- /dev/null +++ b/rand/fipstest.h @@ -0,0 +1,69 @@ +/* -*-c-*- + * + * FIPS140 randomness tests + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_FIPSTEST_H +#define CATACOMB_FIPSTEST_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +/*----- Magic numbers -----------------------------------------------------*/ + +#define FIPSTEST_BUFSZ 2500 + +#define FIPSTEST_OK 0u +#define FIPSTEST_MONOBIT 1u +#define FIPSTEST_POKER 2u +#define FIPSTEST_RUNS 4u +#define FIPSTEST_LONGRUNS 8u + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @fipstest@ --- * + * + * Arguments: @const octet *p@ = pointer to a buffer of @FIPSTEST_BUFSZ@ + * bytes + * + * Returns: Zero if OK, or a bitmask of failed tests. + * + * Use: Performs the FIPS140 randomness tests on a block of data. + */ + +extern unsigned fipstest(const octet */*p*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/rand/grand.c b/rand/grand.c new file mode 100644 index 0000000..17d248b --- /dev/null +++ b/rand/grand.c @@ -0,0 +1,155 @@ +/* -*-c-*- + * + * Generic interface to random number generators + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#include "grand.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @grand_byte@ --- * + * + * Arguments: @grand *r@ = pointet to generic generator + * + * Returns: A uniformly-distributed pseudorandom integer in the interval + * %$[0, 256)$%. + */ + +octet grand_byte(grand *r) +{ + if (r->ops->byte != grand_byte) + return (r->ops->byte(r)); + else if (r->ops->word != grand_word) + return (r->ops->word(r) & 0xff); + else if (r->ops->fill != grand_fill) { + octet o; + r->ops->fill(r, &o, 1); + return (o); + } else + return (grand_range(r, 256)); +} + +/* --- @grand_word@ --- * + * + * Arguments: @grand *r@ = pointet to generic generator + * + * Returns: A uniformly-distributed pseudorandom integer in the interval + * %$[0, 2^{32})$%. + */ + +uint32 grand_word(grand *r) +{ + if (r->ops->word != grand_word) + return (r->ops->word(r)); + else { + octet b[4]; + grand_fill(r, b, sizeof(b)); + return (LOAD32(b)); + } +} + +/* --- @grand_range@ --- * + * + * Arguments: @grand *r@ = pointet to generic generator + * @uint32 l@ = limit for acceptable results + * + * Returns: A uniformly-distributed pseudorandom integer in the interval + * %$[0, l)$%. + */ + +uint32 grand_range(grand *r, uint32 l) +{ + if (r->ops->range != grand_range) + return (r->ops->range(r, l)); + else { + uint32 m, z; + uint32 (*w)(grand */*r*/); + uint32 x; + + /* --- Decide where to get data from --- * + * + * The choice of %$2^{32} - 1$% as a limit when using @grand_word@ isn't + * wonderful, but working with %$2^{32}$% is awkward and the loss of a + * few return values isn't significant. The algorithm below still + * successfully returns uniformly distributed results. + */ + + if (r->ops->max) { + w = r->ops->raw; + m = r->ops->max; + } else { + w = grand_word; + m = 0xffffffff; + } + + /* --- Work out maximum acceptable return value --- * + * + * This will be the highest multiple of @l@ less than @m@. + */ + + z = m - (m % l); + + /* --- Generate numbers until something acceptable is found --- * + * + * This will require an expected number of attempts less than 2. + */ + + do x = w(r); while (x >= z); + return (x % l); + } +} + +/* --- @grand_fill@ --- * + * + * Arguments: @grand *r@ = pointet to generic generator + * @void *p@ = pointer to a buffer + * @size_t sz@ = size of the buffer + * + * Returns: --- + * + * Use: Fills a buffer with uniformly distributed pseudorandom bytes + * (see @grand_byte@). + */ + +void grand_fill(grand *r, void *p, size_t sz) +{ + if (r->ops->fill != grand_fill) + r->ops->fill(r, p, sz); + else { + octet *q = p; + while (sz) { + *q++ = r->ops->byte(r); + sz--; + } + } +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/rand/grand.h b/rand/grand.h new file mode 100644 index 0000000..ec11404 --- /dev/null +++ b/rand/grand.h @@ -0,0 +1,161 @@ +/* -*-c-*- + * + * Generic interface to random number generators + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GRAND_H +#define CATACOMB_GRAND_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +/*----- Generic random number generator interface -------------------------*/ + +typedef struct grand { + const struct grand_ops *ops; +} grand; + +typedef struct grand_ops { + + /* --- Various important properties --- */ + + const char *name; /* Generator's name */ + unsigned f; /* Various flags */ + uint32 max; /* Maximum raw output */ + + /* --- Maintenance methods --- */ + + int (*misc)(grand */*r*/, unsigned /*op*/, ...); /* Miscellaneous ops */ + void (*destroy)(grand */*r*/); /* Destroy generator context */ + + /* --- Output methods --- * + * + * Only one of these operations need actually be implemented. All the + * other operations may be synthesized. Of course, performance is improved + * if more are provided. + */ + + uint32 (*raw)(grand */*r*/); /* Uniform over %$[0, max)$% */ + octet (*byte)(grand */*r*/); /* Uniform over %$[0, 256)$% */ + uint32 (*word)(grand */*r*/); /* Uniform over %$[0, 2^{32})$% */ + uint32 (*range)(grand */*r*/, uint32 /*l*/); /* Uniform over %$[0, l)$% */ + void (*fill)(grand */*r*/, void */*p*/, size_t /*sz*/); /* Fill buffer */ +} grand_ops; + +#define GR_DESTROY(r) (r)->ops->destroy((r)) +#define GR_RAW(r) (r)->ops->raw((r)) +#define GR_WORD(r) (r)->ops->word((r)) +#define GR_RANGE(r, l) (r)->ops->range((r), (l)) +#define GR_FILL(r, p, sz) (r)->ops->fill((r), (p), (sz)) + +/* --- Flag types --- */ + +#define GRAND_CRYPTO 1u /* Cryptographically strong */ + +/* --- Operation types --- */ + +enum { + + /* --- Required operations --- */ + + GRAND_CHECK, /* @unsigned op2@ */ + + /* --- Standard seeding operations --- */ + + GRAND_SEEDINT, /* @int i@ */ + GRAND_SEEDUINT32, /* @uint32 i@ */ + GRAND_SEEDBLOCK, /* @const void *p, size_t sz@ */ + GRAND_SEEDMP, /* @mp *m@ */ + GRAND_SEEDRAND /* @grand *g@ */ + + /* --- Generator-specific operations --- */ + +#define GRAND_SPECIFIC(ch) ((unsigned)(ch) << 8) +}; + +#define GRAND_BADOP assert(((void)"bad grand_misc op", 0)) + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @grand_byte@ --- * + * + * Arguments: @grand *r@ = pointet to generic generator + * + * Returns: A uniformly-distributed pseudorandom integer in the interval + * %$[0, 256)$%. + */ + +extern octet grand_byte(grand */*r*/); + +/* --- @grand_word@ --- * + * + * Arguments: @grand *r@ = pointet to generic generator + * + * Returns: A uniformly-distributed pseudorandom integer in the interval + * %$[0, 2^{32})$%. + */ + +extern uint32 grand_word(grand */*r*/); + +/* --- @grand_range@ --- * + * + * Arguments: @grand *r@ = pointet to generic generator + * @uint32 l@ = limit for acceptable results + * + * Returns: A uniformly-distributed pseudorandom integer in the interval + * %$[0, l)$%. + */ + +extern uint32 grand_range(grand */*r*/, uint32 /*l*/); + +/* --- @grand_fill@ --- * + * + * Arguments: @grand *r@ = pointet to generic generator + * @void *p@ = pointer to a buffer + * @size_t sz@ = size of the buffer + * + * Returns: --- + * + * Use: Fills a buffer with uniformly distributed pseudorandom bytes + * (see @grand_byte@). + */ + +extern void grand_fill(grand */*r*/, void */*p*/, size_t /*sz*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/rand/lcrand.c b/rand/lcrand.c new file mode 100644 index 0000000..6944a71 --- /dev/null +++ b/rand/lcrand.c @@ -0,0 +1,304 @@ +/* -*-c-*- + * + * Simple linear congruential generator + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include +#include + +#include "grand.h" +#include "lcrand.h" + +/*----- Magic numbers -----------------------------------------------------*/ + +/* --- The generator parameters --- */ + +#define P LCRAND_P /* Modulus */ +#define A LCRAND_A /* Multiplier (primitive mod @p@) */ +#define C LCRAND_C /* Additive constant */ + +/* --- Precomputed values for modular reduction --- */ + +#define D 5 /* %$p = 2^{32} - d$% */ + +/* --- Other useful bits --- */ + +#define P256 4294967040u /* Highest multiple of 256 < %$p$% */ + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @lcrand@ --- * + * + * Arguments: @uint32 x@ = seed value + * + * Returns: New state of the generator. + * + * Use: Steps the generator. Returns %$ax + c \bmod p$%. + */ + +uint32 lcrand(uint32 x) +{ + uint32 a[2], xx[2]; + uint32 yy[2]; + + /* --- Unpack things into the arrays --- */ + + a[0] = U16(A); a[1] = U16(A >> 16); + xx[0] = U16(x); xx[1] = U16(x >> 16); + + /* --- Multiply everything together --- * + * + * This is plain old long multiplication, although it looks a bit strange. + * I set up the top and bottom partial products directly where they're + * supposed to be. The cross terms I add together, with the low 16 bits in + * @q@ and the high 32 bits in @p@. These I then add into the product. + */ + + { + uint32 p, q; + + yy[0] = a[0] * xx[0]; + yy[1] = a[1] * xx[1]; + + p = a[0] * xx[1]; + q = p + a[1] * xx[0]; + p = ((q < p) << 16) + (q >> 16); + q = U16(q) << 16; + + q += yy[0]; + if (q < yy[0]) + p++; + else + p += (q >> 16) >> 16; + yy[0] = q; + + yy[1] += p; + } + + /* --- Now reduce mod p --- * + * + * I'm using shifts and adds to do the multiply step here. This needs to + * be changed if @D@ ever becomes something other than 5. + */ + +#if D != 5 +# error "Change shift sequence!" +#endif + + { + uint32 q; + + q = yy[1]; + x = yy[0]; + + while (q) { + uint32 y, z; + y = q >> 30; + z = q << 2; + z += q; + if (z < q) + y++; + else + y += (q >> 16) >> 16; + q = y; + x += z; + if (x < z || x > P) + x -= P; + } + } + + /* --- Now add on the constant --- */ + + x += C; + if (x < C || x >= P) + x -= P; + + /* --- Done --- */ + + return (x); +} + +/* --- @lcrand_range@ --- * + * + * Arguments: @uint32 *x@ = pointer to seed value (updated) + * @uint32 m@ = limit allowable + * + * Returns: A uniformly distributed pseudorandom integer in the interval + * %$[0, m)$%. + */ + +uint32 lcrand_range(uint32 *x, uint32 m) +{ + uint32 xx = *x; + uint32 r = P - P % m; + do xx = lcrand(xx); while (xx >= r); + *x = xx; + return (xx % m); +} + +/*----- Generic interface -------------------------------------------------*/ + +typedef struct gctx { + grand r; + uint32 x; +} gctx; + +static void gdestroy(grand *r) +{ + gctx *g = (gctx *)r; + DESTROY(g); +} + +static int gmisc(grand *r, unsigned op, ...) +{ + gctx *g = (gctx *)r; + va_list ap; + int rc = 0; + va_start(ap, op); + + switch (op) { + case GRAND_CHECK: + switch (va_arg(ap, unsigned)) { + case GRAND_CHECK: + case GRAND_SEEDINT: + case GRAND_SEEDUINT32: + case GRAND_SEEDRAND: + rc = 1; + break; + default: + rc = 0; + break; + } + break; + case GRAND_SEEDINT: + g->x = va_arg(ap, unsigned); + break; + case GRAND_SEEDUINT32: + g->x = va_arg(ap, uint32); + break; + case GRAND_SEEDRAND: { + grand *rr = va_arg(ap, grand *); + uint32 x; + do x = rr->ops->word(rr); while (x >= P || x == LCRAND_FIXEDPT); + g->x = x; + } break; + default: + GRAND_BADOP; + break; + } + + va_end(ap); + return (rc); +} + +static uint32 graw(grand *r) +{ + gctx *g = (gctx *)r; + g->x = lcrand(g->x); + return (g->x); +} + +static octet gbyte(grand *r) +{ + gctx *g = (gctx *)r; + uint32 x = g->x; + do x = lcrand(x); while (x >= P256); + g->x = x; + return (x / (P256 / 256)); +} + +static uint32 grange(grand *r, uint32 l) +{ + gctx *g = (gctx *)r; + return (lcrand_range(&g->x, l)); +} + +static const grand_ops gops = { + "lcrand", + LCRAND_P, 0, + gmisc, gdestroy, + graw, gbyte, grand_word, grange, grand_fill +}; + +/* --- @lcrand_create@ --- * + * + * Arguments: @uint32 x@ = initial seed + * + * Returns: Pointer to a generic generator. + * + * Use: Constructs a generic generator interface over a linear + * congruential generator. + */ + +grand *lcrand_create(uint32 x) +{ + gctx *g = CREATE(gctx); + g->r.ops = &gops; + g->x = x; + return (&g->r); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +static int verify(dstr *v) +{ + uint32 x = *(uint32 *)v[0].buf; + uint32 y = *(uint32 *)v[1].buf; + uint32 z = lcrand(x); + int ok = 1; + if (y != z) { + fprintf(stderr, + "\n*** lcrand failed. lcrand(%lu) = %lu, expected %lu\n", + (unsigned long)x, (unsigned long)z, (unsigned long)y); + ok = 0; + } + return (ok); +} + +static test_chunk tests[] = { + { "lcrand", verify, { &type_uint32, &type_uint32, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, tests, SRCDIR"/t/lcrand"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/rand/lcrand.h b/rand/lcrand.h new file mode 100644 index 0000000..9102096 --- /dev/null +++ b/rand/lcrand.h @@ -0,0 +1,119 @@ +/* -*-c-*- + * + * Simple linear congruential generator + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the linear congruential generator ------------------------* + * + * This pseudorandom number generator is simple, but has absolutely no + * cryptographic strength whatever. It may be used whenever random numbers + * are required but cryptographic strength is not, for example when + * generating numbers for use in primality tests. To be honest, it's not + * even particularly fast, although a certain amount of effort has been + * expended on making it better than awfully slow. To put things in + * perspective, it can't quite spit bytes out as fast as OFB DES. (Then + * again, bytes aren't its natural output format.) Its main use is probably + * seeding a Fibonacci generator. + * + * There exists a fixed-point input @LCRAND_FIXEDPT@ -- when fed to the + * generator it comes straight back out again. All other inputs less than + * the modulus are part of the same sequence of period %$p - 1$%. + * + * The generator has been tested for its statistical properties. George + * Marsaglia's Diehard tests give it a reasonably clean bill of health. + * + * The modulus %$p$% is chosen as the largest prime number less than + * %$2^{32}$%. The multiplier %$a$% and additive constant %$c$% are based on + * the decimal expansions of %$\pi$% and %$e$%, with the additional + * restriction that the multiplier must be a primitive element modulo %$p$%. + * The fixed point value is determined as %$c / (1 - a) \bmod p$%. + */ + +#ifndef CATACOMB_LCRAND_H +#define CATACOMB_LCRAND_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +/*----- Constants ---------------------------------------------------------*/ + +#define LCRAND_P 4294967291u /* Modulus for the generator */ +#define LCRAND_A 314159265u /* Multiplier (primitive mod @p@) */ +#define LCRAND_C 271828183u /* Additive constant */ + +#define LCRAND_FIXEDPT 3223959250u /* Fixed point (only bad input) */ + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @lcrand@ --- * + * + * Arguments: @uint32 x@ = seed value + * + * Returns: New state of the generator. + * + * Use: Steps the generator. Returns %$ax + c \bmod p$%. + */ + +extern uint32 lcrand(uint32 /*x*/); + +/* --- @lcrand_range@ --- * + * + * Arguments: @uint32 *x@ = pointer to seed value (updated) + * @uint32 m@ = limit allowable + * + * Returns: A uniformly distributed pseudorandom integer in the interval + * %$[0, m)$%. + */ + +extern uint32 lcrand_range(uint32 */*x*/, uint32 /*m*/); + +/* --- @lcrand_create@ --- * + * + * Arguments: @uint32 x@ = initial seed + * + * Returns: Pointer to a generic generator. + * + * Use: Constructs a generic generator interface over a linear + * congruential generator. + */ + +extern grand *lcrand_create(uint32 /*x*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/rand/maurer.c b/rand/maurer.c new file mode 100644 index 0000000..d66194e --- /dev/null +++ b/rand/maurer.c @@ -0,0 +1,233 @@ +/* -*-c-*- + * + * Maurer's universal statistical test + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include +#include + +#include "maurer.h" + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct bitscan { + const octet *p; + unsigned b; + uint32 a; +} bitscan; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @maurer_init@ --- * + * + * Arguments: @maurer_ctx *m@ = pointer to a context to initialize + * @unsigned l@ = number of bits to take at a time + * + * Returns: Minimum recommended amount of data to test. + * + * Use: Initializes a Maurer testing context. Note that @l@ values + * larger than 16 are not supported, and values less than 6 can + * give bizarre results. + */ + +unsigned long maurer_init(maurer_ctx *m, unsigned l) +{ + size_t i; + + assert(((void)"(maurer_init): chunks larger than 16 bits not supported", + 0 < l && l <= 16)); + + m->l = l; + m->a = 0; + m->b = 0; + m->n = 0; + m->x = 0; + + m->t = xmalloc(sizeof(unsigned long) << l); + for (i = 0; i < (1 << l); i++) + m->t[i] = 0; + return (((1000ul << l) * l + 7)/8); +} + +/* --- @bits@ --- * + * + * Arguments: @maurer_ctx *m@ = pointer to testing context + * @const octet **p@ = address of a buffer pointer + * @const octet *q@ = limit of the buffer pointer + * @unsigned *x@ = address to store next chunk + * + * Returns: Nonzero if some more bits arrived. + * + * Use: Reads some bits from a buffer. + */ + +static int bits(maurer_ctx *m, const octet **p, const octet *q, unsigned *x) +{ + while (m->b < m->l) { + if (*p >= q) + return (0); + m->a |= U8(*(*p)++) << m->b; + m->b += 8; + } + *x = m->a & ((1 << m->l) - 1); + m->a >>= m->l; + m->b -= m->l; + m->n++; + return (1); +} + +/* --- @maurer_test@ --- * + * + * Arguments: @maurer_ctx *m@ = pointer to a Maurer testing context + * @const void *buf@ = pointer to a buffer of data + * @size_t sz@ = size of the buffer + * + * Returns: --- + * + * Use: Scans a buffer of data and updates the testing context. + */ + +void maurer_test(maurer_ctx *m, const void *buf, size_t sz) +{ + const octet *p = buf, *l = p + sz; + unsigned long q = 10 << m->l; + unsigned x; + + /* --- Initialize the table --- */ + + while (m->n < q) { + if (!bits(m, &p, l, &x)) + return; + m->t[x] = m->n; + } + + /* --- Update the statistic --- */ + + while (bits(m, &p, l, &x)) { + m->x += log(m->n - m->t[x]); + m->t[x] = m->n; + } +} + +/* --- @maurer_done@ --- * + * + * Arguments: @maurer_ctx *m@ = pointer to a Maurer testing context + * + * Returns: The statistic %$Z_u = (X_u - \mu)/\sigma$%, which should be + * normally distributed with a mean of 0 and variance of 1. + * + * Use: Returns the result of Maurer's universal statistical test. + * Also frees the memory allocated during initialization. + * + * If insufficient data was received, the value @HUGE_VAL@ is + * returned. + */ + +double maurer_done(maurer_ctx *m) +{ + double x, mu, c, sigma; + unsigned long q = 10 << m->l, k; + + /* --- Table for means and variances --- */ + + struct { double mu, var_1; } vtab[] = { + { 0.7326495, 0.690 }, + { 1.5374383, 1.338 }, + { 2.4016068, 1.901 }, + { 3.3112247, 2.358 }, + { 4.2534266, 2.705 }, + { 5.2177052, 2.945 }, + { 6.1962507, 3.125 }, + { 7.1836656, 3.238 }, + { 8.1764248, 3.311 }, + { 9.1723243, 3.356 }, + { 10.170032 , 3.384 }, + { 11.168765 , 3.401 }, + { 12.168070 , 3.410 }, + { 13.167693 , 3.416 }, + { 14.167488 , 3.419 }, + { 15.167379 , 3.421 } + }; + + /* --- Check for bogus requests --- */ + + if (m->n < q) { + x = HUGE_VAL; + goto done; + } + + /* --- Do the maths --- * + * + * This produces %$X_u$%, which should be normally distributed with a mean + * and variance we can compute. + */ + + k = m->n - q; + x = m->x/(k * log(2)); + + /* --- Now translate this into %$Z_u$% distributed as %$N(0, 1)$% --- */ + + mu = vtab[m->l - 1].mu; + c = 0.7 - 0.8/m->l + (1.6 + 12.8/m->l) * pow(k, -4.0/m->l); + sigma = sqrt(c * c * vtab[m->l - 1].var_1 / k); + x = (x - mu)/sigma; + + /* --- Done (phew!) --- */ + +done: + xfree(m->t); + return (x); +} + +/* --- @maurer@ --- * + * + * Arguments: @const octet *p@ = pointer to a buffer of data + * @size_t sz@ = size of the buffer + * @unsigned l@ = number of bits to take at a time + * + * Returns: The statistic %$Z_u$%. + * + * Use: Simple interface to Maurer's universal statistical test. For + * large %$l$% you should use the more complicated restartable + * interface. + */ + +double maurer(const octet *p, size_t sz, unsigned l) +{ + maurer_ctx m; + + maurer_init(&m, l); + maurer_test(&m, p, sz); + return (maurer_done(&m)); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/rand/maurer.h b/rand/maurer.h new file mode 100644 index 0000000..0acfd39 --- /dev/null +++ b/rand/maurer.h @@ -0,0 +1,117 @@ +/* -*-c-*- + * + * Maurer's universal statistical test + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MAURER_H +#define CATACOMB_MAURER_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct maurer_ctx { + unsigned l; /* Chunk size, in bits */ + uint32 a; /* Bitscanner accumulator */ + unsigned b; /* Number of bits in accumulator */ + unsigned long n; /* Number of chunks read so far */ + double x; /* Statistic value */ + unsigned long *t; /* Offset table */ +} maurer_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @maurer_init@ --- * + * + * Arguments: @maurer_ctx *m@ = pointer to a context to initialize + * @unsigned l@ = number of bits to take at a time + * + * Returns: Minimum recommended amount of data to test. + * + * Use: Initializes a Maurer testing context. Note that @l@ values + * larger than 16 are not supported, and values less than 6 can + * give bizarre results. + */ + +extern unsigned long maurer_init(maurer_ctx */*m*/, unsigned /*l*/); + +/* --- @maurer_test@ --- * + * + * Arguments: @maurer_ctx *m@ = pointer to a Maurer testing context + * @const void *buf@ = pointer to a buffer of data + * @size_t sz@ = size of the buffer + * + * Returns: --- + * + * Use: Scans a buffer of data and updates the testing context. + */ + +extern void maurer_test(maurer_ctx */*m*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @maurer_done@ --- * + * + * Arguments: @maurer_ctx *m@ = pointer to a Maurer testing context + * + * Returns: The statistic %$Z_u = (X_u - \mu)/\sigma$%, which should be + * normally distributed with a mean of 0 and variance of 1. + * + * Use: Returns the result of Maurer's universal statistical test. + * Also frees the memory allocated during initialization. + * + * If insufficient data was received, the value @HUGE_VAL@ is + * returned. + */ + +extern double maurer_done(maurer_ctx */*m*/); + +/* --- @maurer@ --- * + * + * Arguments: @const octet *p@ = pointer to a buffer of data + * @size_t sz@ = size of the buffer + * @unsigned l@ = number of bits to take at a time + * + * Returns: The statistic %$Z_u$%. + * + * Use: Simple interface to Maurer's universal statistical test. For + * large %$l$% you should use the more complicated restartable + * interface. + */ + +extern double maurer(const octet */*p*/, size_t /*sz*/, unsigned /*l*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/rand/noise.c b/rand/noise.c new file mode 100644 index 0000000..6ab1070 --- /dev/null +++ b/rand/noise.c @@ -0,0 +1,459 @@ +/* -*-c-*- + * + * Acquisition of environmental noise (Unix-specific) + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "config.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#ifdef HAVE_SETGROUPS +# include +#endif + +#include +#include + +#include "noise.h" +#include "paranoia.h" +#include "rand.h" + +/*----- Magical numbers ---------------------------------------------------*/ + +#define NOISE_KIDLIFE 100000 /* @noise_filter@ child lifetime */ +#define MILLION 1000000 /* One million */ + +/*----- Noise source definition -------------------------------------------*/ + +const rand_source noise_source = { noise_acquire, noise_timer }; + +/*----- Static variables --------------------------------------------------*/ + +/* --- Timer differences --- */ + +static unsigned long noise_last; /* Last time recorded */ +static unsigned long noise_diff; /* Last first order difference */ + +/* --- Setuid program handling --- */ + +static uid_t noise_uid = NOISE_NOSETUID; /* Uid to set to spawn processes */ +static gid_t noise_gid = NOISE_NOSETGID; /* Gid to set to spawn processes */ + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @bitcount@ --- * + * + * Arguments: @unsigned long x@ = a word containing bits + * + * Returns: The number of bits set in the word. + */ + +static int bitcount(unsigned long x) +{ + char ctab[] = { 0, 1, 1, 2, 1, 2, 2, 3, + 1, 2, 2, 3, 2, 3, 3, 4 }; + int count = 0; + while (x) { + count += ctab[x & 0xfu]; + x >>= 4; + } + return (count); +} + +/* --- @timer@ --- * + * + * Arguments: @rand_pool *r@ = pointer to randomness pool + * @struct timeval *tv@ = pointer to time block + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Low-level timer contributor. + */ + +static int timer(rand_pool *r, struct timeval *tv) +{ + unsigned long x, d, dd; + int de, dde; + int ret; + + x = tv->tv_usec + MILLION * tv->tv_sec; + d = x ^ noise_last; + dd = d ^ noise_diff; + noise_diff = d; + de = bitcount(d); + dde = bitcount(dd); + rand_add(r, tv, sizeof(*tv), de <= dde ? de : dde); + ret = (de || dde); + BURN(tv); x = d = dd = de = dde = 0; + return (ret); +} + +/* --- @noise_timer@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Contributes the current time to the randomness pool. + * A guess at the number of useful bits contributed is made, + * based on first and second order bit differences. This isn't + * ever-so reliable, but it's better than nothing. + */ + +int noise_timer(rand_pool *r) +{ + struct timeval tv; + gettimeofday(&tv, 0); + return (timer(r, &tv)); +} + +/* --- @noise_devrandom@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Attempts to obtain some randomness from the system entropy + * pool. All bits from the device are assumed to be good. + */ + +int noise_devrandom(rand_pool *r) +{ + int fd; + octet buf[RAND_POOLSZ]; + ssize_t len; + int ret = 0; + + /* --- Be nice to other clients of the random device --- * + * + * Attempt to open the device nonblockingly. If that works, take up to + * one bufferful and then close again. If there's no data to be read, + * then that's tough and we go away again, on the grounds that the device + * needs to get some more entropy from somewhere. + */ + + if ((fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK)) >= 0 || + (fd = open("/dev/arandom", O_RDONLY | O_NONBLOCK)) >= 0 || + (fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) >= 0) { + if ((len = read(fd, buf, sizeof(buf))) > 0) { + rand_add(r, buf, len, len * 8); + BURN(buf); + ret = 1; + } + close(fd); + } + noise_timer(r); + return (ret); +} + +/* --- @noise_setid@ --- * + * + * Arguments: @uid_t uid@ = uid to set + * @gid_t gid@ = gid to set + * + * Returns: --- + * + * Use: Sets the user and group ids to be used by @noise_filter@ + * when running child processes. This is useful to avoid + * giving shell commands (even carefully written ones) undue + * privileges. This interface is Unix-specific + */ + +void noise_setid(uid_t uid, gid_t gid) +{ + noise_uid = uid; + noise_gid = gid; +} + +/* --- @noise_filter@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @int good@ = number of good bits per 1024 bits + * @const char *c@ = shell command to run + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Attempts to execute a shell command, and dump it into the + * randomness pool. A very rough estimate of the number of + * good bits is made, based on the size of the command's output. + * This function calls @waitpid@, so be careful. Before execing + * the command, the process uid and gid are set to the values + * given to @noise_setid@, and an attempt is made to reset the + * list of supplementary groups. The environment passed to + * the command has been severly lobotimized. If the command + * fails to complete within a short time period, it is killed. + * Paranoid use of close-on-exec flags for file descriptors is + * recommended. + * + * This interface is Unix-specific. + */ + +int noise_filter(rand_pool *r, int good, const char *c) +{ + char buf[4096]; + pid_t kid; + int fd[2]; + struct timeval dead; + int ret = 0; + const char *env[] = { + "PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc", + 0 + }; + + /* --- Remember when this business started --- */ + + gettimeofday(&dead, 0); + timer(r, &dead); + + /* --- Create a pipe --- */ + + if (pipe(fd)) + return (ret); + + /* --- Fork a child off --- */ + + fflush(0); + kid = fork(); + if (kid < 0) { + close(fd[0]); + close(fd[1]); + return (ret); + } + + /* --- Handle the child end of the deal --- */ + + if (kid == 0) { + int f; + + /* --- Set the pipe as standard output, close standard input --- */ + + close(0); close(1); close(2); + + if (fd[1] != 1) { + if (dup2(fd[1], 1) < 0) _exit(127); + close(fd[1]); + } + + if ((f = open("/dev/null", O_RDONLY)) != 0 || + (f = open("/dev/null", O_WRONLY)) != 2) + _exit(127); + + /* --- Play games with uids --- */ + + if (noise_gid != NOISE_NOSETGID) { + setgid(noise_gid); + setegid(noise_gid); +#ifdef HAVE_SETGROUPS + setgroups(1, &noise_gid); +#endif + } + + if (noise_uid != NOISE_NOSETUID) { + setuid(noise_uid); + seteuid(noise_uid); + } + + /* --- Start the process up --- */ + + execle("/bin/sh", "-c", c, (char *)0, env); + _exit(127); + } + + /* --- Sort out my end of the deal --- */ + + close(fd[1]); + + /* --- Decide on the deadline --- */ + + TV_ADDL(&dead, &dead, 0, NOISE_KIDLIFE); + + /* --- Now read, and think --- */ + + for (;;) { + struct timeval now, diff; + fd_set rd; + + gettimeofday(&now, 0); + timer(r, &now); + if (TV_CMP(&now, >, &dead)) + break; + TV_SUB(&diff, &dead, &now); + + FD_ZERO(&rd); + FD_SET(fd[0], &rd); + + if (select(fd[0] + 1, &rd, 0, 0, &diff) < 0) + break; + if (FD_ISSET(fd[0], &rd)) { + ssize_t sz; + int goodbits; + + if ((sz = read(fd[0], buf, sizeof(buf))) <= 0) + break; + goodbits = (sz * good) / 128; + rand_add(r, buf, sz, goodbits); + ret = 1; + } + } + + /* --- We've finished with it: kill the child process --- * + * + * This is morally questionable. On the other hand, I don't want to be + * held up in the @waitpid@ call if I can possibly help it. Maybe a + * double-fork is worth doing here. + */ + + close(fd[0]); + BURN(buf); + noise_timer(r); + kill(kid, SIGKILL); + waitpid(kid, 0, 0); + return (ret); +} + +/* --- @noise_freewheel@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Runs a free counter for a short while as a desparate attempt + * to get randomness from somewhere. This is actually quite + * effective. + */ + +#ifdef USE_FREEWHEEL + +static jmp_buf fwjmp; + +static void fwalarm(int sig) +{ + siglongjmp(fwjmp, 1); +} + +int noise_freewheel(rand_pool *r) +{ + void (*sigal)(int) = 0; + struct itimerval oitv, itv = { { 0, 0 }, { 0, 5000 } }; + int rc = 0; + volatile uint32 fwcount = 0; + + if (!sigsetjmp(fwjmp, 1)) { + if ((sigal = signal(SIGALRM, fwalarm)) == SIG_ERR) + return (0); + if (setitimer(ITIMER_REAL, &itv, &oitv)) + goto done; + for (;;) + fwcount++; + } else { + octet buf[4]; + STORE32(buf, fwcount); + rand_add(r, buf, sizeof(buf), 16); + rc = 1; + } + +done: + signal(SIGALRM, sigal); + if (oitv.it_value.tv_sec || oitv.it_value.tv_usec) + TV_SUB(&oitv.it_value, &oitv.it_value, &itv.it_value); + setitimer(ITIMER_REAL, &oitv, 0); + return (rc); +} + +#else + +int noise_freewheel(rand_pool *r) +{ + return (0); +} + +#endif + +/* --- @noise_enquire@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Runs some shell commands to enquire about the prevailing + * environment. This can gather quite a lot of low-quality + * entropy. + */ + +int noise_enquire(rand_pool *r) +{ + struct tab { + const char *cmd; + unsigned rate; + } tab[] = { + { "ps alxww || ps -elf", 16 }, + { "netstat -n", 6 }, + { "ifconfig -a", 8 }, + { "df", 20 }, + { "w", 6 }, + { "ls -align /tmp/.", 10 }, + { 0, 0 } + }; + int i; + + for (i = 0; tab[i].cmd; i++) + noise_filter(r, tab[i].rate, tab[i].cmd); + return (1); +} + +/* --- @noise_acquire@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: --- + * + * Use: Acquires some randomness from somewhere. + */ + +void noise_acquire(rand_pool *r) +{ + unsigned i; + for (i = 0; i < 8; i++) + noise_freewheel(r); + if (!noise_devrandom(r)) { + noise_enquire(r); + for (i = 0; i < 8; i++) + noise_freewheel(r); + } +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/rand/noise.h b/rand/noise.h new file mode 100644 index 0000000..ad93c7e --- /dev/null +++ b/rand/noise.h @@ -0,0 +1,163 @@ +/* -*-c-*- + * + * Acquisition of environmental noise (Unix-specific) + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_NOISE_H +#define CATACOMB_NOISE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_RAND_H +# include "rand.h" +#endif + +/*----- Noise source definition -------------------------------------------*/ + +extern const rand_source noise_source; + +/*----- Magic numbers -----------------------------------------------------*/ + +#define NOISE_NOSETUID ((uid_t)-1) +#define NOISE_NOSETGID ((gid_t)-1) + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @noise_timer@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Contributes the current time to the randomness pool. + * A guess at the number of useful bits contributed is made, + * based on first and second order bit differences. This isn't + * ever-so reliable, but it's better than nothing. + */ + +extern int noise_timer(rand_pool */*r*/); + +/* --- @noise_devrandom@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Attempts to obtain some randomness from the system entropy + * pool. All bits from the device are assumed to be good. + */ + +extern int noise_devrandom(rand_pool */*r*/); + +/* --- @noise_setid@ --- * + * + * Arguments: @uid_t uid@ = uid to set + * @gid_t gid@ = gid to set + * + * Returns: --- + * + * Use: Sets the user and group ids to be used by @noise_filter@ + * when running child processes. This is useful to avoid + * giving shell commands (even carefully written ones) undue + * privileges. This interface is Unix-specific. + */ + +extern void noise_setid(uid_t /*uid*/, gid_t /*gid*/); + +/* --- @noise_filter@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @int good@ = number of good bits per 1024 bits + * @const char *c@ = shell command to run + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Attempts to execute a shell command, and dump it into the + * randomness pool. A very rough estimate of the number of + * good bits is made, based on the size of the command's output. + * This function calls @waitpid@, so be careful. Before execing + * the command, the process uid and gid are set to the values + * given to @noise_setid@, and an attempt is made to reset the + * list of supplementary groups. The environment passed to + * the command has been severly lobotimized. If the command + * fails to complete within a short time period, it is killed. + * Paranoid use of close-on-exec flags for file descriptors is + * recommended. + * + * This interface is Unix-specific. + */ + +extern int noise_filter(rand_pool */*r*/, int /*good*/, const char */*c*/); + +/* --- @noise_freewheel@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Runs a free counter for a short while as a desparate attempt + * to get randomness from somewhere. This is actually quite + * effective. + */ + +int noise_freewheel(rand_pool */*r*/); + +/* --- @noise_enquire@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Runs some shell commands to enquire about the prevailing + * environment. This can gather quite a lot of low-quality + * entropy. + */ + +extern int noise_enquire(rand_pool */*r*/); + +/* --- @noise_acquire@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: --- + * + * Use: Acquires some randomness from somewhere. + */ + +extern void noise_acquire(rand_pool */*r*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/rand/rand.c b/rand/rand.c new file mode 100644 index 0000000..fa6dab8 --- /dev/null +++ b/rand/rand.c @@ -0,0 +1,584 @@ +/* -*-c-*- + * + * Secure random number generator + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include +#include + +#include "arena.h" +#include "blowfish-cbc.h" +#include "paranoia.h" +#include "rand.h" +#include "rmd160.h" +#include "rmd160-hmac.h" + +/*----- Static variables --------------------------------------------------*/ + +static const grand_ops gops; + +typedef struct gctx { + grand r; + rand_pool p; +} gctx; + +static gctx *pool = 0; /* Default random pool */ + +/*----- Macros ------------------------------------------------------------*/ + +#define RAND_RESOLVE(r) do { \ + if ((r) == RAND_GLOBAL) { \ + if (!pool) \ + pool = (gctx *)rand_create(); \ + (r) = &pool->p; \ + } \ +} while (0) + +#define TIMER(r) do { \ + if ((r)->s && (r)->s->timer) \ + (r)->s->timer(r); \ +} while (0) + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rand_init@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: --- + * + * Use: Initializes a randomness pool. The pool doesn't start out + * very random: that's your job to sort out. A good suggestion + * would be to attach an appropriate noise source and call + * @rand_seed@. + */ + +void rand_init(rand_pool *r) +{ + RAND_RESOLVE(r); + memset(r->pool, 0, sizeof(r->pool)); + memset(r->buf, 0, sizeof(r->buf)); + r->i = 0; + r->irot = 0; + r->ibits = r->obits = 0; + r->o = RAND_SECSZ; + r->s = 0; + rmd160_hmacinit(&r->k, 0, 0); + rand_gate(r); +} + +/* --- @rand_noisesrc@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @const rand_source *s@ = pointer to source definition + * + * Returns: --- + * + * Use: Sets a noise source for a randomness pool. When the pool's + * estimate of good random bits falls to zero, the @getnoise@ + * function is called, passing the pool handle as an argument. + * It is expected to increase the number of good bits by at + * least one, because it'll be called over and over again until + * there are enough bits to satisfy the caller. The @timer@ + * function is called frequently throughout the generator's + * operation. + */ + +void rand_noisesrc(rand_pool *r, const rand_source *s) +{ + RAND_RESOLVE(r); + r->s = s; +} + +/* --- @rand_seed@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @unsigned bits@ = number of bits to ensure + * + * Returns: --- + * + * Use: Ensures that there are at least @bits@ good bits of entropy + * in the pool. It is recommended that you call this after + * initializing a new pool. Requesting @bits > RAND_IBITS@ is + * doomed to failure (and is an error). + */ + +void rand_seed(rand_pool *r, unsigned bits) +{ + RAND_RESOLVE(r); + + assert(((void)"bits pointlessly large in rand_seed", bits <= RAND_IBITS)); + assert(((void)"no noise source in rand_seed", r->s)); + + while (r->ibits < bits) + r->s->getnoise(r); + rand_gate(r); +} + +/* --- @rand_key@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @const void *k@ = pointer to key data + * @size_t sz@ = size of key data + * + * Returns: --- + * + * Use: Sets the secret key for a randomness pool. The key is used + * when mixing in new random bits. + */ + +void rand_key(rand_pool *r, const void *k, size_t sz) +{ + RAND_RESOLVE(r); + rmd160_hmacinit(&r->k, k, sz); +} + +/* --- @rand_add@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @const void *p@ = pointer a buffer of data to add + * @size_t sz@ = size of the data buffer + * @unsigned goodbits@ = number of good bits estimated in buffer + * + * Returns: --- + * + * Use: Mixes the data in the buffer with the contents of the + * pool. The estimate of the number of good bits is added to + * the pool's own count. The mixing operation is not + * cryptographically strong. However, data in the input pool + * isn't output directly, only through the one-way gating + * operation, so that shouldn't matter. + */ + +void rand_add(rand_pool *r, const void *p, size_t sz, unsigned goodbits) +{ + const octet *c = p; + int i, rot; + +#if RAND_POOLSZ != 128 +# error Polynomial in rand_add is out of date. Fix it. +#endif + + RAND_RESOLVE(r); + + i = r->i; rot = r->irot; + + while (sz) { + octet o = *c++; + r->pool[i] ^= (ROL8(o, rot) ^ + r->pool[(i + 1) % RAND_POOLSZ] ^ + r->pool[(i + 2) % RAND_POOLSZ] ^ + r->pool[(i + 7) % RAND_POOLSZ]); + rot = (rot + 5) & 7; + i++; if (i >= RAND_POOLSZ) i -= RAND_POOLSZ; + sz--; + } + + r->i = i; + r->irot = rot; + r->ibits += goodbits; + if (r->ibits > RAND_IBITS) + r->ibits = RAND_IBITS; +} + +/* --- @rand_goodbits@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Estimate of the number of good bits remaining in the pool. + */ + +unsigned rand_goodbits(rand_pool *r) +{ + RAND_RESOLVE(r); + return (r->ibits + r->obits); +} + +/* --- @rand_gate@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: --- + * + * Use: Mixes up the entire state of the generator in a nonreversible + * way. + */ + +void rand_gate(rand_pool *r) +{ + octet mac[RMD160_HASHSZ]; + + RAND_RESOLVE(r); + TIMER(r); + + /* --- Hash up all the data in the pool --- */ + + { + rmd160_macctx mc; + + rmd160_macinit(&mc, &r->k); + rmd160_machash(&mc, r->pool, sizeof(r->pool)); + rmd160_machash(&mc, r->buf, sizeof(r->buf)); + rmd160_macdone(&mc, mac); + BURN(mc); + } + + /* --- Now mangle all of the data based on the hash --- */ + + { + blowfish_cbcctx bc; + + blowfish_cbcinit(&bc, mac, sizeof(mac), 0); + blowfish_cbcencrypt(&bc, r->pool, r->pool, sizeof(r->pool)); + blowfish_cbcencrypt(&bc, r->buf, r->buf, sizeof(r->buf)); + BURN(bc); + } + + /* --- Reset the various state variables --- */ + + r->o = RAND_SECSZ; + r->obits += r->ibits; + if (r->obits > RAND_OBITS) { + r->ibits = r->obits - r->ibits; + r->obits = RAND_OBITS; + } else + r->ibits = 0; + TIMER(r); +} + +/* --- @rand_stretch@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: --- + * + * Use: Stretches the contents of the output buffer by transforming + * it in a nonreversible way. This doesn't add any entropy + * worth speaking about, but it works well enough when the + * caller doesn't care about that sort of thing. + */ + +void rand_stretch(rand_pool *r) +{ + octet mac[RMD160_HASHSZ]; + + RAND_RESOLVE(r); + TIMER(r); + + /* --- Hash up all the data in the buffer --- */ + + { + rmd160_macctx mc; + + rmd160_macinit(&mc, &r->k); + rmd160_machash(&mc, r->pool, sizeof(r->pool)); + rmd160_machash(&mc, r->buf, sizeof(r->buf)); + rmd160_macdone(&mc, mac); + BURN(mc); + } + + /* --- Now mangle the buffer based on that hash --- */ + + { + blowfish_cbcctx bc; + + blowfish_cbcinit(&bc, mac, sizeof(mac), 0); + blowfish_cbcencrypt(&bc, r->buf, r->buf, sizeof(r->buf)); + BURN(bc); + } + + /* --- Reset the various state variables --- */ + + r->o = RAND_SECSZ; + TIMER(r); +} + +/* --- @rand_get@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @void *p@ = pointer to output buffer + * @size_t sz@ = size of output buffer + * + * Returns: --- + * + * Use: Gets random data from the pool. The pool's contents can't be + * determined from the output of this function; nor can the + * output data be determined from a knowledge of the data input + * to the pool wihtout also having knowledge of the secret key. + * The good bits counter is decremented, although no special + * action is taken if it reaches zero. + */ + +void rand_get(rand_pool *r, void *p, size_t sz) +{ + octet *o = p; + + RAND_RESOLVE(r); + TIMER(r); + + if (!sz) + return; + for (;;) { + if (r->o + sz <= RAND_BUFSZ) { + memcpy(o, r->buf + r->o, sz); + r->o += sz; + break; + } else { + size_t chunk = RAND_BUFSZ - r->o; + if (chunk) { + memcpy(o, r->buf + r->o, chunk); + sz -= chunk; + o += chunk; + } + rand_stretch(r); + } + } + + if (r->obits > sz * 8) + r->obits -= sz * 8; + else + r->obits = 0; +} + +/* --- @rand_getgood@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @void *p@ = pointer to output buffer + * @size_t sz@ = size of output buffer + * + * Returns: --- + * + * Use: Gets random data from the pool, ensuring that there are + * enough good bits. This interface isn't recommended: it makes + * the generator slow, and doesn't provide much more security + * than @rand_get@, assuming you've previously done a + * @rand_seed@. + */ + +void rand_getgood(rand_pool *r, void *p, size_t sz) +{ + octet *o = p; + + RAND_RESOLVE(r); + + if (!sz) + return; + if (!r->s || !r->s->getnoise) { + rand_get(r, p, sz); + return; + } + TIMER(r); + + while (sz) { + size_t chunk = sz; + + if (chunk * 8 > r->obits) { + if (chunk * 8 > r->ibits + r->obits) + do r->s->getnoise(r); while (r->ibits + r->obits < 256); + rand_gate(r); + if (chunk * 8 > r->obits) + chunk = r->obits / 8; + } + + if (chunk + r->o > RAND_BUFSZ) + chunk = RAND_BUFSZ - r->o; + + memcpy(o, r->buf + r->o, chunk); + r->o += chunk; + r->obits -= chunk * 8; + o += chunk; + sz -= chunk; + } +} + +/*----- Generic random number generator interface -------------------------*/ + +#define GRESOLVE(g, r) do { \ + if (r != &rand_global) \ + g = (gctx *)r; \ + else { \ + if (!pool) \ + pool = (gctx *)rand_create(); \ + g = pool; \ + } \ +} while (0) + +static void gdestroy(grand *r) +{ + gctx *g; + GRESOLVE(g, r); + if (g != pool) { + BURN(*g); + S_DESTROY(g); + } +} + +static int gmisc(grand *r, unsigned op, ...) +{ + gctx *g; + va_list ap; + int rc = 0; + va_start(ap, op); + + GRESOLVE(g, r); + switch (op) { + case GRAND_CHECK: + switch (va_arg(ap, unsigned)) { + case GRAND_CHECK: + case GRAND_SEEDINT: + case GRAND_SEEDUINT32: + case GRAND_SEEDBLOCK: + case GRAND_SEEDRAND: + case RAND_GATE: + case RAND_STRETCH: + case RAND_KEY: + case RAND_NOISESRC: + case RAND_SEED: + case RAND_TIMER: + case RAND_GOODBITS: + case RAND_ADD: + rc = 1; + break; + default: + rc = 0; + break; + } + break; + case GRAND_SEEDINT: { + unsigned u = va_arg(ap, unsigned); + rand_add(&g->p, &u, sizeof(u), sizeof(u)); + } break; + case GRAND_SEEDUINT32: { + uint32 i = va_arg(ap, uint32); + rand_add(&g->p, &i, sizeof(i), 4); + } break; + case GRAND_SEEDBLOCK: { + const void *p = va_arg(ap, const void *); + size_t sz = va_arg(ap, size_t); + rand_add(&g->p, p, sz, sz); + } break; + case GRAND_SEEDRAND: { + grand *rr = va_arg(ap, grand *); + octet buf[16]; + rr->ops->fill(rr, buf, sizeof(buf)); + rand_add(&g->p, buf, sizeof(buf), 8); + } break; + case RAND_GATE: + rand_gate(&g->p); + break; + case RAND_STRETCH: + rand_stretch(&g->p); + break; + case RAND_KEY: { + const void *k = va_arg(ap, const void *); + size_t sz = va_arg(ap, size_t); + rand_key(&g->p, k, sz); + } break; + case RAND_NOISESRC: + rand_noisesrc(&g->p, va_arg(ap, const rand_source *)); + break; + case RAND_SEED: + rand_seed(&g->p, va_arg(ap, unsigned)); + break; + case RAND_TIMER: + TIMER(&g->p); + break; + case RAND_GOODBITS: + rc = rand_goodbits(&g->p); + break; + case RAND_ADD: { + const void *p = va_arg(ap, const void *); + size_t sz = va_arg(ap, size_t); + unsigned goodbits = va_arg(ap, unsigned); + rand_add(&g->p, p, sz, goodbits); + } break; + default: + GRAND_BADOP; + break; + } + + va_end(ap); + return (rc); +} + +static octet gbyte(grand *r) +{ + gctx *g; + octet o; + GRESOLVE(g, r); + rand_getgood(&g->p, &o, 1); + return (o); +} + +static uint32 gword(grand *r) +{ + gctx *g; + octet b[4]; + GRESOLVE(g, r); + rand_getgood(&g->p, &b, sizeof(b)); + return (LOAD32(b)); +} + +static void gfill(grand *r, void *p, size_t sz) +{ + gctx *g; + GRESOLVE(g, r); + rand_get(&g->p, p, sz); +} + +static const grand_ops gops = { + "rand", + GRAND_CRYPTO, 0, + gmisc, gdestroy, + gword, gbyte, gword, grand_range, gfill +}; + +grand rand_global = { &gops }; + +/* --- @rand_create@ --- * + * + * Arguments: --- + * + * Returns: Pointer to a generic generator. + * + * Use: Constructs a generic generator interface over a Catacomb + * entropy pool generator. + */ + +grand *rand_create(void) +{ + gctx *g = S_CREATE(gctx); + g->r.ops = &gops; + rand_init(&g->p); + return (&g->r); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/rand/rand.h b/rand/rand.h new file mode 100644 index 0000000..a024c0f --- /dev/null +++ b/rand/rand.h @@ -0,0 +1,313 @@ +/* -*-c-*- + * + * Secure random number generator + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the random number generator ------------------------------* + * + * The algorithm is one of the author's own devising. It may therefore be + * worth a certain amount of skepticism. However, I've thought about this + * method for over a year before actually considering it worth implementing. + * With a little bit of luck, it should have received some peer review by the + * time this code is actually properly released, and it'll be worth a bit + * more confidence. My earlier generator was very similar in structure to + * the Linux /dev/random device. This generator is intended to address + * concerns I expressed about the Linux generator in a Usenet article to + * sci.crypt. + * + * The generator is divided into two parts: an input pool and an output + * buffer. New random data is placed into the pool in the way described + * below, which is shamelessly stolen from the Linux /dev/random generator. + * The only interaction that the pool has on the output buffer is through the + * keyed `gating' operation, which mixes up and redistributes all of the + * generator's state in an irreversible manner. Random bytes, when + * requested, are extracted from the output buffer in a linear fashion. + * + * The input pool is best seen as being eight shift registers in parallel. + * Data is added to the pool one octet at a time. Each bit of a new octet is + * added to a different shift register, by adding it (mod 2) with other bits + * according to the coefficients of a primitive polynomial. Each new byte is + * rotated before being added into the pool, in a half-hearted attempt to + * protect against biases in the input data (e.g., top bits being clear on + * ASCII text). + * + * The gating operation takes a keyed hash of the entire generator state, + * uses it as the key for a symmetric cipher, and encrypts the state. The + * key is then discarded. The result is that every ouptut bit of the + * operation depends in a complex way on every input bit, but the operation + * cannot be reversed. + * + * As an added wrinkle, 160 bits of the output buffer are never actually + * output. They are used in the gating operation only, as an extra item that + * an adversary has to guess before predicting generator output. + */ + +#ifndef CATACOMB_RAND_H +#define CATACOMB_RAND_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_RMD160_HMAC_H +# include "rmd160-hmac.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define RAND_POOLSZ 128 /* Input pool size in bytes */ +#define RAND_BUFSZ 512 /* Output buffer size in bytes */ +#define RAND_SECSZ 20 /* Secret octets in output buffer */ + +#define RAND_IBITS (RAND_POOLSZ * 8) +#define RAND_OBITS (RAND_BUFSZ * 8) + +/*----- Data structures ---------------------------------------------------*/ + +/* --- A random number generator pool --- */ + +typedef struct rand_pool { + octet pool[RAND_POOLSZ]; /* Actual contents of the pool */ + unsigned i; /* Current index into pool */ + unsigned irot; /* Current rotation applied */ + unsigned ibits; /* Number of good bits in pool */ + octet buf[RAND_BUFSZ]; /* Random octet output buffer */ + unsigned o; /* Current index into buffer */ + unsigned obits; /* Number of good bits in buffer */ + rmd160_mackey k; /* Secret key for this pool */ + const struct rand_source *s; /* System-specific noise source */ +} rand_pool; + +#define RAND_GLOBAL ((rand_pool *)0) /* The global randomness pool */ + +/* --- A noise source --- */ + +typedef struct rand_source { + void (*getnoise)(rand_pool */*r*/); /* Acquire more noise */ + int (*timer)(rand_pool */*r*/); /* Get noise from current time */ +} rand_source; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @rand_init@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: --- + * + * Use: Initializes a randomness pool. The pool doesn't start out + * very random: that's your job to sort out. + */ + +extern void rand_init(rand_pool */*r*/); + +/* --- @rand_noisesrc@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @const rand_source *s@ = pointer to source definition + * + * Returns: --- + * + * Use: Sets a noise source for a randomness pool. When the pool's + * estimate of good random bits falls to zero, the @getnoise@ + * function is called, passing the pool handle as an argument. + * It is expected to increase the number of good bits by at + * least one, because it'll be called over and over again until + * there are enough bits to satisfy the caller. The @timer@ + * function is called frequently throughout the generator's + * operation. + */ + +extern void rand_noisesrc(rand_pool */*r*/, const rand_source */*s*/); + +/* --- @rand_seed@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @unsigned bits@ = number of bits to ensure + * + * Returns: --- + * + * Use: Ensures that there are at least @bits@ good bits of entropy + * in the pool. It is recommended that you call this after + * initializing a new pool. Requesting @bits > RAND_IBITS@ is + * doomed to failure (and is an error). + */ + +extern void rand_seed(rand_pool */*r*/, unsigned /*bits*/); + +/* --- @rand_key@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @const void *k@ = pointer to key data + * @size_t sz@ = size of key data + * + * Returns: --- + * + * Use: Sets the secret key for a randomness pool. The key is used + * when mixing in new random bits. + */ + +extern void rand_key(rand_pool */*r*/, const void */*k*/, size_t /*sz*/); + +/* --- @rand_add@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @const void *p@ = pointer a buffer of data to add + * @size_t sz@ = size of the data buffer + * @unsigned goodbits@ = number of good bits estimated in buffer + * + * Returns: --- + * + * Use: Mixes the data in the buffer with the contents of the + * pool. The estimate of the number of good bits is added to + * the pool's own count. The mixing operation is not + * cryptographically strong. However, data in the input pool + * isn't output directly, only through the one-way gating + * operation, so that shouldn't matter. + */ + +extern void rand_add(rand_pool */*r*/, + const void */*p*/, size_t /*sz*/, + unsigned /*goodbits*/); + +/* --- @rand_goodbits@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Estimate of the number of good bits remaining in the pool. + */ + +extern unsigned rand_goodbits(rand_pool */*r*/); + +/* --- @rand_gate@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: --- + * + * Use: Mixes up the entire state of the generator in a nonreversible + * way. + */ + +extern void rand_gate(rand_pool */*r*/); + +/* --- @rand_stretch@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: --- + * + * Use: Stretches the contents of the output buffer by transforming + * it in a nonreversible way. This doesn't add any entropy + * worth speaking about, but it works well enough when the + * caller doesn't care about that sort of thing. + */ + +extern void rand_stretch(rand_pool */*r*/); + +/* --- @rand_get@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @void *p@ = pointer to output buffer + * @size_t sz@ = size of output buffer + * + * Returns: --- + * + * Use: Gets random data from the pool. The pool's contents can't be + * determined from the output of this function; nor can the + * output data be determined from a knowledge of the data input + * to the pool without also having knowledge of the secret key. + * The good bits counter is decremented, although no special + * action is taken if it reaches zero. + */ + +extern void rand_get(rand_pool */*r*/, void */*p*/, size_t /*sz*/); + +/* --- @rand_getgood@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @void *p@ = pointer to output buffer + * @size_t sz@ = size of output buffer + * + * Returns: --- + * + * Use: Gets random data from the pool. The pool's contents can't be + * determined from the output of this function; nor can the + * output data be determined from a knowledge of the data input + * to the pool wihtout also having knowledge of the secret key. + * If a noise source is attached to the pool in question, it is + * called to replenish the supply of good bits in the pool; + * otherwise this call is equivalent to @rand_get@. + */ + +extern void rand_getgood(rand_pool */*r*/, void */*p*/, size_t /*sz*/); + +/*----- Generic random number generator interface -------------------------*/ + +/* --- Miscellaneous operations --- */ + +enum { + RAND_GATE = GRAND_SPECIFIC('R'), /* No args */ + RAND_STRETCH, /* No args */ + RAND_KEY, /* @const void *k, size_t sz@ */ + RAND_NOISESRC, /* @const rand_source *s@ */ + RAND_SEED, /* @unsigned bits@ */ + RAND_TIMER, /* No args */ + RAND_GOODBITS, /* No args */ + RAND_ADD /* @const void *p, size_t sz,@ + * @unsigned goodbits */ +}; + +/* --- Default random number generator --- */ + +extern grand rand_global; + +/* --- @rand_create@ --- * + * + * Arguments: --- + * + * Returns: Pointer to a generic generator. + * + * Use: Constructs a generic generator interface over a Catacomb + * entropy pool generator. + */ + +extern grand *rand_create(void); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/rand/sslprf.c b/rand/sslprf.c new file mode 100644 index 0000000..83a4c84 --- /dev/null +++ b/rand/sslprf.c @@ -0,0 +1,356 @@ +/* -*-c-*- + * + * The SSL pseudo-random function + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include "arena.h" +#include "ghash.h" +#include "grand.h" +#include "paranoia.h" +#include "sslprf.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @step@ --- * + * + * Arguments: @sslprf_ctx *c@ = pointer to context structure + * + * Returns: --- + * + * Use: Steps the generator. + */ + +static void step(sslprf_ctx *c) +{ + octet buf[64]; + size_t n, sz; + octet x; + ghash *h, *hh; + octet *p; + + h = GH_INIT(c->ci); + x = 'A' + c->i - 1; + for (sz = c->i++; sz > 0; sz -= n) { + n = sz; + if (n > sizeof(buf)) + n = sizeof(buf); + memset(buf, x, n); + GH_HASH(h, buf, n); + } + GH_HASH(h, c->k, c->ksz); + GH_HASH(h, c->sd, c->sdsz); + p = GH_DONE(h, 0); + + hh = GH_INIT(c->co); + GH_HASH(hh, c->k, c->ksz); + GH_HASH(hh, p, c->ihashsz); + c->p = GH_DONE(hh, 0); + GH_DESTROY(h); + + c->h = hh; + c->sz = c->ohashsz; +} + +/* --- @sslprf_init@ --- * + * + * Arguments: @sslprf_ctx *c@ = pointer to a context structure + * @const gchash *hco, *hci@ = outer and inner hash functions + * @const void *k@ = pointer to secret buffer + * @size_t ksz@ = size of the secret + * @const void *sd@ = pointer to seed buffer + * @size_t sdsz@ = size of the seed + * + * Returns: --- + * + * Use: Initializes an SSL generator context. + */ + +void sslprf_init(sslprf_ctx *c, const gchash *hco, const gchash *hci, + const void *k, size_t ksz, + const void *sd, size_t sdsz) +{ + c->co = hco; c->ci = hci; + c->ohashsz = hco->hashsz; c->ihashsz = hci->hashsz; + c->k = k; c->ksz = ksz; c->sd = sd; c->sdsz = sdsz; + c->i = 1; + step(c); +} + +/* --- @sslprf_encrypt@ --- * + * + * Arguments: @sslprf_ctx *c@ = pointer to a context structure + * @const void *src@ = pointer to source buffer + * @void *dest@ = pointer to destination buffer + * @size_t sz@ = size of the buffers + * + * Returns: --- + * + * Use: Encrypts data using the SSL pseudo-random function. If the + * destination pointer is null, the generator is spun and no + * output is produced; if the source pointer is null, raw output + * from the generator is written; otherwise, the source data is + * XORed with the generator output. + */ + +void sslprf_encrypt(sslprf_ctx *c, const void *src, void *dest, size_t sz) +{ + const octet *s = src; + octet *d = dest; + size_t i, n; + + while (sz) { + if (!c->sz) { + GH_DESTROY(c->h); + step(c); + } + n = c->sz; + if (n > sz) + n = sz; + if (d) { + if (!s) + memcpy(d, c->p, n); + else { + for (i = 0; i < n; i++) d[i] = s[i] ^ c->p[i]; + s += n; + } + d += n; + } + c->p += n; + c->sz -= n; + sz -= n; + } +} + +/* --- @sslprf_free@ --- * + * + * Arguments: @sslprf_ctx@ = pointer to a context + * + * Returns: --- + * + * Use: Frees resources held in an SSL generator context. + */ + +void sslprf_free(sslprf_ctx *c) +{ + GH_DESTROY(c->h); +} + +/* --- Generic random number generator --- */ + +typedef struct grctx { + grand r; + grand_ops ops; + sslprf_ctx prf; +} grctx; + +static void grdestroy(grand *r) +{ + grctx *g = (grctx *)r; + xfree((char *)g->ops.name); + xfree((octet *)g->prf.sd); + sslprf_free(&g->prf); + BURN(*g); + S_DESTROY(g); +} + +static void seed(grctx *g, const void *p, size_t sz) +{ + octet *q; + xfree((octet *)g->prf.sd); + g->prf.sd = q = xmalloc(sz); + memcpy(q, p, sz); + g->prf.sdsz = sz; +} + +static int grmisc(grand *r, unsigned op, ...) +{ + grctx *g = (grctx *)r; + va_list ap; + int rc = 0; + uint32 i; + octet buf[4]; + va_start(ap, op); + + switch (op) { + case GRAND_CHECK: + switch (va_arg(ap, unsigned)) { + case GRAND_CHECK: + case GRAND_SEEDINT: + case GRAND_SEEDUINT32: + case GRAND_SEEDBLOCK: + case GRAND_SEEDRAND: + rc = 1; + break; + default: + rc = 0; + break; + } + break; + case GRAND_SEEDINT: + i = va_arg(ap, unsigned); + STORE32(buf, i); + seed(g, buf, sizeof(buf)); + break; + case GRAND_SEEDUINT32: + i = va_arg(ap, uint32); + STORE32(buf, i); + seed(g, buf, sizeof(buf)); + break; + case GRAND_SEEDBLOCK: { + const void *p = va_arg(ap, const void *); + size_t sz = va_arg(ap, size_t); + seed(g, p, sz); + } break; + case GRAND_SEEDRAND: { + grand *rr = va_arg(ap, grand *); + octet buf[16]; + rr->ops->fill(rr, buf, sizeof(buf)); + seed(g, buf, sizeof(buf)); + } break; + default: + GRAND_BADOP; + break; + } + + va_end(ap); + return (rc); +} + +static octet grbyte(grand *r) +{ + grctx *g = (grctx *)r; + octet o; + sslprf_encrypt(&g->prf, 0, &o, 1); + return (o); +} + +static uint32 grword(grand *r) +{ + grctx *g = (grctx *)r; + octet b[4]; + sslprf_encrypt(&g->prf, 0, &b, sizeof(b)); + return (LOAD32(b)); +} + +static void grfill(grand *r, void *p, size_t sz) +{ + grctx *g = (grctx *)r; + sslprf_encrypt(&g->prf, 0, p, sz); +} + +static const grand_ops grops = { + "", + GRAND_CRYPTO, 0, + grmisc, grdestroy, + grword, grbyte, grword, grand_range, grfill +}; + +/* ---@sslprf_rand@ --- * + * + * Arguments: @const gchash *hco, const gchash *hci@ = hash functions + * @const void *k@ = pointer to the key material + * @size_t ksz@ = size of the key material + * @const void *sd@ = pointer to the seed material + * @size_t sdsz@ = size of the seed material + * + * Returns: Pointer to generic random number generator interface. + * + * Use: Creates a generic generator which does TLS data expansion. + */ + +grand *sslprf_rand(const gchash *hco, const gchash *hci, + const void *k, size_t ksz, + const void *sd, size_t sdsz) +{ + grctx *g = S_CREATE(grctx); + dstr d = DSTR_INIT; + octet *q = xmalloc(sdsz); + memcpy(q, sd, sdsz); + dstr_putf(&d, "sslprf(%s,%s)", hco->name, hci->name); + g->ops = grops; + g->ops.name = xstrdup(d.buf); + g->r.ops = &g->ops; + dstr_destroy(&d); + sslprf_init(&g->prf, hco, hci, k, ksz, q, sdsz); + return (&g->r); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include +#include + +#include +#include + +#include "sha.h" +#include "md5.h" + +static int v_generate(dstr *v) +{ + grand *g; + dstr d = DSTR_INIT; + int ok = 1; + + g = sslprf_rand(&md5, &sha, v[0].buf, v[0].len, v[1].buf, v[1].len); + dstr_ensure(&d, v[2].len); + d.len = v[2].len; + g->ops->fill(g, d.buf, d.len); + g->ops->destroy(g); + if (memcmp(v[2].buf, d.buf, d.len) != 0) { + ok = 0; + printf("\nfail sslprf:" + "\n\tkey = "); + type_hex.dump(&v[0], stdout); + printf("\n\tseed = "); type_hex.dump(&v[1], stdout); + printf("\n\texpected = "); type_hex.dump(&v[2], stdout); + printf("\n\tcalculated = "); type_hex.dump(&d, stdout); + putchar('\n'); + } + return (ok); +} + +static test_chunk defs[] = { + { "sslprf", v_generate, { &type_hex, &type_hex, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/t/sslprf"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/rand/sslprf.h b/rand/sslprf.h new file mode 100644 index 0000000..5f5467b --- /dev/null +++ b/rand/sslprf.h @@ -0,0 +1,135 @@ +/* -*-c-*- + * + * The SSL pseudo-random function + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_SSLPRF_H +#define CATACOMB_SSLPRF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GMAC_H +# include "gmac.h" +#endif + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct sslprf_ctx { + const gchash *co, *ci; /* Outer and inner hash functions */ + size_t ohashsz, ihashsz; /* Size of the hash outputs */ + ghash *h; /* Hash context from last time */ + const octet *k; /* Pointer to the secret */ + size_t ksz; /* Size of the secret buffer */ + const octet *sd; /* Pointer to the seed */ + size_t sdsz; /* Size of the seed buffer */ + unsigned i; /* Which iteration this is */ + octet *p; /* Pointer to output buffer */ + size_t sz; /* How many bytes are left */ +} sslprf_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @sslprf_init@ --- * + * + * Arguments: @sslprf_ctx *c@ = pointer to a context structure + * @const gchash *hco, *hci@ = outer and inner hash functions + * @const void *k@ = pointer to secret buffer + * @size_t ksz@ = size of the secret + * @const void *sd@ = pointer to seed buffer + * @size_t sdsz@ = size of the seed + * + * Returns: --- + * + * Use: Initializes an SSL generator context. + */ + +extern void sslprf_init(sslprf_ctx */*c*/, + const gchash */*hco*/, const gchash */*hci*/, + const void */*k*/, size_t /*ksz*/, + const void */*sd*/, size_t /*sdsz*/); + +/* --- @sslprf_encrypt@ --- * + * + * Arguments: @sslprf_ctx *c@ = pointer to a context structure + * @const void *src@ = pointer to source buffer + * @void *dest@ = pointer to destination buffer + * @size_t sz@ = size of the buffers + * + * Returns: --- + * + * Use: Encrypts data using the SSL pseudo-random function. If the + * destination pointer is null, the generator is spun and no + * output is produced; if the source pointer is null, raw output + * from the generator is written; otherwise, the source data is + * XORed with the generator output. + */ + +extern void sslprf_encrypt(sslprf_ctx */*c*/, + const void */*src*/, void */*dest*/, + size_t /*sz*/); + +/* --- @sslprf_free@ --- * + * + * Arguments: @sslprf_ctx@ = pointer to a context + * + * Returns: --- + * + * Use: Frees resources held in an SSL generator context. + */ + +extern void sslprf_free(sslprf_ctx */*c*/); + +/* ---@sslprf_rand@ --- * + * + * Arguments: @const gchash *hco, const gchash *hci@ = hash functions + * @const void *k@ = pointer to the key material + * @size_t ksz@ = size of the key material + * @const void *sd@ = pointer to the seed material + * @size_t sdsz@ = size of the seed material + * + * Returns: Pointer to generic random number generator interface. + * + * Use: Creates a generic generator which does TLS data expansion. + */ + +extern grand *sslprf_rand(const gchash */*hco*/, const gchash */*hci*/, + const void */*k*/, size_t /*ksz*/, + const void */*sd*/, size_t /*sdsz*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/rand/t/lcrand b/rand/t/lcrand new file mode 100644 index 0000000..6cc9dce --- /dev/null +++ b/rand/t/lcrand @@ -0,0 +1,32 @@ +# Test vectors for linear congruential generator + +lcrand { + # --- Standard stuff --- + + 0 271828183; + 271828183 996300340; + 996300340 228306184; + 228306184 1171467301; + 1171467301 3265426054; + 3265426054 2636049353; + 2636049353 3799512036; + 3799512036 2414373801; + 2414373801 1059474234; + 1059474234 2734911993; + 2734911993 239668818; + 239668818 1752802481; + 1752802481 34386946; + 34386946 1344553049; + 1344553049 1121833700; + 1121833700 636134543; + + # --- Particular outputs --- + + 2282233179 4294967290; + 2624567577 0; + 2966901975 1; + + # --- Fixed point --- + + 3223959250 3223959250; +} diff --git a/rand/t/sslprf b/rand/t/sslprf new file mode 100644 index 0000000..1538684 --- /dev/null +++ b/rand/t/sslprf @@ -0,0 +1,9 @@ +# SSL pseudo-random function + +sslprf { + # --- Generated using SSLeay --- + + 4837879a5040b1499a9cae62747e4857b090a0334683d8492d1d87933b58fa07523d4b8d0df762b62caddf7ac1304cd9 3ace3cb1ee080975da0dc748207c2bc0eb995746d0b37ab4789932a32ec5347b3ace3cb100000000b28539b8285cbc37622b65d8efcba4ad13eb42712c47d6f5 c15e3166e8a743e6b5da7d9cbcc08c2e4107887a70f2a4e16b54243276c48894569f2916c6cb610bb84b766b7283dca0a346fcce41683ec01f06c17e91758d5d31fbd1ca0a7d75b909035f04786f41efde988d20f5d1fecad337a3a23a16fde1beae5400bc3f357c; + + 53a82e555607a83890bfc633ff7f1d9ecc7d225f450dff3a8d46dd370033968fc456ae8b6fe3639c71fa2ba9d0f798aa 3ace3ca4ac5e36c228a5ce350f22261eadacdc48873b317843061aa679ed15e63ace3ca4000000009ba10a4a1837535a372de6784f037f6cc36c3113cdcc1465 798b2f8eee4cd6b35a220f8d446672762e8dd53bae7bd773877a1dfe0aa446b4274bafd546e94b1bbe4c2d56a6e60d06871b117a7d562859f36ce2082def1c134b1c117022fe449b2da85e6d2c8e763bec6e35889a315d8686e391c277377beb037dd91accddacd1; +} diff --git a/rand/t/tlsprf b/rand/t/tlsprf new file mode 100644 index 0000000..ace9066 --- /dev/null +++ b/rand/t/tlsprf @@ -0,0 +1,9 @@ +# TLS pseudo-random function + +tlsprf { + # --- Generated using SSLeay --- + + 3bfcccfb9e0bf44585b7a5ffcc7ff3b27be9462d5190664b96613a089f21c06e6f4788e3a963683d5cddea86982682dc 7365727665722066696e697368656416da63a061e9dee1884336c7345060d39d8d5fb7cd42a6b15bdd4eda44890edc41137ffe 4975842aca48f758ede77403; + + 3bfcccfb9e0bf44585b7a5ffcc7ff3b27be9462d5190664b96613a089f21c06e6f4788e3a963683d5cddea86982682dc 6b657920657870616e73696f6e3acb7aca624a68136e34e262b3e813ea234662db262a2c5791986fbe101707f7201dca6e8c753a5f2d8be10a69e08577ff9d6ec92d8c3ed17be5ef40f029ad11 be41fda006e5fc3423589714c374f7de3a8bc1315610a419acdf62aee16462dcec00aa5ca4e1d615a3d0b87a4cf10bc9cfc3509f2a9a879708092ce0bd54cc12b3fa2238569a8327cbd314f779f653783f5119a81986e49750b4e300e6cbbebcc782a65cc72f302c; +} diff --git a/rand/tlsprf.c b/rand/tlsprf.c new file mode 100644 index 0000000..3f055b0 --- /dev/null +++ b/rand/tlsprf.c @@ -0,0 +1,540 @@ +/* -*-c-*- + * + * The TLS pseudo-random function + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include "arena.h" +#include "gmac.h" +#include "grand.h" +#include "paranoia.h" +#include "tlsprf.h" + +/*----- The data expansion function ---------------------------------------*/ + +/* --- @tlsdx_init@ --- * + * + * Arguments: @tlsdx_ctx *c@ = pointer to a context + * @gmac *m@ = pointer to a generic MAC instance + * @const void *sd@ = pointer to the seed block + * @size_t sdsz@ = size of the seed block + * + * Returns: --- + * + * Use: Initializes a context for the TLS data expansion function. + * This doesn't take ownership of the MAC instance or the seed + * memory, nor does it allocate copies. + */ + +void tlsdx_init(tlsdx_ctx *c, gmac *m, const void *sd, size_t sdsz) +{ + c->k = m; + c->hashsz = GM_CLASS(c->k)->hashsz; + c->sd = sd; c->sdsz = sdsz; + + c->i = GM_INIT(c->k); + GH_HASH(c->i, sd, sdsz); + c->ai = GH_DONE(c->i, 0); + c->o = GM_INIT(c->k); + GH_HASH(c->o, c->ai, c->hashsz); + GH_HASH(c->o, sd, sdsz); + c->p = GH_DONE(c->o, 0); + c->sz = c->hashsz; +} + +/* --- @tlsdx_encrypt@ --- * + * + * Arguments: @tlsdx_ctx *c@ = pointer to a context + * @const void *src@ = pointer to source data + * @void *dest@ = pointer to destination buffer + * @size_t sz@ = size of buffer + * + * Returns: --- + * + * Use: Encrypts data using the TLS data expansion function. If the + * destination pointer is null, the generator is spun and no + * output is produced; if the source pointer is null, raw output + * from the generator is written; otherwise, the source data is + * XORed with the generator output. + */ + +void tlsdx_encrypt(tlsdx_ctx *c, const void *src, void *dest, size_t sz) +{ + const octet *s = src; + octet *d = dest; + ghash *h; + size_t i; + size_t n; + + while (sz) { + if (c->sz) + n = c->sz; + else { + h = GM_INIT(c->k); + GH_HASH(h, c->ai, c->hashsz); + c->ai = GH_DONE(h, 0); + GH_DESTROY(c->i); + c->i = h; + GH_DESTROY(c->o); + h = c->o = GM_INIT(c->k); + GH_HASH(h, c->ai, c->hashsz); + GH_HASH(h, c->sd, c->sdsz); + c->p = GH_DONE(h, 0); + c->sz = n = c->hashsz; + } + if (n > sz) + n = sz; + if (d) { + if (!s) + memcpy(d, c->p, n); + else { + for (i = 0; i < n; i++) d[i] = s[i] ^ c->p[i]; + s += n; + } + d += n; + } + c->p += n; + c->sz -= n; + sz -= n; + } +} + +/* --- @tlsdx_free@ --- * + * + * Arguments: @tlsdx_ctx *c@ = pointer to the context block + * + * Returns: --- + * + * Use: Frees a context for the TLS data expansion function + */ + +void tlsdx_free(tlsdx_ctx *c) +{ + GH_DESTROY(c->i); + GH_DESTROY(c->o); +} + +/* --- Generic random number generator --- */ + +typedef struct dx_grctx { + grand r; + grand_ops ops; + tlsdx_ctx dx; +} dx_grctx; + +static void dx_grdestroy(grand *r) +{ + dx_grctx *g = (dx_grctx *)r; + xfree((char *)g->ops.name); + xfree((octet *)g->dx.sd); + g->dx.k->ops->destroy(g->dx.k); + tlsdx_free(&g->dx); + BURN(*g); + S_DESTROY(g); +} + +static void dx_seed(dx_grctx *g, const void *p, size_t sz) +{ + octet *q; + xfree((octet *)g->dx.sd); + g->dx.sd = q = xmalloc(sz); + memcpy(q, p, sz); + g->dx.sdsz = sz; +} + +static int dx_grmisc(grand *r, unsigned op, ...) +{ + dx_grctx *g = (dx_grctx *)r; + va_list ap; + int rc = 0; + uint32 i; + octet buf[4]; + va_start(ap, op); + + switch (op) { + case GRAND_CHECK: + switch (va_arg(ap, unsigned)) { + case GRAND_CHECK: + case GRAND_SEEDINT: + case GRAND_SEEDUINT32: + case GRAND_SEEDBLOCK: + case GRAND_SEEDRAND: + rc = 1; + break; + default: + rc = 0; + break; + } + break; + case GRAND_SEEDINT: + i = va_arg(ap, unsigned); + STORE32(buf, i); + dx_seed(g, buf, sizeof(buf)); + break; + case GRAND_SEEDUINT32: + i = va_arg(ap, uint32); + STORE32(buf, i); + dx_seed(g, buf, sizeof(buf)); + break; + case GRAND_SEEDBLOCK: { + const void *p = va_arg(ap, const void *); + size_t sz = va_arg(ap, size_t); + dx_seed(g, p, sz); + } break; + case GRAND_SEEDRAND: { + grand *rr = va_arg(ap, grand *); + octet buf[16]; + rr->ops->fill(rr, buf, sizeof(buf)); + dx_seed(g, buf, sizeof(buf)); + } break; + default: + GRAND_BADOP; + break; + } + + va_end(ap); + return (rc); +} + +static octet dx_grbyte(grand *r) +{ + dx_grctx *g = (dx_grctx *)r; + octet o; + tlsdx_encrypt(&g->dx, 0, &o, 1); + return (o); +} + +static uint32 dx_grword(grand *r) +{ + dx_grctx *g = (dx_grctx *)r; + octet b[4]; + tlsdx_encrypt(&g->dx, 0, &b, sizeof(b)); + return (LOAD32(b)); +} + +static void dx_grfill(grand *r, void *p, size_t sz) +{ + dx_grctx *g = (dx_grctx *)r; + tlsdx_encrypt(&g->dx, 0, p, sz); +} + +static const grand_ops dx_grops = { + "", + GRAND_CRYPTO, 0, + dx_grmisc, dx_grdestroy, + dx_grword, dx_grbyte, dx_grword, grand_range, dx_grfill +}; + +/* ---@tlsdx_rand@ --- * + * + * Arguments: @const gcmac *mc@ = MAC function to use + * @const void *k@ = pointer to the key material + * @size_t ksz@ = size of the key material + * @const void *sd@ = pointer to the seed material + * @size_t sdsz@ = size of the seed material + * + * Returns: Pointer to generic random number generator interface. + * + * Use: Creates a generic generator which does TLS data expansion. + */ + +grand *tlsdx_rand(const gcmac *mc, const void *k, size_t ksz, + const void *sd, size_t sdsz) +{ + dx_grctx *g = S_CREATE(dx_grctx); + dstr d = DSTR_INIT; + gmac *m = GM_KEY(mc, k, ksz); + octet *q = xmalloc(sdsz); + memcpy(q, sd, sdsz); + dstr_putf(&d, "tlsdx(%s)", mc->name); + g->ops = dx_grops; + g->ops.name = xstrdup(d.buf); + g->r.ops = &g->ops; + dstr_destroy(&d); + tlsdx_init(&g->dx, m, q, sdsz); + return (&g->r); +} + +/* --- The actual very paranoid PRF ---------------------------------------*/ + +/* --- @tlsprf_init@ --- * + * + * Arguments: @tlsprf_ctx *c@ = pointer to context block + * @const gcmac *mcx, *mcy@ = left and right MAC functions + * @const void *k@ = pointer to the key material + * @size_t ksz@ = size of the key material + * @const void *sd@ = pointer to the seed material + * @size_t sdsz@ = size of the seed material + * + * Returns: --- + * + * Use: Initializes a TLS PRF context. + */ + +void tlsprf_init(tlsprf_ctx *c, const gcmac *mcx, const gcmac *mcy, + const void *k, size_t ksz, const void *sd, size_t sdsz) +{ + size_t n = (ksz + 1)/2; + const octet *kk = k; + tlsdx_init(&c->px, mcx->key(kk, n), sd, sdsz); + tlsdx_init(&c->py, mcy->key(kk + ksz - n, n), sd, sdsz); +} + +/* --- @tlsprf_encrypt@ --- * + * + * Arguments: @tlsprf_ctx *c@ = pointer to a context + * @const void *src@ = pointer to source data + * @void *dest@ = pointer to destination buffer + * @size_t sz@ = size of buffer + * + * Returns: --- + * + * Use: Encrypts data using the TLS pseudo-random function. If the + * destination pointer is null, the generator is spun and no + * output is produced; if the source pointer is null, raw output + * from the generator is written; otherwise, the source data is + * XORed with the generator output. + */ + +void tlsprf_encrypt(tlsprf_ctx *c, const void *src, void *dest, size_t sz) +{ + tlsdx_encrypt(&c->px, src, dest, sz); + tlsdx_encrypt(&c->py, dest, dest, sz); +} + +/* --- @tlsprf_free@ --- * + * + * Arguments: @tlsprf_ctx *c@ = pointer to a context + * + * Returns: --- + * + * Use: Frees a TLS PRF context. + */ + +void tlsprf_free(tlsprf_ctx *c) +{ + c->px.k->ops->destroy(c->px.k); + c->py.k->ops->destroy(c->py.k); + tlsdx_free(&c->px); + tlsdx_free(&c->py); +} + +/* --- Generic random number generator --- */ + +typedef struct prf_grctx { + grand r; + grand_ops ops; + tlsprf_ctx prf; +} prf_grctx; + +static void prf_grdestroy(grand *r) +{ + prf_grctx *g = (prf_grctx *)r; + xfree((char *)g->ops.name); + xfree((octet *)g->prf.px.sd); + tlsprf_free(&g->prf); + BURN(*g); + S_DESTROY(g); +} + +static void prf_seed(prf_grctx *g, const void *p, size_t sz) +{ + octet *q; + + xfree((octet *)g->prf.px.sz); + g->prf.px.sd = g->prf.py.sd = q = xmalloc(sz); + memcpy(q, p, sz); + g->prf.px.sdsz = g->prf.py.sdsz = sz; +} + +static int prf_grmisc(grand *r, unsigned op, ...) +{ + prf_grctx *g = (prf_grctx *)r; + va_list ap; + int rc = 0; + uint32 i; + octet buf[4]; + va_start(ap, op); + + switch (op) { + case GRAND_CHECK: + switch (va_arg(ap, unsigned)) { + case GRAND_CHECK: + case GRAND_SEEDINT: + case GRAND_SEEDUINT32: + case GRAND_SEEDBLOCK: + case GRAND_SEEDRAND: + rc = 1; + break; + default: + rc = 0; + break; + } + break; + case GRAND_SEEDINT: + i = va_arg(ap, unsigned); + STORE32(buf, i); + prf_seed(g, buf, sizeof(buf)); + break; + case GRAND_SEEDUINT32: + i = va_arg(ap, uint32); + STORE32(buf, i); + prf_seed(g, buf, sizeof(buf)); + break; + case GRAND_SEEDBLOCK: { + const void *p = va_arg(ap, const void *); + size_t sz = va_arg(ap, size_t); + prf_seed(g, p, sz); + } break; + case GRAND_SEEDRAND: { + grand *rr = va_arg(ap, grand *); + octet buf[16]; + rr->ops->fill(rr, buf, sizeof(buf)); + prf_seed(g, buf, sizeof(buf)); + } break; + default: + GRAND_BADOP; + break; + } + + va_end(ap); + return (rc); +} + +static octet prf_grbyte(grand *r) +{ + prf_grctx *g = (prf_grctx *)r; + octet o; + tlsprf_encrypt(&g->prf, 0, &o, 1); + return (o); +} + +static uint32 prf_grword(grand *r) +{ + prf_grctx *g = (prf_grctx *)r; + octet b[4]; + tlsprf_encrypt(&g->prf, 0, &b, sizeof(b)); + return (LOAD32(b)); +} + +static void prf_grfill(grand *r, void *p, size_t sz) +{ + prf_grctx *g = (prf_grctx *)r; + tlsprf_encrypt(&g->prf, 0, p, sz); +} + +static const grand_ops prf_grops = { + "", + GRAND_CRYPTO, 0, + prf_grmisc, prf_grdestroy, + prf_grword, prf_grbyte, prf_grword, grand_range, prf_grfill +}; + +/* ---@tlsprf_rand@ --- * + * + * Arguments: @const gcmac *mcx, *mcy@ = MAC function to use + * @const void *k@ = pointer to the key material + * @size_t ksz@ = size of the key material + * @const void *sd@ = pointer to the seed material + * @size_t sdsz@ = size of the seed material + * + * Returns: Pointer to generic random number generator interface. + * + * Use: Creates a generic generator which does TLS data expansion. + */ + +grand *tlsprf_rand(const gcmac *mcx, const gcmac *mcy, + const void *k, size_t ksz, const void *sd, size_t sdsz) +{ + prf_grctx *g = S_CREATE(prf_grctx); + dstr d = DSTR_INIT; + octet *q = xmalloc(sdsz); + memcpy(q, sd, sdsz); + dstr_putf(&d, "tlsprf(%s,%s)", mcx->name, mcy->name); + g->ops = prf_grops; + g->ops.name = xstrdup(d.buf); + g->r.ops = &g->ops; + dstr_destroy(&d); + tlsprf_init(&g->prf, mcx, mcy, k, ksz, q, sdsz); + return (&g->r); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include +#include + +#include +#include + +#include "sha-hmac.h" +#include "md5-hmac.h" + +static int v_generate(dstr *v) +{ + grand *g; + dstr d = DSTR_INIT; + int ok = 1; + + g = tlsprf_rand(&md5_hmac, &sha_hmac, + v[0].buf, v[0].len, v[1].buf, v[1].len); + dstr_ensure(&d, v[2].len); + d.len = v[2].len; + g->ops->fill(g, d.buf, d.len); + g->ops->destroy(g); + if (memcmp(v[2].buf, d.buf, d.len) != 0) { + ok = 0; + printf("\nfail tlsprf:" + "\n\tkey = "); + type_hex.dump(&v[0], stdout); + printf("\n\tseed = "); type_hex.dump(&v[1], stdout); + printf("\n\texpected = "); type_hex.dump(&v[2], stdout); + printf("\n\tcalculated = "); type_hex.dump(&d, stdout); + putchar('\n'); + } + return (ok); +} + +static test_chunk defs[] = { + { "tlsprf", v_generate, { &type_hex, &type_hex, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/t/tlsprf"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/rand/tlsprf.h b/rand/tlsprf.h new file mode 100644 index 0000000..f655e71 --- /dev/null +++ b/rand/tlsprf.h @@ -0,0 +1,203 @@ +/* -*-c-*- + * + * The TLS pseudo-random function + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_TLSPRF_H +#define CATACOMB_TLSPRF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GMAC_H +# include "gmac.h" +#endif + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct tlsdx_ctx { + gmac *k; /* The MAC key to use */ + size_t hashsz; /* Size of hash outputs */ + ghash *i, *o; /* Inner and outer hash contexts */ + const octet *sd; /* Pointer to seed buffer */ + size_t sdsz; /* Size of the seed buffer */ + octet *p; /* Pointer to buffered output */ + size_t sz; /* Bytes remaining in buffer */ + octet *ai; /* Pointer to inner result */ +} tlsdx_ctx; + +typedef struct tlsprf_ctx { + tlsdx_ctx px, py; +} tlsprf_ctx; + +/*----- The data expansion function ---------------------------------------*/ + +/* --- @tlsdx_init@ --- * + * + * Arguments: @tlsdx_ctx *c@ = pointer to a context + * @gmac *m@ = pointer to a generic MAC instance + * @const void *sd@ = pointer to the seed block + * @size_t sdsz@ = size of the seed block + * + * Returns: --- + * + * Use: Initializes a context for the TLS data expansion function. + * This doesn't take ownership of the MAC instance or the seed + * memory, nor does it allocate copies. + */ + +extern void tlsdx_init(tlsdx_ctx */*c*/, gmac */*m*/, + const void */*sd*/, size_t /*sdsz*/); + +/* --- @tlsdx_encrypt@ --- * + * + * Arguments: @tlsdx_ctx *c@ = pointer to a context + * @const void *src@ = pointer to source data + * @void *dest@ = pointer to destination buffer + * @size_t sz@ = size of buffer + * + * Returns: --- + * + * Use: Encrypts data using the TLS data expansion function. If the + * destination pointer is null, the generator is spun and no + * output is produced; if the source pointer is null, raw output + * from the generator is written; otherwise, the source data is + * XORed with the generator output. + */ + +extern void tlsdx_encrypt(tlsdx_ctx */*c*/, const void */*src*/, + void */*dest*/, size_t /*sz*/); + +/* --- @tlsdx_free@ --- * + * + * Arguments: @tlsdx_ctx *c@ = pointer to the context block + * + * Returns: --- + * + * Use: Frees a context for the TLS data expansion function + */ + +extern void tlsdx_free(tlsdx_ctx */*c*/); + +/* ---@tlsdx_rand@ --- * + * + * Arguments: @const gcmac *mc@ = MAC function to use + * @const void *k@ = pointer to the key material + * @size_t ksz@ = size of the key material + * @const void *sd@ = pointer to the seed material + * @size_t sdsz@ = size of the seed material + * + * Returns: Pointer to generic random number generator interface. + * + * Use: Creates a generic generator which does TLS data expansion. + */ + +extern grand *tlsdx_rand(const gcmac */*mc*/, + const void */*k*/, size_t /*ksz*/, + const void */*sd*/, size_t /*sdsz*/); + +/* --- The actual very paranoid PRF ---------------------------------------*/ + +/* --- @tlsprf_init@ --- * + * + * Arguments: @tlsprf_ctx *c@ = pointer to context block + * @const gcmac *mcx, *mcy@ = left and right MAC functions + * @const void *k@ = pointer to the key material + * @size_t ksz@ = size of the key material + * @const void *sd@ = pointer to the seed material + * @size_t sdsz@ = size of the seed material + * + * Returns: --- + * + * Use: Initializes a TLS PRF context. + */ + +extern void tlsprf_init(tlsprf_ctx */*c*/, + const gcmac */*mcx*/, const gcmac */*mcy*/, + const void */*k*/, size_t /*ksz*/, + const void */*sd*/, size_t /*sdsz*/); + +/* --- @tlsprf_encrypt@ --- * + * + * Arguments: @tlsprf_ctx *c@ = pointer to a context + * @const void *src@ = pointer to source data + * @void *dest@ = pointer to destination buffer + * @size_t sz@ = size of buffer + * + * Returns: --- + * + * Use: Encrypts data using the TLS pseudo-random function. If the + * destination pointer is null, the generator is spun and no + * output is produced; if the source pointer is null, raw output + * from the generator is written; otherwise, the source data is + * XORed with the generator output. + */ + +extern void tlsprf_encrypt(tlsprf_ctx */*c*/, + const void */*src*/, void */*dest*/, + size_t /*sz*/); + +/* --- @tlsprf_free@ --- * + * + * Arguments: @tlsprf_ctx *c@ = pointer to a context + * + * Returns: --- + * + * Use: Frees a TLS PRF context. + */ + +extern void tlsprf_free(tlsprf_ctx */*c*/); + +/* ---@tlsprf_rand@ --- * + * + * Arguments: @const gcmac *mcx, *mcy@ = MAC function to use + * @const void *k@ = pointer to the key material + * @size_t ksz@ = size of the key material + * @const void *sd@ = pointer to the seed material + * @size_t sdsz@ = size of the seed material + * + * Returns: Pointer to generic random number generator interface. + * + * Use: Creates a generic generator which does TLS data expansion. + */ + +extern grand *tlsprf_rand(const gcmac */*mcx*/, const gcmac */*mcy*/, + const void */*k*/, size_t /*ksz*/, + const void */*sd*/, size_t /*sdsz*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/rc2-tab.h b/rc2-tab.h deleted file mode 100644 index 4a0a29a..0000000 --- a/rc2-tab.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*-c-*- - * - * $Id: rc2-tab.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Substitution table for RC2 - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_RC2_TAB_H -#define CATACOMB_RC2_TAB_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- S-box table -------------------------------------------------------*/ - -#define RC2_PI { \ - 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, \ - 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, \ - 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, \ - 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, \ - 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, \ - 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, \ - 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, \ - 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, \ - 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, \ - 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, \ - 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, \ - 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, \ - 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, \ - 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, \ - 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, \ - 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, \ - 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, \ - 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, \ - 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, \ - 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, \ - 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, \ - 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, \ - 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, \ - 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, \ - 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, \ - 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, \ - 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, \ - 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, \ - 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, \ - 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, \ - 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, \ - 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad \ -} - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rc2.c b/rc2.c deleted file mode 100644 index 8241c06..0000000 --- a/rc2.c +++ /dev/null @@ -1,329 +0,0 @@ -/* -*-c-*- - * - * $Id: rc2.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The RC2 block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "paranoia.h" -#include "rc2.h" -#include "rc2-tab.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet rc2_keysz[] = { KSZ_RANGE, RC2_KEYSZ, 1, 128, 1 }; - -/*----- Important tables --------------------------------------------------*/ - -static const octet pi[256] = RC2_PI; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rc2_braindamage@ --- * - * - * Arguments: @rc2_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to key material - * @size_t sz@ = size of key material in bytes - * @unsigned eb@ = desired effective key size, in bits - * - * Returns: --- - * - * Use: Initializes an RC2 expanded key, and braindamages it to the - * requested effective key size. This is here for compatibility - * reasons. You should be using @rc2_init@ in normal code, - * which doesn't actually apply braindamage. - */ - -void rc2_braindamage(rc2_ctx *k, const void *buf, size_t sz, unsigned eb) -{ - unsigned t8; - uint16 tm; - unsigned i; - uint16 *kk; - octet l[128]; - - KSZ_ASSERT(rc2, sz); - - /* --- Compute the braindamage parameters --- */ - - t8 = (eb + 7) / 8; - tm = 0xff & ((1 << (8 + eb - 8 * t8)) - 1); - - /* --- Copy and expand the initial key --- */ - - if (sz > sizeof(l)) - sz = sizeof(l); - memcpy(l, buf, sz); - - for (i = sz; i < sizeof(l); i++) - l[i] = pi[U8(l[i - 1] + l[i - sz])]; - - /* --- Braindamage the key --- */ - - i = sizeof(l) - t8; - l[i] = pi[l[i] & tm]; - while (i) { - i--; - l[i] = pi[U8(l[i + 1] ^ l[i + t8])]; - } - - /* --- Write it to the key block --- */ - - kk = k->k; - for (i = 0; i < sizeof(l); i += 2) - *kk++ = LOAD16_L(l + i); - BURN(l); -} - -/* --- @rc2_init@ --- * - * - * Arguments: @rc2_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to key material - * @size_t sz@ = size of key material in bytes - * - * Returns: --- - * - * Use: Initializes an RC2 expanded key. The effective key size is - * set to be equal to the real key size, in bits. - */ - -void rc2_init(rc2_ctx *k, const void *buf, size_t sz) -{ - rc2_braindamage(k, buf, sz, sz * 8); -} - -/*----- Encryption and decryption -----------------------------------------*/ - -#define MIX(a, b, c, d, r, kk) do { \ - a += *kk++ + (d & c) + (~d & b); \ - a = ROL16(a, r); \ -} while (0) - -#define MASH(a, d, k) do { \ - a += k[d & 63]; \ -} while (0) - -#define UNMIX(a, b, c, d, r, kk) do { \ - a = ROR16(a, r); \ - a -= *--kk + (d & c) + (~d & b); \ -} while (0) - -#define UNMASH(a, d, k) do { \ - a -= k[d & 63]; \ -} while (0) - -/* --- @rc2_eblk@, @rc2_dblk@ --- * - * - * Arguments: @const rc2_ctx *k@ = pointer to RC2 context - * @const uint32 s[2]@ = pointer to source block - * @const uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -void rc2_eblk(const rc2_ctx *k, const uint32 *s, uint32 *dst) -{ - uint16 a = U16(s[0] >> 0), b = U16(s[0] >> 16); - uint16 c = U16(s[1] >> 0), d = U16(s[1] >> 16); - const uint16 *kk = k->k; - - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MASH(a, d, k->k); MASH(b, a, k->k); - MASH(c, b, k->k); MASH(d, c, k->k); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MASH(a, d, k->k); MASH(b, a, k->k); - MASH(c, b, k->k); MASH(d, c, k->k); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); - MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); - - dst[0] = a | (b << 16); dst[1] = c | (d << 16); -} - -void rc2_dblk(const rc2_ctx *k, const uint32 *s, uint32 *dst) -{ - uint16 a = U16(s[0] >> 0), b = U16(s[0] >> 16); - uint16 c = U16(s[1] >> 0), d = U16(s[1] >> 16); - const uint16 *kk = k->k + 64; - - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMASH(d, c, k->k); UNMASH(c, b, k->k); - UNMASH(b, a, k->k); UNMASH(a, d, k->k); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMASH(d, c, k->k); UNMASH(c, b, k->k); - UNMASH(b, a, k->k); UNMASH(a, d, k->k); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); - UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); - - dst[0] = a | (b << 16); dst[1] = c | (d << 16); -} - -/*----- Custom test rig ---------------------------------------------------* - * - * I need to test the braindamage feature. - */ - -#ifdef TEST_RIG - -#include -#include - -static int verify(dstr *v) -{ - rc2_ctx k; - uint32 p[RC2_BLKSZ / 4]; - uint32 c[RC2_BLKSZ / 4]; - uint32 d[RC2_BLKSZ / 4]; - dstr b = DSTR_INIT; - unsigned bd = *(unsigned *)v[1].buf; - int ok = 1; - - /* --- Initialize the key buffer --- */ - - dstr_ensure(&b, RC2_BLKSZ); - b.len = RC2_BLKSZ; - rc2_braindamage(&k, v[0].buf, v[0].len, bd); - BLKC_LOAD(RC2, p, v[2].buf); - BLKC_LOAD(RC2, c, v[3].buf); - - /* --- Test encryption --- */ - - BLKC_MOVE(RC2, d, p); - rc2_eblk(&k, d, d); - BLKC_STORE(RC2, b.buf, d); - if (memcmp(b.buf, v[3].buf, RC2_BLKSZ)) { - ok = 0; - printf("\nfail encryption:" - "\n\tkey = "); - type_hex.dump(&v[0], stdout); - printf("\n\tbraindamage= %u", bd); - printf("\n\tplaintext = "); type_hex.dump(&v[2], stdout); - printf("\n\texpected = "); type_hex.dump(&v[3], stdout); - printf("\n\tcalculated = "); type_hex.dump(&b, stdout); - putchar('\n'); - } - - /* --- Test decryption --- */ - - BLKC_MOVE(RC2, d, c); - rc2_dblk(&k, d, d); - BLKC_STORE(RC2, b.buf, d); - if (memcmp(b.buf, v[2].buf, RC2_BLKSZ)) { - ok = 0; - printf("\nfail decryption:" - "\n\tkey = "); - type_hex.dump(&v[0], stdout); - printf("\n\tbraindamage= %u", bd); - printf("\n\tciphertext = "); type_hex.dump(&v[3], stdout); - printf("\n\texpected = "); type_hex.dump(&v[2], stdout); - printf("\n\tcalculated = "); type_hex.dump(&b, stdout); - putchar('\n'); - } - - /* --- Return --- */ - - return (ok); -} - -static test_chunk defs[] = { - { "rc2", verify, { &type_hex, &type_int, &type_hex, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, defs, SRCDIR"/tests/rc2"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rc2.h b/rc2.h deleted file mode 100644 index 5d35b14..0000000 --- a/rc2.h +++ /dev/null @@ -1,130 +0,0 @@ -/* -*-c-*- - * - * $Id: rc2.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The RC2 block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the RC2 block cipher -------------------------------------* - * - * RC2 was designed by Ron Rivest, and for a long time was a trade secret of - * RSA Data Security Inc. Like RC4, it leaked out, and has now been - * described in RFC2268. The RC2 key schedule is known to have some - * weaknesses, although I'm not aware of any major results against the cipher - * itself. I'm also not aware of any legal problems with using the RC2 - * cipher. - * - * The oddest feature in the cipher is the key schedule. It expands the - * initial key material to 128 bytes, and then `brain-damages' it, according - * to a supplied `effective key-bits' parameter, before expanding the - * remaining key material back into the buffer. - * - * The key schedule allows second preimages to be computed trivially. - */ - -#ifndef CATACOMB_RC2_H -#define CATACOMB_RC2_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magical numbers ---------------------------------------------------*/ - -#define RC2_BLKSZ 8 -#define RC2_KEYSZ 16 -#define RC2_CLASS (N, L, 64) - -extern const octet rc2_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct rc2_ctx { - uint16 k[64]; -} rc2_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @rc2_braindamage@ --- * - * - * Arguments: @rc2_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to key material - * @size_t sz@ = size of key material in bytes - * @unsigned eb@ = desired effective key size, in bits - * - * Returns: --- - * - * Use: Initializes an RC2 expanded key, and braindamages it to the - * requested effective key size. This is here for compatibility - * reasons. You should be using @rc2_init@ in normal code, - * which doesn't actually apply braindamage. - */ - -extern void rc2_braindamage(rc2_ctx */*k*/, const void */*buf*/, - size_t /*sz*/, unsigned /*eb*/); - -/* --- @rc2_init@ --- * - * - * Arguments: @rc2_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to key material - * @size_t sz@ = size of key material in bytes - * - * Returns: --- - * - * Use: Initializes an RC2 expanded key. The effective key size is - * set to be equal to the real key size, in bits. - */ - -extern void rc2_init(rc2_ctx */*k*/, const void */*buf*/, size_t /*sz*/); - -/* --- @rc2_eblk@, @rc2_dblk@ --- * - * - * Arguments: @const rc2_ctx *k@ = pointer to RC2 context - * @const uint32 s[2]@ = pointer to source block - * @const uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void rc2_eblk(const rc2_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); -extern void rc2_dblk(const rc2_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rc4.c b/rc4.c deleted file mode 100644 index 83b5104..0000000 --- a/rc4.c +++ /dev/null @@ -1,369 +0,0 @@ -/* -*-c-*- - * - * $Id: rc4.c,v 1.6 2004/04/08 01:36:15 mdw Exp $ - * - * The alleged RC4 stream cipher - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include -#include - -#include "arena.h" -#include "gcipher.h" -#include "grand.h" -#include "paranoia.h" -#include "rc4.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet rc4_keysz[] = { KSZ_RANGE, RC4_KEYSZ, 1, 255, 1 }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rc4_addkey@ --- * - * - * Arguments: @rc4_ctx *ctx@ = pointer to context to key - * @const void *k@ = pointer to key data to use - * @size_t sz@ = size of the key data - * - * Returns: --- - * - * Use: Mixes key data with an RC4 context. The RC4 context is not - * reset before mixing. This may be used to mix new key - * material with an existing RC4 context. - */ - -void rc4_addkey(rc4_ctx *ctx, const void *k, size_t sz) -{ - unsigned i, j; - const octet *p = k, *q = p + sz; - - KSZ_ASSERT(rc4, sz); - - for (i = j = 0; i < 256; i++) { - unsigned si = ctx->s[i]; - j = (j + si + *p++) & 0xff; - ctx->s[i] = ctx->s[j]; - ctx->s[j] = si; - if (p == q) - p = k; - } - - ctx->i = ctx->j = 0; -} - -/* --- @rc4_init@ --- * - * - * Arguments: @rc4_ctx *ctx@ = pointer to context to initialize - * @const void *k@ = pointer to key data to use - * @size_t sz@ = size of the key data - * - * Returns: --- - * - * Use: Initializes an RC4 context ready for use. - */ - -void rc4_init(rc4_ctx *ctx, const void *k, size_t sz) -{ - unsigned i; - - for (i = 0; i < 256; i++) - ctx->s[i] = i; - ctx->f = 0; - rc4_addkey(ctx, k, sz); -} - -/* --- @rc4_encrypt@ --- * - * - * Arguments: @rc4_ctx *ctx@ = pointer to context to use - * @const void *src@ = pointer to the source block - * @void *dest@ = pointer to the destination block - * @size_t sz@ = size of the block - * - * Returns: --- - * - * Use: Encrypts or decrypts a block of data. The destination may - * be null to just grind the generator around for a while. It's - * recommended that you say `@rc4_encrypt(&ctx, 0, 0, 1024)@' - * after initializing a new context, to prevent keystream - * guessing attacks. The source may be null to just extract a - * big lump of data from the generator. - */ - -void rc4_encrypt(rc4_ctx *ctx, const void *src, void *dest, size_t sz) -{ - const octet *s = src; - octet *d = dest; - - if (!d) - RC4_OPEN(ctx, while (sz) { unsigned x; RC4_BYTE(x); sz--; }); - else if (!s) - RC4_OPEN(ctx, while (sz) { RC4_BYTE(*d++); sz--; }); - else - RC4_OPEN(ctx, - while (sz) { unsigned x; RC4_BYTE(x); *d++ = *s++ ^ x; sz--; }); -} - -/*----- Generic cipher interface ------------------------------------------*/ - -typedef struct gctx { - gcipher c; - rc4_ctx rc4; -} gctx; - -static const gcipher_ops gops; - -static gcipher *ginit(const void *k, size_t sz) -{ - gctx *g = S_CREATE(gctx); - g->c.ops = &gops; - rc4_init(&g->rc4, k, sz); - return (&g->c); -} - -static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) -{ - gctx *g = (gctx *)c; - rc4_encrypt(&g->rc4, s, t, sz); -} - -static void gdestroy(gcipher *c) -{ - gctx *g = (gctx *)c; - BURN(*g); - S_DESTROY(g); -} - -static const gcipher_ops gops = { - &rc4, - gencrypt, gencrypt, gdestroy, 0, 0 -}; - -const gccipher rc4 = { - "rc4", rc4_keysz, 0, - ginit -}; - -/*----- Generic random number generator interface -------------------------*/ - -typedef struct grctx { - grand r; - rc4_ctx rc4; -} grctx; - -static void grdestroy(grand *r) -{ - grctx *g = (grctx *)r; - BURN(*g); - S_DESTROY(g); -} - -static int grmisc(grand *r, unsigned op, ...) -{ - grctx *g = (grctx *)r; - va_list ap; - int rc = 0; - uint32 i; - octet buf[4]; - va_start(ap, op); - - switch (op) { - case GRAND_CHECK: - switch (va_arg(ap, unsigned)) { - case GRAND_CHECK: - case GRAND_SEEDINT: - case GRAND_SEEDUINT32: - case GRAND_SEEDBLOCK: - case GRAND_SEEDRAND: - rc = 1; - break; - default: - rc = 0; - break; - } - break; - case GRAND_SEEDINT: - i = va_arg(ap, unsigned); - STORE32(buf, i); - rc4_addkey(&g->rc4, buf, sizeof(buf)); - break; - case GRAND_SEEDUINT32: - i = va_arg(ap, uint32); - STORE32(buf, i); - rc4_addkey(&g->rc4, buf, sizeof(buf)); - break; - case GRAND_SEEDBLOCK: { - const void *p = va_arg(ap, const void *); - size_t sz = va_arg(ap, size_t); - rc4_addkey(&g->rc4, p, sz); - } break; - case GRAND_SEEDRAND: { - grand *rr = va_arg(ap, grand *); - octet buf[16]; - rr->ops->fill(rr, buf, sizeof(buf)); - rc4_addkey(&g->rc4, buf, sizeof(buf)); - } break; - default: - GRAND_BADOP; - break; - } - - va_end(ap); - return (rc); -} - -static octet grbyte(grand *r) -{ - grctx *g = (grctx *)r; - octet o; - RC4_OPEN(&g->rc4, RC4_BYTE(o);); - return (o); -} - -static uint32 grword(grand *r) -{ - grctx *g = (grctx *)r; - octet b[4]; - int i; - RC4_OPEN(&g->rc4, - for (i = 0; i < sizeof(b); i++) - RC4_BYTE(b[i]);); - return (LOAD32(b)); -} - -static void grfill(grand *r, void *p, size_t sz) -{ - grctx *g = (grctx *)r; - rc4_encrypt(&g->rc4, 0, p, sz); -} - -static const grand_ops grops = { - "rc4", - GRAND_CRYPTO, 0, - grmisc, grdestroy, - grword, grbyte, grword, grand_range, grfill -}; - -/* --- @rc4_rand@ --- * - * - * Arguments: @const void *k@ = pointer to key material - * @size_t sz@ = size of key material - * - * Returns: Pointer to generic random number generator interface. - * - * Use: Creates a random number interface wrapper around an - * OFB-mode block cipher. - */ - -grand *rc4_rand(const void *k, size_t sz) -{ - grctx *g = S_CREATE(grctx); - g->r.ops = &grops; - rc4_init(&g->rc4, k, sz); - return (&g->r); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include -#include - -#include -#include - -static int v_encrypt(dstr *v) -{ - rc4_ctx ctx; - dstr d = DSTR_INIT; - int ok = 1; - - rc4_init(&ctx, v[0].buf, v[0].len); - dstr_ensure(&d, v[1].len); - d.len = v[1].len; - rc4_encrypt(&ctx, v[1].buf, d.buf, d.len); - - if (memcmp(v[2].buf, d.buf, d.len) != 0) { - ok = 0; - printf("\nfail encryption:" - "\n\tkey = "); - type_hex.dump(&v[0], stdout); - printf("\n\tplaintext = "); type_hex.dump(&v[1], stdout); - printf("\n\texpected = "); type_hex.dump(&v[2], stdout); - printf("\n\tcalculated = "); type_hex.dump(&d, stdout); - putchar('\n'); - } - - return (ok); -} - -static int v_generate(dstr *v) -{ - rc4_ctx ctx; - dstr d = DSTR_INIT; - int ok = 1; - - rc4_init(&ctx, v[0].buf, v[0].len); - rc4_encrypt(&ctx, 0, 0, *(int *)v[1].buf); - dstr_ensure(&d, v[2].len); - d.len = v[2].len; - rc4_encrypt(&ctx, 0, d.buf, d.len); - - if (memcmp(v[2].buf, d.buf, d.len) != 0) { - ok = 0; - printf("\nfail generation:" - "\n\tkey = "); - type_hex.dump(&v[0], stdout); - printf("\n\tskip len = %i", *(int *)v[1].buf); - printf("\n\texpected = "); type_hex.dump(&v[2], stdout); - printf("\n\tcalculated = "); type_hex.dump(&d, stdout); - putchar('\n'); - } - - return (ok); -} - -static test_chunk defs[] = { - { "rc4-encrypt", v_encrypt, { &type_hex, &type_hex, &type_hex, 0 } }, - { "rc4-generate", v_generate, { &type_hex, &type_int, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, defs, SRCDIR"/tests/rc4"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rc4.h b/rc4.h deleted file mode 100644 index 7df1348..0000000 --- a/rc4.h +++ /dev/null @@ -1,197 +0,0 @@ -/* -*-c-*- - * - * $Id: rc4.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * The alleged RC4 stream cipher - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on RC4 ------------------------------------------------------* - * - * RC4 is a stream cipher desgigned by Ron Rivest. For a while RC4 was a - * trade secret of RSA Data Security, Inc., but somehow source code for a - * cipher which interworks with RC4 was posted to the Cypherpunks mailing - * list. - */ - -#ifndef CATACOMB_RC4_H -#define CATACOMB_RC4_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct rc4_ctx { - unsigned i, j; /* Indices into the @S@ table */ - unsigned f; /* Flags word */ - octet s[256]; /* The ever-changing @S@ table */ -} rc4_ctx; - -#define RC4F_OPEN 1u - -/*----- Macros ------------------------------------------------------------*/ - -/* --- @RC4_OPEN@ --- * - * - * Arguments: @ctx@ = pointer to an RC4 context - * @guts@ = code to perform within the RC4 context - * - * Use: Performs some code within an RC4 context. Some of the - * parameters are extracted from the context and held in local - * variables for speed. Multiple calls to @RC4_BYTE@ may be - * made within the open context. A context must only be - * opened once at a time. - */ - -#define RC4_OPEN(ctx, guts) do { \ - unsigned _rc4_i = (ctx)->i; \ - unsigned _rc4_j = (ctx)->j; \ - octet *_rc4_s = (ctx)->s; \ - \ - assert(((void)"RC4 context may only be opened once at a time", \ - ((ctx)->f & RC4F_OPEN) == 0)); \ - (ctx)->f |= RC4F_OPEN; \ - \ - guts \ - \ - (ctx)->f &= ~RC4F_OPEN; \ - (ctx)->i = _rc4_i; \ - (ctx)->j = _rc4_j; \ -} while (0) - -/* --- @RC4_BYTE@ --- * - * - * Arguments: @x@ = output variable to set - * - * Use: Extracts an octet from the lexically innermost open RC4 - * context and places it in the variable @x@. - */ - -#define RC4_BYTE(x) do { \ - unsigned _si, _sj; \ - _rc4_i = (_rc4_i + 1) & 0xff; \ - _si = _rc4_s[_rc4_i]; \ - _rc4_j = (_rc4_j + _si) & 0xff; \ - _sj = _rc4_s[_rc4_j]; \ - _rc4_s[_rc4_i] = _sj; \ - _rc4_s[_rc4_j] = _si; \ - (x) = _rc4_s[(_si + _sj) & 0xff]; \ -} while (0) - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @rc4_addkey@ --- * - * - * Arguments: @rc4_ctx *ctx@ = pointer to context to key - * @const void *k@ = pointer to key data to use - * @size_t sz@ = size of the key data - * - * Returns: --- - * - * Use: Mixes key data with an RC4 context. The RC4 context is not - * reset before mixing. This may be used to mix new key - * material with an existing RC4 context. - */ - -extern void rc4_addkey(rc4_ctx */*ctx*/, const void */*k*/, size_t /*sz*/); - -/* --- @rc4_init@ --- * - * - * Arguments: @rc4_ctx *ctx@ = pointer to context to initialize - * @const void *k@ = pointer to key data to use - * @size_t sz@ = size of the key data - * - * Returns: --- - * - * Use: Initializes an RC4 context ready for use. - */ - -extern void rc4_init(rc4_ctx */*ctx*/, const void */*k*/, size_t /*sz*/); - -/* --- @rc4_encrypt@ --- * - * - * Arguments: @rc4_ctx *ctx@ = pointer to context to use - * @const void *src@ = pointer to the source block - * @void *dest@ = pointer to the destination block - * @size_t sz@ = size of the block - * - * Returns: --- - * - * Use: Encrypts or decrypts a block of data. The destination may - * be null to just grind the generator around for a while. It's - * recommended that you say `@rc4_encrypt(&ctx, 0, 0, 1024)@' - * after initializing a new context, to prevent keystream - * guessing attacks. The source may be null to just extract a - * big lump of data from the generator. - */ - -extern void rc4_encrypt(rc4_ctx */*ctx*/, - const void */*src*/, void */*dest*/, - size_t /*sz*/); - -/*----- Generic cipher interface ------------------------------------------*/ - -#define RC4_KEYSZ 16 -extern const octet rc4_keysz[]; - -extern const gccipher rc4; - -/*----- Generic random number generator interface -------------------------*/ - -/* --- @rc4_rand@ --- * - * - * Arguments: @const void *k@ = pointer to key material - * @size_t sz@ = size of key material - * - * Returns: Pointer to generic random number generator interface. - * - * Use: Creates a random number interface wrapper around an - * OFB-mode block cipher. - */ - -extern grand *rc4_rand(const void */*k*/, size_t /*sz*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rc5.c b/rc5.c deleted file mode 100644 index 306b5ec..0000000 --- a/rc5.c +++ /dev/null @@ -1,232 +0,0 @@ -/* -*-c-*- - * - * $Id: rc5.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The RC5-32/12 block cipher - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include -#include - -#include "arena.h" -#include "blkc.h" -#include "gcipher.h" -#include "rc5.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet rc5_keysz[] = { KSZ_RANGE, RC5_KEYSZ, 1, 255, 1 }; - -/*----- Internal magical constants ----------------------------------------*/ - -#define T ((RC5_ROUNDS + 1) * 2) -#define P 0xb7e15163 -#define Q 0x9e3779b9 - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rc5_init@ --- * - * - * Arguments: @rc5_ctx *k@ = pointer to a key block - * @const void *sbuf@ = pointer to key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Initializes an RC5 key block. - */ - -void rc5_init(rc5_ctx *k, const void *sbuf, size_t sz) -{ - uint32 *l; - size_t w; - - /* --- Set up the @L@ table --- * - * - * This is slightly unfortunately defined. - */ - - KSZ_ASSERT(rc5, sz); - - { - int i; - const octet *p = sbuf; - - /* --- Create the buffer --- */ - - w = (sz + 3) / 4; - l = XS_ALLOC(w * sizeof(uint32)); - - /* --- Extract the key material --- */ - - for (i = 0; sz > 3; i++) { - l[i] = LOAD32_L(p); - p += 4; - sz -= 4; - } - - /* --- Fix up the tail end --- */ - - if (sz) { - uint32 x = U8(*p++); - if (sz > 1) x |= (U8(*p++) << 8); - if (sz > 2) x |= (U8(*p++) << 16); - l[i] = x; - } - } - - /* --- Initialize the @S@ table --- */ - - { - int i; - - k->s[0] = P; - for (i = 1; i < T; i++) - k->s[i] = k->s[i - 1] + Q; - } - - /* --- Mix in the key --- */ - - { - int m = 3 * (w > T ? w : T); - int i, j, c; - uint32 a, b; - - for (c = i = j = a = b = 0; c < m; c++) { - uint32 x; - - x = k->s[i] + a + b; - k->s[i] = a = ROL32(x, 3); - i++; if (i >= T) i = 0; - - x = l[j] + a + b; - l[j] = b = ROL32(x, a + b); - j++; if (j >= w) j = 0; - } - } - - memset(l, 0, w * sizeof(uint32)); - XS_FREE(l); -} - -/* --- @EROUND@, @DROUND@ --- */ - -#define EROUND(x, y, k) do { \ - uint32 _x; \ - _x = x ^ y; x = ROL32(_x, y) + k[0]; \ - _x = y ^ x; y = ROL32(_x, x) + k[1]; \ - k += 2; \ -} while (0) - -#define DROUND(x, y, k) do { \ - uint32 _x; \ - k -= 2; \ - _x = y - k[1]; y = ROR32(_x, x) ^ x; \ - _x = x - k[0]; x = ROR32(_x, y) ^ y; \ -} while (0) - -/* --- @EBLK@, @DBLK@ --- */ - -#define EBLK(a, b, c, d, k) do { \ - uint32 _l, _r; \ - const uint32 *_k = (k)->s; \ - \ - _l = (a) + _k[0]; \ - _r = (b) + _k[1]; \ - _k += 2; \ - \ - EROUND(_l, _r, _k); \ - EROUND(_l, _r, _k); \ - EROUND(_l, _r, _k); \ - EROUND(_l, _r, _k); \ - EROUND(_l, _r, _k); \ - EROUND(_l, _r, _k); \ - EROUND(_l, _r, _k); \ - EROUND(_l, _r, _k); \ - EROUND(_l, _r, _k); \ - EROUND(_l, _r, _k); \ - EROUND(_l, _r, _k); \ - EROUND(_l, _r, _k); \ - (c) = _l; \ - (d) = _r; \ -} while (0) - -#define DBLK(a, b, c, d, k) do { \ - uint32 _l, _r; \ - const uint32 *_k = (k)->s + T; \ - \ - _l = (a); \ - _r = (b); \ - \ - DROUND(_l, _r, _k); \ - DROUND(_l, _r, _k); \ - DROUND(_l, _r, _k); \ - DROUND(_l, _r, _k); \ - DROUND(_l, _r, _k); \ - DROUND(_l, _r, _k); \ - DROUND(_l, _r, _k); \ - DROUND(_l, _r, _k); \ - DROUND(_l, _r, _k); \ - DROUND(_l, _r, _k); \ - DROUND(_l, _r, _k); \ - DROUND(_l, _r, _k); \ - \ - _k -= 2; \ - (d) = _r - _k[1]; \ - (c) = _l - _k[0]; \ -} while (0) - -/* --- @rc5_eblk@, @rc5_dblk@ --- * - * - * Arguments: @const rc5_ctx *k@ = pointer to RC5 context block - * @const uint32 s[2]@ = pointer to source block - * @uint32 *d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low level block encryption and decryption. - */ - -void rc5_eblk(const rc5_ctx *k, const uint32 *s, uint32 *d) -{ - EBLK(s[0], s[1], d[0], d[1], k); -} - -void rc5_dblk(const rc5_ctx *k, const uint32 *s, uint32 *d) -{ - DBLK(s[0], s[1], d[0], d[1], k); -} - -/* --- Test rig --- */ - -BLKC_TEST(RC5, rc5) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rc5.h b/rc5.h deleted file mode 100644 index c029832..0000000 --- a/rc5.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -*-c-*- - * - * $Id: rc5.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * The RC5-32/12 block cipher - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the RC5 block cipher -------------------------------------* - * - * RC5 was designed by Ron Rivest as a test vehicle for the use of data- - * dependent rotations in cryptographic transformations. The algorithm is - * covered by a patent held by RSA Security Inc. (US Patent# 5,724,428). - * It's vulnerable to some clever differential attacks, which can break it in - * about %$2^{44}$% chosen plaintexts. I don't recommend the use of this - * cipher. - */ - -#ifndef CATACOMB_RC5_H -#define CATACOMB_RC5_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -/*----- Magic numbers -----------------------------------------------------*/ - -#define RC5_ROUNDS 12 -#define RC5_KEYSZ 10 -#define RC5_BLKSZ 8 -#define RC5_CLASS (N, L, 64) - -extern const octet rc5_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct rc5_ctx { - uint32 s[2 * (RC5_ROUNDS + 1)]; -} rc5_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @rc5_init@ --- * - * - * Arguments: @rc5_ctx *k@ = pointer to a key block - * @const void *sbuf@ = pointer to key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Initializes an RC5 key block. - */ - -extern void rc5_init(rc5_ctx */*k*/, const void */*sbuf*/, size_t /*sz*/); - -/* --- @rc5_eblk@, @rc5_dblk@ --- * - * - * Arguments: @const rc5_ctx *k@ = pointer to RC5 context block - * @const uint32 s[2]@ = pointer to source block - * @uint32 *d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low level block encryption and decryption. - */ - -extern void rc5_eblk(const rc5_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); -extern void rc5_dblk(const rc5_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rho.c b/rho.c deleted file mode 100644 index a02eeba..0000000 --- a/rho.c +++ /dev/null @@ -1,300 +0,0 @@ -/* -*-c-*- - * - * $Id: rho.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Pollard's rho algorithm for discrete logs - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "fibrand.h" -#include "mp.h" -#include "mpmont.h" -#include "mprand.h" -#include "rho.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rho@ --- * - * - * Arguments: @rho_ctx *cc@ = pointer to the context structure - * @void *x, *y@ = two (equal) base values (try 1) - * @mp *a, *b@ = logs of %$x$% (see below) - * - * Returns: The discrete logarithm %$\log_g a$%, or null if the algorithm - * failed. (This is unlikely, though possible.) - * - * Use: Uses Pollard's rho algorithm to compute discrete logs in the - * group %$G$% generated by %$g$%. - * - * The algorithm works by finding a cycle in a pseudo-random - * walk. The function @ops->split@ should return an element - * from %$\{\,0, 1, 2\,\}$% according to its argument, in order - * to determine the walk. At each step in the walk, we know a - * group element %$x \in G$% together with its representation as - * a product of powers of %$g$% and $%a$% (i.e., we know that - * %$x = g^\alpha a^\beta$% for some %$\alpha$%, %$\beta$%). - * - * Locating a cycle gives us a collision - * - * %$g^{\alpha} a^{\beta} = g^{\alpha'} a^{\beta'}$% - * - * Taking logs of both sides (to base %$g$%) gives us that - * - * %$\log a\equiv\frac{\alpha-\alpha'}{\beta'-\beta}\bmod{n}$% - * - * Good initial values are %$x = y = 1$% (the multiplicative - * identity of %$G$%) and %$\alpha\equiv\beta\equiv0\bmod{n}$%. - * If that doesn't work then start choosing more `interesting' - * values. - * - * Note that the algorithm requires minimal space but - * %$O(\sqrt{n})$% time. Don't do this on large groups, - * particularly if you can find a decent factor base. - * - * Finally, note that this function will free the input values - * when it's finished with them. This probably isn't a great - * problem. - */ - -static void step(rho_ctx *cc, void *x, mp **a, mp **b) -{ - switch (cc->ops->split(x)) { - case 0: - cc->ops->mul(x, cc->g, cc->c); - *a = mp_add(*a, *a, MP_ONE); - if (MP_CMP(*a, >=, cc->n)) - *a = mp_sub(*a, *a, cc->n); - break; - case 1: - cc->ops->sqr(x, cc->c); - *a = mp_lsl(*a, *a, 1); - if (MP_CMP(*a, >=, cc->n)) - *a = mp_sub(*a, *a, cc->n); - *b = mp_lsl(*b, *b, 1); - if (MP_CMP(*b, >=, cc->n)) - *b = mp_sub(*b, *b, cc->n); - break; - case 2: - cc->ops->mul(x, cc->a, cc->c); - *b = mp_add(*b, *b, MP_ONE); - if (MP_CMP(*b, >=, cc->n)) - *b = mp_sub(*b, *b, cc->n); - break; - } -} - -mp *rho(rho_ctx *cc, void *x, void *y, mp *a, mp *b) -{ - mp *aa = MP_COPY(a), *bb = MP_COPY(b); - mp *g; - - /* --- Grind through the random walk until we find a collision --- */ - - do { - step(cc, x, &a, &b); - step(cc, y, &aa, &bb); - step(cc, y, &aa, &bb); - } while (!cc->ops->eq(x, y)); - cc->ops->drop(x); - cc->ops->drop(y); - - /* --- Now sort out the mess --- */ - - aa = mp_sub(aa, a, aa); - bb = mp_sub(bb, bb, b); - g = MP_NEW; - mp_gcd(&g, &bb, 0, bb, cc->n); - if (!MP_EQ(g, MP_ONE)) { - mp_drop(aa); - aa = 0; - } else { - aa = mp_mul(aa, aa, bb); - mp_div(0, &aa, aa, cc->n); - } - - /* --- Done --- */ - - mp_drop(bb); - mp_drop(g); - mp_drop(a); - mp_drop(b); - return (aa); -} - -/* --- @rho_prime@ --- * - * - * Arguments: @mp *g@ = generator for the group - * @mp *a@ = value to find the logarithm of - * @mp *n@ = order of the group - * @mp *p@ = prime size of the underlying prime field - * - * Returns: The discrete logarithm %$\log_g a$%. - * - * Use: Computes discrete logarithms in a subgroup of a prime field. - */ - -static void prime_sqr(void *x, void *c) -{ - mp **p = x; - mp *a = *p; - a = mp_sqr(a, a); - a = mpmont_reduce(c, a, a); - *p = a; -} - -static void prime_mul(void *x, void *y, void *c) -{ - mp **p = x; - mp *a = *p; - a = mpmont_mul(c, a, a, y); - *p = a; -} - -static int prime_eq(void *x, void *y) -{ - return (MP_EQ(*(mp **)x, *(mp **)y)); -} - -static int prime_split(void *x) -{ - /* --- Notes on the splitting function --- * - * - * The objective is to produce a simple pseudorandom mapping from the - * underlying field \gf{p} to \{\,0, 1, 2\,\}$%. This is further - * constrained by the fact that we must not have %$1 \mapsto 1$% (since - * otherwise the stepping function above will loop). - * - * The function we choose is very simple: we take the least significant - * word from the integer, add one (to prevent the %$1 \mapsto 1$% property - * described above) and reduce modulo 3. This is slightly biased against - * the result 2, but this doesn't appear to be relevant. - */ - - return (((*(mp **)x)->v[0] + 1) % 3); -} - -static void prime_drop(void *x) -{ - MP_DROP(*(mp **)x); -} - -static const rho_ops prime_ops = { - prime_sqr, prime_mul, prime_eq, prime_split, prime_drop -}; - -mp *rho_prime(mp *g, mp *a, mp *n, mp *p) -{ - rho_ctx cc; - grand *r = 0; - mpmont mm; - mp *x, *y; - mp *aa, *bb; - mp *l; - - /* --- Initialization --- */ - - mpmont_create(&mm, p); - cc.ops = &prime_ops; - cc.c = &mm; - cc.n = n; - cc.g = mpmont_mul(&mm, MP_NEW, g, mm.r2); - cc.a = mpmont_mul(&mm, MP_NEW, a, mm.r2); - x = MP_COPY(mm.r); - y = MP_COPY(x); - aa = bb = MP_ZERO; - - /* --- The main loop --- */ - - while ((l = rho(&cc, &x, &y, aa, bb)) == 0) { - mp_expfactor f[2]; - - if (!r) - r = fibrand_create(0); - aa = mprand_range(MP_NEW, n, r, 0); - bb = mprand_range(MP_NEW, n, r, 0); - f[0].base = cc.g; f[0].exp = aa; - f[1].base = cc.a; f[1].exp = bb; - x = mpmont_mexpr(&mm, MP_NEW, f, 2); - y = MP_COPY(x); - } - - /* --- Throw everything away now --- */ - - if (r) - r->ops->destroy(r); - mp_drop(cc.g); - mp_drop(cc.a); - mpmont_destroy(&mm); - return (l); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#include "dh.h" - -int main(void) -{ - dh_param dp; - mp *x, *y; - grand *r = fibrand_create(0); - mpmont mm; - mp *l; - int ok; - - fputs("rho: ", stdout); - fflush(stdout); - - dh_gen(&dp, 32, 256, 0, r, pgen_evspin, 0); - x = mprand_range(MP_NEW, dp.q, r, 0); - mpmont_create(&mm, dp.p); - y = mpmont_exp(&mm, MP_NEW, dp.g, x); - mpmont_destroy(&mm); - l = rho_prime(dp.g, y, dp.q, dp.p); - if (MP_EQ(x, l)) { - fputs(". ok\n", stdout); - ok = 1; - } else { - fputs("\n*** rho (discrete logs) failed\n", stdout); - ok = 0; - } - - mp_drop(l); - mp_drop(x); - mp_drop(y); - r->ops->destroy(r); - dh_paramfree(&dp); - assert(mparena_count(MPARENA_GLOBAL) == 0); - - return (ok ? 0 : EXIT_FAILURE); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rho.h b/rho.h deleted file mode 100644 index 75bf7fa..0000000 --- a/rho.h +++ /dev/null @@ -1,131 +0,0 @@ -/* -*-c-*- - * - * $Id: rho.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Pollard's rho algorithm for discrete logs - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_RHO_H -#define CATACOMB_RHO_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- The group operations table --- */ - -typedef struct rho_ops { - void (*sqr)(void *x, void *c); - void (*mul)(void *x, void *y, void *c); - int (*eq)(void *x, void *y); - int (*split)(void *x); - void (*drop)(void *x); -} rho_ops; - -/* --- The Pollard's rho context structure --- */ - -typedef struct rho_ctx { - const rho_ops *ops; /* Group operations table */ - void *c; /* Context for group operations */ - void *g, *a; /* Generator and argument for log */ - mp *n; /* Cyclic group order */ -} rho_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @rho@ --- * - * - * Arguments: @rho_ctx *cc@ = pointer to the context structure - * @void *x, *y@ = two (equal) base values (try 1) - * @mp *a, *b@ = logs of %$x$% (see below) - * - * Returns: The discrete logarithm %$\log_g a$%, or null if the algorithm - * failed. (This is unlikely, though possible.) - * - * Use: Uses Pollard's rho algorithm to compute discrete logs in the - * group %$G$% generated by %$g$%. - * - * The algorithm works by finding a cycle in a pseudo-random - * walk. The function @ops->split@ should return an element - * from %$\{\,0, 1, 2\,\}$% according to its argument, in order - * to determine the walk. At each step in the walk, we know a - * group element %$x \in G$% together with its representation as - * a product of powers of %$g$% and $%a$% (i.e., we know that - * %$x = g^\alpha a^\beta$% for some %$\alpha$%, %$\beta$%). - * - * Locating a cycle gives us a collision - * - * %$g^{\alpha} a^{\beta} = g^{\alpha'} a^{\beta'}$% - * - * Taking logs of both sides (to base %$g$%) gives us that - * - * %$\log a\equiv\frac{\alpha-\alpha'}{\beta'-\beta}\bmod{n}$% - * - * Good initial values are %$x = y = 1$% (the multiplicative - * identity of %$G$%) and %$\alpha\equiv\beta\equiv0\bmod{n}$%. - * If that doesn't work then start choosing more `interesting' - * values. - * - * Note that the algorithm requires minimal space but - * %$O(\sqrt{n})$% time. Don't do this on large groups, - * particularly if you can find a decent factor base. - * - * Finally, note that this function will free the input values - * when it's finished with them. This probably isn't a great - * problem. - */ - -extern mp *rho(rho_ctx */*cc*/, void */*x*/, void */*y*/, - mp */*a*/, mp */*b*/); - -/* --- @rho_prime@ --- * - * - * Arguments: @mp *g@ = generator for the group - * @mp *a@ = value to find the logarithm of - * @mp *n@ = order of the group - * @mp *p@ = prime size of the underlying prime field - * - * Returns: The discrete logarithm %$\log_g a$%. - * - * Use: Computes discrete logarithms in a subgroup of a prime field. - */ - -extern mp *rho_prime(mp */*g*/, mp */*a*/, mp */*n*/, mp */*p*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rijndael-base.c b/rijndael-base.c deleted file mode 100644 index 5230cbc..0000000 --- a/rijndael-base.c +++ /dev/null @@ -1,135 +0,0 @@ -/* -*-c-*- - * - * $Id: rijndael-base.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Low-level stuff for all Rijndael block sizes - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "rijndael.h" -#include "rijndael-base.h" -#include "rijndael-tab.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet rijndael_keysz[] = { KSZ_RANGE, RIJNDAEL_KEYSZ, 4, 32, 4 }; - -/*----- Constant tables ---------------------------------------------------*/ - -const octet rijndael_s[256] = RIJNDAEL_S; -const octet rijndael_si[256] = RIJNDAEL_SI; -const uint32 rijndael_t[4][256] = RIJNDAEL_T; -const uint32 rijndael_ti[4][256] = RIJNDAEL_TI; -const uint32 rijndael_u[4][256] = RIJNDAEL_U; -const octet rijndael_rcon[] = RIJNDAEL_RCON; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rijndael_setup@ --- * - * - * Arguments: @rijndael_ctx *k@ = pointer to context to initialize - * @unsigned nb@ = number of words in the block - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Low-level key-scheduling. - */ - -void rijndael_setup(rijndael_ctx *k, unsigned nb, const void *buf, size_t sz) -{ - unsigned nk, nr, nw; - unsigned i, j, jj; - const octet *p; - uint32 ww; - - /* --- Sort out the key size --- */ - - KSZ_ASSERT(rijndael, sz); - nk = sz / 4; - - /* --- Select the number of rounds --- */ - - nr = (nk > nb ? nk : nb) + 6; - if (nr < 10) - nr = 10; - k->nr = nr; - - /* --- Fetch the first key words out --- */ - - p = buf; - for (i = 0; i < nk; i++) { - k->w[i] = LOAD32_B(p); - p += 4; - } - - /* --- Expand this material to fill the rest of the table --- */ - - nw = (nr + 1) * nb; - ww = k->w[i - 1]; - p = RCON; - for (; i < nw; i++) { - uint32 w = k->w[i - nk]; - if (i % nk == 0) { - ww = ROL32(ww, 8); - w ^= SUB(S, ww, ww, ww, ww) ^ (*p++ << 24); - } else if (nk > 6 && i % nk == 4) - w ^= SUB(S, ww, ww, ww, ww); - else - w ^= ww; - k->w[i] = ww = w; - } - - /* --- Make the decryption keys --- */ - - j = nw; i = 0; - - j -= nb; jj = 0; - for (; i < nb; i++) - k->wi[i] = k->w[j + jj++]; - - for (; i < nw - nb; i += nb) { - j -= nb; - for (jj = 0; jj < nb; jj++) { - uint32 w = k->w[j + jj]; - k->wi[i + jj] = MIX(U, w, w, w, w); - } - } - - j -= nb; jj = 0; - for (; i < nw; i++) - k->wi[i] = k->w[j + jj++]; -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rijndael-base.h b/rijndael-base.h deleted file mode 100644 index e3f168d..0000000 --- a/rijndael-base.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*-c-*- - * - * $Id: rijndael-base.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Internal header for Rijndael implementation - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_RIJNDAEL_BASE_H -#define CATACOMB_RIJNDAEL_BASE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -/*----- Constant tables ---------------------------------------------------*/ - -extern const octet rijndael_s[256]; -extern const octet rijndael_si[256]; -extern const uint32 rijndael_t[4][256]; -extern const uint32 rijndael_ti[4][256]; -extern const uint32 rijndael_u[4][256]; -extern const octet rijndael_rcon[]; - -#define S rijndael_s -#define SI rijndael_si -#define T rijndael_t -#define TI rijndael_ti -#define U rijndael_u -#define RCON rijndael_rcon - -/*----- Handy macros ------------------------------------------------------*/ - -#define SUB(s, a, b, c, d) \ - (s[U8((a) >> 24)] << 24 | s[U8((b) >> 16)] << 16 | \ - s[U8((c) >> 8)] << 8 | s[U8((d) >> 0)] << 0) - -#define MIX(t, a, b, c, d) \ - (t[0][U8((a) >> 24)] ^ t[1][U8((b) >> 16)] ^ \ - t[2][U8((c) >> 8)] ^ t[3][U8((d) >> 0)]) - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rijndael-mktab.c b/rijndael-mktab.c deleted file mode 100644 index 0ecdfcd..0000000 --- a/rijndael-mktab.c +++ /dev/null @@ -1,370 +0,0 @@ -/* -*-c-*- - * - * $Id: rijndael-mktab.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Build precomputed tables for the Rijndael block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include - -/*----- Magic variables ---------------------------------------------------*/ - -static octet s[256], si[256]; -static uint32 t[4][256], ti[4][256]; -static uint32 u[4][256]; -static octet rc[32]; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mul@ --- * - * - * Arguments: @unsigned x, y@ = polynomials over %$\gf{2^8}$% - * @unsigned m@ = modulus - * - * Returns: The product of two polynomials. - * - * Use: Computes a product of polynomials, quite slowly. - */ - -static unsigned mul(unsigned x, unsigned y, unsigned m) -{ - unsigned a = 0; - unsigned i; - - for (i = 0; i < 8; i++) { - if (y & 1) - a ^= x; - y >>= 1; - x <<= 1; - if (x & 0x100) - x ^= m; - } - - return (a); -} - -/* --- @sbox@ --- * - * - * Build the S-box. - * - * This is built from inversion in the multiplicative group of - * %$\gf{2^8}[x]/(p(x))$%, where %$p(x) = x^8 + x^4 + x^3 + x + 1$%, followed - * by an affine transformation treating inputs as vectors over %$\gf{2}$%. - * The result is a horrible function. - * - * The inversion is done slightly sneakily, by building log and antilog - * tables. Let %$a$% be an element of the finite field. If the inverse of - * %$a$% is %$a^{-1}$%, then %$\log a a^{-1} = 0$%. Hence - * %$\log a = -\log a^{-1}$%. This saves fiddling about with Euclidean - * algorithm. - */ - -#define S_MOD 0x11b - -static void sbox(void) -{ - octet log[256], alog[256]; - unsigned x; - unsigned i; - unsigned g; - - /* --- Find a suitable generator, and build log tables --- */ - - log[0] = 0; - for (g = 2; g < 256; g++) { - x = 1; - for (i = 0; i < 256; i++) { - log[x] = i; - alog[i] = x; - x = mul(x, g, S_MOD); - if (x == 1 && i != 254) - goto again; - } - goto done; - again:; - } - fprintf(stderr, "couldn't find generator\n"); - exit(EXIT_FAILURE); -done:; - - /* --- Now grind through and do the affine transform --- * - * - * The matrix multiply is an AND and a parity op. The add is an XOR. - */ - - for (i = 0; i < 256; i++) { - unsigned j; - unsigned m = 0xf8; - unsigned v = i ? alog[255 - log[i]] : 0; - - assert(i == 0 || mul(i, v, S_MOD) == 1); - - x = 0; - for (j = 0; j < 8; j++) { - unsigned r; - r = v & m; - r = (r >> 4) ^ r; - r = (r >> 2) ^ r; - r = (r >> 1) ^ r; - x = (x << 1) | (r & 1); - m = ROR8(m, 1); - } - x ^= 0x63; - s[i] = x; - si[x] = i; - } -} - -/* --- @tbox@ --- * - * - * Construct the t tables for doing the round function efficiently. - */ - -static void tbox(void) -{ - unsigned i; - - for (i = 0; i < 256; i++) { - uint32 a, b, c, d; - uint32 w; - - /* --- Build a forwards t-box entry --- */ - - a = s[i]; - b = a << 1; if (b & 0x100) b ^= S_MOD; - c = a ^ b; - w = (c << 0) | (a << 8) | (a << 16) | (b << 24); - t[0][i] = w; - t[1][i] = ROR32(w, 8); - t[2][i] = ROR32(w, 16); - t[3][i] = ROR32(w, 24); - - /* --- Build a backwards t-box entry --- */ - - a = mul(si[i], 0x0e, S_MOD); - b = mul(si[i], 0x09, S_MOD); - c = mul(si[i], 0x0d, S_MOD); - d = mul(si[i], 0x0b, S_MOD); - w = (d << 0) | (c << 8) | (b << 16) | (a << 24); - ti[0][i] = w; - ti[1][i] = ROR32(w, 8); - ti[2][i] = ROR32(w, 16); - ti[3][i] = ROR32(w, 24); - } -} - -/* --- @ubox@ --- * - * - * Construct the tables for performing the decryption key schedule. - */ - -static void ubox(void) -{ - unsigned i; - - for (i = 0; i < 256; i++) { - uint32 a, b, c, d; - uint32 w; - a = mul(i, 0x0e, S_MOD); - b = mul(i, 0x09, S_MOD); - c = mul(i, 0x0d, S_MOD); - d = mul(i, 0x0b, S_MOD); - w = (d << 0) | (c << 8) | (b << 16) | (a << 24); - u[0][i] = w; - u[1][i] = ROR32(w, 8); - u[2][i] = ROR32(w, 16); - u[3][i] = ROR32(w, 24); - } -} - -/* --- Round constants --- */ - -static void rcon(void) -{ - unsigned r = 1; - int i; - - for (i = 0; i < sizeof(rc); i++) { - rc[i] = r; - r <<= 1; - if (r & 0x100) - r ^= S_MOD; - } -} - -/* --- @main@ --- */ - -int main(void) -{ - int i, j; - - puts("\ -/* -*-c-*-\n\ - *\n\ - * Rijndael tables [generated]\n\ - */\n\ -\n\ -#ifndef CATACOMB_RIJNDAEL_TAB_H\n\ -#define CATACOMB_RIJNDAEL_TAB_H\n\ -"); - - /* --- Write out the S-box --- */ - - sbox(); - fputs("\ -/* --- The byte substitution and its inverse --- */\n\ -\n\ -#define RIJNDAEL_S { \\\n\ - ", stdout); - for (i = 0; i < 256; i++) { - printf("0x%02x", s[i]); - if (i == 255) - fputs(" \\\n}\n\n", stdout); - else if (i % 8 == 7) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - fputs("\ -#define RIJNDAEL_SI { \\\n\ - ", stdout); - for (i = 0; i < 256; i++) { - printf("0x%02x", si[i]); - if (i == 255) - fputs(" \\\n}\n\n", stdout); - else if (i % 8 == 7) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - /* --- Write out the big t tables --- */ - - tbox(); - fputs("\ -/* --- The big round tables --- */\n\ -\n\ -#define RIJNDAEL_T { \\\n\ - { ", stdout); - for (j = 0; j < 4; j++) { - for (i = 0; i < 256; i++) { - printf("0x%08lx", (unsigned long)t[j][i]); - if (i == 255) { - if (j == 3) - fputs(" } \\\n}\n\n", stdout); - else - fputs(" }, \\\n\ - \\\n\ - { ", stdout); - } else if (i % 4 == 3) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - } - - fputs("\ -#define RIJNDAEL_TI { \\\n\ - { ", stdout); - for (j = 0; j < 4; j++) { - for (i = 0; i < 256; i++) { - printf("0x%08lx", (unsigned long)ti[j][i]); - if (i == 255) { - if (j == 3) - fputs(" } \\\n}\n\n", stdout); - else - fputs(" }, \\\n\ - \\\n\ - { ", stdout); - } else if (i % 4 == 3) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - } - - /* --- Write out the big u tables --- */ - - ubox(); - fputs("\ -/* --- The decryption key schedule tables --- */\n\ -\n\ -#define RIJNDAEL_U { \\\n\ - { ", stdout); - for (j = 0; j < 4; j++) { - for (i = 0; i < 256; i++) { - printf("0x%08lx", (unsigned long)u[j][i]); - if (i == 255) { - if (j == 3) - fputs(" } \\\n}\n\n", stdout); - else - fputs(" }, \\\n\ - \\\n\ - { ", stdout); - } else if (i % 4 == 3) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - } - - /* --- Round constants --- */ - - rcon(); - fputs("\ -/* --- The round constants --- */\n\ -\n\ -#define RIJNDAEL_RCON { \\\n\ - ", stdout); - for (i = 0; i < sizeof(rc); i++) { - printf("0x%02x", rc[i]); - if (i == sizeof(rc) - 1) - fputs(" \\\n}\n\n", stdout); - else if (i % 8 == 7) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - /* --- Done --- */ - - puts("#endif"); - - if (fclose(stdout)) { - fprintf(stderr, "error writing data\n"); - exit(EXIT_FAILURE); - } - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rijndael.c b/rijndael.c deleted file mode 100644 index 9eb5f21..0000000 --- a/rijndael.c +++ /dev/null @@ -1,160 +0,0 @@ -/* -*-c-*- - * - * $Id: rijndael.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * The Rijndael block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "rijndael.h" -#include "rijndael-base.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rijndael_init@ --- * - * - * Arguments: @rijndael_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Initializes a Rijndael context with a particular key. This - * implementation of Rijndael doesn't impose any particular - * limits on the key size except that it must be multiple of 4 - * bytes long. 256 bits seems sensible, though. - */ - -void rijndael_init(rijndael_ctx *k, const void *buf, size_t sz) -{ - rijndael_setup(k, RIJNDAEL_BLKSZ / 4, buf, sz); -} - -/* --- @rijndael_eblk@, @rijndael_dblk@ --- * - * - * Arguments: @const rijndael_ctx *k@ = pointer to Rijndael context - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -#define DO(what, t, aa, bb, cc, dd, a, b, c, d, w) do { \ - aa = what(t, a, b, c, d) ^ *w++; \ - bb = what(t, b, c, d, a) ^ *w++; \ - cc = what(t, c, d, a, b) ^ *w++; \ - dd = what(t, d, a, b, c) ^ *w++; \ -} while (0) - -#define UNDO(what, t, aa, bb, cc, dd, a, b, c, d, w) do { \ - aa = what(t, a, d, c, b) ^ *w++; \ - bb = what(t, b, a, d, c) ^ *w++; \ - cc = what(t, c, b, a, d) ^ *w++; \ - dd = what(t, d, c, b, a) ^ *w++; \ -} while (0) - -void rijndael_eblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst) -{ - uint32 a = s[0], b = s[1], c = s[2], d = s[3]; - uint32 aa, bb, cc, dd; - const uint32 *w = k->w; - - a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; - aa = a; bb = b; cc = c; dd = d; - - switch (k->nr) { - case 14: - DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); - case 13: - DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); - case 12: - DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); - case 11: - DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); - case 10: - default: - DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); - DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); - DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); - DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); - DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); - DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); - DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); - DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); - DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); - } - DO(SUB, S, a, b, c, d, aa, bb, cc, dd, w); - - dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; -} - -void rijndael_dblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst) -{ - uint32 a = s[0], b = s[1], c = s[2], d = s[3]; - uint32 aa, bb, cc, dd; - const uint32 *w = k->wi; - - a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; - aa = a; bb = b; cc = c; dd = d; - - switch (k->nr) { - case 14: - UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); - case 13: - UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); - case 12: - UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); - case 11: - UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); - case 10: - default: - UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); - UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); - UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); - UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); - UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); - UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); - UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); - UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); - UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); - } - UNDO(SUB, SI, a, b, c, d, aa, bb, cc, dd, w); - - dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; -} - -BLKC_TEST(RIJNDAEL, rijndael) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rijndael.h b/rijndael.h deleted file mode 100644 index b1ba75f..0000000 --- a/rijndael.h +++ /dev/null @@ -1,128 +0,0 @@ -/* -*-c-*- - * - * $Id: rijndael.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * The Rijndael block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the Rijndael block cipher --------------------------------* - * - * Invented by Joan Daemen and Vincent Rijmen, Rijndael is a fast, elegant - * and relatively simple 128-bit block cipher. It was chosen by NIST to be - * the new Advanced Encryption Standard (AES) algorithm. - * - * Rijnadel appears to have a low security margin. I recommend waiting - * before using Rijndael for any sensitive applications. - */ - -#ifndef CATACOMB_RIJNDAEL_H -#define CATACOMB_RIJNDAEL_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magical numbers ---------------------------------------------------*/ - -#define RIJNDAEL_BLKSZ 16 -#define RIJNDAEL_KEYSZ 32 -#define RIJNDAEL_CLASS (N, B, 128) - -extern const octet rijndael_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -#define RIJNDAEL_MAXROUNDS 16 -#define RIJNDAEL_KWORDS ((RIJNDAEL_MAXROUNDS + 1) * 8) - -typedef struct rijndael_ctx { - unsigned nr; - uint32 w[RIJNDAEL_KWORDS]; - uint32 wi[RIJNDAEL_KWORDS]; -} rijndael_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @rijndael_setup@ --- * - * - * Arguments: @rijndael_ctx *k@ = pointer to context to initialize - * @unsigned nb@ = number of words in the block - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Low-level key-scheduling. Don't call this directly. - */ - -extern void rijndael_setup(rijndael_ctx */*k*/, unsigned /*nb*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @rijndael_init@ --- * - * - * Arguments: @rijndael_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Initializes a Rijndael context with a particular key. This - * implementation of Rijndael doesn't impose any particular - * limits on the key size except that it must be multiple of 4 - * bytes long. 256 bits seems sensible, though. - */ - -extern void rijndael_init(rijndael_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @rijndael_eblk@, @rijndael_dblk@ --- * - * - * Arguments: @const rijndael_ctx *k@ = pointer to Rijndael context - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void rijndael_eblk(const rijndael_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); -extern void rijndael_dblk(const rijndael_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rijndael192.c b/rijndael192.c deleted file mode 100644 index aef5955..0000000 --- a/rijndael192.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -*-c-*- - * - * $Id: rijndael192.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The Rijndael block cipher, 192-bit version - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "rijndael.h" -#include "rijndael192.h" -#include "rijndael-base.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rijndael192_init@ --- * - * - * Arguments: @rijndael_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Initializes a Rijndael context with a particular key. This - * implementation of Rijndael doesn't impose any particular - * limits on the key size except that it must be multiple of 4 - * bytes long. 256 bits seems sensible, though. - */ - -void rijndael192_init(rijndael_ctx *k, const void *buf, size_t sz) -{ - rijndael_setup(k, RIJNDAEL192_BLKSZ / 4, buf, sz); -} - -/* --- @rijndael192_eblk@, @rijndael192_dblk@ --- * - * - * Arguments: @const rijndael_ctx *k@ = pointer to Rijndael context - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -#define DO(what, t, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w) do { \ - aa = what(t, a, b, c, d) ^ *w++; \ - bb = what(t, b, c, d, e) ^ *w++; \ - cc = what(t, c, d, e, f) ^ *w++; \ - dd = what(t, d, e, f, a) ^ *w++; \ - ee = what(t, e, f, a, b) ^ *w++; \ - ff = what(t, f, a, b, c) ^ *w++; \ -} while (0) - -#define UNDO(what, t, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w) do { \ - aa = what(t, a, f, e, d) ^ *w++; \ - bb = what(t, b, a, f, e) ^ *w++; \ - cc = what(t, c, b, a, f) ^ *w++; \ - dd = what(t, d, c, b, a) ^ *w++; \ - ee = what(t, e, d, c, b) ^ *w++; \ - ff = what(t, f, e, d, c) ^ *w++; \ -} while (0) - -void rijndael192_eblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst) -{ - uint32 a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5]; - uint32 aa, bb, cc, dd, ee, ff; - const uint32 *w = k->w; - - a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; e ^= *w++; f ^= *w++; - aa = a; bb = b; cc = c; dd = d; ee = e; ff = f; - - switch (k->nr) { - case 14: - DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - case 13: - DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - case 12: - default: - DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - } - DO(SUB, S, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - - dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; dst[4] = e; dst[5] = f; -} - -void rijndael192_dblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst) -{ - uint32 a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5]; - uint32 aa, bb, cc, dd, ee, ff; - const uint32 *w = k->wi; - - a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; e ^= *w++; f ^= *w++; - aa = a; bb = b; cc = c; dd = d; ee = e; ff = f; - - switch (k->nr) { - case 14: - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - case 13: - UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - case 12: - default: - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); - } - UNDO(SUB, SI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); - - dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; dst[4] = e; dst[5] = f; -} - -BLKC_TEST(RIJNDAEL192, rijndael192) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rijndael192.h b/rijndael192.h deleted file mode 100644 index fb3d013..0000000 --- a/rijndael192.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -*-c-*- - * - * $Id: rijndael192.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The Rijndael block cipher, 192-bit version - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_RIJNDAEL192_H -#define CATACOMB_RIJNDAEL192_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_RIJNDAEL_H -# include "rijndael.h" -#endif - -/*----- Magical numbers ---------------------------------------------------*/ - -#define RIJNDAEL192_BLKSZ 24 -#define RIJNDAEL192_KEYSZ 32 -#define RIJNDAEL192_CLASS (N, B, 192) - -#define rijndael192_keysz rijndael_keysz - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct rijndael_ctx rijndael192_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @rijndael192_init@ --- * - * - * Arguments: @rijndael_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Initializes a Rijndael context with a particular key. This - * implementation of Rijndael doesn't impose any particular - * limits on the key size except that it must be multiple of 4 - * bytes long. 256 bits seems sensible, though. - */ - -extern void rijndael192_init(rijndael_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @rijndael_eblk@, @rijndael_dblk@ --- * - * - * Arguments: @const rijndael_ctx *k@ = pointer to Rijndael context - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void rijndael192_eblk(const rijndael_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); -extern void rijndael192_dblk(const rijndael_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rijndael256.c b/rijndael256.c deleted file mode 100644 index 27f06d7..0000000 --- a/rijndael256.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -*-c-*- - * - * $Id: rijndael256.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The Rijndael block cipher, 256-bit version - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "rijndael.h" -#include "rijndael256.h" -#include "rijndael-base.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rijndael256_init@ --- * - * - * Arguments: @rijndael_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Initializes a Rijndael context with a particular key. This - * implementation of Rijndael doesn't impose any particular - * limits on the key size except that it must be multiple of 4 - * bytes long. 256 bits seems sensible, though. - */ - -void rijndael256_init(rijndael_ctx *k, const void *buf, size_t sz) -{ - rijndael_setup(k, RIJNDAEL256_BLKSZ / 4, buf, sz); -} - -/* --- @rijndael256_eblk@, @rijndael256_dblk@ --- * - * - * Arguments: @const rijndael_ctx *k@ = pointer to Rijndael context - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -#define DO(what, t, \ - aa, bb, cc, dd, ee, ff, gg, hh, \ - a, b, c, d, e, f, g, h, w) do { \ - aa = what(t, a, b, d, e) ^ *w++; \ - bb = what(t, b, c, e, f) ^ *w++; \ - cc = what(t, c, d, f, g) ^ *w++; \ - dd = what(t, d, e, g, h) ^ *w++; \ - ee = what(t, e, f, h, a) ^ *w++; \ - ff = what(t, f, g, a, b) ^ *w++; \ - gg = what(t, g, h, b, c) ^ *w++; \ - hh = what(t, h, a, c, d) ^ *w++; \ -} while (0) - -#define UNDO(what, t, \ - aa, bb, cc, dd, ee, ff, gg, hh, \ - a, b, c, d, e, f, g, h, w) do { \ - aa = what(t, a, h, f, e) ^ *w++; \ - bb = what(t, b, a, g, f) ^ *w++; \ - cc = what(t, c, b, h, g) ^ *w++; \ - dd = what(t, d, c, a, h) ^ *w++; \ - ee = what(t, e, d, b, a) ^ *w++; \ - ff = what(t, f, e, c, b) ^ *w++; \ - gg = what(t, g, f, d, c) ^ *w++; \ - hh = what(t, h, g, e, d) ^ *w++; \ -} while (0) - -void rijndael256_eblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst) -{ - uint32 a = s[0], b = s[1], c = s[2], d = s[3]; - uint32 e = s[4], f = s[5], g = s[6], h = s[7]; - uint32 aa, bb, cc, dd, ee, ff, gg, hh; - const uint32 *w = k->w; - - a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; - e ^= *w++; f ^= *w++; g ^= *w++; h ^= *w++; - - DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - DO(SUB, S, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - - dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; - dst[4] = e; dst[5] = f; dst[6] = g; dst[7] = h; -} - -void rijndael256_dblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst) -{ - uint32 a = s[0], b = s[1], c = s[2], d = s[3]; - uint32 e = s[4], f = s[5], g = s[6], h = s[7]; - uint32 aa, bb, cc, dd, ee, ff, gg, hh; - const uint32 *w = k->wi; - - a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; - e ^= *w++; f ^= *w++; g ^= *w++; h ^= *w++; - - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); - UNDO(SUB, SI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); - - dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; - dst[4] = e; dst[5] = f; dst[6] = g; dst[7] = h; -} - -BLKC_TEST(RIJNDAEL256, rijndael256) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rijndael256.h b/rijndael256.h deleted file mode 100644 index 79ab09e..0000000 --- a/rijndael256.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -*-c-*- - * - * $Id: rijndael256.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The Rijndael block cipher, 256-bit version - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_RIJNDAEL256_H -#define CATACOMB_RIJNDAEL256_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_RIJNDAEL_H -# include "rijndael.h" -#endif - -/*----- Magical numbers ---------------------------------------------------*/ - -#define RIJNDAEL256_BLKSZ 32 -#define RIJNDAEL256_KEYSZ 32 -#define RIJNDAEL256_CLASS (N, B, 256) - -#define rijndael256_keysz rijndael_keysz - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct rijndael_ctx rijndael256_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @rijndael256_init@ --- * - * - * Arguments: @rijndael_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Initializes a Rijndael context with a particular key. This - * implementation of Rijndael doesn't impose any particular - * limits on the key size except that it must be multiple of 4 - * bytes long. 256 bits seems sensible, though. - */ - -extern void rijndael256_init(rijndael_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @rijndael_eblk@, @rijndael_dblk@ --- * - * - * Arguments: @const rijndael_ctx *k@ = pointer to Rijndael context - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void rijndael256_eblk(const rijndael_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); -extern void rijndael256_dblk(const rijndael_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rmd128.c b/rmd128.c deleted file mode 100644 index 10f56c4..0000000 --- a/rmd128.c +++ /dev/null @@ -1,358 +0,0 @@ -/* -*-c-*- - * - * $Id: rmd128.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The RIPEMD-128 message digest function - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "rmd128.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rmd128_compress@ --- * - * - * Arguments: @rmd128_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: RIPEMD-128 compression function. - */ - -void rmd128_compress(rmd128_ctx *ctx, const void *sbuf) -{ - uint32 a, b, c, d; - uint32 A, B, C, D; - uint32 buf[16]; - - /* --- Fetch the chaining variables --- */ - - a = A = ctx->a; - b = B = ctx->b; - c = C = ctx->c; - d = D = ctx->d; - - /* --- Fetch the buffer contents --- */ - - { - int i; - const octet *p; - - for (i = 0, p = sbuf; i < 16; i++, p += 4) - buf[i] = LOAD32_L(p); - } - - /* --- Definitions for round functions --- */ - -#define F(x, y, z) ((x) ^ (y) ^ (z)) -#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define H(x, y, z) (((x) | ~(y)) ^ (z)) -#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) - -#define T(w, x, y, z, i, r, f, k) do { \ - uint32 _t = w + f(x, y, z) + buf[i] + k; \ - w = ROL32(_t, r); \ -} while (0) - -#define F1(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000) -#define G1(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x5a827999) -#define H1(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x6ed9eba1) -#define I1(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x8f1bbcdc) - -#define F2(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x50a28be6) -#define G2(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x5c4dd124) -#define H2(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x6d703ef3) -#define I2(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000) - - /* --- First the left hand side --- */ - - F1(a, b, c, d, 0, 11); - F1(d, a, b, c, 1, 14); - F1(c, d, a, b, 2, 15); - F1(b, c, d, a, 3, 12); - F1(a, b, c, d, 4, 5); - F1(d, a, b, c, 5, 8); - F1(c, d, a, b, 6, 7); - F1(b, c, d, a, 7, 9); - F1(a, b, c, d, 8, 11); - F1(d, a, b, c, 9, 13); - F1(c, d, a, b, 10, 14); - F1(b, c, d, a, 11, 15); - F1(a, b, c, d, 12, 6); - F1(d, a, b, c, 13, 7); - F1(c, d, a, b, 14, 9); - F1(b, c, d, a, 15, 8); - - G1(a, b, c, d, 7, 7); - G1(d, a, b, c, 4, 6); - G1(c, d, a, b, 13, 8); - G1(b, c, d, a, 1, 13); - G1(a, b, c, d, 10, 11); - G1(d, a, b, c, 6, 9); - G1(c, d, a, b, 15, 7); - G1(b, c, d, a, 3, 15); - G1(a, b, c, d, 12, 7); - G1(d, a, b, c, 0, 12); - G1(c, d, a, b, 9, 15); - G1(b, c, d, a, 5, 9); - G1(a, b, c, d, 2, 11); - G1(d, a, b, c, 14, 7); - G1(c, d, a, b, 11, 13); - G1(b, c, d, a, 8, 12); - - H1(a, b, c, d, 3, 11); - H1(d, a, b, c, 10, 13); - H1(c, d, a, b, 14, 6); - H1(b, c, d, a, 4, 7); - H1(a, b, c, d, 9, 14); - H1(d, a, b, c, 15, 9); - H1(c, d, a, b, 8, 13); - H1(b, c, d, a, 1, 15); - H1(a, b, c, d, 2, 14); - H1(d, a, b, c, 7, 8); - H1(c, d, a, b, 0, 13); - H1(b, c, d, a, 6, 6); - H1(a, b, c, d, 13, 5); - H1(d, a, b, c, 11, 12); - H1(c, d, a, b, 5, 7); - H1(b, c, d, a, 12, 5); - - I1(a, b, c, d, 1, 11); - I1(d, a, b, c, 9, 12); - I1(c, d, a, b, 11, 14); - I1(b, c, d, a, 10, 15); - I1(a, b, c, d, 0, 14); - I1(d, a, b, c, 8, 15); - I1(c, d, a, b, 12, 9); - I1(b, c, d, a, 4, 8); - I1(a, b, c, d, 13, 9); - I1(d, a, b, c, 3, 14); - I1(c, d, a, b, 7, 5); - I1(b, c, d, a, 15, 6); - I1(a, b, c, d, 14, 8); - I1(d, a, b, c, 5, 6); - I1(c, d, a, b, 6, 5); - I1(b, c, d, a, 2, 12); - - /* --- And then the right hand side --- */ - - F2(A, B, C, D, 5, 8); - F2(D, A, B, C, 14, 9); - F2(C, D, A, B, 7, 9); - F2(B, C, D, A, 0, 11); - F2(A, B, C, D, 9, 13); - F2(D, A, B, C, 2, 15); - F2(C, D, A, B, 11, 15); - F2(B, C, D, A, 4, 5); - F2(A, B, C, D, 13, 7); - F2(D, A, B, C, 6, 7); - F2(C, D, A, B, 15, 8); - F2(B, C, D, A, 8, 11); - F2(A, B, C, D, 1, 14); - F2(D, A, B, C, 10, 14); - F2(C, D, A, B, 3, 12); - F2(B, C, D, A, 12, 6); - - G2(A, B, C, D, 6, 9); - G2(D, A, B, C, 11, 13); - G2(C, D, A, B, 3, 15); - G2(B, C, D, A, 7, 7); - G2(A, B, C, D, 0, 12); - G2(D, A, B, C, 13, 8); - G2(C, D, A, B, 5, 9); - G2(B, C, D, A, 10, 11); - G2(A, B, C, D, 14, 7); - G2(D, A, B, C, 15, 7); - G2(C, D, A, B, 8, 12); - G2(B, C, D, A, 12, 7); - G2(A, B, C, D, 4, 6); - G2(D, A, B, C, 9, 15); - G2(C, D, A, B, 1, 13); - G2(B, C, D, A, 2, 11); - - H2(A, B, C, D, 15, 9); - H2(D, A, B, C, 5, 7); - H2(C, D, A, B, 1, 15); - H2(B, C, D, A, 3, 11); - H2(A, B, C, D, 7, 8); - H2(D, A, B, C, 14, 6); - H2(C, D, A, B, 6, 6); - H2(B, C, D, A, 9, 14); - H2(A, B, C, D, 11, 12); - H2(D, A, B, C, 8, 13); - H2(C, D, A, B, 12, 5); - H2(B, C, D, A, 2, 14); - H2(A, B, C, D, 10, 13); - H2(D, A, B, C, 0, 13); - H2(C, D, A, B, 4, 7); - H2(B, C, D, A, 13, 5); - - I2(A, B, C, D, 8, 15); - I2(D, A, B, C, 6, 5); - I2(C, D, A, B, 4, 8); - I2(B, C, D, A, 1, 11); - I2(A, B, C, D, 3, 14); - I2(D, A, B, C, 11, 14); - I2(C, D, A, B, 15, 6); - I2(B, C, D, A, 0, 14); - I2(A, B, C, D, 5, 6); - I2(D, A, B, C, 12, 9); - I2(C, D, A, B, 2, 12); - I2(B, C, D, A, 13, 9); - I2(A, B, C, D, 9, 12); - I2(D, A, B, C, 7, 5); - I2(C, D, A, B, 10, 15); - I2(B, C, D, A, 14, 8); - - /* --- Recombine the two halves --- */ - - { - uint32 - tmp = ctx->b + c + D; - ctx->b = ctx->c + d + A; - ctx->c = ctx->d + a + B; - ctx->d = ctx->a + b + C; - ctx->a = tmp; - } -} - -/* --- @rmd128_init@ --- * - * - * Arguments: @rmd128_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void rmd128_init(rmd128_ctx *ctx) -{ - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; - ctx->off = 0; - ctx->nl = ctx->nh = 0; -} - -/* --- @rmd128_set@ --- * - * - * Arguments: @rmd128_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -void rmd128_set(rmd128_ctx *ctx, const void *buf, unsigned long count) -{ - const octet *p = buf; - ctx->a = LOAD32_L(p + 0); - ctx->b = LOAD32_L(p + 4); - ctx->c = LOAD32_L(p + 8); - ctx->d = LOAD32_L(p + 12); - ctx->off = 0; - ctx->nl = U32(count); - ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); -} - -/* --- @rmd128_hash@ --- * - * - * Arguments: @rmd128_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void rmd128_hash(rmd128_ctx *ctx, const void *buf, size_t sz) -{ - HASH_BUFFER(RMD128, rmd128, ctx, buf, sz); -} - -/* --- @rmd128_done@ --- * - * - * Arguments: @rmd128_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -void rmd128_done(rmd128_ctx *ctx, void *hash) -{ - octet *p = hash; - HASH_MD5STRENGTH(RMD128, rmd128, ctx); - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); -} - -/* --- @rmd128_state@ --- * - * - * Arguments: @rmd128_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @rmd128_set@. - */ - -unsigned long rmd128_state(rmd128_ctx *ctx, void *state) -{ - octet *p = state; - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); - return (ctx->nl | ((ctx->nh << 16) << 16)); -} - -/* --- Generic interface --- */ - -GHASH_DEF(RMD128, rmd128) - -/* --- Test code --- */ - -HASH_TEST(RMD128, rmd128) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rmd128.h b/rmd128.h deleted file mode 100644 index b121e3c..0000000 --- a/rmd128.h +++ /dev/null @@ -1,158 +0,0 @@ -/* -*-c-*- - * - * $Id: rmd128.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The RIPEMD-128 message digest function - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the RIPEMD-128 hash function -----------------------------* - * - * RIPEMD-128 was invented by Hans Dobbertin, Antoon Bosselaers and Bart - * Preneel, as a drop-in replacement for MD5 (with the same sized output). - * It's a cut-down version of RIPEMD-160, which should be used in preference. - */ - -#ifndef CATACOMB_RMD128_H -#define CATACOMB_RMD128_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define RMD128_BUFSZ 64 -#define RMD128_HASHSZ 16 -#define RMD128_STATESZ 16 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct rmd128_ctx { - uint32 a, b, c, d; /* Chaining variables */ - uint32 nl, nh; /* Byte count so far */ - unsigned off; /* Offset into buffer */ - octet buf[RMD128_BUFSZ]; /* Accumulation buffer */ -} rmd128_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @rmd128_compress@ --- * - * - * Arguments: @rmd128_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: RIPEMD-128 compression function. - */ - -extern void rmd128_compress(rmd128_ctx */*ctx*/, const void */*sbuf*/); - -/* --- @rmd128_init@ --- * - * - * Arguments: @rmd128_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -extern void rmd128_init(rmd128_ctx */*ctx*/); - -/* --- @rmd128_set@ --- * - * - * Arguments: @rmd128_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -extern void rmd128_set(rmd128_ctx */*ctx*/, - const void */*buf*/, unsigned long /*count*/); - -/* --- @rmd128_hash@ --- * - * - * Arguments: @rmd128_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -extern void rmd128_hash(rmd128_ctx */*ctx*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @rmd128_done@ --- * - * - * Arguments: @rmd128_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -extern void rmd128_done(rmd128_ctx */*ctx*/, void */*hash*/); - -/* --- @rmd128_state@ --- * - * - * Arguments: @rmd128_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @rmd128_set@. - */ - -extern unsigned long rmd128_state(rmd128_ctx */*ctx*/, void */*state*/); - -/*----- Generic hash interface --------------------------------------------*/ - -extern const gchash rmd128; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rmd160.c b/rmd160.c deleted file mode 100644 index f481209..0000000 --- a/rmd160.c +++ /dev/null @@ -1,401 +0,0 @@ -/* -*-c-*- - * - * $Id: rmd160.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * The RIPEMD-160 message digest function - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "rmd160.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rmd160_compress@ --- * - * - * Arguments: @rmd160_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: RIPEMD-160 compression function. - */ - -void rmd160_compress(rmd160_ctx *ctx, const void *sbuf) -{ - uint32 a, b, c, d, e; - uint32 A, B, C, D, E; - uint32 buf[16]; - - /* --- Fetch the chaining variables --- */ - - a = A = ctx->a; - b = B = ctx->b; - c = C = ctx->c; - d = D = ctx->d; - e = E = ctx->e; - - /* --- Fetch the buffer contents --- */ - - { - int i; - const octet *p; - - for (i = 0, p = sbuf; i < 16; i++, p += 4) - buf[i] = LOAD32_L(p); - } - - /* --- Definitions for round functions --- */ - -#define F(x, y, z) ((x) ^ (y) ^ (z)) -#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define H(x, y, z) (((x) | ~(y)) ^ (z)) -#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define J(x, y, z) ((x) ^ ((y) | ~(z))) - -#define T(v, w, x, y, z, i, r, f, k) do { \ - uint32 _t = v + f(w, x, y) + buf[i] + k; \ - v = ROL32(_t, r) + z; x = ROL32(x, 10); \ -} while (0) - -#define F1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000) -#define G1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x5a827999) -#define H1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6ed9eba1) -#define I1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x8f1bbcdc) -#define J1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0xa953fd4e) - -#define F2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0x50a28be6) -#define G2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x5c4dd124) -#define H2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6d703ef3) -#define I2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x7a6d76e9) -#define J2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000) - - /* --- First the left hand side --- */ - - F1(a, b, c, d, e, 0, 11); - F1(e, a, b, c, d, 1, 14); - F1(d, e, a, b, c, 2, 15); - F1(c, d, e, a, b, 3, 12); - F1(b, c, d, e, a, 4, 5); - F1(a, b, c, d, e, 5, 8); - F1(e, a, b, c, d, 6, 7); - F1(d, e, a, b, c, 7, 9); - F1(c, d, e, a, b, 8, 11); - F1(b, c, d, e, a, 9, 13); - F1(a, b, c, d, e, 10, 14); - F1(e, a, b, c, d, 11, 15); - F1(d, e, a, b, c, 12, 6); - F1(c, d, e, a, b, 13, 7); - F1(b, c, d, e, a, 14, 9); - F1(a, b, c, d, e, 15, 8); - - G1(e, a, b, c, d, 7, 7); - G1(d, e, a, b, c, 4, 6); - G1(c, d, e, a, b, 13, 8); - G1(b, c, d, e, a, 1, 13); - G1(a, b, c, d, e, 10, 11); - G1(e, a, b, c, d, 6, 9); - G1(d, e, a, b, c, 15, 7); - G1(c, d, e, a, b, 3, 15); - G1(b, c, d, e, a, 12, 7); - G1(a, b, c, d, e, 0, 12); - G1(e, a, b, c, d, 9, 15); - G1(d, e, a, b, c, 5, 9); - G1(c, d, e, a, b, 2, 11); - G1(b, c, d, e, a, 14, 7); - G1(a, b, c, d, e, 11, 13); - G1(e, a, b, c, d, 8, 12); - - H1(d, e, a, b, c, 3, 11); - H1(c, d, e, a, b, 10, 13); - H1(b, c, d, e, a, 14, 6); - H1(a, b, c, d, e, 4, 7); - H1(e, a, b, c, d, 9, 14); - H1(d, e, a, b, c, 15, 9); - H1(c, d, e, a, b, 8, 13); - H1(b, c, d, e, a, 1, 15); - H1(a, b, c, d, e, 2, 14); - H1(e, a, b, c, d, 7, 8); - H1(d, e, a, b, c, 0, 13); - H1(c, d, e, a, b, 6, 6); - H1(b, c, d, e, a, 13, 5); - H1(a, b, c, d, e, 11, 12); - H1(e, a, b, c, d, 5, 7); - H1(d, e, a, b, c, 12, 5); - - I1(c, d, e, a, b, 1, 11); - I1(b, c, d, e, a, 9, 12); - I1(a, b, c, d, e, 11, 14); - I1(e, a, b, c, d, 10, 15); - I1(d, e, a, b, c, 0, 14); - I1(c, d, e, a, b, 8, 15); - I1(b, c, d, e, a, 12, 9); - I1(a, b, c, d, e, 4, 8); - I1(e, a, b, c, d, 13, 9); - I1(d, e, a, b, c, 3, 14); - I1(c, d, e, a, b, 7, 5); - I1(b, c, d, e, a, 15, 6); - I1(a, b, c, d, e, 14, 8); - I1(e, a, b, c, d, 5, 6); - I1(d, e, a, b, c, 6, 5); - I1(c, d, e, a, b, 2, 12); - - J1(b, c, d, e, a, 4, 9); - J1(a, b, c, d, e, 0, 15); - J1(e, a, b, c, d, 5, 5); - J1(d, e, a, b, c, 9, 11); - J1(c, d, e, a, b, 7, 6); - J1(b, c, d, e, a, 12, 8); - J1(a, b, c, d, e, 2, 13); - J1(e, a, b, c, d, 10, 12); - J1(d, e, a, b, c, 14, 5); - J1(c, d, e, a, b, 1, 12); - J1(b, c, d, e, a, 3, 13); - J1(a, b, c, d, e, 8, 14); - J1(e, a, b, c, d, 11, 11); - J1(d, e, a, b, c, 6, 8); - J1(c, d, e, a, b, 15, 5); - J1(b, c, d, e, a, 13, 6); - - /* --- And then the right hand side --- */ - - F2(A, B, C, D, E, 5, 8); - F2(E, A, B, C, D, 14, 9); - F2(D, E, A, B, C, 7, 9); - F2(C, D, E, A, B, 0, 11); - F2(B, C, D, E, A, 9, 13); - F2(A, B, C, D, E, 2, 15); - F2(E, A, B, C, D, 11, 15); - F2(D, E, A, B, C, 4, 5); - F2(C, D, E, A, B, 13, 7); - F2(B, C, D, E, A, 6, 7); - F2(A, B, C, D, E, 15, 8); - F2(E, A, B, C, D, 8, 11); - F2(D, E, A, B, C, 1, 14); - F2(C, D, E, A, B, 10, 14); - F2(B, C, D, E, A, 3, 12); - F2(A, B, C, D, E, 12, 6); - - G2(E, A, B, C, D, 6, 9); - G2(D, E, A, B, C, 11, 13); - G2(C, D, E, A, B, 3, 15); - G2(B, C, D, E, A, 7, 7); - G2(A, B, C, D, E, 0, 12); - G2(E, A, B, C, D, 13, 8); - G2(D, E, A, B, C, 5, 9); - G2(C, D, E, A, B, 10, 11); - G2(B, C, D, E, A, 14, 7); - G2(A, B, C, D, E, 15, 7); - G2(E, A, B, C, D, 8, 12); - G2(D, E, A, B, C, 12, 7); - G2(C, D, E, A, B, 4, 6); - G2(B, C, D, E, A, 9, 15); - G2(A, B, C, D, E, 1, 13); - G2(E, A, B, C, D, 2, 11); - - H2(D, E, A, B, C, 15, 9); - H2(C, D, E, A, B, 5, 7); - H2(B, C, D, E, A, 1, 15); - H2(A, B, C, D, E, 3, 11); - H2(E, A, B, C, D, 7, 8); - H2(D, E, A, B, C, 14, 6); - H2(C, D, E, A, B, 6, 6); - H2(B, C, D, E, A, 9, 14); - H2(A, B, C, D, E, 11, 12); - H2(E, A, B, C, D, 8, 13); - H2(D, E, A, B, C, 12, 5); - H2(C, D, E, A, B, 2, 14); - H2(B, C, D, E, A, 10, 13); - H2(A, B, C, D, E, 0, 13); - H2(E, A, B, C, D, 4, 7); - H2(D, E, A, B, C, 13, 5); - - I2(C, D, E, A, B, 8, 15); - I2(B, C, D, E, A, 6, 5); - I2(A, B, C, D, E, 4, 8); - I2(E, A, B, C, D, 1, 11); - I2(D, E, A, B, C, 3, 14); - I2(C, D, E, A, B, 11, 14); - I2(B, C, D, E, A, 15, 6); - I2(A, B, C, D, E, 0, 14); - I2(E, A, B, C, D, 5, 6); - I2(D, E, A, B, C, 12, 9); - I2(C, D, E, A, B, 2, 12); - I2(B, C, D, E, A, 13, 9); - I2(A, B, C, D, E, 9, 12); - I2(E, A, B, C, D, 7, 5); - I2(D, E, A, B, C, 10, 15); - I2(C, D, E, A, B, 14, 8); - - J2(B, C, D, E, A, 12, 8); - J2(A, B, C, D, E, 15, 5); - J2(E, A, B, C, D, 10, 12); - J2(D, E, A, B, C, 4, 9); - J2(C, D, E, A, B, 1, 12); - J2(B, C, D, E, A, 5, 5); - J2(A, B, C, D, E, 8, 14); - J2(E, A, B, C, D, 7, 6); - J2(D, E, A, B, C, 6, 8); - J2(C, D, E, A, B, 2, 13); - J2(B, C, D, E, A, 13, 6); - J2(A, B, C, D, E, 14, 5); - J2(E, A, B, C, D, 0, 15); - J2(D, E, A, B, C, 3, 13); - J2(C, D, E, A, B, 9, 11); - J2(B, C, D, E, A, 11, 11); - - /* --- Recombine the two halves --- */ - - { - uint32 - tmp = ctx->b + c + D; - ctx->b = ctx->c + d + E; - ctx->c = ctx->d + e + A; - ctx->d = ctx->e + a + B; - ctx->e = ctx->a + b + C; - ctx->a = tmp; - } -} - -/* --- @rmd160_init@ --- * - * - * Arguments: @rmd160_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void rmd160_init(rmd160_ctx *ctx) -{ - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; - ctx->e = 0xc3d2e1f0; - ctx->off = 0; - ctx->nl = ctx->nh = 0; -} - -/* --- @rmd160_set@ --- * - * - * Arguments: @rmd160_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -void rmd160_set(rmd160_ctx *ctx, const void *buf, unsigned long count) -{ - const octet *p = buf; - ctx->a = LOAD32_L(p + 0); - ctx->b = LOAD32_L(p + 4); - ctx->c = LOAD32_L(p + 8); - ctx->d = LOAD32_L(p + 12); - ctx->e = LOAD32_L(p + 16); - ctx->off = 0; - ctx->nl = U32(count); - ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); -} - -/* --- @rmd160_hash@ --- * - * - * Arguments: @rmd160_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void rmd160_hash(rmd160_ctx *ctx, const void *buf, size_t sz) -{ - HASH_BUFFER(RMD160, rmd160, ctx, buf, sz); -} - -/* --- @rmd160_done@ --- * - * - * Arguments: @rmd160_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -void rmd160_done(rmd160_ctx *ctx, void *hash) -{ - octet *p = hash; - HASH_MD5STRENGTH(RMD160, rmd160, ctx); - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); - STORE32_L(p + 16, ctx->e); -} - -/* --- @rmd160_state@ --- * - * - * Arguments: @rmd160_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @rmd160_set@. - */ - -unsigned long rmd160_state(rmd160_ctx *ctx, void *state) -{ - octet *p = state; - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); - STORE32_L(p + 16, ctx->e); - return (ctx->nl | ((ctx->nh << 16) << 16)); -} - -/* --- Generic interface --- */ - -GHASH_DEF(RMD160, rmd160) - -/* --- Test code --- */ - -HASH_TEST(RMD160, rmd160) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rmd160.h b/rmd160.h deleted file mode 100644 index f97a462..0000000 --- a/rmd160.h +++ /dev/null @@ -1,161 +0,0 @@ -/* -*-c-*- - * - * $Id: rmd160.h,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * The RIPEMD-160 message digest function - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the RIPEMD-160 hash function -----------------------------* - * - * RIPEMD-160 was invented by Hans Dobbertin, Antoon Bosselaers and Bart - * Preneel. It's a strengthened version of the original RIPEMD hash - * function, fixing a vulnerability discovered by Hans Dobbertin. The - * RIPEMD-160 design team appears well respected in the cryptographic - * community. The author finds them more plausible than SHA-1, which is the - * best alternative hash function. - */ - -#ifndef CATACOMB_RMD160_H -#define CATACOMB_RMD160_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define RMD160_BUFSZ 64 -#define RMD160_HASHSZ 20 -#define RMD160_STATESZ 20 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct rmd160_ctx { - uint32 a, b, c, d, e; /* Chaining variables */ - uint32 nl, nh; /* Byte count so far */ - unsigned off; /* Offset into buffer */ - octet buf[RMD160_BUFSZ]; /* Accumulation buffer */ -} rmd160_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @rmd160_compress@ --- * - * - * Arguments: @rmd160_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: RIPEMD-160 compression function. - */ - -extern void rmd160_compress(rmd160_ctx */*ctx*/, const void */*sbuf*/); - -/* --- @rmd160_init@ --- * - * - * Arguments: @rmd160_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -extern void rmd160_init(rmd160_ctx */*ctx*/); - -/* --- @rmd160_set@ --- * - * - * Arguments: @rmd160_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -extern void rmd160_set(rmd160_ctx */*ctx*/, - const void */*buf*/, unsigned long /*count*/); - -/* --- @rmd160_hash@ --- * - * - * Arguments: @rmd160_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -extern void rmd160_hash(rmd160_ctx */*ctx*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @rmd160_done@ --- * - * - * Arguments: @rmd160_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -extern void rmd160_done(rmd160_ctx */*ctx*/, void */*hash*/); - -/* --- @rmd160_state@ --- * - * - * Arguments: @rmd160_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @rmd160_set@. - */ - -extern unsigned long rmd160_state(rmd160_ctx */*ctx*/, void */*state*/); - -/*----- Generic hash interface --------------------------------------------*/ - -extern const gchash rmd160; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rmd256.c b/rmd256.c deleted file mode 100644 index e2fc70a..0000000 --- a/rmd256.c +++ /dev/null @@ -1,376 +0,0 @@ -/* -*-c-*- - * - * $Id: rmd256.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The RIPEMD-256 message digest function - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "rmd256.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rmd256_compress@ --- * - * - * Arguments: @rmd256_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: RIPEMD-256 compression function. - */ - -void rmd256_compress(rmd256_ctx *ctx, const void *sbuf) -{ - uint32 a, b, c, d; - uint32 A, B, C, D; - uint32 buf[16]; - - /* --- Fetch the chaining variables --- */ - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - A = ctx->A; - B = ctx->B; - C = ctx->C; - D = ctx->D; - - /* --- Fetch the buffer contents --- */ - - { - int i; - const octet *p; - - for (i = 0, p = sbuf; i < 16; i++, p += 4) - buf[i] = LOAD32_L(p); - } - - /* --- Definitions for round functions --- */ - -#define F(x, y, z) ((x) ^ (y) ^ (z)) -#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define H(x, y, z) (((x) | ~(y)) ^ (z)) -#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) - -#define T(w, x, y, z, i, r, f, k) do { \ - uint32 _t = w + f(x, y, z) + buf[i] + k; \ - w = ROL32(_t, r); \ -} while (0) - -#define F1(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000) -#define G1(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x5a827999) -#define H1(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x6ed9eba1) -#define I1(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x8f1bbcdc) - -#define F2(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x50a28be6) -#define G2(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x5c4dd124) -#define H2(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x6d703ef3) -#define I2(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000) - - /* --- We must do both sides together --- */ - - F1(a, b, c, d, 0, 11); - F1(d, a, b, c, 1, 14); - F1(c, d, a, b, 2, 15); - F1(b, c, d, a, 3, 12); - F1(a, b, c, d, 4, 5); - F1(d, a, b, c, 5, 8); - F1(c, d, a, b, 6, 7); - F1(b, c, d, a, 7, 9); - F1(a, b, c, d, 8, 11); - F1(d, a, b, c, 9, 13); - F1(c, d, a, b, 10, 14); - F1(b, c, d, a, 11, 15); - F1(a, b, c, d, 12, 6); - F1(d, a, b, c, 13, 7); - F1(c, d, a, b, 14, 9); - F1(b, c, d, a, 15, 8); - - F2(A, B, C, D, 5, 8); - F2(D, A, B, C, 14, 9); - F2(C, D, A, B, 7, 9); - F2(B, C, D, A, 0, 11); - F2(A, B, C, D, 9, 13); - F2(D, A, B, C, 2, 15); - F2(C, D, A, B, 11, 15); - F2(B, C, D, A, 4, 5); - F2(A, B, C, D, 13, 7); - F2(D, A, B, C, 6, 7); - F2(C, D, A, B, 15, 8); - F2(B, C, D, A, 8, 11); - F2(A, B, C, D, 1, 14); - F2(D, A, B, C, 10, 14); - F2(C, D, A, B, 3, 12); - F2(B, C, D, A, 12, 6); - - G1(A, b, c, d, 7, 7); - G1(d, A, b, c, 4, 6); - G1(c, d, A, b, 13, 8); - G1(b, c, d, A, 1, 13); - G1(A, b, c, d, 10, 11); - G1(d, A, b, c, 6, 9); - G1(c, d, A, b, 15, 7); - G1(b, c, d, A, 3, 15); - G1(A, b, c, d, 12, 7); - G1(d, A, b, c, 0, 12); - G1(c, d, A, b, 9, 15); - G1(b, c, d, A, 5, 9); - G1(A, b, c, d, 2, 11); - G1(d, A, b, c, 14, 7); - G1(c, d, A, b, 11, 13); - G1(b, c, d, A, 8, 12); - - G2(a, B, C, D, 6, 9); - G2(D, a, B, C, 11, 13); - G2(C, D, a, B, 3, 15); - G2(B, C, D, a, 7, 7); - G2(a, B, C, D, 0, 12); - G2(D, a, B, C, 13, 8); - G2(C, D, a, B, 5, 9); - G2(B, C, D, a, 10, 11); - G2(a, B, C, D, 14, 7); - G2(D, a, B, C, 15, 7); - G2(C, D, a, B, 8, 12); - G2(B, C, D, a, 12, 7); - G2(a, B, C, D, 4, 6); - G2(D, a, B, C, 9, 15); - G2(C, D, a, B, 1, 13); - G2(B, C, D, a, 2, 11); - - H1(A, B, c, d, 3, 11); - H1(d, A, B, c, 10, 13); - H1(c, d, A, B, 14, 6); - H1(B, c, d, A, 4, 7); - H1(A, B, c, d, 9, 14); - H1(d, A, B, c, 15, 9); - H1(c, d, A, B, 8, 13); - H1(B, c, d, A, 1, 15); - H1(A, B, c, d, 2, 14); - H1(d, A, B, c, 7, 8); - H1(c, d, A, B, 0, 13); - H1(B, c, d, A, 6, 6); - H1(A, B, c, d, 13, 5); - H1(d, A, B, c, 11, 12); - H1(c, d, A, B, 5, 7); - H1(B, c, d, A, 12, 5); - - H2(a, b, C, D, 15, 9); - H2(D, a, b, C, 5, 7); - H2(C, D, a, b, 1, 15); - H2(b, C, D, a, 3, 11); - H2(a, b, C, D, 7, 8); - H2(D, a, b, C, 14, 6); - H2(C, D, a, b, 6, 6); - H2(b, C, D, a, 9, 14); - H2(a, b, C, D, 11, 12); - H2(D, a, b, C, 8, 13); - H2(C, D, a, b, 12, 5); - H2(b, C, D, a, 2, 14); - H2(a, b, C, D, 10, 13); - H2(D, a, b, C, 0, 13); - H2(C, D, a, b, 4, 7); - H2(b, C, D, a, 13, 5); - - I1(A, B, C, d, 1, 11); - I1(d, A, B, C, 9, 12); - I1(C, d, A, B, 11, 14); - I1(B, C, d, A, 10, 15); - I1(A, B, C, d, 0, 14); - I1(d, A, B, C, 8, 15); - I1(C, d, A, B, 12, 9); - I1(B, C, d, A, 4, 8); - I1(A, B, C, d, 13, 9); - I1(d, A, B, C, 3, 14); - I1(C, d, A, B, 7, 5); - I1(B, C, d, A, 15, 6); - I1(A, B, C, d, 14, 8); - I1(d, A, B, C, 5, 6); - I1(C, d, A, B, 6, 5); - I1(B, C, d, A, 2, 12); - - I2(a, b, c, D, 8, 15); - I2(D, a, b, c, 6, 5); - I2(c, D, a, b, 4, 8); - I2(b, c, D, a, 1, 11); - I2(a, b, c, D, 3, 14); - I2(D, a, b, c, 11, 14); - I2(c, D, a, b, 15, 6); - I2(b, c, D, a, 0, 14); - I2(a, b, c, D, 5, 6); - I2(D, a, b, c, 12, 9); - I2(c, D, a, b, 2, 12); - I2(b, c, D, a, 13, 9); - I2(a, b, c, D, 9, 12); - I2(D, a, b, c, 7, 5); - I2(c, D, a, b, 10, 15); - I2(b, c, D, a, 14, 8); - - /* --- Recombine the two halves --- */ - - ctx->a += A; - ctx->b += B; - ctx->c += C; - ctx->d += D; - ctx->A += a; - ctx->B += b; - ctx->C += c; - ctx->D += d; -} - -/* --- @rmd256_init@ --- * - * - * Arguments: @rmd256_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void rmd256_init(rmd256_ctx *ctx) -{ - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; - ctx->A = 0x76543210; - ctx->B = 0xfedcba98; - ctx->C = 0x89abcdef; - ctx->D = 0x01234567; - ctx->off = 0; - ctx->nl = ctx->nh = 0; -} - -/* --- @rmd256_set@ --- * - * - * Arguments: @rmd256_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -void rmd256_set(rmd256_ctx *ctx, const void *buf, unsigned long count) -{ - const octet *p = buf; - ctx->a = LOAD32_L(p + 0); - ctx->b = LOAD32_L(p + 4); - ctx->c = LOAD32_L(p + 8); - ctx->d = LOAD32_L(p + 12); - ctx->A = LOAD32_L(p + 16); - ctx->B = LOAD32_L(p + 20); - ctx->C = LOAD32_L(p + 24); - ctx->D = LOAD32_L(p + 28); - ctx->off = 0; - ctx->nl = U32(count); - ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); -} - -/* --- @rmd256_hash@ --- * - * - * Arguments: @rmd256_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void rmd256_hash(rmd256_ctx *ctx, const void *buf, size_t sz) -{ - HASH_BUFFER(RMD256, rmd256, ctx, buf, sz); -} - -/* --- @rmd256_done@ --- * - * - * Arguments: @rmd256_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -void rmd256_done(rmd256_ctx *ctx, void *hash) -{ - octet *p = hash; - HASH_MD5STRENGTH(RMD256, rmd256, ctx); - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); - STORE32_L(p + 16, ctx->A); - STORE32_L(p + 20, ctx->B); - STORE32_L(p + 24, ctx->C); - STORE32_L(p + 28, ctx->D); -} - -/* --- @rmd256_state@ --- * - * - * Arguments: @rmd256_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @rmd256_set@. - */ - -unsigned long rmd256_state(rmd256_ctx *ctx, void *state) -{ - octet *p = state; - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); - STORE32_L(p + 16, ctx->A); - STORE32_L(p + 20, ctx->B); - STORE32_L(p + 24, ctx->C); - STORE32_L(p + 28, ctx->D); - return (ctx->nl | ((ctx->nh << 16) << 16)); -} - -/* --- Generic interface --- */ - -GHASH_DEF(RMD256, rmd256) - -/* --- Test code --- */ - -HASH_TEST(RMD256, rmd256) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rmd256.h b/rmd256.h deleted file mode 100644 index aa1e883..0000000 --- a/rmd256.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -*-c-*- - * - * $Id: rmd256.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The RIPEMD-256 message digest function - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the RIPEMD-256 hash function -----------------------------* - * - * RIPEMD-256 was invented by Hans Dobbertin, Antoon Bosselaers and Bart - * Preneel. It's a double-width version of RIPEMD-128, constructed simply by - * not gluing together the two parallel computations which RIPEMD-128 usually - * does in its compression function. The authors warn that, while its output - * is twice as wide as that of RIPEMD-128, they don't expect it to offer any - * more security. - */ - -#ifndef CATACOMB_RMD256_H -#define CATACOMB_RMD256_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define RMD256_BUFSZ 64 -#define RMD256_HASHSZ 32 -#define RMD256_STATESZ 32 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct rmd256_ctx { - uint32 a, b, c, d; /* Chaining variables */ - uint32 A, B, C, D; /* More chaining variables */ - uint32 nl, nh; /* Byte count so far */ - unsigned off; /* Offset into buffer */ - octet buf[RMD256_BUFSZ]; /* Accumulation buffer */ -} rmd256_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @rmd256_compress@ --- * - * - * Arguments: @rmd256_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: RIPEMD-256 compression function. - */ - -extern void rmd256_compress(rmd256_ctx */*ctx*/, const void */*sbuf*/); - -/* --- @rmd256_init@ --- * - * - * Arguments: @rmd256_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -extern void rmd256_init(rmd256_ctx */*ctx*/); - -/* --- @rmd256_set@ --- * - * - * Arguments: @rmd256_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -extern void rmd256_set(rmd256_ctx */*ctx*/, - const void */*buf*/, unsigned long /*count*/); - -/* --- @rmd256_hash@ --- * - * - * Arguments: @rmd256_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -extern void rmd256_hash(rmd256_ctx */*ctx*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @rmd256_done@ --- * - * - * Arguments: @rmd256_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -extern void rmd256_done(rmd256_ctx */*ctx*/, void */*hash*/); - -/* --- @rmd256_state@ --- * - * - * Arguments: @rmd256_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @rmd256_set@. - */ - -extern unsigned long rmd256_state(rmd256_ctx */*ctx*/, void */*state*/); - -/*----- Generic hash interface --------------------------------------------*/ - -extern const gchash rmd256; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rmd320.c b/rmd320.c deleted file mode 100644 index a91f874..0000000 --- a/rmd320.c +++ /dev/null @@ -1,426 +0,0 @@ -/* -*-c-*- - * - * $Id: rmd320.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The RIPEMD-320 message digest function - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "rmd320.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rmd320_compress@ --- * - * - * Arguments: @rmd320_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: RIPEMD-320 compression function. - */ - -void rmd320_compress(rmd320_ctx *ctx, const void *sbuf) -{ - uint32 a, b, c, d, e; - uint32 A, B, C, D, E; - uint32 buf[16]; - - /* --- Fetch the chaining variables --- */ - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - e = ctx->e; - - A = ctx->A; - B = ctx->B; - C = ctx->C; - D = ctx->D; - E = ctx->E; - - /* --- Fetch the buffer contents --- */ - - { - int i; - const octet *p; - - for (i = 0, p = sbuf; i < 16; i++, p += 4) - buf[i] = LOAD32_L(p); - } - - /* --- Definitions for round functions --- */ - -#define F(x, y, z) ((x) ^ (y) ^ (z)) -#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define H(x, y, z) (((x) | ~(y)) ^ (z)) -#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define J(x, y, z) ((x) ^ ((y) | ~(z))) - -#define T(v, w, x, y, z, i, r, f, k) do { \ - uint32 _t = v + f(w, x, y) + buf[i] + k; \ - v = ROL32(_t, r) + z; x = ROL32(x, 10); \ -} while (0) - -#define F1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000) -#define G1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x5a827999) -#define H1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6ed9eba1) -#define I1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x8f1bbcdc) -#define J1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0xa953fd4e) - -#define F2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0x50a28be6) -#define G2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x5c4dd124) -#define H2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6d703ef3) -#define I2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x7a6d76e9) -#define J2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000) - - /* --- We must do both lines together --- */ - - F1(a, b, c, d, e, 0, 11); - F1(e, a, b, c, d, 1, 14); - F1(d, e, a, b, c, 2, 15); - F1(c, d, e, a, b, 3, 12); - F1(b, c, d, e, a, 4, 5); - F1(a, b, c, d, e, 5, 8); - F1(e, a, b, c, d, 6, 7); - F1(d, e, a, b, c, 7, 9); - F1(c, d, e, a, b, 8, 11); - F1(b, c, d, e, a, 9, 13); - F1(a, b, c, d, e, 10, 14); - F1(e, a, b, c, d, 11, 15); - F1(d, e, a, b, c, 12, 6); - F1(c, d, e, a, b, 13, 7); - F1(b, c, d, e, a, 14, 9); - F1(a, b, c, d, e, 15, 8); - - F2(A, B, C, D, E, 5, 8); - F2(E, A, B, C, D, 14, 9); - F2(D, E, A, B, C, 7, 9); - F2(C, D, E, A, B, 0, 11); - F2(B, C, D, E, A, 9, 13); - F2(A, B, C, D, E, 2, 15); - F2(E, A, B, C, D, 11, 15); - F2(D, E, A, B, C, 4, 5); - F2(C, D, E, A, B, 13, 7); - F2(B, C, D, E, A, 6, 7); - F2(A, B, C, D, E, 15, 8); - F2(E, A, B, C, D, 8, 11); - F2(D, E, A, B, C, 1, 14); - F2(C, D, E, A, B, 10, 14); - F2(B, C, D, E, A, 3, 12); - F2(A, B, C, D, E, 12, 6); - - G1(e, A, b, c, d, 7, 7); - G1(d, e, A, b, c, 4, 6); - G1(c, d, e, A, b, 13, 8); - G1(b, c, d, e, A, 1, 13); - G1(A, b, c, d, e, 10, 11); - G1(e, A, b, c, d, 6, 9); - G1(d, e, A, b, c, 15, 7); - G1(c, d, e, A, b, 3, 15); - G1(b, c, d, e, A, 12, 7); - G1(A, b, c, d, e, 0, 12); - G1(e, A, b, c, d, 9, 15); - G1(d, e, A, b, c, 5, 9); - G1(c, d, e, A, b, 2, 11); - G1(b, c, d, e, A, 14, 7); - G1(A, b, c, d, e, 11, 13); - G1(e, A, b, c, d, 8, 12); - - G2(E, a, B, C, D, 6, 9); - G2(D, E, a, B, C, 11, 13); - G2(C, D, E, a, B, 3, 15); - G2(B, C, D, E, a, 7, 7); - G2(a, B, C, D, E, 0, 12); - G2(E, a, B, C, D, 13, 8); - G2(D, E, a, B, C, 5, 9); - G2(C, D, E, a, B, 10, 11); - G2(B, C, D, E, a, 14, 7); - G2(a, B, C, D, E, 15, 7); - G2(E, a, B, C, D, 8, 12); - G2(D, E, a, B, C, 12, 7); - G2(C, D, E, a, B, 4, 6); - G2(B, C, D, E, a, 9, 15); - G2(a, B, C, D, E, 1, 13); - G2(E, a, B, C, D, 2, 11); - - H1(d, e, A, B, c, 3, 11); - H1(c, d, e, A, B, 10, 13); - H1(B, c, d, e, A, 14, 6); - H1(A, B, c, d, e, 4, 7); - H1(e, A, B, c, d, 9, 14); - H1(d, e, A, B, c, 15, 9); - H1(c, d, e, A, B, 8, 13); - H1(B, c, d, e, A, 1, 15); - H1(A, B, c, d, e, 2, 14); - H1(e, A, B, c, d, 7, 8); - H1(d, e, A, B, c, 0, 13); - H1(c, d, e, A, B, 6, 6); - H1(B, c, d, e, A, 13, 5); - H1(A, B, c, d, e, 11, 12); - H1(e, A, B, c, d, 5, 7); - H1(d, e, A, B, c, 12, 5); - - H2(D, E, a, b, C, 15, 9); - H2(C, D, E, a, b, 5, 7); - H2(b, C, D, E, a, 1, 15); - H2(a, b, C, D, E, 3, 11); - H2(E, a, b, C, D, 7, 8); - H2(D, E, a, b, C, 14, 6); - H2(C, D, E, a, b, 6, 6); - H2(b, C, D, E, a, 9, 14); - H2(a, b, C, D, E, 11, 12); - H2(E, a, b, C, D, 8, 13); - H2(D, E, a, b, C, 12, 5); - H2(C, D, E, a, b, 2, 14); - H2(b, C, D, E, a, 10, 13); - H2(a, b, C, D, E, 0, 13); - H2(E, a, b, C, D, 4, 7); - H2(D, E, a, b, C, 13, 5); - - I1(C, d, e, A, B, 1, 11); - I1(B, C, d, e, A, 9, 12); - I1(A, B, C, d, e, 11, 14); - I1(e, A, B, C, d, 10, 15); - I1(d, e, A, B, C, 0, 14); - I1(C, d, e, A, B, 8, 15); - I1(B, C, d, e, A, 12, 9); - I1(A, B, C, d, e, 4, 8); - I1(e, A, B, C, d, 13, 9); - I1(d, e, A, B, C, 3, 14); - I1(C, d, e, A, B, 7, 5); - I1(B, C, d, e, A, 15, 6); - I1(A, B, C, d, e, 14, 8); - I1(e, A, B, C, d, 5, 6); - I1(d, e, A, B, C, 6, 5); - I1(C, d, e, A, B, 2, 12); - - I2(c, D, E, a, b, 8, 15); - I2(b, c, D, E, a, 6, 5); - I2(a, b, c, D, E, 4, 8); - I2(E, a, b, c, D, 1, 11); - I2(D, E, a, b, c, 3, 14); - I2(c, D, E, a, b, 11, 14); - I2(b, c, D, E, a, 15, 6); - I2(a, b, c, D, E, 0, 14); - I2(E, a, b, c, D, 5, 6); - I2(D, E, a, b, c, 12, 9); - I2(c, D, E, a, b, 2, 12); - I2(b, c, D, E, a, 13, 9); - I2(a, b, c, D, E, 9, 12); - I2(E, a, b, c, D, 7, 5); - I2(D, E, a, b, c, 10, 15); - I2(c, D, E, a, b, 14, 8); - - J1(B, C, D, e, A, 4, 9); - J1(A, B, C, D, e, 0, 15); - J1(e, A, B, C, D, 5, 5); - J1(D, e, A, B, C, 9, 11); - J1(C, D, e, A, B, 7, 6); - J1(B, C, D, e, A, 12, 8); - J1(A, B, C, D, e, 2, 13); - J1(e, A, B, C, D, 10, 12); - J1(D, e, A, B, C, 14, 5); - J1(C, D, e, A, B, 1, 12); - J1(B, C, D, e, A, 3, 13); - J1(A, B, C, D, e, 8, 14); - J1(e, A, B, C, D, 11, 11); - J1(D, e, A, B, C, 6, 8); - J1(C, D, e, A, B, 15, 5); - J1(B, C, D, e, A, 13, 6); - - J2(b, c, d, E, a, 12, 8); - J2(a, b, c, d, E, 15, 5); - J2(E, a, b, c, d, 10, 12); - J2(d, E, a, b, c, 4, 9); - J2(c, d, E, a, b, 1, 12); - J2(b, c, d, E, a, 5, 5); - J2(a, b, c, d, E, 8, 14); - J2(E, a, b, c, d, 7, 6); - J2(d, E, a, b, c, 6, 8); - J2(c, d, E, a, b, 2, 13); - J2(b, c, d, E, a, 13, 6); - J2(a, b, c, d, E, 14, 5); - J2(E, a, b, c, d, 0, 15); - J2(d, E, a, b, c, 3, 13); - J2(c, d, E, a, b, 9, 11); - J2(b, c, d, E, a, 11, 11); - - /* --- Write out the result --- */ - - ctx->a += A; - ctx->b += B; - ctx->c += C; - ctx->d += D; - ctx->e += E; - ctx->A += a; - ctx->B += b; - ctx->C += c; - ctx->D += d; - ctx->E += e; -} - -/* --- @rmd320_init@ --- * - * - * Arguments: @rmd320_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void rmd320_init(rmd320_ctx *ctx) -{ - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; - ctx->e = 0xc3d2e1f0; - ctx->A = 0x76543210; - ctx->B = 0xfedcba98; - ctx->C = 0x89abcdef; - ctx->D = 0x01234567; - ctx->E = 0x3c2d1e0f; - ctx->off = 0; - ctx->nl = ctx->nh = 0; -} - -/* --- @rmd320_set@ --- * - * - * Arguments: @rmd320_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -void rmd320_set(rmd320_ctx *ctx, const void *buf, unsigned long count) -{ - const octet *p = buf; - ctx->a = LOAD32_L(p + 0); - ctx->b = LOAD32_L(p + 4); - ctx->c = LOAD32_L(p + 8); - ctx->d = LOAD32_L(p + 12); - ctx->e = LOAD32_L(p + 16); - ctx->A = LOAD32_L(p + 20); - ctx->B = LOAD32_L(p + 24); - ctx->C = LOAD32_L(p + 28); - ctx->D = LOAD32_L(p + 32); - ctx->E = LOAD32_L(p + 36); - ctx->off = 0; - ctx->nl = U32(count); - ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); -} - -/* --- @rmd320_hash@ --- * - * - * Arguments: @rmd320_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void rmd320_hash(rmd320_ctx *ctx, const void *buf, size_t sz) -{ - HASH_BUFFER(RMD320, rmd320, ctx, buf, sz); -} - -/* --- @rmd320_done@ --- * - * - * Arguments: @rmd320_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -void rmd320_done(rmd320_ctx *ctx, void *hash) -{ - octet *p = hash; - HASH_MD5STRENGTH(RMD320, rmd320, ctx); - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); - STORE32_L(p + 16, ctx->e); - STORE32_L(p + 20, ctx->A); - STORE32_L(p + 24, ctx->B); - STORE32_L(p + 28, ctx->C); - STORE32_L(p + 32, ctx->D); - STORE32_L(p + 36, ctx->E); -} - -/* --- @rmd320_state@ --- * - * - * Arguments: @rmd320_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @rmd320_set@. - */ - -unsigned long rmd320_state(rmd320_ctx *ctx, void *state) -{ - octet *p = state; - STORE32_L(p + 0, ctx->a); - STORE32_L(p + 4, ctx->b); - STORE32_L(p + 8, ctx->c); - STORE32_L(p + 12, ctx->d); - STORE32_L(p + 16, ctx->e); - STORE32_L(p + 20, ctx->A); - STORE32_L(p + 24, ctx->B); - STORE32_L(p + 28, ctx->C); - STORE32_L(p + 32, ctx->D); - STORE32_L(p + 36, ctx->E); - return (ctx->nl | ((ctx->nh << 16) << 16)); -} - -/* --- Generic interface --- */ - -GHASH_DEF(RMD320, rmd320) - -/* --- Test code --- */ - -HASH_TEST(RMD320, rmd320) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rmd320.h b/rmd320.h deleted file mode 100644 index 592e96f..0000000 --- a/rmd320.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -*-c-*- - * - * $Id: rmd320.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The RIPEMD-320 message digest function - * - * (c) 1998 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the RIPEMD-320 hash function -----------------------------* - * - * RIPEMD-320 was invented by Hans Dobbertin, Antoon Bosselaers and Bart - * Preneel. It's a double-width version of RIPEMD-160, constructed simply by - * not gluing together the two parallel computations which RIPEMD-160 usually - * does in its compression function. The authors warn that, while its output - * is twice as wide as that of RIPEMD-160, they don't expect it to offer any - * more security. - */ - -#ifndef CATACOMB_RMD320_H -#define CATACOMB_RMD320_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define RMD320_BUFSZ 64 -#define RMD320_HASHSZ 40 -#define RMD320_STATESZ 40 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct rmd320_ctx { - uint32 a, b, c, d, e; /* Chaining variables */ - uint32 A, B, C, D, E; /* More chaining variables */ - uint32 nl, nh; /* Byte count so far */ - unsigned off; /* Offset into buffer */ - octet buf[RMD320_BUFSZ]; /* Accumulation buffer */ -} rmd320_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @rmd320_compress@ --- * - * - * Arguments: @rmd320_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: RIPEMD-320 compression function. - */ - -extern void rmd320_compress(rmd320_ctx */*ctx*/, const void */*sbuf*/); - -/* --- @rmd320_init@ --- * - * - * Arguments: @rmd320_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -extern void rmd320_init(rmd320_ctx */*ctx*/); - -/* --- @rmd320_set@ --- * - * - * Arguments: @rmd320_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -extern void rmd320_set(rmd320_ctx */*ctx*/, - const void */*buf*/, unsigned long /*count*/); - -/* --- @rmd320_hash@ --- * - * - * Arguments: @rmd320_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -extern void rmd320_hash(rmd320_ctx */*ctx*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @rmd320_done@ --- * - * - * Arguments: @rmd320_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -extern void rmd320_done(rmd320_ctx */*ctx*/, void */*hash*/); - -/* --- @rmd320_state@ --- * - * - * Arguments: @rmd320_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @rmd320_set@. - */ - -extern unsigned long rmd320_state(rmd320_ctx */*ctx*/, void */*state*/); - -/*----- Generic hash interface --------------------------------------------*/ - -extern const gchash rmd320; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rsa-fetch.c b/rsa-fetch.c deleted file mode 100644 index 0236b67..0000000 --- a/rsa-fetch.c +++ /dev/null @@ -1,87 +0,0 @@ -/* -*-c-*- - * - * $Id: rsa-fetch.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Key fetching for RSA public and private keys - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "key.h" -#include "rsa.h" - -/*----- Key fetching ------------------------------------------------------*/ - -const key_fetchdef rsa_pubfetch[] = { - { "n", offsetof(rsa_pub, n), KENC_MP, 0 }, - { "e", offsetof(rsa_pub, e), KENC_MP, 0 }, - { 0, 0, 0, 0 } -}; - -static const key_fetchdef priv[] = { - { "p", offsetof(rsa_priv, p), KENC_MP, 0 }, - { "q", offsetof(rsa_priv, q), KENC_MP, 0 }, - { "q-inv", offsetof(rsa_priv, q_inv), KENC_MP, 0 }, - { "d", offsetof(rsa_priv, d), KENC_MP, 0 }, - { "d-mod-p", offsetof(rsa_priv, dp), KENC_MP, 0 }, - { "d-mod-q", offsetof(rsa_priv, dq), KENC_MP, 0 }, - { 0, 0, 0, 0 } -}; - -const key_fetchdef rsa_privfetch[] = { - { "n", offsetof(rsa_priv, n), KENC_MP, 0 }, - { "e", offsetof(rsa_priv, e), KENC_MP, 0 }, - { "private", 0, KENC_STRUCT, priv }, - { 0, 0, 0, 0 } -}; - -/* --- @rsa_pubfree@, @rsa_privfree@ --- * - * - * Arguments: @rsa_pub *rp@, @rsa_priv *rp@ = pointer to key block - * - * Returns: --- - * - * Use: Frees an RSA key block. - */ - -void rsa_pubfree(rsa_pub *rp) -{ - mp_drop(rp->n); - mp_drop(rp->e); -} - -void rsa_privfree(rsa_priv *rp) -{ - mp_drop(rp->n); - mp_drop(rp->e); - mp_drop(rp->p); - mp_drop(rp->q); - mp_drop(rp->q_inv); - mp_drop(rp->d); - mp_drop(rp->dp); - mp_drop(rp->dq); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rsa-gen.c b/rsa-gen.c deleted file mode 100644 index 6005f61..0000000 --- a/rsa-gen.c +++ /dev/null @@ -1,191 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * RSA parameter generation - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "grand.h" -#include "mp.h" -#include "mpint.h" -#include "pgen.h" -#include "rsa.h" -#include "strongprime.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rsa_gen@ --- * - * - * Arguments: @rsa_priv *rp@ = pointer to block to be filled in - * @unsigned nbits@ = required modulus size in bits - * @grand *r@ = random number source - * @unsigned n@ = number of attempts to make - * @pgen_proc *event@ = event handler function - * @void *ectx@ = argument for the event handler - * - * Returns: Zero if all went well, nonzero otherwise. - * - * Use: Constructs a pair of strong RSA primes and other useful RSA - * parameters. A small encryption exponent is chosen if - * possible. - */ - -int rsa_gen(rsa_priv *rp, unsigned nbits, grand *r, unsigned n, - pgen_proc *event, void *ectx) -{ - pgen_gcdstepctx g; - mp *phi = MP_NEW; - - /* --- Bits of initialization --- */ - - rp->e = mp_fromulong(MP_NEW, 0x10001); - rp->d = MP_NEW; - - /* --- Generate strong primes %$p$% and %$q$% --- * - * - * Constrain the GCD of @q@ to ensure that overly small private exponents - * are impossible. Current results suggest that if %$d < n^{0.29}$% then - * it can be guessed fairly easily. This implementation is rather more - * conservative about that sort of thing. - */ - -again: - if ((rp->p = strongprime("p", MP_NEWSEC, nbits/2, r, n, event, ectx)) == 0) - goto fail_p; - - /* --- Do painful fiddling with GCD steppers --- */ - - { - mp *q; - rabin rb; - - if ((q = strongprime_setup("q", MP_NEWSEC, &g.jp, nbits / 2, - r, n, event, ectx)) == 0) - goto fail_q; - g.r = mp_lsr(MP_NEW, rp->p, 1); - g.g = MP_NEW; - g.max = MP_256; - q = pgen("q", q, q, event, ectx, n, pgen_gcdstep, &g, - rabin_iters(nbits/2), pgen_test, &rb); - pfilt_destroy(&g.jp); - mp_drop(g.r); - if (!q) { - mp_drop(g.g); - if (n) - goto fail_q; - mp_drop(rp->p); - goto again; - } - rp->q = q; - } - - /* --- Ensure that %$p > q$% --- * - * - * Also ensure that %$p$% and %$q$% are sufficiently different to deter - * square-root-based factoring methods. - */ - - phi = mp_sub(phi, rp->p, rp->q); - if (MP_LEN(phi) * 4 < MP_LEN(rp->p) * 3 || - MP_LEN(phi) * 4 < MP_LEN(rp->q) * 3) { - mp_drop(rp->p); - mp_drop(g.g); - if (n) - goto fail_q; - mp_drop(rp->q); - goto again; - } - - if (MP_NEGP(phi)) { - mp *z = rp->p; - rp->p = rp->q; - rp->q = z; - } - - /* --- Work out the modulus and the CRT coefficient --- */ - - rp->n = mp_mul(MP_NEW, rp->p, rp->q); - rp->q_inv = mp_modinv(MP_NEW, rp->q, rp->p); - - /* --- Work out %$\varphi(n) = (p - 1)(q - 1)$% --- * - * - * Save on further multiplications by noting that %$n = pq$% is known and - * that %$(p - 1)(q - 1) = pq - p - q + 1$%. To minimize the size of @d@ - * (useful for performance reasons, although not very because an overly - * small @d@ will be rejected for security reasons) this is then divided by - * %$\gcd(p - 1, q - 1)$%. - */ - - phi = mp_sub(phi, rp->n, rp->p); - phi = mp_sub(phi, phi, rp->q); - phi = mp_add(phi, phi, MP_ONE); - phi = mp_lsr(phi, phi, 1); - mp_div(&phi, 0, phi, g.g); - - /* --- Decide on a public exponent --- * - * - * Simultaneously compute the private exponent. - */ - - mp_gcd(&g.g, 0, &rp->d, phi, rp->e); - if (!MP_EQ(g.g, MP_ONE) && MP_LEN(rp->d) * 4 > MP_LEN(rp->n) * 3) - goto fail_e; - - /* --- Work out exponent residues --- */ - - rp->dp = MP_NEW; phi = mp_sub(phi, rp->p, MP_ONE); - mp_div(0, &rp->dp, rp->d, phi); - - rp->dq = MP_NEW; phi = mp_sub(phi, rp->q, MP_ONE); - mp_div(0, &rp->dq, rp->d, phi); - - /* --- Done --- */ - - mp_drop(phi); - mp_drop(g.g); - return (0); - - /* --- Tidy up when something goes wrong --- */ - -fail_e: - mp_drop(g.g); - mp_drop(phi); - mp_drop(rp->n); - mp_drop(rp->q_inv); - mp_drop(rp->q); -fail_q: - mp_drop(rp->p); -fail_p: - mp_drop(rp->e); - if (rp->d) - mp_drop(rp->d); - return (-1); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rsa-priv.c b/rsa-priv.c deleted file mode 100644 index fe427bb..0000000 --- a/rsa-priv.c +++ /dev/null @@ -1,262 +0,0 @@ -/* -*-c-*- - * - * $Id: rsa-priv.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * RSA private-key operations - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include "mp.h" -#include "mpmont.h" -#include "mprand.h" -#include "rsa.h" - -/*----- Public key operations ---------------------------------------------*/ - -/* --- @rsa_privcreate@ --- * - * - * Arguments: @rsa_privctx *rd@ = pointer to an RSA private key context - * @rsa_priv *rp@ = pointer to RSA private key - * @grand *r@ = pointer to random number source for blinding - * - * Returns: --- - * - * Use: Initializes an RSA private-key context. Keeping a context - * for several decryption or signing operations provides a minor - * performance benefit. - * - * The random number source may be null if blinding is not - * desired. This improves decryption speed, at the risk of - * permitting timing attacks. - */ - -void rsa_privcreate(rsa_privctx *rd, rsa_priv *rp, grand *r) -{ - rd->rp = rp; - rd->r = r; - if (r) - mpmont_create(&rd->nm, rp->n); - mpmont_create(&rd->pm, rp->p); - mpmont_create(&rd->qm, rp->q); -} - -/* --- @rsa_privdestroy@ --- * - * - * Arguments: @rsa_privctx *rd@ = pointer to an RSA decryption context - * - * Returns: --- - * - * Use: Destroys an RSA decryption context. - */ - -void rsa_privdestroy(rsa_privctx *rd) -{ - if (rd->r) - mpmont_destroy(&rd->nm); - mpmont_destroy(&rd->pm); - mpmont_destroy(&rd->qm); -} - -/* --- @rsa_privop@ --- * - * - * Arguments: @rsa_privctx *rd@ = pointer to RSA private key context - * @mp *d@ = destination - * @mp *c@ = input message - * - * Returns: The transformed output message. - * - * Use: Performs an RSA private key operation. This function takes - * advantage of knowledge of the key factors in order to speed - * up decryption. It also blinds the ciphertext prior to - * decryption and unblinds it afterwards to thwart timing - * attacks. - */ - -mp *rsa_privop(rsa_privctx *rd, mp *d, mp *c) -{ - mp *ki = MP_NEW; - rsa_priv *rp = rd->rp; - - /* --- If so desired, set up a blinding constant --- * - * - * Choose a constant %$k$% relatively prime to the modulus %$m$%. Compute - * %$c' = c k^e \bmod n$%, and %$k^{-1} \bmod n$%. Don't bother with the - * CRT stuff here because %$e$% is chosen to be small. - */ - - c = MP_COPY(c); - if (rd->r) { - mp *k = MP_NEWSEC, *g = MP_NEW; - - do { - k = mprand_range(k, rp->n, rd->r, 0); - mp_gcd(&g, 0, &ki, rp->n, k); - } while (!MP_EQ(g, MP_ONE)); - k = mpmont_mul(&rd->nm, k, k, rd->nm.r2); - k = mpmont_expr(&rd->nm, k, k, rp->e); - c = mpmont_mul(&rd->nm, c, c, k); - mp_drop(k); - mp_drop(g); - } - - /* --- Do the actual modular exponentiation --- * - * - * Use a slightly hacked version of the Chinese Remainder Theorem stuff. - * - * Let %$q' = q^{-1} \bmod p$%. Then note that - * %$c^d \equiv q (q'(c_p^{d_p} - c_q^{d_q}) \bmod p) + c_q^{d_q} \pmod n$% - */ - - { - mp *cp = MP_NEW, *cq = MP_NEW; - - /* --- Work out the two halves of the result --- */ - - mp_div(0, &cp, c, rp->p); - cp = mpmont_exp(&rd->pm, cp, cp, rp->dp); - - mp_div(0, &cq, c, rp->q); - cq = mpmont_exp(&rd->qm, cq, cq, rp->dq); - - /* --- Combine the halves using the result above --- */ - - d = mp_sub(d, cp, cq); - mp_div(0, &d, d, rp->p); - d = mpmont_mul(&rd->pm, d, d, rp->q_inv); - d = mpmont_mul(&rd->pm, d, d, rd->pm.r2); - - d = mp_mul(d, d, rp->q); - d = mp_add(d, d, cq); - if (MP_CMP(d, >=, rp->n)) - d = mp_sub(d, d, rp->n); - - /* --- Tidy away temporary variables --- */ - - mp_drop(cp); - mp_drop(cq); - } - - /* --- Finally, possibly remove the blinding factor --- */ - - if (ki) { - d = mpmont_mul(&rd->nm, d, d, ki); - d = mpmont_mul(&rd->nm, d, d, rd->nm.r2); - mp_drop(ki); - } - - /* --- Done --- */ - - mp_drop(c); - return (d); -} - -/* --- @rsa_qprivop@ --- * - * - * Arguments: @rsa_priv *rp@ = pointer to RSA parameters - * @mp *d@ = destination - * @mp *c@ = input message - * @grand *r@ = pointer to random number source for blinding - * - * Returns: Correctly transformed output message - * - * Use: Performs an RSA private key operation, very carefully. - */ - -mp *rsa_qprivop(rsa_priv *rp, mp *d, mp *c, grand *r) -{ - rsa_privctx rd; - rsa_privcreate(&rd, rp, r); - d = rsa_privop(&rd, d, c); - rsa_privdestroy(&rd); - return (d); -} - -/*----- Operations with padding -------------------------------------------*/ - -/* --- @rsa_sign@ --- * - * - * Arguments: @rsa_privctx *rp@ = pointer to an RSA private key context - * @mp *d@ = where to put the result - * @const void *m@ = pointer to input message - * @size_t msz@ = size of input message - * @rsa_pad *e@ = encoding procedure - * @void *earg@ = argument pointer for encoding procedure - * - * Returns: The signature, as a multiprecision integer, or null on - * failure. - * - * Use: Computes an RSA digital signature. - */ - -mp *rsa_sign(rsa_privctx *rp, mp *d, const void *m, size_t msz, - rsa_pad *e, void *earg) -{ - octet *p; - unsigned long nb = mp_bits(rp->rp->n); - size_t n = (nb + 7)/8; - arena *a = d && d->a ? d->a->a : arena_global; - - p = x_alloc(a, n); - d = e(d, m, msz, p, n, nb, earg); - x_free(a, p); - return (d ? rsa_privop(rp, d, d) : 0); -} - -/* --- @rsa_decrypt@ --- * - * - * Arguments: @rsa_privctx *rp@ = pointer to an RSA private key context - * @mp *m@ = encrypted message, as a multiprecision integer - * @dstr *d@ = pointer to output string - * @rsa_decunpad *e@ = decoding procedure - * @void *earg@ = argument pointer for decoding procedure - * - * Returns: The length of the output string if successful, negative on - * failure. - * - * Use: Does RSA decryption. - */ - -int rsa_decrypt(rsa_privctx *rp, mp *m, dstr *d, - rsa_decunpad *e, void *earg) -{ - mp *p = rsa_privop(rp, MP_NEW, m); - unsigned long nb = mp_bits(rp->rp->n); - size_t n = (nb + 7)/8; - int rc; - - dstr_ensure(d, n); - rc = e(p, (octet *)d->buf + d->len, n, nb, earg); - if (rc >= 0) - d->len += rc; - mp_drop(p); - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rsa-pub.c b/rsa-pub.c deleted file mode 100644 index e89d6ff..0000000 --- a/rsa-pub.c +++ /dev/null @@ -1,192 +0,0 @@ -/* -*-c-*- - * - * $Id: rsa-pub.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * [RSA encryption with padding * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include "mp.h" -#include "mpmont.h" -#include "rsa.h" - -/*----- Public key operations ---------------------------------------------*/ - -/* --- @rsa_pubcreate@ --- * - * - * Arguments: @rsa_pubctx *rd@ = pointer to an RSA public key context - * @rsa_pub *rp@ = pointer to RSA public key - * - * Returns: --- - * - * Use: Initializes an RSA public-key context. - */ - -void rsa_pubcreate(rsa_pubctx *rd, rsa_pub *rp) -{ - rd->rp = rp; - mpmont_create(&rd->mm, rp->n); -} - -/* --- @rsa_pubdestroy@ --- * - * - * Arguments: @rsa_pubctx *rd@ = pointer to an RSA public key context - * - * Returns: --- - * - * Use: Destroys an RSA public-key context. - */ - -void rsa_pubdestroy(rsa_pubctx *rd) -{ - mpmont_destroy(&rd->mm); -} - -/* --- @rsa_pubop@ --- * - * - * Arguments: @rsa_pubctx *rd@ = pointer to an RSA public key context - * @mp *d@ = destination - * @mp *p@ = input message - * - * Returns: The transformed output message. - * - * Use: Performs an RSA public key operation. - */ - -mp *rsa_pubop(rsa_pubctx *rd, mp *d, mp *p) -{ - return (mpmont_exp(&rd->mm, d, p, rd->rp->e)); -} - -/* --- @rsa_qpubop@ --- * - * - * Arguments: @rsa_pub *rp@ = pointer to RSA parameters - * @mp *d@ = destination - * @mp *p@ = input message - * - * Returns: Correctly transformed output message. - * - * Use: Performs an RSA public key operation. - */ - -mp *rsa_qpubop(rsa_pub *rp, mp *d, mp *c) -{ - rsa_pubctx rd; - rsa_pubcreate(&rd, rp); - d = rsa_pubop(&rd, d, c); - rsa_pubdestroy(&rd); - return (d); -} - -/*----- Operations with padding -------------------------------------------*/ - -/* --- @rsa_encrypt@ --- * - * - * Arguments: @rsa_pubctx *rp@ = pointer to an RSA public key context - * @mp *d@ = proposed destination integer - * @const void *m@ = pointer to input message - * @size_t msz@ = size of input message - * @rsa_pad *e@ = encoding procedure - * @void *earg@ = argument pointer for encoding procedure - * - * Returns: The encrypted message, as a multiprecision integer, or null - * on failure. - * - * Use: Does RSA encryption. - */ - -mp *rsa_encrypt(rsa_pubctx *rp, mp *d, const void *m, size_t msz, - rsa_pad *e, void *earg) -{ - octet *p; - unsigned long nb = mp_bits(rp->rp->n); - size_t n = (nb + 7)/8; - arena *a = d && d->a ? d->a->a : arena_global; - - p = x_alloc(a, n); - d = e(d, m, msz, p, n, nb, earg); - x_free(a, p); - return (d ? rsa_pubop(rp, d, d) : 0); -} - -/* --- @rsa_verify@ --- * - * - * Arguments: @rsa_pubctx *rp@ = pointer to an RSA public key contxt - * @mp *s@ = the signature, as a multiprecision integer - * @const void *m@ = pointer to message to verify, or null - * @size_t msz@ = size of input message - * @dstr *d@ = pointer to output string, or null - * @rsa_vfrunpad *e@ = decoding procedure - * @void *earg@ = argument pointer for decoding procedure - * - * Returns: The length of the output string if successful (0 if no output - * was wanted); negative on failure. - * - * Use: Does RSA signature verification. To use a signature scheme - * with recovery, pass in @m == 0@ and @d != 0@: the recovered - * message should appear in @d@. To use a signature scheme with - * appendix, provide @m != 0@ and @d == 0@; the result should be - * zero for success. - */ - -int rsa_verify(rsa_pubctx *rp, mp *s, const void *m, size_t msz, - dstr *d, rsa_vrfunpad *e, void *earg) -{ - mp *p = rsa_pubop(rp, MP_NEW, s); - unsigned long nb = mp_bits(rp->rp->n); - size_t n = (nb + 7)/8; - dstr dd = DSTR_INIT; - int rc; - - /* --- Decoder protocol --- * - * - * We deal with two kinds of decoders: ones with message recovery and ones - * with appendix. A decoder with recovery will leave a message in the - * buffer and exit nonzero: we'll check that against @m@ if provided and - * just leave it otherwise. A decoder with appendix will inspect @m@ and - * return zero or @-1@ itself. - */ - - if (!d) d = ⅆ - dstr_ensure(d, n); - rc = e(p, m, msz, (octet *)d->buf + d->len, n, nb, earg); - if (rc > 0 && m) { - if (rc != msz || memcmp(d->buf + d->len, m, msz) != 0) - rc = -1; - else - rc = 0; - } - if (rc > 0) - d->len += rc; - mp_drop(p); - dstr_destroy(&dd); - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rsa-recover.c b/rsa-recover.c deleted file mode 100644 index 4546cc3..0000000 --- a/rsa-recover.c +++ /dev/null @@ -1,242 +0,0 @@ -/* -*-c-*- - * - * $Id: rsa-recover.c,v 1.7 2004/04/08 01:36:15 mdw Exp $ - * - * Recover RSA parameters - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "mp.h" -#include "mpmont.h" -#include "rsa.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @rsa_recover@ --- * - * - * Arguments: @rsa_priv *rp@ = pointer to parameter block - * - * Returns: Zero if all went well, nonzero if the parameters make no - * sense. - * - * Use: Derives the full set of RSA parameters given a minimal set. - */ - -int rsa_recover(rsa_priv *rp) -{ - /* --- If there is no modulus, calculate it --- */ - - if (!rp->n) { - if (!rp->p || !rp->q) - return (-1); - rp->n = mp_mul(MP_NEW, rp->p, rp->q); - } - - /* --- If there are no factors, compute them --- */ - - else if (!rp->p || !rp->q) { - - /* --- If one is missing, use simple division to recover the other --- */ - - if (rp->p || rp->q) { - mp *r = MP_NEW; - if (rp->p) - mp_div(&rp->q, &r, rp->n, rp->p); - else - mp_div(&rp->p, &r, rp->n, rp->q); - if (!MP_EQ(r, MP_ZERO)) { - mp_drop(r); - return (-1); - } - mp_drop(r); - } - - /* --- Otherwise use the public and private moduli --- */ - - else if (!rp->e || !rp->d) - return (-1); - else { - mp *t; - size_t s; - mp a; mpw aw; - mp *m1; - mpmont mm; - int i; - mp *z = MP_NEW; - - /* --- Work out the appropriate exponent --- * - * - * I need to compute %$s$% and %$t$% such that %$2^s t = e d - 1$%, and - * %$t$% is odd. - */ - - t = mp_mul(MP_NEW, rp->e, rp->d); - t = mp_sub(t, t, MP_ONE); - t = mp_odd(t, t, &s); - - /* --- Set up for the exponentiation --- */ - - mpmont_create(&mm, rp->n); - m1 = mp_sub(MP_NEW, rp->n, mm.r); - - /* --- Now for the main loop --- * - * - * Choose candidate integers and attempt to factor the modulus. - */ - - mp_build(&a, &aw, &aw + 1); - i = 0; - for (;;) { - again: - - /* --- Choose a random %$a$% and calculate %$z = a^t \bmod n$% --- * - * - * If %$z \equiv 1$% or %$z \equiv -1 \pmod n$% then this iteration - * is a failure. - */ - - aw = primetab[i++]; - z = mpmont_mul(&mm, z, &a, mm.r2); - z = mpmont_expr(&mm, z, z, t); - if (MP_EQ(z, mm.r) || MP_EQ(z, m1)) - continue; - - /* --- Now square until something interesting happens --- * - * - * Compute %$z^{2i} \bmod n$%. Eventually, I'll either get %$-1$% or - * %$1$%. If the former, the number is uninteresting, and I need to - * restart. If the latter, the previous number minus 1 has a common - * factor with %$n$%. - */ - - for (;;) { - mp *zz = mp_sqr(MP_NEW, z); - zz = mpmont_reduce(&mm, zz, zz); - if (MP_EQ(zz, mm.r)) { - mp_drop(zz); - goto done; - } else if (MP_EQ(zz, m1)) { - mp_drop(zz); - goto again; - } - mp_drop(z); - z = zz; - } - } - - /* --- Do the factoring --- * - * - * Here's how it actually works. I've found an interesting square - * root of %$1 \pmod n$%. Any square root of 1 must be congruent to - * %$\pm 1$% modulo both %$p$% and %$q$%. Both congruent to %$1$% is - * boring, as is both congruent to %$-1$%. Subtracting one from the - * result makes it congruent to %$0$% modulo %$p$% or %$q$% (and - * nobody cares which), and hence can be extracted by a GCD - * operation. - */ - - done: - z = mpmont_reduce(&mm, z, z); - z = mp_sub(z, z, MP_ONE); - rp->p = MP_NEW; - mp_gcd(&rp->p, 0, 0, rp->n, z); - rp->q = MP_NEW; - mp_div(&rp->q, 0, rp->n, rp->p); - mp_drop(z); - mp_drop(t); - mp_drop(m1); - if (MP_CMP(rp->p, <, rp->q)) { - z = rp->p; - rp->p = rp->q; - rp->q = z; - } - mpmont_destroy(&mm); - } - } - - /* --- If %$e$% or %$d$% is missing, recalculate it --- */ - - if (!rp->e || !rp->d) { - mp *phi; - mp *g = MP_NEW; - mp *p1, *q1; - - /* --- Compute %$\varphi(n)$% --- */ - - phi = mp_sub(MP_NEW, rp->n, rp->p); - phi = mp_sub(phi, phi, rp->q); - phi = mp_add(phi, phi, MP_ONE); - p1 = mp_sub(MP_NEW, rp->p, MP_ONE); - q1 = mp_sub(MP_NEW, rp->q, MP_ONE); - mp_gcd(&g, 0, 0, p1, q1); - mp_div(&phi, 0, phi, g); - mp_drop(p1); - mp_drop(q1); - - /* --- Recover the other exponent --- */ - - if (rp->e) - mp_gcd(&g, 0, &rp->d, phi, rp->e); - else if (rp->d) - mp_gcd(&g, 0, &rp->e, phi, rp->d); - else { - mp_drop(phi); - mp_drop(g); - return (-1); - } - - mp_drop(phi); - if (!MP_EQ(g, MP_ONE)) { - mp_drop(g); - return (-1); - } - mp_drop(g); - } - - /* --- Compute %$q^{-1} \bmod p$% --- */ - - if (!rp->q_inv) - mp_gcd(0, 0, &rp->q_inv, rp->p, rp->q); - - /* --- Compute %$d \bmod (p - 1)$% and %$d \bmod (q - 1)$% --- */ - - if (!rp->dp) { - mp *p1 = mp_sub(MP_NEW, rp->p, MP_ONE); - mp_div(0, &rp->dp, rp->d, p1); - mp_drop(p1); - } - if (!rp->dq) { - mp *q1 = mp_sub(MP_NEW, rp->q, MP_ONE); - mp_div(0, &rp->dq, rp->d, q1); - mp_drop(q1); - } - - /* --- Done --- */ - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rsa-test.c b/rsa-test.c deleted file mode 100644 index e4c330f..0000000 --- a/rsa-test.c +++ /dev/null @@ -1,514 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Testing RSA padding operations - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "fibrand.h" -#include "rsa.h" - -/*----- Main code ---------------------------------------------------------*/ - -static int tencpad(int nbits, - dstr *p, int rc, mp *c, - const char *ename, dstr *eparam, rsa_pad *e, void *earg) -{ - size_t n = (nbits + 7)/8; - void *q = xmalloc(n); - mp *d; - int ok = 1; - - d = e(MP_NEW, p->buf, p->len, q, n, nbits, earg); - if (!d == !rc || (!rc && !MP_EQ(d, c))) { - ok = 0; - fprintf(stderr, "*** %s padding failed!\n", ename); - fprintf(stderr, "*** padding bits = %d\n", nbits); - if (eparam) { - fprintf(stderr, "*** encoding parameters = "); - type_hex.dump(eparam, stderr); - fputc('\n', stderr); - } - fprintf(stderr, "*** input message = "); type_hex.dump(p, stderr); - if (rc) - fprintf(stderr, "\n*** expected failure\n"); - else { - MP_EPRINTX("\n*** expected", c); - MP_EPRINTX("*** computed", d); - } - } - mp_drop(d); - mp_drop(c); - xfree(q); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -#define tsigpad tencpad - -#define DSTR_EQ(x, y) \ - ((x)->len == (y)->len && !memcmp((x)->buf, (y)->buf, (x)->len)) - -static int tdecpad(int nbits, - mp *c, int rc, dstr *p, - const char *ename, dstr *eparam, - rsa_decunpad *e, void *earg) -{ - dstr d = DSTR_INIT; - int n = (nbits + 7)/8; - int ok = 1; - - dstr_ensure(&d, n); - n = e(c, (octet *)d.buf, n, nbits, earg); - if (n >= 0) - d.len += n; - if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) { - ok = 0; - fprintf(stderr, "*** %s encryption unpadding failed!\n", ename); - fprintf(stderr, "*** padding bits = %d\n", nbits); - if (eparam) { - fprintf(stderr, "*** encoding parameters = "); - type_hex.dump(eparam, stderr); - fputc('\n', stderr); - } - MP_EPRINTX("*** input", c); - if (rc < 0) - fprintf(stderr, "*** expected failure\n"); - else { - fprintf(stderr, "*** expected: %d = ", rc); type_hex.dump(p, stderr); - fprintf(stderr, "\n*** computed: %d = ", n); type_hex.dump(&d, stderr); - fprintf(stderr, "\n"); - } - } - mp_drop(c); - dstr_destroy(&d); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tvrfpad(int nbits, - mp *c, dstr *m, int rc, dstr *p, - const char *ename, dstr *eparam, - rsa_vrfunpad *e, void *earg) -{ - dstr d = DSTR_INIT; - int n = (nbits + 7)/8; - int ok = 1; - - dstr_ensure(&d, n); - n = e(c, m->len ? (octet *)m->buf : 0, m->len, - (octet *)d.buf, n, nbits, earg); - if (n >= 0) - d.len += n; - if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) { - ok = 0; - fprintf(stderr, "*** %s signature unpadding failed!\n", ename); - fprintf(stderr, "*** padding bits = %d\n", nbits); - MP_EPRINTX("*** input", c); - if (eparam) { - fprintf(stderr, "*** encoding parameters = "); - type_hex.dump(eparam, stderr); - fputc('\n', stderr); - } - fprintf(stderr, "*** message = "); type_hex.dump(m, stderr); - if (rc < 0) - fprintf(stderr, "\n*** expected failure\n"); - else { - fprintf(stderr, "\n*** expected = %d: ", rc); type_hex.dump(p, stderr); - fprintf(stderr, "\n*** computed = %d: ", n); type_hex.dump(&d, stderr); - fprintf(stderr, "\n"); - } - } - mp_drop(c); - dstr_destroy(&d); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tencpub(rsa_pub *rp, - dstr *p, int rc, mp *c, - const char *ename, dstr *eparam, rsa_pad *e, void *earg) -{ - mp *d; - rsa_pubctx rpc; - int ok = 1; - - rsa_pubcreate(&rpc, rp); - d = rsa_encrypt(&rpc, MP_NEW, p->buf, p->len, e, earg); - if (!d == !rc || (!rc && !MP_EQ(d, c))) { - ok = 0; - fprintf(stderr, "*** encrypt with %s padding failed!\n", ename); - MP_EPRINTX("*** key.n", rp->n); - MP_EPRINTX("*** key.e", rp->e); - if (eparam) { - fprintf(stderr, "*** encoding parameters = "); - type_hex.dump(eparam, stderr); - fputc('\n', stderr); - } - fprintf(stderr, "*** input message = "); type_hex.dump(p, stderr); - if (rc) - fprintf(stderr, "\n*** expected failure\n"); - else { - MP_EPRINTX("\n*** expected", c); - MP_EPRINTX("*** computed", d); - } - } - rsa_pubdestroy(&rpc); - rsa_pubfree(rp); - mp_drop(d); - mp_drop(c); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tsigpriv(rsa_priv *rp, - dstr *p, int rc, mp *c, - const char *ename, dstr *eparam, rsa_pad *e, void *earg) -{ - mp *d; - grand *r = fibrand_create(0); - rsa_privctx rpc; - int ok = 1; - - rsa_privcreate(&rpc, rp, r); - d = rsa_sign(&rpc, MP_NEW, p->buf, p->len, e, earg); - if (!d == !rc || (!rc && !MP_EQ(d, c))) { - ok = 0; - fprintf(stderr, "*** sign with %s padding failed!\n", ename); - MP_EPRINTX("*** key.n", rp->n); - MP_EPRINTX("*** key.d", rp->d); - MP_EPRINTX("*** key.e", rp->e); - if (eparam) { - fprintf(stderr, "*** encoding parameters = "); - type_hex.dump(eparam, stderr); - fputc('\n', stderr); - } - fprintf(stderr, "*** input message = "); type_hex.dump(p, stderr); - if (rc) - fprintf(stderr, "\n*** expected failure\n"); - else { - MP_EPRINTX("\n*** expected", c); - MP_EPRINTX("\n*** computed", d); - } - } - rsa_privdestroy(&rpc); - rsa_privfree(rp); - mp_drop(d); - mp_drop(c); - GR_DESTROY(r); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tdecpriv(rsa_priv *rp, - mp *c, int rc, dstr *p, - const char *ename, dstr *eparam, - rsa_decunpad *e, void *earg) -{ - rsa_privctx rpc; - dstr d = DSTR_INIT; - grand *r = fibrand_create(0); - int n; - int ok = 1; - - rsa_privcreate(&rpc, rp, r); - n = rsa_decrypt(&rpc, c, &d, e, earg); - if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) { - ok = 0; - fprintf(stderr, "*** decryption with %s padding failed!\n", ename); - MP_EPRINTX("*** key.n", rp->n); - MP_EPRINTX("*** key.d", rp->d); - MP_EPRINTX("*** key.e", rp->e); - if (eparam) { - fprintf(stderr, "*** encoding parameters = "); - type_hex.dump(eparam, stderr); - fputc('\n', stderr); - } - MP_EPRINTX("*** input", c); - if (rc < 0) - fprintf(stderr, "*** expected failure\n"); - else { - fprintf(stderr, "*** expected = %d: ", rc); type_hex.dump(p, stderr); - fprintf(stderr, "\n*** computed = %d: ", n); type_hex.dump(&d, stderr); - fprintf(stderr, "\n"); - } - } - rsa_privdestroy(&rpc); - rsa_privfree(rp); - mp_drop(c); - dstr_destroy(&d); - GR_DESTROY(r); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -static int tvrfpub(rsa_pub *rp, - mp *c, dstr *m, int rc, dstr *p, - const char *ename, dstr *eparam, - rsa_vrfunpad *e, void *earg) -{ - rsa_pubctx rpc; - dstr d = DSTR_INIT; - int n; - int ok = 1; - - rsa_pubcreate(&rpc, rp); - n = rsa_verify(&rpc, c, m->len ? m->buf : 0, m->len, &d, e, earg); - if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) { - ok = 0; - fprintf(stderr, "*** verification with %s padding failed!\n", ename); - MP_EPRINTX("*** key.n", rp->n); - MP_EPRINTX("*** key.e", rp->e); - if (eparam) { - fprintf(stderr, "*** encoding parameters = "); - type_hex.dump(eparam, stderr); - fputc('\n', stderr); - } - MP_EPRINTX("*** input", c); - fprintf(stderr, "*** message = "); type_hex.dump(m, stderr); - if (rc < 0) - fprintf(stderr, "\n*** expected failure\n"); - else { - fprintf(stderr, "\n*** expected = %d: ", rc); type_hex.dump(p, stderr); - fprintf(stderr, "\n*** computed = %d: ", n); type_hex.dump(&d, stderr); - fprintf(stderr, "\n"); - } - } - rsa_pubdestroy(&rpc); - rsa_pubfree(rp); - mp_drop(c); - dstr_destroy(&d); - assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); -} - -/*----- Deep magic --------------------------------------------------------* - * - * Wahey! Whacko macro programming on curry and lager. There's nothing like - * it. - */ - -#define DECL_priv \ - rsa_priv rp = { 0 }; -#define FUNC_priv \ - rp.n = *(mp **)v++->buf; \ - rp.e = *(mp **)v++->buf; \ - rp.d = *(mp **)v++->buf; \ - rsa_recover(&rp); -#define ARG_priv \ - &rp, -#define TAB_priv \ - &type_mp, &type_mp, &type_mp, - -#define DECL_pub \ - rsa_pub rp; -#define FUNC_pub \ - rp.n = *(mp **)v++->buf; \ - rp.e = *(mp **)v++->buf; -#define ARG_pub \ - &rp, -#define TAB_pub \ - &type_mp, &type_mp, - -#define DECL_pad \ - int nbits; -#define FUNC_pad \ - nbits = *(int *)v++->buf; -#define ARG_pad \ - nbits, -#define TAB_pad \ - &type_int, - -#define DECL_enc \ - dstr *p; \ - int rc; \ - mp *c; -#define FUNC_enc \ - p = v++; \ - rc = *(int *)v++->buf; \ - c = *(mp **)v++->buf; -#define ARG_enc \ - p, rc, c, -#define TAB_enc \ - &type_hex, &type_int, &type_mp, - -#define DECL_sig DECL_enc -#define FUNC_sig FUNC_enc -#define ARG_sig ARG_enc -#define TAB_sig TAB_enc - -#define DECL_dec \ - mp *c; \ - int rc; \ - dstr *p; -#define FUNC_dec \ - c = *(mp **)v++->buf; \ - rc = *(int *)v++->buf; \ - p = v++; -#define ARG_dec \ - c, rc, p, -#define TAB_dec \ - &type_mp, &type_int, &type_hex, - -#define DECL_vrf \ - mp *c; \ - dstr *m; \ - int rc; \ - dstr *p; -#define FUNC_vrf \ - c = *(mp **)v++->buf; \ - m = v++; \ - rc = *(int *)v++->buf; \ - p = v++; -#define ARG_vrf \ - c, m, rc, p, -#define TAB_vrf \ - &type_mp, &type_hex, &type_int, &type_hex, - -#define DECL_p1enc \ - pkcs1 p1; \ - dstr *ep; -#define FUNC_p1enc \ - p1.r = fib; \ - ep = v++; \ - p1.ep = ep->buf; \ - p1.epsz = ep->len; -#define ARG_p1enc \ - "pkcs1", ep, pkcs1_cryptencode, &p1 -#define TAB_p1enc \ - &type_hex - -#define DECL_p1sig DECL_p1enc -#define FUNC_p1sig FUNC_p1enc -#define ARG_p1sig \ - "pkcs1", ep, pkcs1_sigencode, &p1 -#define TAB_p1sig TAB_p1enc - -#define DECL_p1dec DECL_p1enc -#define FUNC_p1dec FUNC_p1enc -#define ARG_p1dec \ - "pkcs1", ep, pkcs1_cryptdecode, &p1 -#define TAB_p1dec TAB_p1enc - -#define DECL_p1vrf DECL_p1enc -#define FUNC_p1vrf FUNC_p1enc -#define ARG_p1vrf \ - "pkcs1", ep, pkcs1_sigdecode, &p1 -#define TAB_p1vrf TAB_p1enc - -#define DECL_oaepenc \ - oaep o; \ - dstr *ep; -#define FUNC_oaepenc \ - o.r = fib; \ - o.cc = gcipher_byname(v++->buf); \ - o.ch = ghash_byname(v++->buf); \ - ep = v++; \ - o.ep = ep->buf; \ - o.epsz = ep->len; -#define ARG_oaepenc \ - "oaep", ep, oaep_encode, &o -#define TAB_oaepenc \ - &type_string, &type_string, &type_hex - -#define DECL_oaepdec DECL_oaepenc -#define FUNC_oaepdec FUNC_oaepenc -#define ARG_oaepdec \ - "oaep", ep, oaep_decode, &o -#define TAB_oaepdec TAB_oaepenc - -#define DECL_psssig \ - pss pp; -#define FUNC_psssig \ - pp.r = fib; \ - pp.cc = gcipher_byname(v++->buf); \ - pp.ch = ghash_byname(v++->buf); \ - pp.ssz = *(int *)v++->buf; -#define ARG_psssig \ - "pss", 0, pss_encode, &pp -#define TAB_psssig \ - &type_string, &type_string, &type_int - -#define DECL_pssvrf DECL_psssig -#define FUNC_pssvrf FUNC_psssig -#define ARG_pssvrf \ - "pss", 0, pss_decode, &pp -#define TAB_pssvrf TAB_psssig - -#define TESTS(DO) \ - DO(pad, enc, p1enc) \ - DO(pad, dec, p1dec) \ - DO(pad, sig, p1sig) \ - DO(pad, vrf, p1vrf) \ - DO(pub, enc, p1enc) \ - DO(priv, dec, p1dec) \ - DO(priv, sig, p1sig) \ - DO(pub, vrf, p1vrf) \ - DO(pad, enc, oaepenc) \ - DO(pad, dec, oaepdec) \ - DO(pub, enc, oaepenc) \ - DO(priv, dec, oaepdec) \ - DO(pad, sig, psssig) \ - DO(pad, vrf, pssvrf) \ - DO(priv, sig, psssig) \ - DO(pub, vrf, pssvrf) - -#define FUNCS(key, op, enc) \ - int t_##key##_##enc(dstr *v) \ - { \ - DECL_##key \ - DECL_##op \ - DECL_##enc \ - fib->ops->misc(fib, GRAND_SEEDINT, 14); \ - FUNC_##key \ - FUNC_##op \ - FUNC_##enc \ - return (t##op##key(ARG_##key ARG_##op ARG_##enc)); \ - } - -#define TAB(key, op, enc) \ - { #enc "-" #key, t_##key##_##enc, { TAB_##key TAB_##op TAB_##enc } }, - -static grand *fib; - -TESTS(FUNCS) - -static const test_chunk tests[] = { - TESTS(TAB) - { 0 } -}; - -int main(int argc, char *argv[]) -{ - sub_init(); - fib = fibrand_create(0); - test_run(argc, argv, tests, SRCDIR "/tests/rsa"); - GR_DESTROY(fib); - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/rsa.h b/rsa.h deleted file mode 100644 index f4b1c14..0000000 --- a/rsa.h +++ /dev/null @@ -1,404 +0,0 @@ -/* -*-c-*- - * - * $Id: rsa.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * The RSA public-key cryptosystem - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_RSA_H -#define CATACOMB_RSA_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -#ifndef CATACOMB_KEY_H -# include "key.h" -#endif - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -#ifndef CATACOMB_PGEN_H -# include "pgen.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- RSA private and public keys --- */ - -typedef struct rsa_pub { - mp *n; - mp *e; -} rsa_pub; - -typedef struct rsa_priv { - mp *n, *p, *q, *q_inv; - mp *e, *d, *dp, *dq; -} rsa_priv; - -/* --- RSA private and public key contexts --- * - * - * These are used to store information about `active' keys which will speed - * up the various operations. - */ - -typedef struct rsa_privctx { - rsa_priv *rp; - grand *r; - mpmont nm, pm, qm; -} rsa_privctx; - -typedef struct rsa_pubctx { - mpmont mm; - rsa_pub *rp; -} rsa_pubctx; - -/* --- Encoding and decoding function schemas --- * - * - * See `oaep.h' and `pkcs1.h' for appropriate encoding functions. - */ - -typedef mp *rsa_pad(mp */*d*/, const void */*m*/, size_t /*msz*/, - octet */*b*/, size_t /*sz*/, - unsigned long /*nbits*/, void */*p*/); - -typedef int rsa_decunpad(mp */*m*/, octet */*b*/, size_t /*sz*/, - unsigned long /*nbits*/, void */*p*/); - -typedef int rsa_vrfunpad(mp */*s*/, const void */*m*/, size_t /*msz*/, - octet */*b*/, size_t /*sz*/, - unsigned long /*nbits*/, void */*p*/); - -/*----- Key fetching ------------------------------------------------------*/ - -extern const key_fetchdef rsa_pubfetch[]; -#define RSA_PUBFETCHSZ 4 - -extern const key_fetchdef rsa_privfetch[]; -#define RSA_PRIVFETCHSZ 12 - -/* --- @rsa_pubfree@, @rsa_privfree@ --- * - * - * Arguments: @rsa_pub *rp@, @rsa_priv *rp@ = pointer to key block - * - * Returns: --- - * - * Use: Frees an RSA key block. - */ - -extern void rsa_pubfree(rsa_pub */*rp*/); -extern void rsa_privfree(rsa_priv */*rp*/); - -/*----- RSA private key operations ----------------------------------------*/ - -/* --- @rsa_privcreate@ --- * - * - * Arguments: @rsa_privctx *rd@ = pointer to an RSA private key context - * @rsa_priv *rp@ = pointer to RSA private key - * @grand *r@ = pointer to random number source for blinding - * - * Returns: --- - * - * Use: Initializes an RSA private-key context. Keeping a context - * for several decryption or signing operations provides a minor - * performance benefit. - * - * The random number source may be null if blinding is not - * desired. This improves decryption speed, at the risk of - * permitting timing attacks. - */ - -extern void rsa_privcreate(rsa_privctx */*rd*/, rsa_priv */*rp*/, - grand */*r*/); - -/* --- @rsa_privdestroy@ --- * - * - * Arguments: @rsa_privctx *rd@ = pointer to an RSA decryption context - * - * Returns: --- - * - * Use: Destroys an RSA decryption context. - */ - -extern void rsa_privdestroy(rsa_privctx */*rd*/); - -/* --- @rsa_privop@ --- * - * - * Arguments: @rsa_privctx *rd@ = pointer to RSA private key context - * @mp *d@ = destination - * @mp *c@ = input message - * - * Returns: The transformed output message. - * - * Use: Performs an RSA private key operation. This function takes - * advantage of knowledge of the key factors in order to speed - * up decryption. It also blinds the ciphertext prior to - * decryption and unblinds it afterwards to thwart timing - * attacks. - */ - -extern mp *rsa_privop(rsa_privctx */*rd*/, mp */*d*/, mp */*c*/); - -/* --- @rsa_qprivop@ --- * - * - * Arguments: @rsa_priv *rp@ = pointer to RSA parameters - * @mp *d@ = destination - * @mp *c@ = input message - * @grand *r@ = pointer to random number source for blinding - * - * Returns: Correctly transformed output message - * - * Use: Performs an RSA private key operation, very carefully. - */ - -extern mp *rsa_qprivop(rsa_priv */*rp*/, mp */*d*/, mp */*c*/, grand */*r*/); - -/* --- @rsa_sign@ --- * - * - * Arguments: @rsa_privctx *rp@ = pointer to an RSA private key context - * @mp *d@ = where to put the result - * @const void *m@ = pointer to input message - * @size_t msz@ = size of input message - * @rsa_pad *e@ = encoding procedure - * @void *earg@ = argument pointer for encoding procedure - * - * Returns: The signature, as a multiprecision integer, or null on - * failure. - * - * Use: Computes an RSA digital signature. - */ - -extern mp *rsa_sign(rsa_privctx */*rp*/, mp */*d*/, - const void */*m*/, size_t /*msz*/, - rsa_pad */*e*/, void */*earg*/); - -/* --- @rsa_decrypt@ --- * - * - * Arguments: @rsa_privctx *rp@ = pointer to an RSA private key context - * @mp *m@ = encrypted message, as a multiprecision integer - * @dstr *d@ = pointer to output string - * @rsa_decunpad *e@ = decoding procedure - * @void *earg@ = argument pointer for decoding procedure - * - * Returns: The length of the output string if successful, negative on - * failure. - * - * Use: Does RSA decryption. - */ - -extern int rsa_decrypt(rsa_privctx */*rp*/, mp */*m*/, - dstr */*d*/, rsa_decunpad */*e*/, void */*earg*/); - -/*----- RSA public key operations -----------------------------------------*/ - -/* --- @rsa_pubcreate@ --- * - * - * Arguments: @rsa_pubctx *rd@ = pointer to an RSA public key context - * @rsa_pub *rp@ = pointer to RSA public key - * - * Returns: --- - * - * Use: Initializes an RSA public-key context. - */ - -extern void rsa_pubcreate(rsa_pubctx */*rd*/, rsa_pub */*rp*/); - -/* --- @rsa_pubdestroy@ --- * - * - * Arguments: @rsa_pubctx *rd@ = pointer to an RSA public key context - * - * Returns: --- - * - * Use: Destroys an RSA public-key context. - */ - -extern void rsa_pubdestroy(rsa_pubctx */*rd*/); - -/* --- @rsa_pubop@ --- * - * - * Arguments: @rsa_pubctx *rd@ = pointer to an RSA public key context - * @mp *d@ = destination - * @mp *p@ = input message - * - * Returns: The transformed output message. - * - * Use: Performs an RSA public key operation. - */ - -extern mp *rsa_pubop(rsa_pubctx */*rd*/, mp */*d*/, mp */*p*/); - -/* --- @rsa_qpubop@ --- * - * - * Arguments: @rsa_pub *rp@ = pointer to RSA parameters - * @mp *d@ = destination - * @mp *p@ = input message - * - * Returns: Correctly transformed output message. - * - * Use: Performs an RSA public key operation. - */ - -extern mp *rsa_qpubop(rsa_pub */*rp*/, mp */*d*/, mp */*c*/); - -/* --- @rsa_encrypt@ --- * - * - * Arguments: @rsa_pubctx *rp@ = pointer to an RSA public key context - * @mp *d@ = proposed destination integer - * @const void *m@ = pointer to input message - * @size_t msz@ = size of input message - * @rsa_pad *e@ = encoding procedure - * @void *earg@ = argument pointer for encoding procedure - * - * Returns: The encrypted message, as a multiprecision integer, or null - * on failure. - * - * Use: Does RSA encryption. - */ - -extern mp *rsa_encrypt(rsa_pubctx */*rp*/, mp */*d*/, - const void */*m*/, size_t /*msz*/, - rsa_pad */*e*/, void */*earg*/); - -/* --- @rsa_verify@ --- * - * - * Arguments: @rsa_pubctx *rp@ = pointer to an RSA public key contxt - * @mp *s@ = the signature, as a multiprecision integer - * @const void *m@ = pointer to message to verify, or null - * @size_t sz@ = size of input message - * @dstr *d@ = pointer to output string, or null - * @rsa_vfrunpad *e@ = decoding procedure - * @void *earg@ = argument pointer for decoding procedure - * - * Returns: The length of the output string if successful (0 if no output - * was wanted); negative on failure. - * - * Use: Does RSA signature verification. To use a signature scheme - * with recovery, pass in @m == 0@ and @d != 0@: the recovered - * message should appear in @d@. To use a signature scheme with - * appendix, provide @m != 0@ and @d == 0@; the result should be - * zero for success. - */ - -extern int rsa_verify(rsa_pubctx */*rp*/, mp */*s*/, - const void */*m*/, size_t /*sz*/, dstr */*d*/, - rsa_vrfunpad */*e*/, void */*earg*/); - -/*----- Miscellaneous operations ------------------------------------------*/ - -/* --- @rsa_gen@ --- * - * - * Arguments: @rsa_priv *rp@ = pointer to block to be filled in - * @unsigned nbits@ = required modulus size in bits - * @grand *r@ = random number source - * @unsigned n@ = number of attempts to make - * @pgen_proc *event@ = event handler function - * @void *ectx@ = argument for the event handler - * - * Returns: Zero if all went well, nonzero otherwise. - * - * Use: Constructs a pair of strong RSA primes and other useful RSA - * parameters. A small encryption exponent is chosen if - * possible. - */ - -extern int rsa_gen(rsa_priv */*rp*/, unsigned /*nbits*/, - grand */*r*/, unsigned /*n*/, - pgen_proc */*event*/, void */*ectx*/); - -/* --- @rsa_recover@ --- * - * - * Arguments: @rsa_priv *rp@ = pointer to parameter block - * - * Returns: Zero if all went well, nonzero if the parameters make no - * sense. - * - * Use: Derives the full set of RSA parameters given a minimal set. - */ - -extern int rsa_recover(rsa_priv */*rp*/); - -/*----- Padding schemes ---------------------------------------------------*/ - -/* --- PKCS1 padding --- */ - -typedef struct pkcs1 { - grand *r; /* Random number source */ - const void *ep; /* Encoding parameters block */ - size_t epsz; /* Size of the parameter block */ -} pkcs1; - -extern rsa_pad pkcs1_cryptencode; -extern rsa_decunpad pkcs1_cryptdecode; -extern rsa_pad pkcs1_sigencode; -extern rsa_vrfunpad pkcs1_sigdecode; - -/* --- OAEP --- */ - -typedef struct oaep { - const gccipher *cc; /* Cipher class for masking */ - const gchash *ch; /* Hash class for parameter block */ - grand *r; /* Random number source */ - const void *ep; /* Encoding parameters block */ - size_t epsz; /* Size of the parameter block */ -} oaep; - -extern rsa_pad oaep_encode; -extern rsa_decunpad oaep_decode; - -/* --- PSS --- */ - -typedef struct pss { - const gccipher *cc; /* Cipher class for masking */ - const gchash *ch; /* Hash class for choosing a seed */ - grand *r; /* Random number source */ - size_t ssz; /* Requested salt size */ -} pss; - -extern rsa_pad pss_encode; -extern rsa_vrfunpad pss_decode; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/rspit.c b/rspit.c deleted file mode 100644 index e471508..0000000 --- a/rspit.c +++ /dev/null @@ -1,1402 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Spit out random numbers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef PORTABLE -# include -#endif - -#include -#include -#include -#include -#include -#include - -#include "fipstest.h" -#include "grand.h" -#include "maurer.h" -#include "key.h" - -#include "lcrand.h" -#include "fibrand.h" -#include "rand.h" -#include "noise.h" - -#include "bbs.h" -#include "mprand.h" - -#include "rc4.h" -#include "seal.h" - -#include "des-ofb.h" -#include "des3-ofb.h" -#include "rc2-ofb.h" -#include "rc5-ofb.h" -#include "mars-ofb.h" -#include "skipjack-ofb.h" -#include "tea-ofb.h" -#include "xtea-ofb.h" -#include "blowfish-ofb.h" -#include "twofish-ofb.h" -#include "idea-ofb.h" -#include "cast128-ofb.h" -#include "cast256-ofb.h" -#include "noekeon-ofb.h" -#include "rijndael-ofb.h" -#include "rijndael192-ofb.h" -#include "rijndael256-ofb.h" -#include "safer-ofb.h" -#include "safersk-ofb.h" -#include "square-ofb.h" -#include "serpent-ofb.h" - -#include "des-counter.h" -#include "des3-counter.h" -#include "rc2-counter.h" -#include "rc5-counter.h" -#include "mars-counter.h" -#include "skipjack-counter.h" -#include "tea-counter.h" -#include "xtea-counter.h" -#include "blowfish-counter.h" -#include "twofish-counter.h" -#include "idea-counter.h" -#include "cast128-counter.h" -#include "cast256-counter.h" -#include "noekeon-counter.h" -#include "rijndael-counter.h" -#include "rijndael192-counter.h" -#include "rijndael256-counter.h" -#include "safer-counter.h" -#include "safersk-counter.h" -#include "square-counter.h" -#include "serpent-counter.h" - -#include "md2-mgf.h" -#include "md4-mgf.h" -#include "md5-mgf.h" -#include "sha-mgf.h" -#include "tiger-mgf.h" -#include "rmd128-mgf.h" -#include "rmd160-mgf.h" -#include "rmd256-mgf.h" -#include "rmd320-mgf.h" - -#include "rmd160.h" - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct gen { - const char *name; - grand *(*seed)(unsigned /*i*/); - unsigned i; - const char *help; -} gen; - -extern gen generators[]; - -#define CIPHERS \ - E(DES, des) \ - E(DES3, des3) \ - E(RC2, rc2) \ - E(RC5, rc5) \ - E(MARS, mars) \ - E(SKIPJACK, skipjack) \ - E(TEA, tea) \ - E(XTEA, xtea) \ - E(BLOWFISH, blowfish) \ - E(TWOFISH, twofish) \ - E(IDEA, idea) \ - E(CAST128, cast128) \ - E(CAST256, cast256) \ - E(SQUARE, square) \ - E(SAFER, safer) \ - E(SAFERSK, safersk) \ - E(NOEKEON, noekeon) \ - E(RIJNDAEL, rijndael) \ - E(RIJNDAEL192, rijndael192) \ - E(RIJNDAEL256, rijndael256) \ - E(SERPENT, serpent) - -#define HASHES \ - E(MD2, md2) \ - E(MD4, md4) \ - E(MD5, md5) \ - E(SHA, sha) \ - E(TIGER, tiger) \ - E(RMD128, rmd128) \ - E(RMD160, rmd160) \ - E(RMD256, rmd256) \ - E(RMD320, rmd320) - -#define E(PRE, pre) CIPHER_##PRE, -enum { CIPHERS CIPHER__bogus }; -#undef E - -#define E(PRE, pre) HASH_##PRE, -enum { HASHES HASH__bogus }; -#undef E - -static struct { - const octet *keysz; - size_t blksz; - grand *(*ofb)(const void */*k*/, size_t /*sz*/); - grand *(*counter)(const void */*k*/, size_t /*sz*/); -} ciphertab[] = { -#define E(PRE, pre) \ - { pre##_keysz, PRE##_BLKSZ, pre##_ofbrand, pre##_counterrand }, - CIPHERS -#undef E -}; - -static struct { - const gchash *h; - const octet *keysz; - grand *(*mgf)(const void */*k*/, size_t /*sz*/); -} hashtab[] = { -#define E(PRE, pre) \ - { &pre, pre##_mgfkeysz, pre##_mgfrand }, - HASHES -#undef E -}; - -/*----- Miscellaneous static data -----------------------------------------*/ - -static FILE *outfp; -static size_t outsz = 0; -static unsigned maurer_lo = 5, maurer_hi = 8; - -static int argc; -static char **argv; - -static unsigned flags = 0; - -#define f_progress 1u -#define f_file 2u -#define f_fips 4u -#define f_maurer 8u -#define f_timer 16u -#define f_discard 32u - -/*----- Help options ------------------------------------------------------*/ - -static void usage(FILE *fp) -{ - pquis(fp, "Usage: $ generator [options]\n"); -} - -static void version(FILE *fp) -{ - pquis(fp, "$, Catacomb version " VERSION "\n"); -} - -static void help(FILE *fp) -{ - version(fp); - fputc('\n', fp); - usage(fp); - pquis(fp, "\n\ -Emits a stream of random bytes suitable for, well, all sorts of things.\n\ -The primary objective is to be able to generate streams of input for\n\ -statistical tests, such as Diehard.\n\ -\n\ -Options are specific to the particular generator, although there's a\n\ -common core set:\n\ -\n\ --h, --help Display this help message.\n\ --v, --version Display the program's version number.\n\ --u, --usage Display a useless usage message.\n\ -\n\ --l, --list Show a list of the supported generators, with\n\ - their options.\n\ --f, --fipstest Run the FIPS 140-1 randomness test.\n\ --m, --maurer[=LO-HI] Run Maurer's universal statistical test.\n\ --o, --output FILE Write output to FILE, not stdout.\n\ --z, --size SIZE Emit SIZE bytes, not an unlimited number.\n\ --p, --progress Show a little progress meter (on stderr).\n\ --T, --timer Keep track of the CPU time used by the generator.\n\ --d, --discard Discard the generated output.\n\ -\n\ -(A SIZE may be followed by `g' for gigabytes, `m' for megabytes, or\n\ -`k' for kilobytes. If unqualified, an amount in bytes is assumed.)\n\ -"); -} - -/*----- Main options parser -----------------------------------------------*/ - -static struct option opts[] = { - - /* --- Standard GNU help options --- */ - - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'v' }, - { "usage", 0, 0, 'u' }, - - /* --- Other useful things --- */ - - { "list", 0, 0, 'l' }, - { "fipstest", 0, 0, 'f' }, - { "maurer", OPTF_ARGOPT, 0, 'm' }, - { "output", OPTF_ARGREQ, 0, 'o' }, - { "size", OPTF_ARGREQ, 0, 'z' }, - { "progress", 0, 0, 'p' }, - { "timer", 0, 0, 'T' }, - { "discard", 0, 0, 'd' }, - - /* --- End of main table --- */ - - { 0, 0, 0, 0 } -}; - -static const char *sopts = "hvu lfm::o:z:pTd"; - -#ifndef OPTION_V - DA_DECL(option_v, struct option); -# define OPTION_V -#endif - -static option_v optv = DA_INIT; -static dstr optd = DSTR_INIT; - -/* --- @addopts@ --- * - * - * Arguments: @const char *s@ = pointer to short options - * @struct option *l@ = pointer to long options - * - * Returns: --- - * - * Use: Adds a collection of options to the table. - */ - -static void addopts(const char *s, struct option *l) -{ - dstr_puts(&optd, s); - if (DA_LEN(&optv)) - DA_SHRINK(&optv, 1); - while (l->name) - DA_PUSH(&optv, *l++); - DA_PUSH(&optv, *l); -} - -/* --- @opt@ --- * - * - * Arguments: --- - * - * Returns: Next option from argument array. - * - * Use: Fetches options, handling the standard ones. - */ - -static int opt(void) -{ - for (;;) { - int i = mdwopt(argc, argv, optd.buf, DA(&optv), 0, 0, 0); - switch (i) { - case 'h': - help(stdout); - exit(0); - case 'v': - version(stdout); - exit(0); - case 'u': - usage(stdout); - exit(0); - case 'l': { - gen *g; - puts("Generators supported:"); - for (g = generators; g->name; g++) - printf(" %s %s\n", g->name, g->help); - exit(0); - } break; - case 'f': - flags |= f_fips; - break; - case 'm': - flags |= f_maurer; - if (optarg) { - char *p; - unsigned long lo, hi; - lo = strtoul(optarg, &p, 0); - if (*p == '-' || *p == ',') - hi = strtoul(p + 1, &p, 0); - else - hi = lo; - if (*p != 0 || hi < lo || lo == 0) - die(EXIT_FAILURE, "bad bit range `%s'", optarg); - maurer_lo = lo; - maurer_hi = hi; - } - break; - case 'o': - if (flags & f_file) - die(EXIT_FAILURE, "already set an output file"); - if (strcmp(optarg, "-") == 0) - outfp = stdout; - else { - outfp = fopen(optarg, "w"); - if (!outfp) { - die(EXIT_FAILURE, "couldn't open output file `%s': %s", - optarg, strerror(errno)); - } - } - flags |= f_file; - break; - case 'z': { - char *p; - outsz = strtoul(optarg, &p, 0); - if (!outsz) - die(EXIT_FAILURE, "bad number `%s'", optarg); - switch (*p) { - case 'G': case 'g': outsz *= 1024; - case 'M': case 'm': outsz *= 1024; - case 'K': case 'k': outsz *= 1024; - case 0: - break; - default: - die(EXIT_FAILURE, "bad suffix `%s'", p); - break; - } - if (*p && p[1] != 0) - die(EXIT_FAILURE, "bad suffix `%s'", p); - } break; - case 'p': - flags |= f_progress; - break; - case 'T': - flags |= f_timer; - break; - case 'd': - flags |= f_discard; - break; - default: - return (i); - } - } -} - -/*----- Manglers for seed strings -----------------------------------------*/ - -/* --- @unhex@ --- * - * - * Arguments: @const char *p@ = pointer to input string - * @char **end@ = where the end goes - * @dstr *d@ = output buffer - * - * Returns: --- - * - * Use: Transforms a hex string into a chunk of binary data. - */ - -static void unhex(const char *p, char **end, dstr *d) -{ - while (p[0] && p[1]) { - int x = p[0], y = p[1]; - if ('0' <= x && x <= '9') x -= '0'; - else if ('A' <= x && x <= 'F') x -= 'A' - 10; - else if ('a' <= x && x <= 'f') x -= 'a' - 10; - else x = 0; - if ('0' <= y && y <= '9') y -= '0'; - else if ('A' <= y && y <= 'F') y -= 'A' - 10; - else if ('a' <= y && y <= 'f') y -= 'a' - 10; - else y = 0; - DPUTC(d, (x << 4) + y); - p += 2; - } - *end = (char *)p; -} - -/* --- Generate a key --- */ - -static void textkey(dstr *d, const char *p, const octet *ksz) -{ - size_t sz = strlen(p); - - if (!sz) - die(EXIT_FAILURE, "zero-length key string"); - if (keysz(sz, ksz) != sz) - DPUTM(d, p, sz); - else { - rmd160_mgfctx g; - rmd160_mgfinit(&g, p, sz); - sz = keysz(0, ksz); - dstr_ensure(d, sz); - rmd160_mgfencrypt(&g, 0, d->buf, sz); - d->len += sz; - } - assert(((void)"I can't seem to choose a good key size", - keysz(d->len, ksz) == d->len)); -} - -static void hexkey(dstr *d, const char *p, const octet *ksz) -{ - char *q; - unhex(optarg, &q, d); - if (*q) - die(EXIT_FAILURE, "bad hex key `%s'", p); - if (keysz(d->len, ksz) != d->len) - die(EXIT_FAILURE, "bad key length"); -} - -static void randkey(dstr *d, const octet *ksz) -{ - size_t sz = keysz(0, ksz); - dstr_ensure(d, sz); - rand_get(RAND_GLOBAL, d->buf, sz); - d->len += sz; -} - -/*----- Generators --------------------------------------------------------*/ - -/* --- Blum-Blum-Shub strong generator --- */ - -static grand *gen_bbs(unsigned i) -{ - /* --- Default modulus --- * - * - * The factors of this number are - * - * @p = 1229936431484295969649886203367009966370895964206162032259292413@ - * @7754313537966036459299022912838407755462506416274551744201653277@ - * @313130311731673973886822067@ - * - * @q = 9798171783943489959487301695884963889684294764514008432498259742@ - * @5374320073594018817245784145742769603334292182227671519041431067@ - * @61344781426317516045890159@ - * - * Both %$p$% and %$q$% are prime; %$(p - 1)/2$% and %$(q - 1)/2$% have no - * common factors. They were found using this program, with random - * starting points. - * - * I hope that, by publishing these factors, I'll dissuade people from - * actually using this modulus in an attempt to attain real security. The - * program is quite quick at finding Blum numbers, so there's no excuse for - * not generating your own. - */ - - const char *mt = - "12051128439013574251357214209433471144307319411973256935382082" - "84356405274180923922403660880355098909699130818163691602989614" - "90135716255689660470370755013177656905237112577648090277537209" - "93607817155427455344810369808478266925293635284364998010510985" - "0503830397166360721262431179505917248447259735253684659338653"; - - /* --- Other things --- */ - - grand *r; - const char *xt = 0; - unsigned bits = 1024; - mp *m, *x; - unsigned show = 0; - const char *kfile = 0, *id = 0, *ktype = 0; - - /* --- Parse options --- */ - - static struct option opts[] = { - { "modulus", OPTF_ARGREQ, 0, 'M' }, - { "generate", 0, 0, 'g' }, - { "seed", OPTF_ARGREQ, 0, 's' }, - { "bits", OPTF_ARGREQ, 0, 'b' }, - { "show", 0, 0, 'S' }, - { "keyring", OPTF_ARGREQ, 0, 'k' }, - { "id", OPTF_ARGREQ, 0, 'i' }, - { "type", OPTF_ARGREQ, 0, 't' }, - { 0, 0, 0, 0 } - }; - - addopts("M:gs:b:Sk:i:t:", opts); - - for (;;) { - int o = opt(); - if (o < 0) - break; - switch (o) { - case 'M': - mt = optarg; - break; - case 'g': - mt = 0; - break; - case 's': - xt = optarg; - break; - case 'b': - bits = strtoul(optarg, 0, 0); - if (bits == 0) - die(EXIT_FAILURE, "bad number of bits `%s'", optarg); - break; - case 'S': - show = 1; - break; - case 'k': - kfile = optarg; - mt = 0; - break; - case 'i': - id = optarg; - mt = 0; - break; - case 't': - ktype = optarg; - mt = 0; - break; - default: - return (0); - } - } - - /* --- Generate a modulus if one is requested --- */ - - if (mt) { - char *p; - m = mp_readstring(MP_NEW, mt, &p, 0); - if (!m || *p || (m->v[0] & 3) != 1) - die(EXIT_FAILURE, "bad modulus `%s'", mt); - /* Unfortunately I don't know how to test for a Blum integer */ - } else if (kfile || id || ktype) { - key_file kf; - key *kk; - key_data *kd; - - /* --- Open the key file --- */ - - if (!kfile) - kfile = "keyring"; - if (key_open(&kf, kfile, KOPEN_READ, key_moan, 0)) { - die(EXIT_FAILURE, "error opening key file `%s': %s", - kfile, strerror(errno)); - } - - /* --- Find the key --- */ - - if (id) { - if ((kk = key_bytag(&kf, id)) == 0) - die(EXIT_FAILURE, "key `%s' not found", id); - } else { - if (!ktype) - ktype = "bbs"; - if ((kk = key_bytype(&kf, ktype)) == 0) - die(EXIT_FAILURE, "no suitable key with type `%s' found", ktype); - } - - /* --- Read the key data --- */ - - if ((kk->k->e & KF_ENCMASK) != KENC_STRUCT) - die(EXIT_FAILURE, "key is not structured"); - if ((kd = key_structfind(kk->k, "n")) == 0) - die(EXIT_FAILURE, "key has no subkey `n'"); - if ((kd->e & KF_ENCMASK) != KENC_MP) - die(EXIT_FAILURE, "incompatible subkey encoding"); - m = MP_COPY(kd->u.m); - key_close(&kf); - } else { - bbs_priv bp; - - if (bbs_gen(&bp, bits, &rand_global, 0, - (flags & f_progress) ? pgen_ev : 0, 0)) - die(EXIT_FAILURE, "modulus generation failed"); - m = bp.n; - - if (show) { - fputs("p = ", stderr); - mp_writefile(bp.p, stderr, 10); - fputs("\nq = ", stderr); - mp_writefile(bp.q, stderr, 10); - fputs("\nn = ", stderr); - mp_writefile(bp.n, stderr, 10); - fputc('\n', stderr); - } - - mp_drop(bp.p); - mp_drop(bp.q); - } - - /* --- Set up a seed --- */ - - if (!xt) - x = mprand(MP_NEW, mp_bits(m) - 1, &rand_global, 1); - else { - char *p; - x = mp_readstring(MP_NEW, xt, &p, 0); - if (*p) - die(EXIT_FAILURE, "bad modulus `%s'", xt); - } - - /* --- Right --- */ - - r = bbs_rand(m, x); - - mp_drop(m); - mp_drop(x); - return (r); -} - -/* --- Catacomb's random number generator --- */ - -static grand *gen_rand(unsigned i) -{ - grand *r = rand_create(); - dstr d = DSTR_INIT; - - static struct option opts[] = { - { "key", OPTF_ARGREQ, 0, 'k' }, - { "text", OPTF_ARGREQ, 0, 't' }, - { "hex", OPTF_ARGREQ, 0, 'H' }, - { 0, 0, 0, 0 } - }; - - addopts("k:t:H:n", opts); - - r->ops->misc(r, RAND_NOISESRC, &noise_source); - r->ops->misc(r, RAND_SEED, 160); - - for (;;) { - int o = opt(); - if (o < 0) - break; - switch (o) { - case 'k': - DRESET(&d); - textkey(&d, optarg, rmd160_hmackeysz); - r->ops->misc(r, RAND_KEY, d.buf, d.len); - break; - case 't': - r->ops->misc(r, GRAND_SEEDBLOCK, optarg, strlen(optarg)); - break; - case 'H': - DRESET(&d); - hexkey(&d, optarg, rmd160_hmackeysz); - r->ops->misc(r, GRAND_SEEDBLOCK, d.buf, d.len); - break; - } - } - - dstr_destroy(&d); - return (r); -} - -/* --- RC4 output --- */ - -static grand *gen_rc4(unsigned i) -{ - grand *r; - dstr d = DSTR_INIT; - - static struct option opts[] = { - { "key", OPTF_ARGREQ, 0, 'k' }, - { "hex", OPTF_ARGREQ, 0, 'H' }, - { 0, 0, 0, 0 } - }; - - addopts("k:H:", opts); - - for (;;) { - int o = opt(); - if (o < 0) - break; - switch (o) { - case 'k': - DRESET(&d); - textkey(&d, optarg, rc4_keysz); - break; - case 'H': - DRESET(&d); - hexkey(&d, optarg, rc4_keysz); - break; - default: - return (0); - } - } - - if (!d.len) - randkey(&d, rc4_keysz); - r = rc4_rand(d.buf, d.len); - dstr_destroy(&d); - return (r); -} - -/* --- SEAL output --- */ - -static grand *gen_seal(unsigned i) -{ - grand *r; - dstr d = DSTR_INIT; - uint32 n = 0; - - static struct option opts[] = { - { "key", OPTF_ARGREQ, 0, 'k' }, - { "hex", OPTF_ARGREQ, 0, 'H' }, - { "sequence", OPTF_ARGREQ, 0, 'n' }, - { 0, 0, 0, 0 } - }; - - addopts("k:H:n:", opts); - - for (;;) { - int o = opt(); - if (o < 0) - break; - switch (o) { - case 'k': - DRESET(&d); - textkey(&d, optarg, seal_keysz); - break; - case 'H': - DRESET(&d); - hexkey(&d, optarg, seal_keysz); - break; - case 'n': { - char *p; - n = strtoul(optarg, &p, 0); - if (*p) - die(EXIT_FAILURE, "bad number `%s'", optarg); - } break; - default: - return (0); - } - } - - if (!d.len) - randkey(&d, seal_keysz); - r = seal_rand(d.buf, d.len, n); - dstr_destroy(&d); - return (r); -} - -/* --- Output feedback generators --- */ - -static grand *gen_ofb(unsigned i) -{ - grand *r; - dstr d = DSTR_INIT; - dstr iv = DSTR_INIT; - - static struct option opts[] = { - { "key", OPTF_ARGREQ, 0, 'k' }, - { "hex", OPTF_ARGREQ, 0, 'H' }, - { "iv", OPTF_ARGREQ, 0, 'i' }, - { 0, 0, 0, 0 } - }; - - addopts("k:H:i:", opts); - - for (;;) { - int o = opt(); - if (o < 0) - break; - switch (o) { - case 'k': - DRESET(&d); - textkey(&d, optarg, ciphertab[i].keysz); - break; - case 'H': - DRESET(&d); - hexkey(&d, optarg, ciphertab[i].keysz); - break; - case 'i': { - char *p; - unhex(optarg, &p, &iv); - if (*p) - die(EXIT_FAILURE, "bad hex IV `%s'", optarg); - } break; - default: - return (0); - } - } - - if (!d.len) - randkey(&d, ciphertab[i].keysz); - r = ciphertab[i].ofb(d.buf, d.len); - if (iv.len) { - if (iv.len != ciphertab[i].blksz) { - die(EXIT_FAILURE, "bad IV length %lu (must be %lu)", - (unsigned long)iv.len, (unsigned long)ciphertab[i].blksz); - } - r->ops->misc(r, GRAND_SEEDBLOCK, iv.buf); - } - - dstr_destroy(&d); - dstr_destroy(&iv); - return (r); -} - -/* --- Counter generators --- */ - -static grand *gen_counter(unsigned i) -{ - grand *r; - dstr d = DSTR_INIT; - dstr iv = DSTR_INIT; - - static struct option opts[] = { - { "key", OPTF_ARGREQ, 0, 'k' }, - { "hex", OPTF_ARGREQ, 0, 'H' }, - { "iv", OPTF_ARGREQ, 0, 'i' }, - { 0, 0, 0, 0 } - }; - - addopts("k:H:i:", opts); - - for (;;) { - int o = opt(); - if (o < 0) - break; - switch (o) { - case 'k': - DRESET(&d); - textkey(&d, optarg, ciphertab[i].keysz); - break; - case 'H': - DRESET(&d); - hexkey(&d, optarg, ciphertab[i].keysz); - break; - case 'i': { - char *p; - unhex(optarg, &p, &iv); - if (*p) - die(EXIT_FAILURE, "bad hex IV `%s'", optarg); - } break; - default: - return (0); - } - } - - if (!d.len) - randkey(&d, ciphertab[i].keysz); - r = ciphertab[i].counter(d.buf, d.len); - if (iv.len) { - if (iv.len != ciphertab[i].blksz) { - die(EXIT_FAILURE, "bad IV length %lu (must be %lu)", - (unsigned long)iv.len, (unsigned long)ciphertab[i].blksz); - } - r->ops->misc(r, GRAND_SEEDBLOCK, iv.buf); - } - - dstr_destroy(&d); - dstr_destroy(&iv); - return (r); -} - -/* --- Mask generators --- */ - -static grand *gen_mgf(unsigned i) -{ - grand *r; - dstr d = DSTR_INIT; - uint32 c = 0; - - static struct option opts[] = { - { "key", OPTF_ARGREQ, 0, 'k' }, - { "hex", OPTF_ARGREQ, 0, 'H' }, - { "index", OPTF_ARGREQ, 0, 'i' }, - { 0, 0, 0, 0 } - }; - - addopts("k:H:i:", opts); - - for (;;) { - int o = opt(); - if (o < 0) - break; - switch (o) { - case 'k': - DRESET(&d); - textkey(&d, optarg, hashtab[i].keysz); - break; - case 'H': - DRESET(&d); - hexkey(&d, optarg, hashtab[i].keysz); - break; - case 'i': { - char *p; - c = strtoul(optarg, &p, 0); - if (*p) - die(EXIT_FAILURE, "bad index `%s'", optarg); - } break; - default: - return (0); - } - } - - if (!d.len) - randkey(&d, hashtab[i].keysz); - - r = hashtab[i].mgf(d.buf, d.len); - if (c) - r->ops->misc(r, GRAND_SEEDUINT32, c); - - dstr_destroy(&d); - return (r); -} - -/* --- Fibonacci generator --- */ - -static grand *gen_fib(unsigned i) -{ - grand *r; - uint32 s = 0; - char *p; - unsigned set = 0; - - static struct option opts[] = { - { "seed", OPTF_ARGREQ, 0, 's' }, - { 0, 0, 0, 0 } - }; - - addopts("s:", opts); - - for (;;) { - int o = opt(); - if (o < 0) - break; - switch (o) { - case 's': - s = strtoul(optarg, &p, 0); - if (*p) - die(EXIT_FAILURE, "bad integer `%s'", optarg); - set = 1; - break; - default: - return (0); - } - } - r = fibrand_create(s); - if (!set) - r->ops->misc(r, GRAND_SEEDRAND, &rand_global); - return (r); -} - -/* --- LC generator --- */ - -static grand *gen_lc(unsigned i) -{ - uint32 s = 0; - char *p; - unsigned set = 0; - - static struct option opts[] = { - { "seed", OPTF_ARGREQ, 0, 's' }, - { 0, 0, 0, 0 } - }; - - addopts("s:", opts); - - for (;;) { - int o = opt(); - if (o < 0) - break; - switch (o) { - case 's': - s = strtoul(optarg, &p, 0); - if (*p) - die(EXIT_FAILURE, "bad integer `%s'", optarg); - set = 1; - break; - default: - return (0); - } - } - if (!set) { - do - s = rand_global.ops->range(&rand_global, LCRAND_P); - while (s == LCRAND_FIXEDPT); - } - return (lcrand_create(s)); -} - -/* --- Basic options parser -- can't generate output --- */ - -static grand *gen_opts(unsigned i) -{ - while (opt() >= 0) - ; - return (0); -} - -/*----- Generators table --------------------------------------------------*/ - -gen generators[] = { - { "fibonacci", gen_fib, 0, - "[-s SEED]" }, - { "lc", gen_lc, 0, - "[-s SEED]" }, -#define E(PRE, pre) \ - { #pre "-ofb", gen_ofb, CIPHER_##PRE, \ - "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" }, - CIPHERS -#undef E -#define E(PRE, pre) \ - { #pre "-counter", gen_counter, CIPHER_##PRE, \ - "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" }, - CIPHERS -#undef E -#define E(PRE, pre) \ - { #pre "-mgf", gen_mgf, HASH_##PRE, \ - "[-k KEY-PHRASE] [-H HEX-KEY] [-i INDEX]" }, - HASHES -#undef E - { "rc4", gen_rc4, 0, - "[-k KEY-PHRASE] [-H HEX-KEY]" }, - { "seal", gen_seal, 0, - "[-k KEY-PHRASE] [-H HEX-KEY] [-n SEQ]" }, - { "rand", gen_rand, 0, - "[-n] [-k KEY-PHRASE] [-t TEXT-BLOCK] [-H HEX-BLOCK]" }, - { "bbs", gen_bbs, 0, - "[-gS] [-s SEED] [-M MODULUS] [-b BITS] [-k KEYRING] [-i TAG] [-t TYPE]" - }, - { 0, 0, 0, 0 }, -}; - -static gen optsg = { "options", gen_opts, 0, - "This message shouldn't be printed." }; - -/*----- Random number generation ------------------------------------------*/ - -static int genfile(const void *buf, size_t sz, void *p) -{ - FILE *fp = p; - if (fwrite(buf, 1, sz, fp) != sz) - die(EXIT_FAILURE, "error writing to file: %s", strerror(errno)); - return (0); -} - -static int genbuf(const void *buf, size_t sz, void *p) -{ - octet **pp = p; - memcpy(*pp, buf, sz); - *pp += sz; - return (0); -} - -typedef struct genmaurer_ctx { - size_t n; - maurer_ctx *m; -} genmaurer_ctx; - -static int genmaurer(const void *buf, size_t sz, void *p) -{ - genmaurer_ctx *g = p; - size_t i; - - for (i = 0; i < g->n; i++) - maurer_test(&g->m[i], buf, sz); - return (0); -} - -static int generate(grand *r, size_t outsz, - int (*func)(const void *buf, size_t sz, void *p), - void *p) -{ - static char kmg[] = { ' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 0 }; - - unsigned percent = 0; - size_t kb = 0; - time_t last; - static char baton[] = "-\\|/"; - char *bp; - int rc; - clock_t clk = 0; - - /* --- Spit out random data --- */ - - last = time(0); - bp = baton; - if (flags & f_progress) { - char *errbuf = xmalloc(BUFSIZ); - setvbuf(stderr, errbuf, _IOLBF, BUFSIZ); - if (outsz) - fprintf(stderr, "[%*s] 0%% 0\r[/\b", 50, ""); - else - fputs("[ ] 0\r[/\b", stderr); - fflush(stderr); - } - -#ifdef SIGPIPE - signal(SIGPIPE, SIG_IGN); -#endif - - do { - octet buf[BUFSIZ]; - size_t sz = sizeof(buf); - clock_t c_start, c_stop; - - /* --- Emit a bufferful (or less) of data --- */ - - if (outsz) { - if (sz > outsz - kb) - sz = outsz - kb; - } - c_start = clock(); - r->ops->fill(r, buf, sz); - c_stop = clock(); - clk += c_stop - c_start; - if (func && (rc = func(buf, sz, p)) != 0) - return (rc); - kb += sz; - - /* --- Update the display --- */ - - if (flags & f_progress) { - time_t t = time(0); - unsigned up = 0; - - if (percent > 100) - up = 1; - - if (!outsz) { - if (difftime(t, last) > 1.0) { - up = 1; - } - if (up) - fputs(" ] ", stderr); - } else { - unsigned pc = kb * 100.0 / outsz; - if (pc > percent || percent > 100 || difftime(t, last) > 1.0) { - if (percent > 100) - percent = 0; - percent &= ~1; - for (; percent < (pc & ~1); percent += 2) - putc('.', stderr); - percent = pc; - for (; pc < 100; pc += 2) - putc(' ', stderr); - fprintf(stderr, "] %3i%% ", percent); - up = 1; - } - } - - if (up) { - size_t q = kb; - char *kk = kmg; - while (q > 8192 && kk[1]) { - q >>= 10; - kk++; - } - fprintf(stderr, "%4i%c\r[", q, *kk); - if (outsz) { - unsigned pc; - for (pc = 0; pc < (percent & ~1); pc += 2) - putc('.', stderr); - } - last = t; - } - - if (percent > 100) - percent = 0; - - if (percent < 100) { - putc(*bp++, stderr); - putc('\b', stderr); - if (!*bp) - bp = baton; - } - fflush(stderr); - } - - /* --- Terminate the loop --- */ - - } while (!outsz || kb < outsz); - - if (flags & f_progress) - fputc('\n', stderr); - if (flags & f_timer) { - fprintf(stderr, "generated %lu bytes ", (unsigned long)outsz); - if (!clk) - fputs("too quickly to measure\n", stderr); - else { - char *kk; - double sec = (double)clk/CLOCKS_PER_SEC; - double bps = (outsz << 3)/sec; - for (kk = kmg; bps > 1024 && kk[1]; kk++, bps /= 1024) - ; - fprintf(stderr, "in %g secs (%g %cb/s)\n", sec, bps, *kk); - } - } - return (0); -} - -/*----- Main code ---------------------------------------------------------*/ - -int main(int ac, char *av[]) -{ - gen *g = &optsg; - grand *r; - - /* --- Initialize mLib --- */ - - ego(av[0]); - sub_init(); - - /* --- Set up the main Catacomb generator --- */ - - rand_noisesrc(RAND_GLOBAL, &noise_source); - rand_seed(RAND_GLOBAL, 160); - - /* --- Initialize the options table --- */ - - addopts(sopts, opts); - argc = ac; - argv = av; - outfp = stdout; - - /* --- Read the generator out of the first argument --- */ - - if (argc > 1 && *argv[1] != '-') { - const char *arg = av[1]; - size_t sz = strlen(arg); - gen *gg; - - g = 0; - for (gg = generators; gg->name; gg++) { - if (strncmp(arg, gg->name, sz) == 0) { - if (gg->name[sz] == 0) { - g = gg; - break; - } else if (g) - die(EXIT_FAILURE, "ambiguous generator name `%s'", arg); - else - g = gg; - } - } - if (!g) - die(EXIT_FAILURE, "unknown generator name `%s'", arg); - argc--; - argv++; - } - - /* --- Get a generic random number generator --- */ - - r = g->seed(g->i); - if (!r || optind != ac - 1) { - usage(stderr); - exit(EXIT_FAILURE); - } - - /* --- Do the FIPS test --- */ - - if (flags & f_fips) { - octet buf[FIPSTEST_BUFSZ]; - unsigned rc; - octet *p = buf; - - generate(r, sizeof(buf), genbuf, &p); - rc = fipstest(buf); - if (rc & FIPSTEST_MONOBIT) - moan("failed monobit test"); - if (rc & FIPSTEST_POKER) - moan("failed poker test"); - if (rc & FIPSTEST_RUNS) - moan("failed runs test"); - if (rc & FIPSTEST_LONGRUNS) - moan("failed long runs test"); - if (!rc && (flags & f_progress)) - fputs("test passed\n", stderr); - return (rc ? EXIT_FAILURE : 0); - } - - /* --- Do Maurer's test --- */ - - if (flags & f_maurer) { - size_t bufsz; - unsigned i; - unsigned rc = 0; - genmaurer_ctx g; - - static struct { double x; const char *sig; } sigtab[] = { - { 3.2905, "1e-3" }, - { 3.0902, "2e-3" }, - { 2.8070, "5e-3" }, - { 2.5758, "1e-2" }, - { 0 , 0 } - }; - - g.n = maurer_hi - maurer_lo + 1; - g.m = xmalloc(g.n * sizeof(maurer_ctx)); - for (i = 0; i < g.n; i++) - maurer_init(&g.m[i], i + maurer_lo); - bufsz = (100 * maurer_hi) << maurer_hi; - - generate(r, bufsz, genmaurer, &g); - - for (i = maurer_lo; i <= maurer_hi; i++) { - double z = maurer_done(&g.m[i - maurer_lo]); - double zz = fabs(z); - unsigned j; - - for (j = 0; sigtab[j].sig; j++) { - if (zz > sigtab[j].x) { - rc = EXIT_FAILURE; - moan("failed, bits = %u, sig = %s, Z_u = %g", - i, sigtab[j].sig, z); - break; - } - } - if (flags & f_progress) - fprintf(stderr, "bits = %u, Z_u = %g\n", i, z); - } - - xfree(g.m); - return (rc); - } - - /* --- Discard --- */ - - if (flags & f_discard) { - generate(r, outsz, 0, 0); - return (0); - } - - /* --- Write to a file --- */ - -#ifndef PORTABLE - if (!(flags & f_file) && isatty(STDOUT_FILENO)) - die(EXIT_FAILURE, "writing output to a terminal is a bad idea"); -#endif - - generate(r, outsz, genfile, outfp); - - /* --- Done --- */ - - r->ops->destroy(r); - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/safer-mktab.c b/safer-mktab.c deleted file mode 100644 index 869d66f..0000000 --- a/safer-mktab.c +++ /dev/null @@ -1,104 +0,0 @@ -/* -*-c-*- - * - * $Id: safer-mktab.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Generate tables for SAFER - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -/*----- Main code ---------------------------------------------------------*/ - -int main(void) -{ - octet s[256], si[256]; - unsigned x, i; - - x = 1; - for (i = 0; i < 256; i++) { - if (x < 256) { - s[i] = x; - si[x] = i; - } - x = (x * 45)%257; - } - s[128] = 0; - si[0] = 128; - - fputs("\ -/* -*-c-*-\n\ - *\n\ - * SAFER tables [generated]\n\ - */\n\ -\n\ -#ifndef CATACOMB_SAFER_TAB_H\n\ -#define CATACOMB_SAFER_TAB_H\n\ -\n\ -", stdout); - - fputs("\ -/* --- S-boxes --- */\n\ -\n\ -#define SAFER_S { \\\n\ - ", stdout); - for (i = 0; i < 256; i++) { - printf("0x%02x", s[i]); - if (i == 255) - fputs(" \\\n}\n\n", stdout); - else if ((i + 1)%8 == 0) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - fputs("\ -#define SAFER_SI { \\\n\ - ", stdout); - for (i = 0; i < 256; i++) { - printf("0x%02x", si[i]); - if (i == 255) - fputs(" \\\n}\n\n", stdout); - else if ((i + 1)%8 == 0) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - puts("#endif"); - - if (fclose(stdout)) { - fprintf(stderr, "error writing data\n"); - exit(EXIT_FAILURE); - } - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/safer.c b/safer.c deleted file mode 100644 index 6a63565..0000000 --- a/safer.c +++ /dev/null @@ -1,325 +0,0 @@ -/* -*-c-*- - * - * $Id: safer.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The SAFER block cipher - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "paranoia.h" -#include "safer.h" -#include "safer-tab.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet safer_keysz[] = { KSZ_SET, 8, 16, 0 }; - -/*----- Important tables --------------------------------------------------*/ - -static const octet s[265] = SAFER_S, si[256] = SAFER_SI; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @safer_setup@ --- * - * - * Arguments: @safer_ctx *k@ = pointer to context to initialize - * @unsigned r@ = number of rounds wanted - * @unsigned f@ = various other flags - * @const void *buf@ = pointer to key material - * @size_t sz@ = size of key material in bytes - * - * Returns: --- - * - * Use: Initializes an SAFER expanded key. A default number of - * rounds is chosen, based on the key length. - */ - -struct ksched { - unsigned i; - octet x[9]; -}; - -static void init(struct ksched *t, const octet *k) -{ - memcpy(t->x, k, 8); - t->i = 1; -} - -static void init_sk(struct ksched *t, const octet *k) -{ - unsigned i; - octet x; - memcpy(t->x, k, 8); - for (x = 0, i = 0; i < 8; x ^= k[i++]) - ; - t->x[8] = x; - t->i = 1; -} - -static void next(struct ksched *t, octet *k) -{ - unsigned i; - if (k) { - memcpy(k, t->x, 8); - if (t->i > 1) { - for (i = 0; i < 8; i++) - k[i] += s[s[U8(9*t->i + i + 1)]]; - } - } - for (i = 0; i < 8; i++) - t->x[i] = ROL8(t->x[i], 3); - t->i++; -} - -static void next_sk(struct ksched *t, octet *k) -{ - unsigned i; - i = (t->i - 1)%9; - if (k) { - if (i < 2) - memcpy(k, t->x + i, 8); - else { - memcpy(k, t->x + i, 9 - i); - memcpy(k + 9 - i, t->x, i - 1); - } - if (t->i > 1) { - for (i = 0; i < 8; i++) - k[i] += s[s[U8(9*t->i + i + 1)]]; - } - } - for (i = 0; i < 9; i++) - t->x[i] = ROL8(t->x[i], 3); - t->i++; -} - -void safer_setup(safer_ctx *k, unsigned r, unsigned f, - const void *buf, size_t sz) -{ - struct ksched ka, kb; - void (*in)(struct ksched *, const octet *); - void (*nx)(struct ksched *, octet *); - octet *kk; - - assert(r <= SAFER_MAXROUNDS); - KSZ_ASSERT(safer, sz); - - if (f & SAFER_SK) { - in = init_sk; - nx = next_sk; - } else { - in = init; - nx = next; - } - - in(&kb, buf); - in(&ka, sz == 8 ? buf : (const octet *)buf + 8); - - k->r = r; - kk = k->k; - while (r) { - nx(&ka, kk); nx(&kb, 0); kk += 8; - nx(&kb, kk); nx(&ka, 0); kk += 8; - r--; - } - nx(&ka, kk); kk += 8; -} - -/* --- @safer_init@, @safersk_init@ --- * - * - * Arguments: @safer_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to key material - * @size_t sz@ = size of key material in bytes - * - * Returns: --- - * - * Use: Initializes an SAFER expanded key. A default number of - * rounds is chosen, based on the key length. - */ - -void safer_init(safer_ctx *k, const void *buf, size_t sz) -{ - safer_setup(k, sz == 8 ? 6 : 10, 0, buf, sz); -} - -void safersk_init(safer_ctx *k, const void *buf, size_t sz) -{ - safer_setup(k, sz == 8 ? 8 : 10, SAFER_SK, buf, sz); -} - -/* --- @safer_eblk@, @safer_dblk@ --- * - * - * Arguments: @const safer_ctx *k@ = pointer to SAFER context - * @const uint32 s[2]@ = pointer to source block - * @const uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -#define UNPACK(src, a, b, c, d, e, f, g, h) do { \ - a = U8(src[0] >> 24); b = U8(src[0] >> 16); \ - c = U8(src[0] >> 8); d = U8(src[0] >> 0); \ - e = U8(src[1] >> 24); f = U8(src[1] >> 16); \ - g = U8(src[1] >> 8); h = U8(src[1] >> 0); \ -} while (0) - -#define PACK(dst, a, b, c, d, e, f, g, h) do { \ - dst[0] = (U8(a) << 24) | (U8(b) << 16) | (U8(c) << 8) | U8(d); \ - dst[1] = (U8(e) << 24) | (U8(f) << 16) | (U8(g) << 8) | U8(h); \ -} while (0) - -#define F(x, y) y += x, x += y -#define G(x, y) x -= y, y -= x - -#define PHT(a, b, c, d, e, f, g, h) do { \ - F(a, b); F(c, d); F(e, f); F(g, h); \ - F(a, c); F(e, g); F(b, d); F(f, h); \ - F(a, e); F(b, f); F(c, g); F(d, h); \ -} while (0) - #define IPHT(a, b, c, d, e, f, g, h) do { \ - G(a, e); G(b, f); G(c, g); G(d, h); \ - G(a, c); G(e, g); G(b, d); G(f, h); \ - G(a, b); G(c, d); G(e, f); G(g, h); \ -} while (0) - -#define KXA(k, a, b, c, d, e, f, g, h) do { \ - a ^= *k++; b += *k++; c += *k++; d ^= *k++; \ - e ^= *k++; f += *k++; g += *k++; h ^= *k++; \ -} while (0) -#define SUB(a, b, c, d, e, f, g, h) do { \ - a = s[U8(a)]; b = si[U8(b)]; c = si[U8(c)]; d = s[U8(d)]; \ - e = s[U8(e)]; f = si[U8(f)]; g = si[U8(g)]; h = s[U8(h)]; \ -} while (0) -#define KAX(k, a, b, c, d, e, f, g, h) do { \ - a += *k++; b ^= *k++; c ^= *k++; d += *k++; \ - e += *k++; f ^= *k++; g ^= *k++; h += *k++; \ -} while (0) - -#define KXS(k, a, b, c, d, e, f, g, h) do { \ - h ^= *--k; g -= *--k; f -= *--k; e ^= *--k; \ - d ^= *--k; c -= *--k; b -= *--k; a ^= *--k; \ -} while (0) -#define ISUB(a, b, c, d, e, f, g, h) do { \ - a = si[U8(a)]; b = s[U8(b)]; c = s[U8(c)]; d = si[U8(d)]; \ - e = si[U8(e)]; f = s[U8(f)]; g = s[U8(g)]; h = si[U8(h)]; \ -} while (0) -#define KSX(k, a, b, c, d, e, f, g, h) do { \ - h -= *--k; g ^= *--k; f ^= *--k; e -= *--k; \ - d -= *--k; c ^= *--k; b ^= *--k; a -= *--k; \ -} while (0) - -#define EROUND(k, a, b, c, d, e, f, g, h) do { \ - KXA(k, a, b, c, d, e, f, g, h); \ - SUB(a, b, c, d, e, f, g, h); \ - KAX(k, a, b, c, d, e, f, g, h); \ - PHT(a, b, c, d, e, f, g, h); \ -} while (0) - -#define DROUND(k, a, b, c, d, e, f, g, h) do { \ - IPHT(a, b, c, d, e, f, g, h); \ - KSX(k, a, b, c, d, e, f, g, h); \ - ISUB(a, b, c, d, e, f, g, h); \ - KXS(k, a, b, c, d, e, f, g, h); \ -} while (0) - - -void safer_eblk(const safer_ctx *k, const uint32 *src, uint32 *dst) -{ - octet a, b, c, d, e, f, g, h; - unsigned r = k->r; - const octet *kk = k->k; - - UNPACK(src, a, b, c, d, e, f, g, h); - while (r >= 3) { - EROUND(kk, a, b, c, d, e, f, g, h); - EROUND(kk, a, e, b, f, c, g, d, h); - EROUND(kk, a, c, e, g, b, d, f, h); - r -= 3; - } - switch (r) { - case 0: - KXA(kk, a, b, c, d, e, f, g, h); - PACK(dst, a, b, c, d, e, f, g ,h); - break; - case 1: - EROUND(kk, a, b, c, d, e, f, g, h); - KXA(kk, a, e, b, f, c, g, d, h); - PACK(dst, a, e, b, f, c, g, d, h); - break; - case 2: - EROUND(kk, a, b, c, d, e, f, g, h); - EROUND(kk, a, e, b, f, c, g, d, h); - KXA(kk, a, c, e, g, b, d, f, h); - PACK(dst, a, c, e, g, b, d, f, h); - break; - } -} - -void safer_dblk(const safer_ctx *k, const uint32 *src, uint32 *dst) -{ - octet a, b, c, d, e, f, g, h; - unsigned r = k->r; - const octet *kk = k->k + 16 * r + 8; - switch (r%3) { - default: - case 0: - UNPACK(src, a, b, c, d, e, f, g, h); - KXS(kk, a, b, c, d, e, f, g, h); - break; - case 1: - UNPACK(src, a, e, b, f, c, g, d, h); - KXS(kk, a, e, b, f, c, g, d, h); - r--; - goto one_round; - case 2: - UNPACK(src, a, c, e, g, b, d, f, h); - KXS(kk, a, c, e, g, b, d, f, h); - r -= 2; - DROUND(kk, a, e, b, f, c, g, d, h); - one_round: - DROUND(kk, a, b, c, d, e, f, g, h); - break; - } - while (r) { - DROUND(kk, a, c, e, g, b, d, f, h); - DROUND(kk, a, e, b, f, c, g, d, h); - DROUND(kk, a, b, c, d, e, f, g, h); - r -= 3; - } - PACK(dst, a, b, c, d, e, f, g, h); -} - -BLKC_TEST(SAFER, safer) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/safer.h b/safer.h deleted file mode 100644 index 198bc8e..0000000 --- a/safer.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -*-c-*- - * - * $Id: safer.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The SAFER block cipher - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the SAFER block cipher -----------------------------------* - * - * SAFER was designed by James Massey (who also worked on IDEA) for Cylink. - * It's free -- patents or other silliness. The original key schedule had - * some weaknesses, and a new one (the SK version) was added. SAFER has a - * variable number of rounds. The standard interface uses the recommended - * number for the given key schedule algorithm and key size. - * - * SAFER got a bad press in Schneier's book `Applied Cryptography'. I think - * this is undeserved. SAFER is a well-designed cipher which mostly looks - * pretty solid. - */ - -#ifndef CATACOMB_SAFER_H -#define CATACOMB_SAFER_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magical numbers ---------------------------------------------------*/ - -#define SAFER_BLKSZ 8 -#define SAFER_KEYSZ 8 -#define SAFER_CLASS (N, B, 64) - -#define SAFERSK_BLKSZ SAFER_BLKSZ -#define SAFERSK_KEYSZ 16 -#define SAFERSK_CLASS SAFER_CLASS - -#define SAFER_MAXROUNDS 12 - -extern const octet safer_keysz[]; -#define safersk_keysz safer_keysz - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct safer_ctx { - octet k[8 * (2 * SAFER_MAXROUNDS + 1)]; - unsigned r; -} safer_ctx, safersk_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @safer_setup@ --- * - * - * Arguments: @safer_ctx *k@ = pointer to context to initialize - * @unsigned r@ = number of rounds wanted - * @unsigned f@ = various other flags - * @const void *buf@ = pointer to key material - * @size_t sz@ = size of key material in bytes - * - * Returns: --- - * - * Use: Initializes an SAFER expanded key. A default number of - * rounds is chosen, based on the key length. - */ - -#define SAFER_SK 1u - -extern void safer_setup(safer_ctx */*k*/, unsigned /*r*/, unsigned /*f*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @safer_init@, @safersk_init@ --- * - * - * Arguments: @safer_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to key material - * @size_t sz@ = size of key material in bytes - * - * Returns: --- - * - * Use: Initializes an SAFER expanded key. A default number of - * rounds is chosen, based on the key length. - */ - -extern void safer_init(safer_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); -extern void safersk_init(safer_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @safer_eblk@, @safer_dblk@ --- * - * - * Arguments: @const safer_ctx *k@ = pointer to SAFER context - * @const uint32 s[2]@ = pointer to source block - * @const uint32 d[2]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void safer_eblk(const safer_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); -extern void safer_dblk(const safer_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); - -#define safersk_eblk safer_eblk -#define safersk_dblk safer_dblk - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/safersk.c b/safersk.c deleted file mode 100644 index 6ea27c9..0000000 --- a/safersk.c +++ /dev/null @@ -1,16 +0,0 @@ -/* -*-c-*- - * - * $Id: safersk.c,v 1.1 2001/04/29 17:37:35 mdw Exp $ - * - * Stub source for SAFER SK - * - * (c) 2001 Straylight/Edgeware - */ - -#include "blkc.h" -#include "safersk.h" - -const char *safersk_magic = "Compile this useless file"; - -BLKC_TEST(SAFERSK, safersk) - diff --git a/safersk.h b/safersk.h deleted file mode 100644 index 7403de7..0000000 --- a/safersk.h +++ /dev/null @@ -1,17 +0,0 @@ -/* -*-c-*- - * - * $Id: safersk.h,v 1.1 2001/04/29 17:37:35 mdw Exp $ - * - * Stub header for SAFER SK - * - * (c) 2001 Straylight/Edgeware - */ - -#ifndef CATACOMB_SAFERSK_H -#define CATACOMB_SAFERSK_H - -#include "safer.h" - -extern const char *safersk_magic; - -#endif diff --git a/seal.c b/seal.c deleted file mode 100644 index 444a11c..0000000 --- a/seal.c +++ /dev/null @@ -1,616 +0,0 @@ -/* -*-c-*- - * - * $Id: seal.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The SEAL pseudo-random function family - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include - -#include "arena.h" -#include "gcipher.h" -#include "grand.h" -#include "paranoia.h" -#include "seal.h" -#include "sha.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet seal_keysz[] = { KSZ_ANY, SHA_HASHSZ }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @gamma@ --- * - * - * Arguments: @uint32 *p@ = output table - * @size_t sz@ = size of the output table - * @const void *k@ = pointer to key material - * @unsigned i@ = integer offset - * - * Returns: --- - * - * Use: Initializes a SEAL key table. - */ - -static void gamma(uint32 *p, size_t sz, const void *k, unsigned i) -{ - uint32 buf[80] = { 0 }; - const octet *kk = k; - uint32 aa = LOAD32(kk); - uint32 bb = LOAD32(kk + 4); - uint32 cc = LOAD32(kk + 8); - uint32 dd = LOAD32(kk + 12); - uint32 ee = LOAD32(kk + 16); - - unsigned skip = i % 5; - i /= 5; - - /* --- While there's hashing to do, do hashing --- */ - - while (sz) { - uint32 a = aa, b = bb, c = cc, d = dd, e = ee; - int j; - - /* --- Initialize and expand the buffer --- */ - - buf[0] = i++; - - for (j = 16; j < 80; j++) { - uint32 x = buf[j - 3] ^ buf[j - 8] ^ buf[j - 14] ^ buf[j - 16]; - buf[j] = ROL32(x, 1); - } - - /* --- Definitions for round functions --- */ - -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define G(x, y, z) ((x) ^ (y) ^ (z)) -#define H(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) - -#define T(v, w, x, y, z, i, f, k) do { \ - uint32 _x; \ - z = ROL32(v, 5) + f(w, x, y) + z + buf[i] + k; \ - w = ROR32(w, 2); \ - _x = v; v = z; z = y; y = x; x = w; w = _x; \ -} while (0) - -#define FF(v, w, x, y, z, i) T(v, w, x, y, z, i, F, 0x5a827999) -#define GG(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0x6ed9eba1) -#define HH(v, w, x, y, z, i) T(v, w, x, y, z, i, H, 0x8f1bbcdc) -#define II(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0xca62c1d6) - - /* --- The main compression function --- * - * - * Since this isn't doing bulk hashing, do it the easy way. - */ - - for (j = 0; j < 20; j++) - FF(a, b, c, d, e, j); - for (j = 20; j < 40; j++) - GG(a, b, c, d, e, j); - for (j = 40; j < 60; j++) - HH(a, b, c, d, e, j); - for (j = 60; j < 80; j++) - II(a, b, c, d, e, j); - - /* --- Do the chaining at the end --- */ - - a += aa; b += bb; c += cc; d += dd; e += ee; - - /* --- Write to the output buffer --- */ - - switch (skip) { - case 0: - if (sz) { *p++ = a; sz--; } - case 1: - if (sz) { *p++ = b; sz--; } - case 2: - if (sz) { *p++ = c; sz--; } - case 3: - if (sz) { *p++ = d; sz--; } - case 4: - if (sz) { *p++ = e; sz--; } - skip = 0; - } - } -} - -/* --- @seal_initkey@ --- * - * - * Arguments: @seal_key *k@ = pointer to key block - * @const void *buf@ = pointer to key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Initializes a SEAL key block. The key material may be any - * size, but if it's not 20 bytes long it's passed to SHA for - * hashing first. - */ - -void seal_initkey(seal_key *k, const void *buf, size_t sz) -{ - /* --- Hash the key if it's the wrong size --- */ - - if (sz == SHA_HASHSZ) - memcpy(k->k, buf, sizeof(k->k)); - else { - sha_ctx c; - sha_init(&c); - sha_hash(&c, buf, sz); - sha_done(&c, k->k); - } - - /* --- Expand the key to fit the various tables --- */ - - gamma(k->t, 512, k->k, 0); - gamma(k->s, 256, k->k, 0x1000); - gamma(k->r, SEAL_R, k->k, 0x2000); -} - -/* --- @seal_reset@ --- * - * - * Arguments: @seal_ctx *c@ = pointer to a SEAL context - * - * Returns: --- - * - * Use: Resets the context so that more data can be extracted from - * it. - */ - -static void seal_reset(seal_ctx *c) -{ - seal_key *k = c->k; - uint32 n = c->n; - uint32 A, B, C, D; - unsigned p; - - /* --- Initialize the new chaining variables --- */ - - if (c->l >= SEAL_R) { - gamma(c->rbuf, SEAL_R, k->k, c->ri); - c->ri += SEAL_R; - c->l = 0; - c->r = c->rbuf; - } - - A = n ^ c->r[0]; - B = ROR32(n, 8) ^ c->r[1]; - C = ROR32(n, 16) ^ c->r[2]; - D = ROR32(n, 24) ^ c->r[3]; - c->l += 4; - c->r += 4; - - /* --- Ensure that everything is sufficiently diffused --- */ - - p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9); - p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9); - p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9); - p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9); - p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9); - p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9); - p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9); - p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9); - - /* --- Write out some context --- */ - - c->n1 = D; c->n2 = B; c->n3 = A; c->n4 = C; - - /* --- Diffuse some more --- */ - - p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9); - p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9); - p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9); - p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9); - - /* --- Write out the magic numbers --- */ - - c->a = A; c->b = B; c->c = C; c->d = D; - c->i = 0; -} - -/* --- @seal_initctx@ --- * - * - * Arguments: @seal_ctx *c@ = pointer to a SEAL context - * @seal_key *k@ = pointer to a SEAL key - * @uint32 n@ = integer sequence number - * - * Returns: --- - * - * Use: Initializes a SEAL context which can be used for random - * number generation or whatever. - */ - -void seal_initctx(seal_ctx *c, seal_key *k, uint32 n) -{ - c->k = k; - c->n = n; - c->l = 0; - c->r = k->r; - c->ri = 0x2000 + SEAL_R; - c->qsz = 0; - seal_reset(c); -} - -/* --- @seal_encrypt@ --- * - * - * Arguments: @seal_ctx *c@ = pointer to a SEAL context - * @const void *src@ = pointer to source data - * @void *dest@ = pointer to destination data - * @size_t sz@ = size of the data - * - * Returns: --- - * - * Use: Encrypts a block of data using SEAL. If @src@ is zero, - * @dest@ is filled with SEAL output. If @dest@ is zero, the - * SEAL generator is just spun around for a bit. This shouldn't - * be necessary, because SEAL isn't RC4. - */ - -void seal_encrypt(seal_ctx *c, const void *src, void *dest, size_t sz) -{ - const octet *s = src; - octet *d = dest; - - /* --- Expect a big dollop of bytes --- */ - - if (sz > c->qsz) { - seal_key *k = c->k; - uint32 A = c->a, B = c->b, C = c->c, D = c->d; - uint32 n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4; - uint32 aa, bb, cc, dd; - unsigned j = c->i; - - /* --- Empty the queue first --- */ - - if (c->qsz) { - if (d) { - unsigned i; - octet *p = c->q + sizeof(c->q) - c->qsz; - for (i = 0; i < c->qsz; i++) - *d++ = (s ? *s++ ^ *p++ : *p++); - } - sz -= c->qsz; - } - - /* --- Main sequence --- */ - - for (;;) { - unsigned P, Q; - - /* --- Reset if we've run out of steam on this iteration --- */ - - if (j == 256) { - seal_reset(c); - A = c->a, B = c->b, C = c->c, D = c->d; - n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4; - j = 0; - } - - /* --- Make some new numbers --- */ - - P = A & 0x7fc; B += k->t[P >> 2]; A = ROR32(A, 9); B ^= A; - Q = B & 0x7fc; C ^= k->t[Q >> 2]; B = ROR32(B, 9); C += B; - P = (P + C) & 0x7fc; D += k->t[P >> 2]; C = ROR32(C, 9); D ^= C; - Q = (Q + D) & 0x7fc; A ^= k->t[Q >> 2]; D = ROR32(D, 9); A += D; - P = (P + A) & 0x7fc; B ^= k->t[P >> 2]; A = ROR32(A, 9); - Q = (Q + B) & 0x7fc; C += k->t[Q >> 2]; B = ROR32(B, 9); - P = (P + C) & 0x7fc; D ^= k->t[P >> 2]; C = ROR32(C, 9); - Q = (Q + D) & 0x7fc; A += k->t[Q >> 2]; D = ROR32(D, 9); - - /* --- Remember the output and set up the next round --- */ - - aa = B + k->s[j + 0]; - bb = C ^ k->s[j + 1]; - cc = D + k->s[j + 2]; - dd = A ^ k->s[j + 3]; - j += 4; - - if (j & 4) - A += n1, B += n2, C ^= n1, D ^= n2; - else - A += n3, B += n4, C ^= n3, D ^= n4; - - /* --- Bail out here if we need to do buffering --- */ - - if (sz < 16) - break; - - /* --- Write the next 16 bytes --- */ - - if (d) { - if (s) { - aa ^= LOAD32_L(s + 0); - bb ^= LOAD32_L(s + 4); - cc ^= LOAD32_L(s + 8); - dd ^= LOAD32_L(s + 12); - s += 16; - } - STORE32_L(d + 0, aa); - STORE32_L(d + 4, bb); - STORE32_L(d + 8, cc); - STORE32_L(d + 12, dd); - d += 16; - } - sz -= 16; - } - - /* --- Write the new queue --- */ - - STORE32_L(c->q + 0, aa); - STORE32_L(c->q + 4, bb); - STORE32_L(c->q + 8, cc); - STORE32_L(c->q + 12, dd); - c->qsz = 16; - - c->a = A; c->b = B; c->c = C; c->d = D; - c->i = j; - } - - /* --- Deal with the rest from the queue --- */ - - if (sz) { - unsigned i; - octet *p = c->q + sizeof(c->q) - c->qsz; - if (d) { - for (i = 0; i < sz; i++) - *d++ = (s ? *s++ ^ *p++ : *p++); - } - c->qsz -= sz; - } -} - -/*----- Generic cipher interface ------------------------------------------*/ - -typedef struct gctx { - gcipher c; - seal_key k; - seal_ctx cc; -} gctx; - -static const gcipher_ops gops; - -static gcipher *ginit(const void *k, size_t sz) -{ - gctx *g = S_CREATE(gctx); - g->c.ops = &gops; - seal_initkey(&g->k, k, sz); - seal_initctx(&g->cc, &g->k, 0); - return (&g->c); -} - -static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) -{ - gctx *g = (gctx *)c; - seal_encrypt(&g->cc, s, t, sz); -} - -static void gsetiv(gcipher *c, const void *iv) -{ - gctx *g = (gctx *)c; - uint32 n = *(const uint32 *)iv; - seal_initctx(&g->cc, &g->k, n); -} - -static void gdestroy(gcipher *c) -{ - gctx *g = (gctx *)c; - BURN(*g); - S_DESTROY(g); -} - -static const gcipher_ops gops = { - &seal, - gencrypt, gencrypt, gdestroy, gsetiv, 0 -}; - -const gccipher seal = { - "seal", seal_keysz, 0, - ginit -}; - -/*----- Generic random number generator interface -------------------------*/ - -typedef struct grctx { - grand r; - seal_key k; - seal_ctx cc; -} grctx; - -static void grdestroy(grand *r) -{ - grctx *g = (grctx *)r; - BURN(*g); - S_DESTROY(g); -} - -static int grmisc(grand *r, unsigned op, ...) -{ - grctx *g = (grctx *)r; - va_list ap; - int rc = 0; - va_start(ap, op); - - switch (op) { - case GRAND_CHECK: - switch (va_arg(ap, unsigned)) { - case GRAND_CHECK: - case GRAND_SEEDINT: - case GRAND_SEEDUINT32: - case GRAND_SEEDBLOCK: - case GRAND_SEEDRAND: - rc = 1; - break; - default: - rc = 0; - break; - } - break; - case GRAND_SEEDINT: - seal_initctx(&g->cc, &g->k, va_arg(ap, int)); - break; - case GRAND_SEEDUINT32: - seal_initctx(&g->cc, &g->k, va_arg(ap, uint32)); - break; - case GRAND_SEEDBLOCK: { - const void *p = va_arg(ap, const void *); - size_t sz = va_arg(ap, size_t); - uint32 n; - if (sz >= 4) - n = LOAD32_L(p); - else { - octet buf[4] = { 0 }; - memcpy(buf, p, sz); - n = LOAD32_L(p); - } - seal_initctx(&g->cc, &g->k, n); - } break; - case GRAND_SEEDRAND: { - grand *rr = va_arg(ap, grand *); - seal_initctx(&g->cc, &g->k, rr->ops->word(rr)); - } break; - default: - GRAND_BADOP; - break; - } - - va_end(ap); - return (rc); -} - -static octet grbyte(grand *r) -{ - grctx *g = (grctx *)r; - octet o; - seal_encrypt(&g->cc, 0, &o, 1); - return (o); -} - -static uint32 grword(grand *r) -{ - grctx *g = (grctx *)r; - octet b[4]; - seal_encrypt(&g->cc, 0, b, 4); - return (LOAD32(b)); -} - -static void grfill(grand *r, void *p, size_t sz) -{ - grctx *g = (grctx *)r; - seal_encrypt(&g->cc, 0, p, sz); -} - -static const grand_ops grops = { - "seal", - GRAND_CRYPTO, 0, - grmisc, grdestroy, - grword, grbyte, grword, grand_range, grfill -}; - -/* --- @seal_rand@ --- * - * - * Arguments: @const void *k@ = pointer to key material - * @size_t sz@ = size of key material - * @uint32 n@ = sequence number - * - * Returns: Pointer to generic random number generator interface. - * - * Use: Creates a random number interface wrapper around a SEAL - * pseudorandom function. - */ - -grand *seal_rand(const void *k, size_t sz, uint32 n) -{ - grctx *g = S_CREATE(grctx); - g->r.ops = &grops; - seal_initkey(&g->k, k, sz); - seal_initctx(&g->cc, &g->k, n); - return (&g->r); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#include - -static int verify(dstr *v) -{ - seal_key k; - seal_ctx c; - uint32 n = *(uint32 *)v[1].buf; - dstr d = DSTR_INIT; - dstr z = DSTR_INIT; - int i; - int ok = 1; - - DENSURE(&d, v[2].len); - DENSURE(&z, v[2].len); - memset(z.buf, 0, v[2].len); - z.len = d.len = v[2].len; - seal_initkey(&k, v[0].buf, v[0].len); - - for (i = 0; i < v[2].len; i++) { - seal_initctx(&c, &k, n); - seal_encrypt(&c, 0, d.buf, i); - seal_encrypt(&c, z.buf, d.buf + i, d.len - i); - if (memcmp(d.buf, v[2].buf, d.len) != 0) { - ok = 0; - printf("*** seal failure\n"); - printf("*** k = "); type_hex.dump(&v[0], stdout); putchar('\n'); - printf("*** n = %08lx\n", (unsigned long)n); - printf("*** i = %i\n", i); - printf("*** expected = "); type_hex.dump(&v[2], stdout); putchar('\n'); - printf("*** computed = "); type_hex.dump(&d, stdout); putchar('\n'); - } - } - - dstr_destroy(&d); - dstr_destroy(&z); - - return (ok); -} - -static test_chunk defs[] = { - { "seal", verify, { &type_hex, &type_uint32, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, defs, SRCDIR"/tests/seal"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/seal.h b/seal.h deleted file mode 100644 index bee3b30..0000000 --- a/seal.h +++ /dev/null @@ -1,165 +0,0 @@ -/* -*-c-*- - * - * $Id: seal.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The SEAL pseudo-random function family - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the SEAL pseudo-random function family -------------------* - * - * SEAL is a slightly odd cryptographic primitive. It was designed by Phil - * Rogaway and Don Coppersmith at IBM, basically as an exercise in producing - * a really fast symmetric cipher of some kind. They succeeded: SEAL is - * faster than the much simpler RC4. - * - * For each key, it gives you %$2^{32}$% different output streams. This - * implementation imposes no length limits on the size of output streams and - * performs careful buffer handling to allow arbitrary amounts of data to be - * extracted. In practice, extracting more than about 64K is possibly dodgy - * from a security point of view. - * - * SEAL is patented. - */ - -#ifndef CATACOMB_SEAL_H -#define CATACOMB_SEAL_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GCIPHER_H -# include "gcipher.h" -#endif - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -#define SEAL_R 256 - -typedef struct seal_key { - octet k[20]; /* Copy of the 160-bit key */ - uint32 t[512]; /* Substitution table */ - uint32 s[256]; /* Magic for each iteration */ - uint32 r[SEAL_R]; /* Magic for the first 64K */ -} seal_key; - -typedef struct seal_ctx { - seal_key *k; /* Pointer to the key block */ - uint32 *r, ri; /* Pointer to current magic */ - uint32 n, l; /* Various indices into things */ - uint32 a, b, c, d; /* Current chaining variables */ - uint32 n1, n2, n3, n4; /* Increments for the variables */ - unsigned i; /* Index into current iteration */ - octet q[16]; /* Output buffer */ - unsigned qsz; /* Number of bytes in the buffer */ - uint32 rbuf[SEAL_R]; /* Buffer for later magic */ -} seal_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @seal_initkey@ --- * - * - * Arguments: @seal_key *k@ = pointer to key block - * @const void *buf@ = pointer to key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Initializes a SEAL key block. The key material may be any - * size, but if it's not 20 bytes long it's passed to SHA for - * hashing first. - */ - -extern void seal_initkey(seal_key */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @seal_initctx@ --- * - * - * Arguments: @seal_ctx *c@ = pointer to a SEAL context - * @seal_key *k@ = pointer to a SEAL key - * @uint32 n@ = integer sequence number - * - * Returns: --- - * - * Use: Initializes a SEAL context which can be used for random - * number generation or whatever. - */ - -extern void seal_initctx(seal_ctx */*c*/, seal_key */*k*/, uint32 /*n*/); - -/* --- @seal_encrypt@ --- * - * - * Arguments: @seal_ctx *c@ = pointer to a SEAL context - * @const void *src@ = pointer to source data - * @void *dest@ = pointer to destination data - * @size_t sz@ = size of the data - * - * Returns: --- - * - * Use: Encrypts a block of data using SEAL. If @src@ is zero, - * @dest@ is filled with SEAL output. If @dest@ is zero, the - * SEAL generator is just spun around for a bit. This shouldn't - * be necessary, because SEAL isn't RC4. - */ - -extern void seal_encrypt(seal_ctx */*c*/, const void */*src*/, - void */*dest*/, size_t /*sz*/); - -/*----- Generic cipher interface ------------------------------------------*/ - -#define SEAL_KEYSZ 20 -extern const octet seal_keysz[]; - -extern const gccipher seal; - -/*----- Generic random number generator interface -------------------------*/ - -/* --- @seal_rand@ --- * - * - * Arguments: @const void *k@ = pointer to key material - * @size_t sz@ = size of key material - * @uint32 n@ = sequence number - * - * Returns: Pointer to generic random number generator interface. - * - * Use: Creates a random number interface wrapper around a SEAL - * pseudorandom function. - */ - -extern grand *seal_rand(const void */*k*/, size_t /*sz*/, uint32 /*n*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/serpent-check.c b/serpent-check.c deleted file mode 100644 index 340af4f..0000000 --- a/serpent-check.c +++ /dev/null @@ -1,101 +0,0 @@ -/* -*-c-*- - * - * $Id: serpent-check.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Check the Serpent S-boxes - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include - -#include "serpent-sbox.h" - -/*----- S-box tables ------------------------------------------------------*/ - -static const octet s[8][16] = { - { 3, 8, 15, 1, 10, 6, 5, 11, 14, 13, 4, 2, 7, 0, 9, 12 }, - { 15, 12, 2, 7, 9, 0, 5, 10, 1, 11, 14, 8, 6, 13, 3, 4 }, - { 8, 6, 7, 9, 3, 12, 10, 15, 13, 1, 14, 4, 0, 11, 5, 2 }, - { 0, 15, 11, 8, 12, 9, 6, 3, 13, 1, 2, 4, 10, 7, 5, 14 }, - { 1, 15, 8, 3, 12, 0, 11, 6, 2, 5, 4, 10, 9, 14, 7, 13 }, - { 15, 5, 2, 11, 4, 10, 9, 12, 0, 3, 14, 8, 13, 6, 7, 1 }, - { 7, 2, 12, 5, 8, 4, 6, 11, 14, 9, 1, 15, 13, 3, 10, 0 }, - { 1, 13, 15, 0, 14, 8, 2, 11, 7, 4, 12, 10, 9, 3, 5, 6 } -}; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @check@ --- * - * - * Arguments: @unsigned a, b, c, d@ = four bitslice output registers - * @const octet *p@ = pointer to S-box - * - * Returns: Zero if OK, nonzero on failure. - * - * Use: Checks that an S-box output is correct. - */ - -static int check(unsigned a, unsigned b, unsigned c, unsigned d, - const octet *p) -{ - octet buf[16]; - octet *q = buf; - unsigned i; - - for (i = 0; i < 16; i++) { - *q++ = (a & 1) | ((b & 1) << 1) | ((c & 1) << 2) | ((d & 1) << 3); - a >>= 1; b >>= 1; c >>= 1; d >>= 1; - } - return (memcmp(buf, p, sizeof(buf))); -} - -#define CHECK(i) do { \ - unsigned a = 0xaaaa, b = 0xcccc, c = 0xf0f0, d = 0xff00; \ - S##i(a, b, c, d); \ - if (check(a, b, c, d, s[i])) { \ - fprintf(stderr, "failure in S%i\n", i); \ - rc = EXIT_FAILURE; \ - } \ - IS##i(a, b, c, d); \ - if (a != 0xaaaa || b != 0xcccc || c != 0xf0f0 || d != 0xff00) { \ - fprintf(stderr, "failure in IS%i\n", i); \ - rc = EXIT_FAILURE; \ - } \ -} while (0) - -int main(void) -{ - int rc = 0; - CHECK(0); CHECK(1); CHECK(2); CHECK(3); - CHECK(4); CHECK(5); CHECK(6); CHECK(7); - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/serpent-sbox.h b/serpent-sbox.h deleted file mode 100644 index 1612330..0000000 --- a/serpent-sbox.h +++ /dev/null @@ -1,230 +0,0 @@ -/* -*-c-*- - * - * $Id: serpent-sbox.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Bitslice S-box implementations - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Credit where it's due ---------------------------------------------* - * - * These S-box expressions are taken from the paper `Speeding up Serpent', by - * Dag Arne Osvik, submitted to AES3. - */ - -#ifndef CATACOMB_SERPENT_SBOX_H -#define CATACOMB_SERPENT_SBOX_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -/*----- Macros provided ---------------------------------------------------*/ - -/* --- @S0@ --- */ - -#define S0(r0, r1, r2, r3) do { \ - uint32 r4; \ - r3 ^= r0; r4 = r1; r1 &= r3; r4 ^= r2; \ - r1 ^= r0; r0 |= r3; r0 ^= r4; r4 ^= r3; \ - r3 ^= r2; r2 |= r1; r2 ^= r4; r4 = ~r4; \ - r4 |= r1; r1 ^= r3; r1 ^= r4; r3 |= r0; \ - r1 ^= r3; r4 ^= r3; \ - r3 = r0; r0 = r1; r1 = r4; \ -} while (0) - -#define IS0(r0, r1, r2, r3) do { \ - uint32 r4; \ - r2 = ~r2; r4 = r1; r1 |= r0; r4 = ~r4; \ - r1 ^= r2; r2 |= r4; r1 ^= r3; r0 ^= r4; \ - r2 ^= r0; r0 &= r3; r4 ^= r0; r0 |= r1; \ - r0 ^= r2; r3 ^= r4; r2 ^= r1; r3 ^= r0; \ - r3 ^= r1; r2 &= r3; r4 ^= r2; \ - r2 = r1; r1 = r4; \ -} while (0) - -/* --- @S1@ --- */ - -#define S1(r0, r1, r2, r3) do { \ - uint32 r4; \ - r0 = ~r0; r2 = ~r2; r4 = r0; r0 &= r1; \ - r2 ^= r0; r0 |= r3; r3 ^= r2; r1 ^= r0; \ - r0 ^= r4; r4 |= r1; r1 ^= r3; r2 |= r0; \ - r2 &= r4; r0 ^= r1; r1 &= r2; r1 ^= r0; \ - r0 &= r2; r0 ^= r4; \ - r4 = r0; r0 = r2; r2 = r3; r3 = r1; r1 = r4; \ -} while (0) - -#define IS1(r0, r1, r2, r3) do { \ - uint32 r4; \ - r4 = r1; r1 ^= r3; r3 &= r1; r4 ^= r2; \ - r3 ^= r0; r0 |= r1; r2 ^= r3; r0 ^= r4; \ - r0 |= r2; r1 ^= r3; r0 ^= r1; r1 |= r3; \ - r1 ^= r0; r4 = ~r4; r4 ^= r1; r1 |= r0; \ - r1 ^= r0; r1 |= r4; r3 ^= r1; \ - r1 = r0; r0 = r4; r4 = r2; r2 = r3; r3 = r4; \ -} while (0) - -/* --- @S2@ --- */ - -#define S2(r0, r1, r2, r3) do { \ - uint32 r4; \ - r4 = r0; r0 &= r2; r0 ^= r3; r2 ^= r1; \ - r2 ^= r0; r3 |= r4; r3 ^= r1; r4 ^= r2; \ - r1 = r3; r3 |= r4; r3 ^= r0; r0 &= r1; \ - r4 ^= r0; r1 ^= r3; r1 ^= r4; r4 = ~r4; \ - r0 = r2; r2 = r1; r1 = r3; r3 = r4; \ -} while (0) - -#define IS2(r0, r1, r2, r3) do { \ - uint32 r4; \ - r2 ^= r3; r3 ^= r0; r4 = r3; r3 &= r2; \ - r3 ^= r1; r1 |= r2; r1 ^= r4; r4 &= r3; \ - r2 ^= r3; r4 &= r0; r4 ^= r2; r2 &= r1; \ - r2 |= r0; r3 = ~r3; r2 ^= r3; r0 ^= r3; \ - r0 &= r1; r3 ^= r4; r3 ^= r0; \ - r0 = r1; r1 = r4; \ -} while (0) - -/* --- @S3@ --- */ - -#define S3(r0, r1, r2, r3) do { \ - uint32 r4; \ - r4 = r0; r0 |= r3; r3 ^= r1; r1 &= r4; \ - r4 ^= r2; r2 ^= r3; r3 &= r0; r4 |= r1; \ - r3 ^= r4; r0 ^= r1; r4 &= r0; r1 ^= r3; \ - r4 ^= r2; r1 |= r0; r1 ^= r2; r0 ^= r3; \ - r2 = r1; r1 |= r3; r1 ^= r0; \ - r0 = r1; r1 = r2; r2 = r3; r3 = r4; \ -} while (0) - -#define IS3(r0, r1, r2, r3) do { \ - uint32 r4; \ - r4 = r2; r2 ^= r1; r0 ^= r2; r4 &= r2; \ - r4 ^= r0; r0 &= r1; r1 ^= r3; r3 |= r4; \ - r2 ^= r3; r0 ^= r3; r1 ^= r4; r3 &= r2; \ - r3 ^= r1; r1 ^= r0; r1 |= r2; r0 ^= r3; \ - r1 ^= r4; r0 ^= r1; \ - r4 = r0; r0 = r2; r2 = r3; r3 = r4; \ -} while (0) - -/* --- @S4@ --- */ - -#define S4(r0, r1, r2, r3) do { \ - uint32 r4; \ - r1 ^= r3; r3 = ~r3; r2 ^= r3; r3 ^= r0; \ - r4 = r1; r1 &= r3; r1 ^= r2; r4 ^= r3; \ - r0 ^= r4; r2 &= r4; r2 ^= r0; r0 &= r1; \ - r3 ^= r0; r4 |= r1; r4 ^= r0; r0 |= r3; \ - r0 ^= r2; r2 &= r3; r0 = ~r0; r4 ^= r2; \ - r2 = r0; r0 = r1; r1 = r4; \ -} while (0) - -#define IS4(r0, r1, r2, r3) do { \ - uint32 r4; \ - r4 = r2; r2 &= r3; r2 ^= r1; r1 |= r3; \ - r1 &= r0; r4 ^= r2; r4 ^= r1; r1 &= r2; \ - r0 = ~r0; r3 ^= r4; r1 ^= r3; r3 &= r0; \ - r3 ^= r2; r0 ^= r1; r2 &= r0; r3 ^= r0; \ - r2 ^= r4, r2 |= r3; r3 ^= r0; r2 ^= r1; \ - r1 = r3; r3 = r4; \ -} while (0) - -/* --- @S5@ --- */ - -#define S5(r0, r1, r2, r3) do { \ - uint32 r4; \ - r0 ^= r1; r1 ^= r3; r3 = ~r3; r4 = r1; \ - r1 &= r0; r2 ^= r3; r1 ^= r2; r2 |= r4; \ - r4 ^= r3; r3 &= r1; r3 ^= r0; r4 ^= r1; \ - r4 ^= r2; r2 ^= r0; r0 &= r3; r2 = ~r2; \ - r0 ^= r4; r4 |= r3; r2 ^= r4; \ - r4 = r3; r3 = r2; r2 = r0; r0 = r1; r1 = r4; \ -} while (0) - -#define IS5(r0, r1, r2, r3) do { \ - uint32 r4; \ - r1 = ~r1; r4 = r3; r2 ^= r1; r3 |= r0; \ - r3 ^= r2; r2 |= r1; r2 &= r0; r4 ^= r3; \ - r2 ^= r4; r4 |= r0; r4 ^= r1; r1 &= r2; \ - r1 ^= r3; r4 ^= r2; r3 &= r4; r4 ^= r1; \ - r3 ^= r4; r4 = ~r4; r3 ^= r0; \ - r0 = r1; r1 = r4; r4 = r3; r3 = r2; r2 = r4; \ -} while (0) - -/* --- @S6@ --- */ - -#define S6(r0, r1, r2, r3) do { \ - uint32 r4; \ - r2 = ~r2; r4 = r3; r3 &= r0; r0 ^= r4; \ - r3 ^= r2; r2 |= r4; r1 ^= r3; r2 ^= r0; \ - r0 |= r1; r2 ^= r1; r4 ^= r0; r0 |= r3; \ - r0 ^= r2; r4 ^= r3; r4 ^= r0; r3 = ~r3; \ - r2 &= r4; r2 ^= r3; \ - r3 = r2; r2 = r4; \ -} while (0) - -#define IS6(r0, r1, r2, r3) do { \ - uint32 r4; \ - r0 ^= r2; r4 = r2; r2 &= r0; r4 ^= r3; \ - r2 = ~r2; r3 ^= r1; r2 ^= r3; r4 |= r0; \ - r0 ^= r2; r3 ^= r4; r4 ^= r1; r1 &= r3; \ - r1 ^= r0; r0 ^= r3; r0 |= r2; r3 ^= r1; \ - r4 ^= r0; \ - r0 = r1; r1 = r2; r2 = r4; \ -} while (0) - -/* --- @S7@ --- */ - -#define S7(r0, r1, r2, r3) do { \ - uint32 r4; \ - r4 = r1; r1 |= r2; r1 ^= r3; r4 ^= r2; \ - r2 ^= r1; r3 |= r4; r3 &= r0; r4 ^= r2; \ - r3 ^= r1; r1 |= r4; r1 ^= r0; r0 |= r4; \ - r0 ^= r2; r1 ^= r4; r2 ^= r1; r1 &= r0; \ - r1 ^= r4; r2 = ~r2; r2 |= r0; r4 ^= r2; \ - r2 = r1; r1 = r3; r3 = r0; r0 = r4; \ -} while (0) - -#define IS7(r0, r1, r2, r3) do { \ - uint32 r4; \ - r4 = r2; r2 ^= r0; r0 &= r3; r4 |= r3; \ - r2 = ~r2; r3 ^= r1; r1 |= r0; r0 ^= r2; \ - r2 &= r4; r3 &= r4; r1 ^= r2; r2 ^= r0; \ - r0 |= r2; r4 ^= r1; r0 ^= r3; r3 ^= r4; \ - r4 |= r0; r3 ^= r2; r4 ^= r2; \ - r2 = r1; r1 = r0; r0 = r3; r3 = r4; \ -} while (0) - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/serpent.c b/serpent.c deleted file mode 100644 index 9c03764..0000000 --- a/serpent.c +++ /dev/null @@ -1,215 +0,0 @@ -/* -*-c-*- - * - * $Id: serpent.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The Serpent block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "serpent.h" -#include "serpent-sbox.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet serpent_keysz[] = { KSZ_RANGE, SERPENT_KEYSZ, 0, 32, 1 }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @serpent_init@ --- * - * - * Arguments: @serpent_ctx *k@ = pointer to context block to initialize - * @const void *buf@ = pointer to input buffer - * @size_t sz@ = size of input buffer - * - * Returns: --- - * - * Use: Initializes a Serpent context. The key may be any length of - * up to 32 bytes (256 bits). - */ - -void serpent_init(serpent_ctx *k, const void *buf, size_t sz) -{ - uint32 a; - unsigned b; - const octet *p, *q; - size_t i; - uint32 pk[8 + 132]; - - KSZ_ASSERT(serpent, sz); - - /* --- Read the key into the buffer --- */ - - if (sz > 32) - sz = 32; - i = 0; p = buf; q = p + sz; - a = 0; b = 0; - while (p < q) { - a |= (uint32)*p++ << b; - b += 8; - if (b == 32) { - pk[i++] = a; - a = 0; b = 0; - } - } - - /* --- Pad short keys --- */ - - if (i < 8) { - a |= 0x01 << b; - b += 8; - pk[i++] = a; - for (; i < 8; i++) - pk[i] = 0; - } - - /* --- Expand the prekeys to fill the buffer --- */ - - for (i = 8; i < 8 + 132; i++) { - uint32 x = (pk[i - 8] ^ pk[i - 5] ^ pk[i - 3] ^ pk[i - 1] ^ - (i - 8) ^ 0x9e3779b9); - k->k[i - 8] = pk[i] = ROL32(x, 11); - } - - /* --- Now substitute everything --- */ - - i = 0; - goto midway; - while (i < 132) { -#define KSUB(r) do { \ - uint32 a, b, c, d; \ - a = k->k[i]; b = k->k[i + 1]; c = k->k[i + 2]; d = k->k[i + 3]; \ - S##r(a, b, c, d); \ - k->k[i] = a; k->k[i + 1] = b; k->k[i + 2] = c; k->k[i + 3] = d; \ - i += 4; \ -} while (0) - KSUB(2); KSUB(1); KSUB(0); KSUB(7); - KSUB(6); KSUB(5); KSUB(4); - midway: - KSUB(3); -#undef KSUB - } -} - -/* --- @serpent_eblk@, @serpent_dblk@ --- * - * - * Arguments: @const serpent_ctx *k@ = pointer to key context - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption. - */ - -#define EROUND(a, b, c, d, r, k) do { \ - a ^= *k++; b ^= *k++; c ^= *k++; d ^= *k++; \ - S##r(a, b, c, d); \ - a = ROL32(a, 13); c = ROL32(c, 3); b ^= a ^ c; d ^= c ^ (a << 3); \ - b = ROL32(b, 1); d = ROL32(d, 7); a ^= b ^ d; c ^= d ^ (b << 7); \ - a = ROL32(a, 5); c = ROL32(c, 22); \ -} while (0) - -#define DROUND(a, b, c, d, r, k) do { \ - IS##r(a, b, c, d); \ - d ^= *--k; c ^= *--k; b ^= *--k; a ^= *--k; \ - a = ROR32(a, 5); c = ROR32(c, 22); a ^= b ^ d; c ^= d ^ (b << 7); \ - b = ROR32(b, 1); d = ROR32(d, 7); b ^= a ^ c; d ^= c ^ (a << 3); \ - a = ROR32(a, 13); c = ROR32(c, 3); \ -} while (0) - -void serpent_eblk(const serpent_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3]; - const uint32 *kk = k->k; - - EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk); - EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk); - EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk); - EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk); - - EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk); - EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk); - EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk); - EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk); - - EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk); - EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk); - EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk); - EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk); - - EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk); - EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk); - EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk); - EROUND(aa, bb, cc, dd, 6, kk); - - aa ^= *kk++; bb ^= *kk++; cc ^= *kk++; dd ^= *kk++; - S7(aa, bb, cc, dd); - aa ^= *kk++; bb ^= *kk++; cc ^= *kk++; dd ^= *kk++; - d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd; -} - -void serpent_dblk(const serpent_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3]; - const uint32 *kk = k->k + 132; - - dd ^= *--kk; cc ^= *--kk; bb ^= *--kk; aa ^= *--kk; - - DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk); - DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk); - DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk); - DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk); - - DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk); - DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk); - DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk); - DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk); - - DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk); - DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk); - DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk); - DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk); - - DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk); - DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk); - DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk); - DROUND(aa, bb, cc, dd, 1, kk); - - IS0(aa, bb, cc, dd); - dd ^= *--kk; cc ^= *--kk; bb ^= *--kk; aa ^= *--kk; - d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd; -} - -BLKC_TEST(SERPENT, serpent) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/serpent.h b/serpent.h deleted file mode 100644 index bbab712..0000000 --- a/serpent.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -*-c-*- - * - * $Id: serpent.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The Serpent block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the Serpent block cipher ---------------------------------* - * - * Serpent was designed and proposed for the AES contest by Ross Anderson, - * Eli Biham and Lars Knudsen. It's not particularly quick, but is - * stunningly secure. The best differential and linear attacks are - * speculated to require %$2^{256}$% texts (it's a 128-bit block cipher). - * The designers originally intended to file a patent, but failed to persue - * it. Use of the algorithm is completely unencumbered. - */ - -#ifndef CATACOMB_SERPENT_H -#define CATACOMB_SERPENT_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magic numbers -----------------------------------------------------*/ - -#define SERPENT_BLKSZ 16 -#define SERPENT_KEYSZ 32 -#define SERPENT_CLASS (N, L, 128) - -extern const octet serpent_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct serpent_ctx { - uint32 k[4 * 33]; -} serpent_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @serpent_init@ --- * - * - * Arguments: @serpent_ctx *k@ = pointer to context block to initialize - * @const void *buf@ = pointer to input buffer - * @size_t sz@ = size of input buffer - * - * Returns: --- - * - * Use: Initializes a Serpent context. The key may be any length of - * up to 32 bytes (256 bits). - */ - -extern void serpent_init(serpent_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @serpent_eblk@, @serpent_dblk@ --- * - * - * Arguments: @const serpent_ctx *k@ = pointer to key context - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption. - */ - -extern void serpent_eblk(const serpent_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); -extern void serpent_dblk(const serpent_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/sha.c b/sha.c deleted file mode 100644 index 157b81b..0000000 --- a/sha.c +++ /dev/null @@ -1,306 +0,0 @@ -/* -*-c-*- - * - * $Id: sha.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * Implementation of the SHA-1 hash function - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "sha.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @sha_compress@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: SHA-1 compression function. - */ - -void sha_compress(sha_ctx *ctx, const void *sbuf) -{ - uint32 a, b, c, d, e; - uint32 buf[80]; - - /* --- Fetch the chaining variables --- */ - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - e = ctx->e; - - /* --- Fetch and expand the buffer contents --- */ - - { - int i; - const octet *p; - - for (i = 0, p = sbuf; i < 16; i++, p += 4) - buf[i] = LOAD32(p); - for (i = 16; i < 80; i++) { - uint32 x = buf[i - 3] ^ buf[i - 8] ^ buf[i - 14] ^ buf[i - 16]; - buf[i] = ROL32(x, 1); - } - } - - /* --- Definitions for round functions --- */ - -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define G(x, y, z) ((x) ^ (y) ^ (z)) -#define H(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) - -#define T(v, w, x, y, z, i, f, k) do { \ - z = ROL32(v, 5) + f(w, x, y) + z + buf[i] + k; \ - w = ROR32(w, 2); \ -} while (0) - -#define FF(v, w, x, y, z, i) T(v, w, x, y, z, i, F, 0x5a827999) -#define GG(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0x6ed9eba1) -#define HH(v, w, x, y, z, i) T(v, w, x, y, z, i, H, 0x8f1bbcdc) -#define II(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0xca62c1d6) - - /* --- The main compression function --- */ - - FF(a, b, c, d, e, 0); - FF(e, a, b, c, d, 1); - FF(d, e, a, b, c, 2); - FF(c, d, e, a, b, 3); - FF(b, c, d, e, a, 4); - FF(a, b, c, d, e, 5); - FF(e, a, b, c, d, 6); - FF(d, e, a, b, c, 7); - FF(c, d, e, a, b, 8); - FF(b, c, d, e, a, 9); - FF(a, b, c, d, e, 10); - FF(e, a, b, c, d, 11); - FF(d, e, a, b, c, 12); - FF(c, d, e, a, b, 13); - FF(b, c, d, e, a, 14); - FF(a, b, c, d, e, 15); - FF(e, a, b, c, d, 16); - FF(d, e, a, b, c, 17); - FF(c, d, e, a, b, 18); - FF(b, c, d, e, a, 19); - - GG(a, b, c, d, e, 20); - GG(e, a, b, c, d, 21); - GG(d, e, a, b, c, 22); - GG(c, d, e, a, b, 23); - GG(b, c, d, e, a, 24); - GG(a, b, c, d, e, 25); - GG(e, a, b, c, d, 26); - GG(d, e, a, b, c, 27); - GG(c, d, e, a, b, 28); - GG(b, c, d, e, a, 29); - GG(a, b, c, d, e, 30); - GG(e, a, b, c, d, 31); - GG(d, e, a, b, c, 32); - GG(c, d, e, a, b, 33); - GG(b, c, d, e, a, 34); - GG(a, b, c, d, e, 35); - GG(e, a, b, c, d, 36); - GG(d, e, a, b, c, 37); - GG(c, d, e, a, b, 38); - GG(b, c, d, e, a, 39); - - HH(a, b, c, d, e, 40); - HH(e, a, b, c, d, 41); - HH(d, e, a, b, c, 42); - HH(c, d, e, a, b, 43); - HH(b, c, d, e, a, 44); - HH(a, b, c, d, e, 45); - HH(e, a, b, c, d, 46); - HH(d, e, a, b, c, 47); - HH(c, d, e, a, b, 48); - HH(b, c, d, e, a, 49); - HH(a, b, c, d, e, 50); - HH(e, a, b, c, d, 51); - HH(d, e, a, b, c, 52); - HH(c, d, e, a, b, 53); - HH(b, c, d, e, a, 54); - HH(a, b, c, d, e, 55); - HH(e, a, b, c, d, 56); - HH(d, e, a, b, c, 57); - HH(c, d, e, a, b, 58); - HH(b, c, d, e, a, 59); - - II(a, b, c, d, e, 60); - II(e, a, b, c, d, 61); - II(d, e, a, b, c, 62); - II(c, d, e, a, b, 63); - II(b, c, d, e, a, 64); - II(a, b, c, d, e, 65); - II(e, a, b, c, d, 66); - II(d, e, a, b, c, 67); - II(c, d, e, a, b, 68); - II(b, c, d, e, a, 69); - II(a, b, c, d, e, 70); - II(e, a, b, c, d, 71); - II(d, e, a, b, c, 72); - II(c, d, e, a, b, 73); - II(b, c, d, e, a, 74); - II(a, b, c, d, e, 75); - II(e, a, b, c, d, 76); - II(d, e, a, b, c, 77); - II(c, d, e, a, b, 78); - II(b, c, d, e, a, 79); - - /* --- Update the chaining variables --- */ - - ctx->a += a; - ctx->b += b; - ctx->c += c; - ctx->d += d; - ctx->e += e; -} - -/* --- @sha_init@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void sha_init(sha_ctx *ctx) -{ - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; - ctx->e = 0xc3d2e1f0; - ctx->off = 0; - ctx->nl = ctx->nh = 0; -} - -/* --- @sha_set@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -void sha_set(sha_ctx *ctx, const void *buf, unsigned long count) -{ - const octet *p = buf; - ctx->a = LOAD32(p + 0); - ctx->b = LOAD32(p + 4); - ctx->c = LOAD32(p + 8); - ctx->d = LOAD32(p + 12); - ctx->e = LOAD32(p + 16); - ctx->off = 0; - ctx->nl = U32(count); - ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); -} - -/* --- @sha_hash@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void sha_hash(sha_ctx *ctx, const void *buf, size_t sz) -{ - HASH_BUFFER(SHA, sha, ctx, buf, sz); -} - -/* --- @sha_done@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -void sha_done(sha_ctx *ctx, void *hash) -{ - octet *p = hash; - HASH_PAD(SHA, sha, ctx, 0x80, 0, 8); - STORE32(ctx->buf + SHA_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3)); - STORE32(ctx->buf + SHA_BUFSZ - 4, ctx->nl << 3); - sha_compress(ctx, ctx->buf); - STORE32(p + 0, ctx->a); - STORE32(p + 4, ctx->b); - STORE32(p + 8, ctx->c); - STORE32(p + 12, ctx->d); - STORE32(p + 16, ctx->e); -} - -/* --- @sha_state@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @sha_set@. - */ - -unsigned long sha_state(sha_ctx *ctx, void *state) -{ - octet *p = state; - STORE32(p + 0, ctx->a); - STORE32(p + 4, ctx->b); - STORE32(p + 8, ctx->c); - STORE32(p + 12, ctx->d); - STORE32(p + 16, ctx->e); - return (ctx->nl | ((ctx->nh << 16) << 16)); -} - -/* --- Generic interface --- */ - -GHASH_DEF(SHA, sha) - -/* --- Test code --- */ - -HASH_TEST(SHA, sha) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/sha.h b/sha.h deleted file mode 100644 index 0ce367a..0000000 --- a/sha.h +++ /dev/null @@ -1,159 +0,0 @@ -/* -*-c-*- - * - * $Id: sha.h,v 1.6 2004/04/08 01:36:15 mdw Exp $ - * - * Implementation of the SHA-1 hash function - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the SHA-1 hash function ----------------------------------* - * - * SHA (Secure Hash Algorithm) was designed by the NSA, for use with the - * Digital Signature Algorithm. It is defined by FIPS 180-1. It has gained - * wide acceptance since its initial publication, and is probably now most - * people's collision-resistant function of choice. The author prefers - * RIPEMD-160, for no particularly good reasons. - */ - -#ifndef CATACOMB_SHA_H -#define CATACOMB_SHA_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define SHA_BUFSZ 64 -#define SHA_HASHSZ 20 -#define SHA_STATESZ 20 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct sha_ctx { - uint32 a, b, c, d, e; /* Chaining variables */ - uint32 nl, nh; /* Byte count so far */ - unsigned off; /* Offset into buffer */ - octet buf[SHA_BUFSZ]; /* Accumulation buffer */ -} sha_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @sha_compress@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: SHA compression function. - */ - -extern void sha_compress(sha_ctx */*ctx*/, const void */*sbuf*/); - -/* --- @sha_init@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -extern void sha_init(sha_ctx */*ctx*/); - -/* --- @sha_set@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -extern void sha_set(sha_ctx */*ctx*/, const void */*buf*/, - unsigned long /*count*/); - -/* --- @sha_hash@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -extern void sha_hash(sha_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/); - -/* --- @sha_done@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -extern void sha_done(sha_ctx */*ctx*/, void */*hash*/); - -/* --- @sha_state@ --- * - * - * Arguments: @sha_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @sha_set@. - */ - -extern unsigned long sha_state(sha_ctx */*ctx*/, void */*state*/); - -/*----- Generic hash interface --------------------------------------------*/ - -extern const gchash sha; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/sha224.c b/sha224.c deleted file mode 100644 index 2eceba0..0000000 --- a/sha224.c +++ /dev/null @@ -1,14 +0,0 @@ -/* -*-c-*- - * - * $Id: sha224.c,v 1.1 2004/03/21 22:43:34 mdw Exp $ - * - * Stub code for SHA-224 - */ - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "sha224.h" - -GHASH_DEF(SHA224, sha224) -HASH_TEST(SHA224, sha224) diff --git a/sha224.h b/sha224.h deleted file mode 100644 index 23684b7..0000000 --- a/sha224.h +++ /dev/null @@ -1,13 +0,0 @@ -/* -*-c-*- - * - * $Id: sha224.h,v 1.1 2004/03/21 22:43:34 mdw Exp $ - * - * Stub header for SHA-224 - */ - -#ifndef CATACOMB_SHA224_H -#define CATACOMB_SHA224_H - -#include "sha256.h" - -#endif diff --git a/sha256.c b/sha256.c deleted file mode 100644 index 683ba13..0000000 --- a/sha256.c +++ /dev/null @@ -1,335 +0,0 @@ -/* -*-c-*- - * - * $Id: sha256.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Implementation of the SHA-256 hash function - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "sha256.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @sha256_compress@, @sha224_compress@ --- * - * - * Arguments: @sha256_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: SHA-256 compression function. - */ - -void sha256_compress(sha256_ctx *ctx, const void *sbuf) -{ - uint32 a, b, c, d, e, f, g, h; - uint32 buf[64]; - - /* --- Fetch the chaining variables --- */ - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - e = ctx->e; - f = ctx->f; - g = ctx->g; - h = ctx->h; - - /* --- Definitions for round functions --- */ - -#define CH(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define MAJ(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) - -#define S0(x) (ROR32((x), 2) ^ ROR32((x), 13) ^ ROR32((x), 22)) -#define S1(x) (ROR32((x), 6) ^ ROR32((x), 11) ^ ROR32((x), 25)) -#define s0(x) (ROR32((x), 7) ^ ROR32((x), 18) ^ LSR32((x), 3)) -#define s1(x) (ROR32((x), 17) ^ ROR32((x), 19) ^ LSR32((x), 10)) - -#define T(a, b, c, d, e, f, g, h, i, k) do { \ - uint32 t1 = h + S1(e) + CH(e, f, g) + k + buf[i]; \ - uint32 t2 = S0(a) + MAJ(a, b, c); \ - d += t1; h = t1 + t2; \ -} while (0) - - /* --- Fetch and expand the buffer contents --- */ - - { - int i; - const octet *p; - - for (i = 0, p = sbuf; i < 16; i++, p += 4) - buf[i] = LOAD32(p); - for (i = 16; i < 64; i++) - buf[i] = s1(buf[i - 2]) + buf[i - 7] + s0(buf[i - 15]) + buf[i - 16]; - } - - /* --- The main compression function --- */ - - T(a, b, c, d, e, f, g, h, 0, 0x428a2f98); - T(h, a, b, c, d, e, f, g, 1, 0x71374491); - T(g, h, a, b, c, d, e, f, 2, 0xb5c0fbcf); - T(f, g, h, a, b, c, d, e, 3, 0xe9b5dba5); - T(e, f, g, h, a, b, c, d, 4, 0x3956c25b); - T(d, e, f, g, h, a, b, c, 5, 0x59f111f1); - T(c, d, e, f, g, h, a, b, 6, 0x923f82a4); - T(b, c, d, e, f, g, h, a, 7, 0xab1c5ed5); - T(a, b, c, d, e, f, g, h, 8, 0xd807aa98); - T(h, a, b, c, d, e, f, g, 9, 0x12835b01); - T(g, h, a, b, c, d, e, f, 10, 0x243185be); - T(f, g, h, a, b, c, d, e, 11, 0x550c7dc3); - T(e, f, g, h, a, b, c, d, 12, 0x72be5d74); - T(d, e, f, g, h, a, b, c, 13, 0x80deb1fe); - T(c, d, e, f, g, h, a, b, 14, 0x9bdc06a7); - T(b, c, d, e, f, g, h, a, 15, 0xc19bf174); - T(a, b, c, d, e, f, g, h, 16, 0xe49b69c1); - T(h, a, b, c, d, e, f, g, 17, 0xefbe4786); - T(g, h, a, b, c, d, e, f, 18, 0x0fc19dc6); - T(f, g, h, a, b, c, d, e, 19, 0x240ca1cc); - T(e, f, g, h, a, b, c, d, 20, 0x2de92c6f); - T(d, e, f, g, h, a, b, c, 21, 0x4a7484aa); - T(c, d, e, f, g, h, a, b, 22, 0x5cb0a9dc); - T(b, c, d, e, f, g, h, a, 23, 0x76f988da); - T(a, b, c, d, e, f, g, h, 24, 0x983e5152); - T(h, a, b, c, d, e, f, g, 25, 0xa831c66d); - T(g, h, a, b, c, d, e, f, 26, 0xb00327c8); - T(f, g, h, a, b, c, d, e, 27, 0xbf597fc7); - T(e, f, g, h, a, b, c, d, 28, 0xc6e00bf3); - T(d, e, f, g, h, a, b, c, 29, 0xd5a79147); - T(c, d, e, f, g, h, a, b, 30, 0x06ca6351); - T(b, c, d, e, f, g, h, a, 31, 0x14292967); - T(a, b, c, d, e, f, g, h, 32, 0x27b70a85); - T(h, a, b, c, d, e, f, g, 33, 0x2e1b2138); - T(g, h, a, b, c, d, e, f, 34, 0x4d2c6dfc); - T(f, g, h, a, b, c, d, e, 35, 0x53380d13); - T(e, f, g, h, a, b, c, d, 36, 0x650a7354); - T(d, e, f, g, h, a, b, c, 37, 0x766a0abb); - T(c, d, e, f, g, h, a, b, 38, 0x81c2c92e); - T(b, c, d, e, f, g, h, a, 39, 0x92722c85); - T(a, b, c, d, e, f, g, h, 40, 0xa2bfe8a1); - T(h, a, b, c, d, e, f, g, 41, 0xa81a664b); - T(g, h, a, b, c, d, e, f, 42, 0xc24b8b70); - T(f, g, h, a, b, c, d, e, 43, 0xc76c51a3); - T(e, f, g, h, a, b, c, d, 44, 0xd192e819); - T(d, e, f, g, h, a, b, c, 45, 0xd6990624); - T(c, d, e, f, g, h, a, b, 46, 0xf40e3585); - T(b, c, d, e, f, g, h, a, 47, 0x106aa070); - T(a, b, c, d, e, f, g, h, 48, 0x19a4c116); - T(h, a, b, c, d, e, f, g, 49, 0x1e376c08); - T(g, h, a, b, c, d, e, f, 50, 0x2748774c); - T(f, g, h, a, b, c, d, e, 51, 0x34b0bcb5); - T(e, f, g, h, a, b, c, d, 52, 0x391c0cb3); - T(d, e, f, g, h, a, b, c, 53, 0x4ed8aa4a); - T(c, d, e, f, g, h, a, b, 54, 0x5b9cca4f); - T(b, c, d, e, f, g, h, a, 55, 0x682e6ff3); - T(a, b, c, d, e, f, g, h, 56, 0x748f82ee); - T(h, a, b, c, d, e, f, g, 57, 0x78a5636f); - T(g, h, a, b, c, d, e, f, 58, 0x84c87814); - T(f, g, h, a, b, c, d, e, 59, 0x8cc70208); - T(e, f, g, h, a, b, c, d, 60, 0x90befffa); - T(d, e, f, g, h, a, b, c, 61, 0xa4506ceb); - T(c, d, e, f, g, h, a, b, 62, 0xbef9a3f7); - T(b, c, d, e, f, g, h, a, 63, 0xc67178f2); - - /* --- Update the chaining variables --- */ - - ctx->a += a; - ctx->b += b; - ctx->c += c; - ctx->d += d; - ctx->e += e; - ctx->f += f; - ctx->g += g; - ctx->h += h; -} - -/* --- @sha256_init@, @sha224_init@ --- * - * - * Arguments: @sha256_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void sha256_init(sha256_ctx *ctx) -{ - ctx->a = 0x6a09e667; - ctx->b = 0xbb67ae85; - ctx->c = 0x3c6ef372; - ctx->d = 0xa54ff53a; - ctx->e = 0x510e527f; - ctx->f = 0x9b05688c; - ctx->g = 0x1f83d9ab; - ctx->h = 0x5be0cd19; - ctx->off = 0; - ctx->nl = ctx->nh = 0; -} - -void sha224_init(sha256_ctx *ctx) -{ - ctx->a = 0xc1059ed8; - ctx->b = 0x367cd507; - ctx->c = 0x3070dd17; - ctx->d = 0xf70e5939; - ctx->e = 0xffc00b31; - ctx->f = 0x68581511; - ctx->g = 0x64f98fa7; - ctx->h = 0xbefa4fa4; - ctx->off = 0; - ctx->nl = ctx->nh = 0; -} - -/* --- @sha256_set@, @sha224_set@ --- * - * - * Arguments: @sha256_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -void sha256_set(sha256_ctx *ctx, const void *buf, unsigned long count) -{ - const octet *p = buf; - ctx->a = LOAD32(p + 0); - ctx->b = LOAD32(p + 4); - ctx->c = LOAD32(p + 8); - ctx->d = LOAD32(p + 12); - ctx->e = LOAD32(p + 16); - ctx->f = LOAD32(p + 20); - ctx->g = LOAD32(p + 24); - ctx->h = LOAD32(p + 28); - ctx->off = 0; - ctx->nl = U32(count); - ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); -} - -/* --- @sha256_hash@, @sha224_hash@ --- * - * - * Arguments: @sha256_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void sha256_hash(sha256_ctx *ctx, const void *buf, size_t sz) -{ - HASH_BUFFER(SHA256, sha256, ctx, buf, sz); -} - -/* --- @sha256_done, @sha224_done@ --- * - * - * Arguments: @sha256_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -static void final(sha256_ctx *ctx) -{ - HASH_PAD(SHA256, sha256, ctx, 0x80, 0, 8); - STORE32(ctx->buf + SHA256_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3)); - STORE32(ctx->buf + SHA256_BUFSZ - 4, ctx->nl << 3); - sha256_compress(ctx, ctx->buf); -} - -void sha256_done(sha256_ctx *ctx, void *hash) -{ - octet *p = hash; - final(ctx); - STORE32(p + 0, ctx->a); - STORE32(p + 4, ctx->b); - STORE32(p + 8, ctx->c); - STORE32(p + 12, ctx->d); - STORE32(p + 16, ctx->e); - STORE32(p + 20, ctx->f); - STORE32(p + 24, ctx->g); - STORE32(p + 28, ctx->h); -} - -void sha224_done(sha224_ctx *ctx, void *hash) -{ - octet *p = hash; - final(ctx); - STORE32(p + 0, ctx->a); - STORE32(p + 4, ctx->b); - STORE32(p + 8, ctx->c); - STORE32(p + 12, ctx->d); - STORE32(p + 16, ctx->e); - STORE32(p + 20, ctx->f); - STORE32(p + 24, ctx->g); -} - -/* --- @sha256_state@, @sha224_state@ --- * - * - * Arguments: @sha256_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @sha256_set@. - */ - -unsigned long sha256_state(sha256_ctx *ctx, void *state) -{ - octet *p = state; - STORE32(p + 0, ctx->a); - STORE32(p + 4, ctx->b); - STORE32(p + 8, ctx->c); - STORE32(p + 12, ctx->d); - STORE32(p + 16, ctx->e); - STORE32(p + 20, ctx->f); - STORE32(p + 24, ctx->g); - STORE32(p + 28, ctx->h); - return (ctx->nl | ((ctx->nh << 16) << 16)); -} - -/* --- Generic interface --- */ - -GHASH_DEF(SHA256, sha256) - -/* --- Test code --- */ - -HASH_TEST(SHA256, sha256) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/sha256.h b/sha256.h deleted file mode 100644 index 7b21dd2..0000000 --- a/sha256.h +++ /dev/null @@ -1,171 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Implementation of the SHA-256 hash function - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the SHA-256 hash function --------------------------------* - * - * SHA-1 (Secure Hash Algorithm) was designed by the NSA, for use with the - * Digital Signature Algorithm. This is an evolution with a larger output - * size, intended to provide security commensurate with 128-bit AES. At the - * time of writing, SHA-256 is very new, and can't be trusted too far. - */ - -#ifndef CATACOMB_SHA256_H -#define CATACOMB_SHA256_H -#define CATACOMB_SHA224_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define SHA256_BUFSZ 64 -#define SHA256_HASHSZ 32 -#define SHA256_STATESZ 32 - -#define SHA224_BUFSZ 64 -#define SHA224_HASHSZ 28 -#define SHA224_STATESZ 32 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct sha256_ctx { - uint32 a, b, c, d, e, f, g, h; /* Chaining variables */ - uint32 nl, nh; /* Byte count so far */ - unsigned off; /* Offset into buffer */ - octet buf[SHA256_BUFSZ]; /* Accumulation buffer */ -} sha256_ctx, sha224_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @sha256_compress@, @sha224_compress@ --- * - * - * Arguments: @sha256_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: SHA-256 compression function. - */ - -extern void sha256_compress(sha256_ctx */*ctx*/, const void */*sbuf*/); -#define sha224_compress sha256_compress - -/* --- @sha256_init@, @sha224_init@ --- * - * - * Arguments: @sha256_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -extern void sha256_init(sha256_ctx */*ctx*/); -extern void sha224_init(sha256_ctx */*ctx*/); - -/* --- @sha256_set@, @sha224_set@ --- * - * - * Arguments: @sha256_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -extern void sha256_set(sha256_ctx */*ctx*/, const void */*buf*/, - unsigned long /*count*/); -#define sha224_set sha256_set - -/* --- @sha256_hash@, @sha224_hash@ --- * - * - * Arguments: @sha256_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -extern void sha256_hash(sha256_ctx */*ctx*/, - const void */*buf*/, size_t /*sz*/); -#define sha224_hash sha256_hash - -/* --- @sha256_done@, @sha224_done@ --- * - * - * Arguments: @sha256_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -extern void sha256_done(sha256_ctx */*ctx*/, void */*hash*/); -extern void sha224_done(sha256_ctx */*ctx*/, void */*hash*/); - -/* --- @sha256_state@, @sha224_state@ --- * - * - * Arguments: @sha256_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @sha256_set@. - */ - -extern unsigned long sha256_state(sha256_ctx */*ctx*/, void */*state*/); -#define sha224_state sha256_state - -/*----- Generic hash interface --------------------------------------------*/ - -extern const gchash sha256; -extern const gchash sha224; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/sha384.c b/sha384.c deleted file mode 100644 index a634ef7..0000000 --- a/sha384.c +++ /dev/null @@ -1,14 +0,0 @@ -/* -*-c-*- - * - * $Id: sha384.c,v 1.1 2000/10/15 17:48:15 mdw Exp $ - * - * Stub code for SHA-384 - */ - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "sha384.h" - -GHASH_DEF(SHA384, sha384) -HASH_TEST(SHA384, sha384) diff --git a/sha384.h b/sha384.h deleted file mode 100644 index 661ca60..0000000 --- a/sha384.h +++ /dev/null @@ -1,13 +0,0 @@ -/* -*-c-*- - * - * $Id: sha384.h,v 1.1 2000/10/15 17:48:15 mdw Exp $ - * - * Stub header for SHA-384 - */ - -#ifndef CATACOMB_SHA384_H -#define CATACOMB_SHA384_H - -#include "sha512.h" - -#endif diff --git a/sha512.c b/sha512.c deleted file mode 100644 index 2f39472..0000000 --- a/sha512.c +++ /dev/null @@ -1,342 +0,0 @@ -/* -*-c-*- - * - * $Id: sha512.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Implementation of the SHA-512 hash function - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "sha512.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @sha512_compress@, @sha384_compress@ --- * - * - * Arguments: @sha512_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: SHA-512 compression function. - */ - -void sha512_compress(sha512_ctx *ctx, const void *sbuf) -{ - kludge64 a, b, c, d, e, f, g, h; - kludge64 buf[80]; - int i; - - static const kludge64 K[80] = { - X64(428a2f98, d728ae22), X64(71374491, 23ef65cd), - X64(b5c0fbcf, ec4d3b2f), X64(e9b5dba5, 8189dbbc), - X64(3956c25b, f348b538), X64(59f111f1, b605d019), - X64(923f82a4, af194f9b), X64(ab1c5ed5, da6d8118), - X64(d807aa98, a3030242), X64(12835b01, 45706fbe), - X64(243185be, 4ee4b28c), X64(550c7dc3, d5ffb4e2), - X64(72be5d74, f27b896f), X64(80deb1fe, 3b1696b1), - X64(9bdc06a7, 25c71235), X64(c19bf174, cf692694), - X64(e49b69c1, 9ef14ad2), X64(efbe4786, 384f25e3), - X64(0fc19dc6, 8b8cd5b5), X64(240ca1cc, 77ac9c65), - X64(2de92c6f, 592b0275), X64(4a7484aa, 6ea6e483), - X64(5cb0a9dc, bd41fbd4), X64(76f988da, 831153b5), - X64(983e5152, ee66dfab), X64(a831c66d, 2db43210), - X64(b00327c8, 98fb213f), X64(bf597fc7, beef0ee4), - X64(c6e00bf3, 3da88fc2), X64(d5a79147, 930aa725), - X64(06ca6351, e003826f), X64(14292967, 0a0e6e70), - X64(27b70a85, 46d22ffc), X64(2e1b2138, 5c26c926), - X64(4d2c6dfc, 5ac42aed), X64(53380d13, 9d95b3df), - X64(650a7354, 8baf63de), X64(766a0abb, 3c77b2a8), - X64(81c2c92e, 47edaee6), X64(92722c85, 1482353b), - X64(a2bfe8a1, 4cf10364), X64(a81a664b, bc423001), - X64(c24b8b70, d0f89791), X64(c76c51a3, 0654be30), - X64(d192e819, d6ef5218), X64(d6990624, 5565a910), - X64(f40e3585, 5771202a), X64(106aa070, 32bbd1b8), - X64(19a4c116, b8d2d0c8), X64(1e376c08, 5141ab53), - X64(2748774c, df8eeb99), X64(34b0bcb5, e19b48a8), - X64(391c0cb3, c5c95a63), X64(4ed8aa4a, e3418acb), - X64(5b9cca4f, 7763e373), X64(682e6ff3, d6b2b8a3), - X64(748f82ee, 5defb2fc), X64(78a5636f, 43172f60), - X64(84c87814, a1f0ab72), X64(8cc70208, 1a6439ec), - X64(90befffa, 23631e28), X64(a4506ceb, de82bde9), - X64(bef9a3f7, b2c67915), X64(c67178f2, e372532b), - X64(ca273ece, ea26619c), X64(d186b8c7, 21c0c207), - X64(eada7dd6, cde0eb1e), X64(f57d4f7f, ee6ed178), - X64(06f067aa, 72176fba), X64(0a637dc5, a2c898a6), - X64(113f9804, bef90dae), X64(1b710b35, 131c471b), - X64(28db77f5, 23047d84), X64(32caab7b, 40c72493), - X64(3c9ebe0a, 15c9bebc), X64(431d67c4, 9c100d4c), - X64(4cc5d4be, cb3e42b6), X64(597f299c, fc657e2a), - X64(5fcb6fab, 3ad6faec), X64(6c44198c, 4a475817) - }; - - /* --- Fetch the chaining variables --- */ - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - e = ctx->e; - f = ctx->f; - g = ctx->g; - h = ctx->h; - - /* --- Definitions for round functions --- */ - -#define CH(d, x, y, z) do { \ - kludge64 _x; AND64((d), (x), (y)); CPL64(_x, (x)); \ - AND64(_x, _x, (z)); OR64((d), (d), _x); \ -} while (0) - -#define MAJ(d, x, y, z) do { \ - kludge64 _x; AND64((d), (x), (y)); AND64(_x, (x), (z)); \ - OR64((d), (d), _x); AND64(_x, (y), (z)); OR64((d), (d), _x); \ -} while (0) - -#define SIGMA(d, x, i, j, k, last, what) do { \ - kludge64 _x; ROR64_((d), (x), (i)); ROR64_(_x, (x), (j)); \ - XOR64((d), (d), _x); last##64_(_x, (x), (k)); XOR64((d), (d), _x); \ -} while (0) - -#define S0(d, x) SIGMA(d, x, 28, 34, 39, ROR, S0); -#define S1(d, x) SIGMA(d, x, 14, 18, 41, ROR, S1); -#define s0(d, x) SIGMA(d, x, 1, 8, 7, LSR, s0); -#define s1(d, x) SIGMA(d, x, 19, 61, 6, LSR, s1); - -#define T(a, b, c, d, e, f, g, h, i) do { \ - kludge64 t1, t2, x; \ - ADD64(t1, buf[i], K[i]); ADD64(t1, t1, h); \ - S1(x, e); ADD64(t1, t1, x); CH(x, e, f, g); ADD64(t1, t1, x); \ - S0(t2, a); MAJ(x, a, b, c); ADD64(t2, t2, x); \ - ADD64(d, d, t1); ADD64(h, t1, t2); \ -} while (0) - - /* --- Fetch and expand the buffer contents --- */ - - { - const octet *p; - - for (i = 0, p = sbuf; i < 16; i++, p += 8) - LOAD64_(buf[i], p); - for (i = 16; i < 80; i++) { - kludge64 x; - buf[i] = buf[i - 7]; s1(x, buf[i - 2]); ADD64(buf[i], buf[i], x); - s0(x, buf[i - 15]); ADD64(buf[i], buf[i], x); - ADD64(buf[i], buf[i], buf[i - 16]); - } - } - - /* --- The main compression function --- */ - - for (i = 0; i < 80; i += 8) { - T(a, b, c, d, e, f, g, h, i + 0); - T(h, a, b, c, d, e, f, g, i + 1); - T(g, h, a, b, c, d, e, f, i + 2); - T(f, g, h, a, b, c, d, e, i + 3); - T(e, f, g, h, a, b, c, d, i + 4); - T(d, e, f, g, h, a, b, c, i + 5); - T(c, d, e, f, g, h, a, b, i + 6); - T(b, c, d, e, f, g, h, a, i + 7); - } - - /* --- Update the chaining variables --- */ - - ADD64(ctx->a, ctx->a, a); - ADD64(ctx->b, ctx->b, b); - ADD64(ctx->c, ctx->c, c); - ADD64(ctx->d, ctx->d, d); - ADD64(ctx->e, ctx->e, e); - ADD64(ctx->f, ctx->f, f); - ADD64(ctx->g, ctx->g, g); - ADD64(ctx->h, ctx->h, h); -} - -/* --- @sha512_init@, @sha384_init@ --- * - * - * Arguments: @sha512_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void sha512_init(sha512_ctx *ctx) -{ - SET64(ctx->a, 0x6a09e667, 0xf3bcc908); - SET64(ctx->b, 0xbb67ae85, 0x84caa73b); - SET64(ctx->c, 0x3c6ef372, 0xfe94f82b); - SET64(ctx->d, 0xa54ff53a, 0x5f1d36f1); - SET64(ctx->e, 0x510e527f, 0xade682d1); - SET64(ctx->f, 0x9b05688c, 0x2b3e6c1f); - SET64(ctx->g, 0x1f83d9ab, 0xfb41bd6b); - SET64(ctx->h, 0x5be0cd19, 0x137e2179); - ctx->off = 0; - ctx->nh = ctx->nl = 0; -} - -void sha384_init(sha512_ctx *ctx) -{ - SET64(ctx->a, 0xcbbb9d5d, 0xc1059ed8); - SET64(ctx->b, 0x629a292a, 0x367cd507); - SET64(ctx->c, 0x9159015a, 0x3070dd17); - SET64(ctx->d, 0x152fecd8, 0xf70e5939); - SET64(ctx->e, 0x67332667, 0xffc00b31); - SET64(ctx->f, 0x8eb44a87, 0x68581511); - SET64(ctx->g, 0xdb0c2e0d, 0x64f98fa7); - SET64(ctx->h, 0x47b5481d, 0xbefa4fa4); - ctx->off = 0; - ctx->nh = ctx->nl = 0; -} - -/* --- @sha512_set@, @sha384_set@ --- * - * - * Arguments: @sha512_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -void sha512_set(sha512_ctx *ctx, const void *buf, unsigned long count) -{ - const octet *p = buf; - LOAD64_(ctx->a, p + 0); - LOAD64_(ctx->b, p + 8); - LOAD64_(ctx->c, p + 16); - LOAD64_(ctx->d, p + 24); - LOAD64_(ctx->e, p + 32); - LOAD64_(ctx->f, p + 40); - LOAD64_(ctx->g, p + 48); - LOAD64_(ctx->h, p + 56); - ctx->off = 0; - ctx->nl = U32(count); - ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); -} - -/* --- @sha512_hash@, @sha384_hash@ --- * - * - * Arguments: @sha512_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void sha512_hash(sha512_ctx *ctx, const void *buf, size_t sz) -{ - HASH_BUFFER(SHA512, sha512, ctx, buf, sz); -} - -/* --- @sha512_done@, @sha384_done@ --- * - * - * Arguments: @sha512_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -static void final(sha512_ctx *ctx) -{ - HASH_PAD(SHA512, sha512, ctx, 0x80, 0, 16); - memset(ctx->buf + SHA512_BUFSZ - 16, 0, 8); - STORE32(ctx->buf + SHA512_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3)); - STORE32(ctx->buf + SHA512_BUFSZ - 4, ctx->nl << 3); - sha512_compress(ctx, ctx->buf); -} - -void sha512_done(sha512_ctx *ctx, void *hash) -{ - octet *p = hash; - final(ctx); - STORE64_(p + 0, ctx->a); - STORE64_(p + 8, ctx->b); - STORE64_(p + 16, ctx->c); - STORE64_(p + 24, ctx->d); - STORE64_(p + 32, ctx->e); - STORE64_(p + 40, ctx->f); - STORE64_(p + 48, ctx->g); - STORE64_(p + 56, ctx->h); -} - -void sha384_done(sha384_ctx *ctx, void *hash) -{ - octet *p = hash; - final(ctx); - STORE64_(p + 0, ctx->a); - STORE64_(p + 8, ctx->b); - STORE64_(p + 16, ctx->c); - STORE64_(p + 24, ctx->d); - STORE64_(p + 32, ctx->e); - STORE64_(p + 40, ctx->f); -} - -/* --- @sha512_state@, @sha384_state@ --- * - * - * Arguments: @sha512_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @sha512_set@. - */ - -unsigned long sha512_state(sha512_ctx *ctx, void *state) -{ - octet *p = state; - STORE64_(p + 0, ctx->a); - STORE64_(p + 8, ctx->b); - STORE64_(p + 16, ctx->c); - STORE64_(p + 24, ctx->d); - STORE64_(p + 32, ctx->e); - STORE64_(p + 40, ctx->f); - STORE64_(p + 48, ctx->g); - STORE64_(p + 56, ctx->h); - return (ctx->nl | ((ctx->nh << 16) << 16)); -} - -/* --- Generic interface --- */ - -GHASH_DEF(SHA512, sha512) - -/* --- Test code --- */ - -HASH_TEST(SHA512, sha512) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/sha512.h b/sha512.h deleted file mode 100644 index f727e82..0000000 --- a/sha512.h +++ /dev/null @@ -1,173 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Implementation of the SHA-512 hash function - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the SHA-512 hash function --------------------------------* - * - * SHA-1 (Secure Hash Algorithm) was designed by the NSA, for use with the - * Digital Signature Algorithm. This is an evolution with a larger output - * size, intended to provide security commensurate with 256-bit AES. At the - * time of writing, SHA-512 is very new, and can't be trusted too far. There - * is also a truncated version, SHA-384, which provides security commensurate - * with 192-bit AES. - */ - -#ifndef CATACOMB_SHA512_H -#define CATACOMB_SHA512_H -#define CATACOMB_SHA384_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define SHA512_BUFSZ 128 -#define SHA512_HASHSZ 64 -#define SHA512_STATESZ 64 - -#define SHA384_BUFSZ 128 -#define SHA384_HASHSZ 48 -#define SHA384_STATESZ 64 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct sha512_ctx { - kludge64 a, b, c, d, e, f, g, h; /* Chaining variables */ - uint32 nh, nl; /* Byte count so far */ - unsigned off; /* Offset into buffer */ - octet buf[SHA512_BUFSZ]; /* Accumulation buffer */ -} sha512_ctx, sha384_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @sha512_compress@, @sha384_compress@ --- * - * - * Arguments: @sha512_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: SHA-512 compression function. - */ - -extern void sha512_compress(sha512_ctx */*ctx*/, const void */*sbuf*/); -#define sha384_compress sha512_compress - -/* --- @sha512_init@, @sha384_init@ --- * - * - * Arguments: @sha512_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -extern void sha512_init(sha512_ctx */*ctx*/); -extern void sha384_init(sha512_ctx */*ctx*/); - -/* --- @sha512_set@, @sha384_set@ --- * - * - * Arguments: @sha512_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -extern void sha512_set(sha512_ctx */*ctx*/, const void */*buf*/, - unsigned long /*count*/); -#define sha384_set sha512_set - -/* --- @sha512_hash@, @sha384_hash@ --- * - * - * Arguments: @sha512_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -extern void sha512_hash(sha512_ctx */*ctx*/, - const void */*buf*/, size_t /*sz*/); -#define sha384_hash sha512_hash - -/* --- @sha512_done@, @sha384_done@ --- * - * - * Arguments: @sha512_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -extern void sha512_done(sha512_ctx */*ctx*/, void */*hash*/); -extern void sha384_done(sha512_ctx */*ctx*/, void */*hash*/); - -/* --- @sha512_state@, @sha384_state@ --- * - * - * Arguments: @sha512_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @sha512_set@. - */ - -extern unsigned long sha512_state(sha512_ctx */*ctx*/, void */*state*/); -#define sha384_state sha512_state - -/*----- Generic hash interface --------------------------------------------*/ - -extern const gchash sha512; -extern const gchash sha384; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/share.c b/share.c deleted file mode 100644 index 1afa189..0000000 --- a/share.c +++ /dev/null @@ -1,382 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Shamir's secret sharing - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include "grand.h" -#include "mp.h" -#include "mpint.h" -#include "mpbarrett.h" -#include "mprand.h" -#include "pgen.h" -#include "rabin.h" -#include "share.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @share_create@ --- * - * - * Arguments: @share *s@ = pointer to share context to initialize - * @unsigned t@ = threshold for the system - * - * Returns: --- - * - * Use: Initializes a sharing context. - */ - -void share_create(share *s, unsigned t) -{ - s->t = t; - s->i = 0; - s->p = 0; - s->v = 0; -} - -/* --- @share_destroy@ --- * - * - * Arguments: @share *s@ = pointer to share context to destroy - * - * Returns: --- - * - * Use: Disposes of a sharing context. All memory is freed, all - * integers are dropped. - */ - -void share_destroy(share *s) -{ - unsigned i; - - /* --- Dispose of the share vector --- */ - - if (s->v) { - for (i = 0; i < s->t; i++) - mp_drop(s->v[i].y); - xfree(s->v); - } - - /* --- Other stuff --- */ - - mp_drop(s->p); -} - -/* --- @share_mkshares@ --- * - * - * Arguments: @share *s@ = pointer to share context to fill in - * @grand *r@ = pointer to random number source - * @mp *n@ = the secret to share - * - * Returns: --- - * - * Use: Initializes a sharing context to be able to create shares. - * The context structure is expected to be mostly filled in. In - * particular, @t@ must be initialized. If @p@ is zero, a prime - * number of appropriate size is generated automatically. If - * @v@ is zero, a vector of appropriate size is allocated. You - * should use the macro @SHARE_INIT@ or @share_create@ to - * construct sharing contexts. - */ - -void share_mkshares(share *s, grand *r, mp *n) -{ - unsigned i; - - /* --- If there's no prime, construct one --- */ - - if (!s->p) { - pgen_filterctx pf; - rabin pr; - mp *p; - unsigned bits = (mp_octets(n) + 1) * 8; - - pf.step = 2; - p = mprand(MP_NEW, bits, r, 1); - s->p = pgen("p", p, p, 0, 0, 0, pgen_filter, &pf, - rabin_iters(bits), pgen_test, &pr); - } - - /* --- Construct the polynomial --- */ - - if (!s->v) - s->v = xmalloc(s->t * sizeof(share_pt)); - for (i = 0; i < s->t - 1; i++) - s->v[i].y = mprand_range(MP_NEWSEC, s->p, r, 0); - s->v[s->t - 1].y = mp_copy(n); -} - -/* --- @share_get@ --- * - * - * Arguments: @share *s@ = pointer to share conext - * @mp *d@ = destination for the share - * @unsigned x@ = share index to fetch - * - * Returns: The share, as requested. - * - * Use: Extracts a share from the system. You may extract @MPW_MAX@ - * shares, or @s->p@ shares from the system, whichever is - * smaller. Shares are indexed from 0. - */ - -mp *share_get(share *s, mp *d, unsigned x) -{ - mpbarrett mb; - mpw uw = x + 1; - mp u; - unsigned i; - - /* --- Various bits of initialization --- */ - - mp_build(&u, &uw, &uw + 1); - mp_drop(d); - - /* --- Evaluate the polynomial at %$x = i + 1$% --- */ - - d = MP_ZERO; - mpbarrett_create(&mb, s->p); - for (i = 0; i < s->t; i++) { - d = mp_mul(d, d, &u); - d = mp_add(d, d, s->v[i].y); - d = mpbarrett_reduce(&mb, d, d); - } - mpbarrett_destroy(&mb); - - return (d); -} - -/* --- @share_addedp@ --- * - * - * Arguments: @share *s@ = pointer to sharing context - * @unsigned x@ = which share number to check - * - * Returns: Nonzero if share @x@ has been added already, zero if it - * hasn't. - */ - -int share_addedp(share *s, unsigned x) -{ - unsigned i; - - for (i = 0; i < s->i; i++) { - if (s->v[i].x == x + 1) - return (1); - } - return (0); -} - -/* --- @share_add@ --- * - * - * Arguments: @share *s@ = pointer to sharing context - * @unsigned x@ = which share number this is - * @mp *y@ = the share value - * - * Returns: Number of shares required before recovery may be performed. - * - * Use: Adds a share to the context. The context must have been - * initialized with the correct prime @p@ and threshold @t@. - */ - -unsigned share_add(share *s, unsigned x, mp *y) -{ - assert(((void)"Share context is full", s->i < s->t)); - assert(((void)"Share already present", !share_addedp(s, x))); - - /* --- If no vector has been allocated, create one --- */ - - if (!s->v) { - unsigned i; - s->v = xmalloc(s->t * sizeof(share_pt)); - s->i = 0; - for (i = 0; i < s->t; i++) - s->v[i].y = 0; - } - - /* --- Store the share in the vector --- */ - - s->v[s->i].x = x + 1; - s->v[s->i].y = mp_copy(y); - s->i++; - - /* --- Done --- */ - - return (s->t - s->i); -} - -/* --- @share_combine@ --- * - * - * Arguments: @share *s@ = pointer to share context - * - * Returns: The secret, as a multiprecision integer. - * - * Use: Reconstructs a secret, given enough shares. - */ - -mp *share_combine(share *s) -{ - mp *a = MP_ZERO; - mpbarrett mb; - unsigned i, j; - mp ii, jj; - mpw iiw, jjw; - mp *m = MP_NEW; - - /* --- Sanity checking --- */ - - assert(((void)"Not enough shares yet", s->i == s->t)); - - /* --- Initialization --- */ - - mpbarrett_create(&mb, s->p); - mp_build(&ii, &iiw, &iiw + 1); - mp_build(&jj, &jjw, &jjw + 1); - - /* --- Grind through the shares --- */ - - for (i = 0; i < s->t; i++) { - mp *c = MP_ONE; - - iiw = s->v[i].x; - for (j = 0; j < s->t; j++) { - if (i == j) - continue; - jjw = s->v[j].x; - if (s->v[j].x >= s->v[i].x) - m = mp_sub(m, &jj, &ii); - else { - m = mp_sub(m, &ii, &jj); - m = mp_sub(m, s->p, m); - } - m = mp_modinv(m, m, s->p); - c = mp_mul(c, c, &jj); - c = mpbarrett_reduce(&mb, c, c); - c = mp_mul(c, c, m); - c = mpbarrett_reduce(&mb, c, c); - } - c = mp_mul(c, c, s->v[i].y); - c = mpbarrett_reduce(&mb, c, c); - a = mp_add(a, a, c); - mp_drop(c); - } - - a = mpbarrett_reduce(&mb, a, a); - mp_drop(m); - mpbarrett_destroy(&mb); - return (a); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include "fibrand.h" - -static int verify(grand *r) -{ - unsigned n = r->ops->range(r, 16) + 8; - unsigned t = r->ops->range(r, n - 1) + 1; - unsigned len = r->ops->range(r, 160); - - mp **v = xmalloc(t * sizeof(mp *)); - unsigned *p = xmalloc(n * sizeof(unsigned)); - mp *sec = mprand(MP_NEW, len, r, 0); - share s; - mp *pp; - mp *ss; - unsigned i; - - int ok = 1; - - for (i = 0; i < n; i++) - p[i] = i; - for (i = 0; i < t; i++) { - unsigned long j = r->ops->range(r, n - i); - unsigned x = p[i]; - p[i] = p[i + j]; - p[i + j] = x; - } - - share_create(&s, t); - share_mkshares(&s, r, sec); - for (i = 0; i < t; i++) - v[i] = share_get(&s, MP_NEW, p[i]); - pp = mp_copy(s.p); - share_destroy(&s); - assert(mparena_count(MPARENA_GLOBAL) + mparena_count(MPARENA_SECURE) == t + 2); - - share_create(&s, t); - s.p = pp; - for (i = 0; i < t; i++) - share_add(&s, p[i], v[i]); - ss = share_combine(&s); - share_destroy(&s); - - if (!MP_EQ(sec, ss)) { - ok = 0; - fprintf(stderr, "\nbad recombination of shares\n"); - }; - - mp_drop(sec); - mp_drop(ss); - - for (i = 0; i < t; i++) - mp_drop(v[i]); - - xfree(v); - xfree(p); - - assert(mparena_count(MPARENA_GLOBAL) + mparena_count(MPARENA_SECURE) == 0); - return (ok); -} - -int main(void) -{ - grand *r = fibrand_create(0); - unsigned i; - int ok = 1; - - fputs("share: ", stdout); - for (i = 0; i < 40; i++) { - if (!verify(r)) - ok = 0; - fputc('.', stdout); - fflush(stdout); - } - - if (ok) - fputs(" ok\n", stdout); - else - fputs(" failed\n", stdout); - return (ok ? EXIT_SUCCESS : EXIT_FAILURE); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/share.h b/share.h deleted file mode 100644 index 5500a4c..0000000 --- a/share.h +++ /dev/null @@ -1,179 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Shamir's secret sharing - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the sharing system ---------------------------------------* - * - * Shamir's secret-sharing system is based on polynomial interpolation modulo - * a prime number. It is `perfect' in that fewer participants than the - * threshold can derive no information about the secret by pooling their - * shares, and `ideal' in that the shares are the same size as the secret. - * - * This implementation stays close to the definition, in order to support - * other schemes for (e.g.) threshold cryptography. It is, however, rather - * slow. - */ - -#ifndef CATACOMB_SHARE_H -#define CATACOMB_SHARE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -#ifndef CATACOMB_MP_H -# include "mp.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -/* --- A secret sharing context --- */ - -typedef struct share_pt { - unsigned x; /* Index of this share */ - mp *y; /* Payload of this share */ -} share_pt; - -typedef struct share { - unsigned t; /* Threshold */ - unsigned i; /* Next free slot in the vector */ - mp *p; /* Modulus for arithmetic */ - share_pt *v; /* Vector of share information */ -} share; - -#define SHARE_INIT(t) { t, 0, 0, 0 } - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @share_create@ --- * - * - * Arguments: @share *s@ = pointer to share context to initialize - * @unsigned t@ = threshold for the system - * - * Returns: --- - * - * Use: Initializes a sharing context. - */ - -extern void share_create(share */*s*/, unsigned /*t*/); - -/* --- @share_destroy@ --- * - * - * Arguments: @share *s@ = pointer to share context to destroy - * - * Returns: --- - * - * Use: Disposes of a sharing context. All memory is freed, all - * integers are dropped. - */ - -extern void share_destroy(share */*s*/); - -/* --- @share_mkshares@ --- * - * - * Arguments: @share *s@ = pointer to share context to fill in - * @grand *r@ = pointer to random number source - * @mp *n@ = the secret to share - * - * Returns: --- - * - * Use: Initializes a sharing context to be able to create shares. - * The context structure is expected to be mostly filled in. In - * particular, @t@ must be initialized. If @p@ is zero, a prime - * number of appropriate size is generated automatically. If - * @v@ is zero, a vector of appropriate size is allocated. You - * should use the macro @SHARE_INIT@ or @share_create@ to - * construct sharing contexts. - */ - -extern void share_mkshares(share */*s*/, grand */*r*/, mp */*n*/); - -/* --- @share_get@ --- * - * - * Arguments: @share *s@ = pointer to share conext - * @mp *d@ = destination for the share - * @unsigned x@ = share index to fetch - * - * Returns: The share, as requested. - * - * Use: Extracts a share from the system. You may extract @MPW_MAX@ - * shares, or @s->p@ shares from the system, whichever is - * smaller. Shares are indexed from 0. - */ - -extern mp *share_get(share */*s*/, mp */*d*/, unsigned /*x*/); - -/* --- @share_addedp@ --- * - * - * Arguments: @share *s@ = pointer to sharing context - * @unsigned x@ = which share number to check - * - * Returns: Nonzero if share @x@ has been added already, zero if it - * hasn't. - */ - -extern int share_addedp(share */*s*/, unsigned /*x*/); - -/* --- @share_add@ --- * - * - * Arguments: @share *s@ = pointer to sharing context - * @unsigned x@ = which share number this is - * @mp *y@ = the share value - * - * Returns: Number of shares required before recovery may be performed. - * - * Use: Adds a share to the context. The context must have been - * initialized with the correct prime @p@ and threshold @t@. - */ - -extern unsigned share_add(share */*s*/, unsigned /*x*/, mp */*y*/); - -/* --- @share_combine@ --- * - * - * Arguments: @share *s@ = pointer to share context - * - * Returns: The secret, as a multiprecision integer. - * - * Use: Reconstructs a secret, given enough shares. - */ - -extern mp *share_combine(share */*s*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/skipjack-tab.h b/skipjack-tab.h deleted file mode 100644 index cee075e..0000000 --- a/skipjack-tab.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*-c-*- - * - * $Id: skipjack-tab.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The Skipjack S-box - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_SKIPJACK_TAB_H -#define CATACOMB_SKIPJACK_TAB_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- The S-box ---------------------------------------------------------*/ - -#define SKIPJACK_S { \ - 0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4, \ - 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9, \ - 0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e, \ - 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28, \ - 0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68, \ - 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53, \ - 0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19, \ - 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2, \ - 0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b, \ - 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8, \ - 0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0, \ - 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90, \ - 0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69, \ - 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76, \ - 0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20, \ - 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d, \ - 0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43, \ - 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18, \ - 0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa, \ - 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4, \ - 0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87, \ - 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40, \ - 0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b, \ - 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5, \ - 0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0, \ - 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2, \ - 0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1, \ - 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8, \ - 0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5, \ - 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac, \ - 0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3, \ - 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46 \ -} - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/skipjack.c b/skipjack.c deleted file mode 100644 index d87f22c..0000000 --- a/skipjack.c +++ /dev/null @@ -1,178 +0,0 @@ -/* -*-c-*- - * - * $Id: skipjack.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * The Skipjack block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "skipjack.h" -#include "skipjack-tab.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet skipjack_keysz[] = { KSZ_SET, 10, 0 }; - -/*----- The Skipjack S-box ------------------------------------------------*/ - -static const octet f[256] = SKIPJACK_S; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @skipjack_init@ --- * - * - * Arguments: @skipjack_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a Skipjack key buffer. The key buffer must be - * exactly 10 bytes long. - */ - -void skipjack_init(skipjack_ctx *k, const void *buf, size_t sz) -{ - const octet *b = buf; - uint32 crud; - KSZ_ASSERT(skipjack, sz); - k->ka = LOAD32(b); - k->kb = LOAD32(b + 4); - crud = LOAD16(b + 8); - k->kc = U32((crud << 16) | (k->ka >> 16)); - k->kd = U32((k->ka << 16) | (k->kb >> 16)); - k->ke = U32((k->kb << 16) | crud); - crud = 0; -} - -/* --- @skipjack_eblk@, @skipjack_dblk@ --- * - * - * Arguments: @const skipjack_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to skipjacktination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -#define G(x, k) do { \ - octet _x = U8(x >> 8), _y = U8(x); \ - _x ^= f[_y ^ U8(k >> 24)]; \ - _y ^= f[_x ^ U8(k >> 16)]; \ - _x ^= f[_y ^ U8(k >> 8)]; \ - _y ^= f[_x ^ U8(k >> 0)]; \ - x = (_x << 8) | _y; \ -} while (0) - -#define RULE_A(w, x, y, z, n, k) do { \ - G(w, k); z ^= w ^ n++; \ -} while (0) - -#define RULE_B(w, x, y, z, n, k) do { \ - x ^= w ^ n++; G(w, k); \ -} while (0) - -void skipjack_eblk(const skipjack_ctx *k, const uint32 *s, uint32 *d) -{ - unsigned n = 1; - uint16 w = U16(s[0] >> 16), x = U16(s[0]); - uint16 y = U16(s[1] >> 16), z = U16(s[1]); - uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd, ke = k->ke; - - RULE_A(w, x, y, z, n, ka); RULE_A(z, w, x, y, n, kb); - RULE_A(y, z, w, x, n, kc); RULE_A(x, y, z, w, n, kd); - RULE_A(w, x, y, z, n, ke); RULE_A(z, w, x, y, n, ka); - RULE_A(y, z, w, x, n, kb); RULE_A(x, y, z, w, n, kc); - RULE_B(w, x, y, z, n, kd); RULE_B(z, w, x, y, n, ke); - RULE_B(y, z, w, x, n, ka); RULE_B(x, y, z, w, n, kb); - RULE_B(w, x, y, z, n, kc); RULE_B(z, w, x, y, n, kd); - RULE_B(y, z, w, x, n, ke); RULE_B(x, y, z, w, n, ka); - RULE_A(w, x, y, z, n, kb); RULE_A(z, w, x, y, n, kc); - RULE_A(y, z, w, x, n, kd); RULE_A(x, y, z, w, n, ke); - RULE_A(w, x, y, z, n, ka); RULE_A(z, w, x, y, n, kb); - RULE_A(y, z, w, x, n, kc); RULE_A(x, y, z, w, n, kd); - RULE_B(w, x, y, z, n, ke); RULE_B(z, w, x, y, n, ka); - RULE_B(y, z, w, x, n, kb); RULE_B(x, y, z, w, n, kc); - RULE_B(w, x, y, z, n, kd); RULE_B(z, w, x, y, n, ke); - RULE_B(y, z, w, x, n, ka); RULE_B(x, y, z, w, n, kb); - - d[0] = ((uint32)w << 16) | (uint32)x; - d[1] = ((uint32)y << 16) | (uint32)z; -} - -#define G_INV(x, k) do { \ - octet _x = U8(x >> 8), _y = U8(x); \ - _y ^= f[_x ^ U8(k >> 0)]; \ - _x ^= f[_y ^ U8(k >> 8)]; \ - _y ^= f[_x ^ U8(k >> 16)]; \ - _x ^= f[_y ^ U8(k >> 24)]; \ - x = (_x << 8) | _y; \ -} while (0) - -#define RULE_A_INV(w, x, y, z, n, i) do { \ - w ^= x ^ --n; G_INV(x, i); \ -} while (0) - -#define RULE_B_INV(w, x, y, z, n, i) do { \ - G_INV(x, i); y ^= x ^ --n; \ -} while (0) - -void skipjack_dblk(const skipjack_ctx *k, const uint32 *s, uint32 *d) -{ - unsigned n = 33; - uint16 w = U16(s[0] >> 16), x = U16(s[0]); - uint16 y = U16(s[1] >> 16), z = U16(s[1]); - uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd, ke = k->ke; - - RULE_B_INV(w, x, y, z, n, kb); RULE_B_INV(x, y, z, w, n, ka); - RULE_B_INV(y, z, w, x, n, ke); RULE_B_INV(z, w, x, y, n, kd); - RULE_B_INV(w, x, y, z, n, kc); RULE_B_INV(x, y, z, w, n, kb); - RULE_B_INV(y, z, w, x, n, ka); RULE_B_INV(z, w, x, y, n, ke); - RULE_A_INV(w, x, y, z, n, kd); RULE_A_INV(x, y, z, w, n, kc); - RULE_A_INV(y, z, w, x, n, kb); RULE_A_INV(z, w, x, y, n, ka); - RULE_A_INV(w, x, y, z, n, ke); RULE_A_INV(x, y, z, w, n, kd); - RULE_A_INV(y, z, w, x, n, kc); RULE_A_INV(z, w, x, y, n, kb); - RULE_B_INV(w, x, y, z, n, ka); RULE_B_INV(x, y, z, w, n, ke); - RULE_B_INV(y, z, w, x, n, kd); RULE_B_INV(z, w, x, y, n, kc); - RULE_B_INV(w, x, y, z, n, kb); RULE_B_INV(x, y, z, w, n, ka); - RULE_B_INV(y, z, w, x, n, ke); RULE_B_INV(z, w, x, y, n, kd); - RULE_A_INV(w, x, y, z, n, kc); RULE_A_INV(x, y, z, w, n, kb); - RULE_A_INV(y, z, w, x, n, ka); RULE_A_INV(z, w, x, y, n, ke); - RULE_A_INV(w, x, y, z, n, kd); RULE_A_INV(x, y, z, w, n, kc); - RULE_A_INV(y, z, w, x, n, kb); RULE_A_INV(z, w, x, y, n, ka); - - d[0] = ((uint32)w << 16) | (uint32)x; - d[1] = ((uint32)y << 16) | (uint32)z; -} - -BLKC_TEST(SKIPJACK, skipjack) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/skipjack.h b/skipjack.h deleted file mode 100644 index 0afff1f..0000000 --- a/skipjack.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -*-c-*- - * - * $Id: skipjack.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The Skipjack block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the Skipjack block cipher --------------------------------* - * - * Skipjack was designed by the NSA, as a type II algorithm to be used in the - * Clipper system. It was initially classified, so that it couldn't be used - * without the key escrow feature, though a team of `respectable' - * cryptographers, including Dorothy Denning, had a quick look at it and - * pronounced it `good', as if this was meant to be convincing. It is - * apparently a particular parameterization of a family which includes type I - * algorithms. Since declassification, Biham has discovered a miss-in-the- - * middle attack which breaks Skipjack with 31 rounds faster than brute - * force. - * - * This implementation is provided for interest's sake, and possibly for - * interoperability, rather than as a good cipher to use. - */ - -#ifndef CATACOMB_SKIPJACK_H -#define CATACOMB_SKIPJACK_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magical numbers ---------------------------------------------------*/ - -#define SKIPJACK_BLKSZ 8 -#define SKIPJACK_KEYSZ 10 -#define SKIPJACK_CLASS (N, B, 64) - -extern const octet skipjack_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct skipjack_ctx { - uint32 ka, kb, kc, kd, ke; -} skipjack_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @skipjack_init@ --- * - * - * Arguments: @skipjack_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a Skipjack key buffer. The key buffer must be - * exactly 10 bytes long. - */ - -extern void skipjack_init(skipjack_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @skipjack_eblk@, @skipjack_dblk@ --- * - * - * Arguments: @const skipjack_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to skipjacktination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void skipjack_eblk(const skipjack_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); -extern void skipjack_dblk(const skipjack_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/square-mktab.c b/square-mktab.c deleted file mode 100644 index f1c7f02..0000000 --- a/square-mktab.c +++ /dev/null @@ -1,368 +0,0 @@ -/* -*-c-*- - * - * $Id: square-mktab.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Build precomputed tables for the Square block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include - -/*----- Magic variables ---------------------------------------------------*/ - -static octet s[256], si[256]; -static uint32 t[4][256], ti[4][256]; -static uint32 u[4][256]; -static octet rc[32]; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mul@ --- * - * - * Arguments: @unsigned x, y@ = polynomials over %$\gf{2^8}$% - * @unsigned m@ = modulus - * - * Returns: The product of two polynomials. - * - * Use: Computes a product of polynomials, quite slowly. - */ - -static unsigned mul(unsigned x, unsigned y, unsigned m) -{ - unsigned a = 0; - unsigned i; - - for (i = 0; i < 8; i++) { - if (y & 1) - a ^= x; - y >>= 1; - x <<= 1; - if (x & 0x100) - x ^= m; - } - - return (a); -} - -/* --- @sbox@ --- * - * - * Build the S-box. - * - * This is built from inversion in the multiplicative group of - * %$\gf{2^8}[x]/(p(x))$%, where %$p(x) = x^8+x^7+x^6+x^5+x^4+x^2+1$%, - * followed by an affine transformation treating inputs as vectors over - * %$\gf{2}$%. The result is a horrible function. - * - * The inversion is done slightly sneakily, by building log and antilog - * tables. Let %$a$% be an element of the finite field. If the inverse of - * %$a$% is %$a^{-1}$%, then %$\log a a^{-1} = 0$%. Hence - * %$\log a = -\log a^{-1}$%. This saves fiddling about with Euclidean - * algorithm. - */ - -#define S_MOD 0x1f5 - -static void sbox(void) -{ - octet log[256], alog[256]; - unsigned x; - unsigned i; - unsigned g; - - /* --- Find a suitable generator, and build log tables --- */ - - log[0] = 0; - for (g = 2; g < 256; g++) { - x = 1; - for (i = 0; i < 256; i++) { - log[x] = i; - alog[i] = x; - x = mul(x, g, S_MOD); - if (x == 1 && i != 254) - goto again; - } - goto done; - again:; - } - fprintf(stderr, "couldn't find generator\n"); - exit(EXIT_FAILURE); -done:; - - /* --- Now grind through and do the affine transform --- * - * - * The matrix multiply is an AND and a parity op. The add is an XOR. - */ - - for (i = 0; i < 256; i++) { - unsigned j; - octet m[] = { 0xd6, 0x7b, 0x3d, 0x1f, 0x0f, 0x05, 0x03, 0x01 }; - unsigned v = i ? alog[255 - log[i]] : 0; - - assert(i == 0 || mul(i, v, S_MOD) == 1); - - x = 0; - for (j = 0; j < 8; j++) { - unsigned r; - r = v & m[j]; - r = (r >> 4) ^ r; - r = (r >> 2) ^ r; - r = (r >> 1) ^ r; - x = (x << 1) | (r & 1); - } - x ^= 0xb1; - s[i] = x; - si[x] = i; - } -} - -/* --- @tbox@ --- * - * - * Construct the t tables for doing the round function efficiently. - */ - -static void tbox(void) -{ - unsigned i; - - for (i = 0; i < 256; i++) { - uint32 a, b, c, d; - uint32 w; - - /* --- Build a forwards t-box entry --- */ - - a = s[i]; - b = a << 1; if (b & 0x100) b ^= S_MOD; - c = a ^ b; - w = (b << 0) | (a << 8) | (a << 16) | (c << 24); - t[0][i] = w; - t[1][i] = ROL32(w, 8); - t[2][i] = ROL32(w, 16); - t[3][i] = ROL32(w, 24); - - /* --- Build a backwards t-box entry --- */ - - a = mul(si[i], 0x0e, S_MOD); - b = mul(si[i], 0x09, S_MOD); - c = mul(si[i], 0x0d, S_MOD); - d = mul(si[i], 0x0b, S_MOD); - w = (a << 0) | (b << 8) | (c << 16) | (d << 24); - ti[0][i] = w; - ti[1][i] = ROL32(w, 8); - ti[2][i] = ROL32(w, 16); - ti[3][i] = ROL32(w, 24); - } -} - -/* --- @ubox@ --- * - * - * Construct the tables for performing the key schedule. - */ - -static void ubox(void) -{ - unsigned i; - - for (i = 0; i < 256; i++) { - uint32 a, b, c; - uint32 w; - a = i; - b = a << 1; if (b & 0x100) b ^= S_MOD; - c = a ^ b; - w = (b << 0) | (a << 8) | (a << 16) | (c << 24); - u[0][i] = w; - u[1][i] = ROL32(w, 8); - u[2][i] = ROL32(w, 16); - u[3][i] = ROL32(w, 24); - } -} - -/* --- Round constants --- */ - -void rcon(void) -{ - unsigned r = 1; - int i; - - for (i = 0; i < sizeof(rc); i++) { - rc[i] = r; - r <<= 1; - if (r & 0x100) - r ^= S_MOD; - } -} - -/* --- @main@ --- */ - -int main(void) -{ - int i, j; - - puts("\ -/* -*-c-*-\n\ - *\n\ - * Square tables [generated]\n\ - */\n\ -\n\ -#ifndef CATACOMB_SQUARE_TAB_H\n\ -#define CATACOMB_SQUARE_TAB_H\n\ -"); - - /* --- Write out the S-box --- */ - - sbox(); - fputs("\ -/* --- The byte substitution and its inverse --- */\n\ -\n\ -#define SQUARE_S { \\\n\ - ", stdout); - for (i = 0; i < 256; i++) { - printf("0x%02x", s[i]); - if (i == 255) - fputs(" \\\n}\n\n", stdout); - else if (i % 8 == 7) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - fputs("\ -#define SQUARE_SI { \\\n\ - ", stdout); - for (i = 0; i < 256; i++) { - printf("0x%02x", si[i]); - if (i == 255) - fputs(" \\\n}\n\n", stdout); - else if (i % 8 == 7) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - /* --- Write out the big t tables --- */ - - tbox(); - fputs("\ -/* --- The big round tables --- */\n\ -\n\ -#define SQUARE_T { \\\n\ - { ", stdout); - for (j = 0; j < 4; j++) { - for (i = 0; i < 256; i++) { - printf("0x%08x", t[j][i]); - if (i == 255) { - if (j == 3) - fputs(" } \\\n}\n\n", stdout); - else - fputs(" }, \\\n\ - \\\n\ - { ", stdout); - } else if (i % 4 == 3) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - } - - fputs("\ -#define SQUARE_TI { \\\n\ - { ", stdout); - for (j = 0; j < 4; j++) { - for (i = 0; i < 256; i++) { - printf("0x%08x", ti[j][i]); - if (i == 255) { - if (j == 3) - fputs(" } \\\n}\n\n", stdout); - else - fputs(" }, \\\n\ - \\\n\ - { ", stdout); - } else if (i % 4 == 3) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - } - - /* --- Write out the big u tables --- */ - - ubox(); - fputs("\ -/* --- The key schedule tables --- */\n\ -\n\ -#define SQUARE_U { \\\n\ - { ", stdout); - for (j = 0; j < 4; j++) { - for (i = 0; i < 256; i++) { - printf("0x%08x", u[j][i]); - if (i == 255) { - if (j == 3) - fputs(" } \\\n}\n\n", stdout); - else - fputs(" }, \\\n\ - \\\n\ - { ", stdout); - } else if (i % 4 == 3) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - } - - /* --- Round constants --- */ - - rcon(); - fputs("\ -/* --- The round constants --- */\n\ -\n\ -#define SQUARE_RCON { \\\n\ - ", stdout); - for (i = 0; i < sizeof(rc); i++) { - printf("0x%02x", rc[i]); - if (i == sizeof(rc) - 1) - fputs(" \\\n}\n\n", stdout); - else if (i % 8 == 7) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - /* --- Done --- */ - - puts("#endif"); - - if (fclose(stdout)) { - fprintf(stderr, "error writing data\n"); - exit(EXIT_FAILURE); - } - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/square.c b/square.c deleted file mode 100644 index 6ed8d86..0000000 --- a/square.c +++ /dev/null @@ -1,196 +0,0 @@ -/* -*-c-*- - * - * $Id: square.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The Square block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "paranoia.h" -#include "square.h" -#include "square-tab.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet square_keysz[] = { KSZ_RANGE, SQUARE_KEYSZ, 4, 16, 4 }; - -/*----- Constant tables ---------------------------------------------------*/ - -static const octet S[256] = SQUARE_S, SI[256] = SQUARE_SI; -static const uint32 T[4][256] = SQUARE_T, TI[4][256] = SQUARE_TI; -static const uint32 U[4][256] = SQUARE_U; -static const octet rcon[] = SQUARE_RCON; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @square_init@ --- * - * - * Arguments: @square_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Initializes a Square context with a particular key. Square - * keys must be a multiple of 32 bits long, and may be at most - * 128 bits. - */ - -void square_init(square_ctx *k, const void *buf, size_t sz) -{ - unsigned nk, nr, nw; - unsigned i, j, jj; - const octet *p; - uint32 ww; - uint32 kk[SQUARE_KWORDS]; - - /* --- Sort out the key size --- */ - - KSZ_ASSERT(square, sz); - nk = sz / 4; - - /* --- Fetch the first key words out --- */ - - p = buf; - for (i = 0; i < nk; i++) { - kk[i] = LOAD32_L(p); - p += 4; - } - nr = 8; - - /* --- Expand this material to fill the rest of the table --- */ - - nw = (nr + 1) * 4; - ww = kk[i - 1]; - p = rcon; - for (; i < nw; i++) { - uint32 w = kk[i - nk]; - if (i % nk == 0) { - ww = ROR32(ww, 8); - w ^= ww ^ *p++; - } else - w ^= ww; - kk[i] = ww = w; - } - - /* --- Make the encryption and decryption keys --- */ - - for (i = 0; i < nr * 4; i++) { - uint32 w = kk[i]; - k->w[i] = (U[0][U8(w >> 0)] ^ U[1][U8(w >> 8)] ^ - U[2][U8(w >> 16)] ^ U[3][U8(w >> 24)]); - } - for (; i < nw; i++) - k->w[i] = kk[i]; - - jj = nw; - for (i = 0; i < nr * 4; i += 4) { - jj -= 4; - for (j = 0; j < 4; j++) - k->wi[i + j] = kk[jj + j]; - } - for (j = 0; j < 4; j++) - k->wi[i + j] = k->w[j]; - - BURN(kk); -} - -/* --- @square_eblk@, @square_dblk@ --- * - * - * Arguments: @const square_ctx *k@ = pointer to Square context - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -#define SUB(s, sh, a, b, c, d) \ - (s[U8((a) >> sh)] << 0 | s[U8((b) >> sh)] << 8 | \ - s[U8((c) >> sh)] << 16 | s[U8((d) >> sh)] << 24) - -#define MIX(t, sh, a, b, c, d) \ - (t[0][U8((a) >> sh)] ^ t[1][U8((b) >> sh)] ^ \ - t[2][U8((c) >> sh)] ^ t[3][U8((d) >> sh)]) - -#define DO(what, t, aa, bb, cc, dd, a, b, c, d, w) do { \ - aa = what(t, 0, a, b, c, d) ^ *w++; \ - bb = what(t, 8, a, b, c, d) ^ *w++; \ - cc = what(t, 16, a, b, c, d) ^ *w++; \ - dd = what(t, 24, a, b, c, d) ^ *w++; \ -} while (0) - -void square_eblk(const square_ctx *k, const uint32 *s, uint32 *dst) -{ - uint32 a = s[0], b = s[1], c = s[2], d = s[3]; - uint32 aa, bb, cc, dd; - const uint32 *w = k->w; - - a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; - - DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); - DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); - DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); - DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); - DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); - DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); - DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); - DO(SUB, S, a, b, c, d, aa, bb, cc, dd, w); - - dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; -} - -void square_dblk(const square_ctx *k, const uint32 *s, uint32 *dst) -{ - uint32 a = s[0], b = s[1], c = s[2], d = s[3]; - uint32 aa, bb, cc, dd; - const uint32 *w = k->wi; - - a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; - - DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); - DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); - DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); - DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); - DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); - DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); - DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); - DO(SUB, SI, a, b, c, d, aa, bb, cc, dd, w); - - dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; -} - -BLKC_TEST(SQUARE, square) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/square.h b/square.h deleted file mode 100644 index 60a0876..0000000 --- a/square.h +++ /dev/null @@ -1,114 +0,0 @@ -/* -*-c-*- - * - * $Id: square.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The Square block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the Square block cipher ----------------------------------* - * - * Invented by Joan Daemen and Vincent Rijmen, Square is a fast and - * relatively simple 128-bit block cipher. It is the predecessor to - * Rijndael. I have grave doubts about the security of Square, though: a - * dedicated attack against Square's structure by Knudsen has been extended - * by the Twofish team against Rijndael, and I believe that this extended - * attack is also effective against Square. This is a shame: the structure - * of Square (and Rijndael) is extremely elegant, and has some extremely nice - * properties. - */ - -#ifndef CATACOMB_SQUARE_H -#define CATACOMB_SQUARE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magical numbers ---------------------------------------------------*/ - -#define SQUARE_BLKSZ 16 -#define SQUARE_KEYSZ 16 -#define SQUARE_CLASS (N, L, 128) - -extern const octet square_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -#define SQUARE_MAXROUNDS 8 -#define SQUARE_KWORDS ((SQUARE_MAXROUNDS + 1) * (SQUARE_BLKSZ / 4)) - -typedef struct square_ctx { - uint32 w[SQUARE_KWORDS]; - uint32 wi[SQUARE_KWORDS]; -} square_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @square_init@ --- * - * - * Arguments: @square_ctx *k@ = pointer to context to initialize - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of the key material - * - * Returns: --- - * - * Use: Initializes a Square context with a particular key. This - * implementation of Square doesn't impose any particular - * limits on the key size except that it must be multiple of 4 - * bytes long. 256 bits seems sensible, though. - */ - -extern void square_init(square_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @square_eblk@, @square_dblk@ --- * - * - * Arguments: @const square_ctx *k@ = pointer to Square context - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void square_eblk(const square_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); -extern void square_dblk(const square_ctx */*k*/, - const uint32 */*s*/, uint32 */*dst*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/sslprf.c b/sslprf.c deleted file mode 100644 index 866ef89..0000000 --- a/sslprf.c +++ /dev/null @@ -1,358 +0,0 @@ -/* -*-c-*- - * - * $Id: sslprf.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The SSL pseudo-random function - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include "arena.h" -#include "ghash.h" -#include "grand.h" -#include "paranoia.h" -#include "sslprf.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @step@ --- * - * - * Arguments: @sslprf_ctx *c@ = pointer to context structure - * - * Returns: --- - * - * Use: Steps the generator. - */ - -static void step(sslprf_ctx *c) -{ - octet buf[64]; - size_t n, sz; - octet x; - ghash *h, *hh; - octet *p; - - h = GH_INIT(c->ci); - x = 'A' + c->i - 1; - for (sz = c->i++; sz > 0; sz -= n) { - n = sz; - if (n > sizeof(buf)) - n = sizeof(buf); - memset(buf, x, n); - GH_HASH(h, buf, n); - } - GH_HASH(h, c->k, c->ksz); - GH_HASH(h, c->sd, c->sdsz); - p = GH_DONE(h, 0); - - hh = GH_INIT(c->co); - GH_HASH(hh, c->k, c->ksz); - GH_HASH(hh, p, c->ihashsz); - c->p = GH_DONE(hh, 0); - GH_DESTROY(h); - - c->h = hh; - c->sz = c->ohashsz; -} - -/* --- @sslprf_init@ --- * - * - * Arguments: @sslprf_ctx *c@ = pointer to a context structure - * @const gchash *hco, *hci@ = outer and inner hash functions - * @const void *k@ = pointer to secret buffer - * @size_t ksz@ = size of the secret - * @const void *sd@ = pointer to seed buffer - * @size_t sdsz@ = size of the seed - * - * Returns: --- - * - * Use: Initializes an SSL generator context. - */ - -void sslprf_init(sslprf_ctx *c, const gchash *hco, const gchash *hci, - const void *k, size_t ksz, - const void *sd, size_t sdsz) -{ - c->co = hco; c->ci = hci; - c->ohashsz = hco->hashsz; c->ihashsz = hci->hashsz; - c->k = k; c->ksz = ksz; c->sd = sd; c->sdsz = sdsz; - c->i = 1; - step(c); -} - -/* --- @sslprf_encrypt@ --- * - * - * Arguments: @sslprf_ctx *c@ = pointer to a context structure - * @const void *src@ = pointer to source buffer - * @void *dest@ = pointer to destination buffer - * @size_t sz@ = size of the buffers - * - * Returns: --- - * - * Use: Encrypts data using the SSL pseudo-random function. If the - * destination pointer is null, the generator is spun and no - * output is produced; if the source pointer is null, raw output - * from the generator is written; otherwise, the source data is - * XORed with the generator output. - */ - -void sslprf_encrypt(sslprf_ctx *c, const void *src, void *dest, size_t sz) -{ - const octet *s = src; - octet *d = dest; - size_t i, n; - - while (sz) { - if (!c->sz) { - GH_DESTROY(c->h); - step(c); - } - n = c->sz; - if (n > sz) - n = sz; - if (d) { - if (!s) - memcpy(d, c->p, n); - else { - for (i = 0; i < n; i++) d[i] = s[i] ^ c->p[i]; - s += n; - } - d += n; - } - c->p += n; - c->sz -= n; - sz -= n; - } -} - -/* --- @sslprf_free@ --- * - * - * Arguments: @sslprf_ctx@ = pointer to a context - * - * Returns: --- - * - * Use: Frees resources held in an SSL generator context. - */ - -void sslprf_free(sslprf_ctx *c) -{ - GH_DESTROY(c->h); -} - -/* --- Generic random number generator --- */ - -typedef struct grctx { - grand r; - grand_ops ops; - sslprf_ctx prf; -} grctx; - -static void grdestroy(grand *r) -{ - grctx *g = (grctx *)r; - xfree((char *)g->ops.name); - xfree((octet *)g->prf.sd); - sslprf_free(&g->prf); - BURN(*g); - S_DESTROY(g); -} - -static void seed(grctx *g, const void *p, size_t sz) -{ - octet *q; - xfree((octet *)g->prf.sd); - g->prf.sd = q = xmalloc(sz); - memcpy(q, p, sz); - g->prf.sdsz = sz; -} - -static int grmisc(grand *r, unsigned op, ...) -{ - grctx *g = (grctx *)r; - va_list ap; - int rc = 0; - uint32 i; - octet buf[4]; - va_start(ap, op); - - switch (op) { - case GRAND_CHECK: - switch (va_arg(ap, unsigned)) { - case GRAND_CHECK: - case GRAND_SEEDINT: - case GRAND_SEEDUINT32: - case GRAND_SEEDBLOCK: - case GRAND_SEEDRAND: - rc = 1; - break; - default: - rc = 0; - break; - } - break; - case GRAND_SEEDINT: - i = va_arg(ap, unsigned); - STORE32(buf, i); - seed(g, buf, sizeof(buf)); - break; - case GRAND_SEEDUINT32: - i = va_arg(ap, uint32); - STORE32(buf, i); - seed(g, buf, sizeof(buf)); - break; - case GRAND_SEEDBLOCK: { - const void *p = va_arg(ap, const void *); - size_t sz = va_arg(ap, size_t); - seed(g, p, sz); - } break; - case GRAND_SEEDRAND: { - grand *rr = va_arg(ap, grand *); - octet buf[16]; - rr->ops->fill(rr, buf, sizeof(buf)); - seed(g, buf, sizeof(buf)); - } break; - default: - GRAND_BADOP; - break; - } - - va_end(ap); - return (rc); -} - -static octet grbyte(grand *r) -{ - grctx *g = (grctx *)r; - octet o; - sslprf_encrypt(&g->prf, 0, &o, 1); - return (o); -} - -static uint32 grword(grand *r) -{ - grctx *g = (grctx *)r; - octet b[4]; - sslprf_encrypt(&g->prf, 0, &b, sizeof(b)); - return (LOAD32(b)); -} - -static void grfill(grand *r, void *p, size_t sz) -{ - grctx *g = (grctx *)r; - sslprf_encrypt(&g->prf, 0, p, sz); -} - -static const grand_ops grops = { - "", - GRAND_CRYPTO, 0, - grmisc, grdestroy, - grword, grbyte, grword, grand_range, grfill -}; - -/* ---@sslprf_rand@ --- * - * - * Arguments: @const gchash *hco, const gchash *hci@ = hash functions - * @const void *k@ = pointer to the key material - * @size_t ksz@ = size of the key material - * @const void *sd@ = pointer to the seed material - * @size_t sdsz@ = size of the seed material - * - * Returns: Pointer to generic random number generator interface. - * - * Use: Creates a generic generator which does TLS data expansion. - */ - -grand *sslprf_rand(const gchash *hco, const gchash *hci, - const void *k, size_t ksz, - const void *sd, size_t sdsz) -{ - grctx *g = S_CREATE(grctx); - dstr d = DSTR_INIT; - octet *q = xmalloc(sdsz); - memcpy(q, sd, sdsz); - dstr_putf(&d, "sslprf(%s,%s)", hco->name, hci->name); - g->ops = grops; - g->ops.name = xstrdup(d.buf); - g->r.ops = &g->ops; - dstr_destroy(&d); - sslprf_init(&g->prf, hco, hci, k, ksz, q, sdsz); - return (&g->r); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include -#include - -#include -#include - -#include "sha.h" -#include "md5.h" - -static int v_generate(dstr *v) -{ - grand *g; - dstr d = DSTR_INIT; - int ok = 1; - - g = sslprf_rand(&md5, &sha, v[0].buf, v[0].len, v[1].buf, v[1].len); - dstr_ensure(&d, v[2].len); - d.len = v[2].len; - g->ops->fill(g, d.buf, d.len); - g->ops->destroy(g); - if (memcmp(v[2].buf, d.buf, d.len) != 0) { - ok = 0; - printf("\nfail sslprf:" - "\n\tkey = "); - type_hex.dump(&v[0], stdout); - printf("\n\tseed = "); type_hex.dump(&v[1], stdout); - printf("\n\texpected = "); type_hex.dump(&v[2], stdout); - printf("\n\tcalculated = "); type_hex.dump(&d, stdout); - putchar('\n'); - } - return (ok); -} - -static test_chunk defs[] = { - { "sslprf", v_generate, { &type_hex, &type_hex, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, defs, SRCDIR"/tests/sslprf"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/sslprf.h b/sslprf.h deleted file mode 100644 index 136ee07..0000000 --- a/sslprf.h +++ /dev/null @@ -1,137 +0,0 @@ -/* -*-c-*- - * - * $Id: sslprf.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The SSL pseudo-random function - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_SSLPRF_H -#define CATACOMB_SSLPRF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GMAC_H -# include "gmac.h" -#endif - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct sslprf_ctx { - const gchash *co, *ci; /* Outer and inner hash functions */ - size_t ohashsz, ihashsz; /* Size of the hash outputs */ - ghash *h; /* Hash context from last time */ - const octet *k; /* Pointer to the secret */ - size_t ksz; /* Size of the secret buffer */ - const octet *sd; /* Pointer to the seed */ - size_t sdsz; /* Size of the seed buffer */ - unsigned i; /* Which iteration this is */ - octet *p; /* Pointer to output buffer */ - size_t sz; /* How many bytes are left */ -} sslprf_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @sslprf_init@ --- * - * - * Arguments: @sslprf_ctx *c@ = pointer to a context structure - * @const gchash *hco, *hci@ = outer and inner hash functions - * @const void *k@ = pointer to secret buffer - * @size_t ksz@ = size of the secret - * @const void *sd@ = pointer to seed buffer - * @size_t sdsz@ = size of the seed - * - * Returns: --- - * - * Use: Initializes an SSL generator context. - */ - -extern void sslprf_init(sslprf_ctx */*c*/, - const gchash */*hco*/, const gchash */*hci*/, - const void */*k*/, size_t /*ksz*/, - const void */*sd*/, size_t /*sdsz*/); - -/* --- @sslprf_encrypt@ --- * - * - * Arguments: @sslprf_ctx *c@ = pointer to a context structure - * @const void *src@ = pointer to source buffer - * @void *dest@ = pointer to destination buffer - * @size_t sz@ = size of the buffers - * - * Returns: --- - * - * Use: Encrypts data using the SSL pseudo-random function. If the - * destination pointer is null, the generator is spun and no - * output is produced; if the source pointer is null, raw output - * from the generator is written; otherwise, the source data is - * XORed with the generator output. - */ - -extern void sslprf_encrypt(sslprf_ctx */*c*/, - const void */*src*/, void */*dest*/, - size_t /*sz*/); - -/* --- @sslprf_free@ --- * - * - * Arguments: @sslprf_ctx@ = pointer to a context - * - * Returns: --- - * - * Use: Frees resources held in an SSL generator context. - */ - -extern void sslprf_free(sslprf_ctx */*c*/); - -/* ---@sslprf_rand@ --- * - * - * Arguments: @const gchash *hco, const gchash *hci@ = hash functions - * @const void *k@ = pointer to the key material - * @size_t ksz@ = size of the key material - * @const void *sd@ = pointer to the seed material - * @size_t sdsz@ = size of the seed material - * - * Returns: Pointer to generic random number generator interface. - * - * Use: Creates a generic generator which does TLS data expansion. - */ - -extern grand *sslprf_rand(const gchash */*hco*/, const gchash */*hci*/, - const void */*k*/, size_t /*ksz*/, - const void */*sd*/, size_t /*sdsz*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/strongprime.c b/strongprime.c deleted file mode 100644 index 866533d..0000000 --- a/strongprime.c +++ /dev/null @@ -1,206 +0,0 @@ -/* -*-c-*- - * - * $Id: strongprime.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Generate `strong' prime numbers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "grand.h" -#include "rand.h" -#include "mp.h" -#include "mpmont.h" -#include "mprand.h" -#include "pgen.h" -#include "pfilt.h" -#include "rabin.h" - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @strongprime_setup@ --- * - * - * Arguments: @const char *name@ = pointer to name root - * @mp *d@ = destination for search start point - * @pfilt *f@ = where to store filter jump context - * @unsigned nbits@ = number of bits wanted - * @grand *r@ = random number source - * @unsigned n@ = number of attempts to make - * @pgen_proc *event@ = event handler function - * @void *ectx@ = argument for the event handler - * - * Returns: A starting point for a `strong' prime search, or zero. - * - * Use: Sets up for a strong prime search, so that primes with - * particular properties can be found. It's probably important - * to note that the number left in the filter context @f@ is - * congruent to 2 (mod 4). - */ - -mp *strongprime_setup(const char *name, mp *d, pfilt *f, unsigned nbits, - grand *r, unsigned n, pgen_proc *event, void *ectx) -{ - mp *s, *t, *q; - dstr dn = DSTR_INIT; - - mp *rr = d; - pgen_filterctx c; - pgen_jumpctx j; - rabin rb; - - /* --- The bitslop parameter --- * - * - * There's quite a lot of prime searching to be done. The constant - * @BITSLOP@ is a (low) approximation to the base-2 log of the expected - * number of steps to find a prime number. Experimentation shows that - * numbers around 10 seem to be good. - */ - -#define BITSLOP 12 - - /* --- Choose two primes %$s$% and %$t$% of half the required size --- */ - - assert(((void)"nbits too small in strongprime_setup", nbits/2 > BITSLOP)); - nbits = nbits/2 - BITSLOP; - c.step = 1; - - rr = mprand(rr, nbits, r, 1); - DRESET(&dn); dstr_putf(&dn, "%s [s]", name); - if ((s = pgen(dn.buf, MP_NEWSEC, rr, event, ectx, n, pgen_filter, &c, - rabin_iters(nbits), pgen_test, &rb)) == 0) - goto fail_s; - - rr = mprand(rr, nbits, r, 1); - DRESET(&dn); dstr_putf(&dn, "%s [t]", name); - if ((t = pgen(dn.buf, MP_NEWSEC, rr, event, ectx, n, pgen_filter, &c, - rabin_iters(nbits), pgen_test, &rb)) == 0) - goto fail_t; - - /* --- Choose a suitable value for %$r = 2it + 1$% for some %$i$% --- */ - - rr = mp_lsl(rr, t, 1); - pfilt_create(&c.f, rr); - rr = mp_lsl(rr, rr, BITSLOP - 1); - rr = mp_add(rr, rr, MP_ONE); - DRESET(&dn); dstr_putf(&dn, "%s [r]", name); - j.j = &c.f; - nbits += BITSLOP; - q = pgen(dn.buf, MP_NEW, rr, event, ectx, n, pgen_jump, &j, - rabin_iters(nbits), pgen_test, &rb); - pfilt_destroy(&c.f); - if (!q) - goto fail_r; - - /* --- Select a suitable starting-point for finding %$p$% --- * - * - * This computes %$p_0 = 2(s^{r - 2} \bmod r)s - 1$%. - */ - - { - mpmont mm; - - mpmont_create(&mm, q); - rr = mp_sub(rr, q, MP_TWO); - rr = mpmont_exp(&mm, rr, s, rr); - mpmont_destroy(&mm); - rr = mp_mul(rr, rr, s); - rr = mp_lsl(rr, rr, 1); - rr = mp_sub(rr, rr, MP_ONE); - } - - /* --- Now find %$p = p_0 + 2jrs$% for some %$j$% --- */ - - { - mp *x; - x = mp_mul(MP_NEW, q, s); - x = mp_lsl(x, x, 1); - pfilt_create(f, x); - x = mp_lsl(x, x, BITSLOP - 1); - rr = mp_add(rr, rr, x); - mp_drop(x); - } - - /* --- Return the result --- */ - - mp_drop(q); - mp_drop(t); - mp_drop(s); - dstr_destroy(&dn); - return (rr); - - /* --- Tidy up if something failed --- */ - -fail_r: - mp_drop(t); -fail_t: - mp_drop(s); -fail_s: - mp_drop(rr); - dstr_destroy(&dn); - return (0); - -#undef BITSLOP -} - -/* --- @strongprime@ --- * - * - * Arguments: @const char *name@ = pointer to name root - * @mp *d@ = destination integer - * @unsigned nbits@ = number of bits wanted - * @grand *r@ = random number source - * @unsigned n@ = number of attempts to make - * @pgen_proc *event@ = event handler function - * @void *ectx@ = argument for the event handler - * - * Returns: A `strong' prime, or zero. - * - * Use: Finds `strong' primes. A strong prime %$p$% is such that - * - * * %$p - 1$% has a large prime factor %$r$%, - * * %$p + 1$% has a large prime factor %$s$%, and - * * %$r - 1$% has a large prime factor %$t$%. - * - * The numbers produced may be slightly larger than requested, - * by a few bits. - */ - -mp *strongprime(const char *name, mp *d, unsigned nbits, grand *r, - unsigned n, pgen_proc *event, void *ectx) -{ - pfilt f; - pgen_jumpctx j; - rabin rb; - - d = strongprime_setup(name, d, &f, nbits, r, n, event, ectx); - j.j = &f; - d = pgen(name, d, d, event, ectx, n, pgen_jump, &j, - rabin_iters(nbits), pgen_test, &rb); - pfilt_destroy(&f); - return (d); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/strongprime.h b/strongprime.h deleted file mode 100644 index 1986d80..0000000 --- a/strongprime.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -*-c-*- - * - * $Id: strongprime.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * Generate `strong' prime numbers - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_STRONGPRIME_H -#define CATACOMB_STRONGPRIME_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -#ifndef CATACOMB_PGEN_H -# include "pgen.h" -#endif - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @strongprime_setup@ --- * - * - * Arguments: @const char *name@ = pointer to name root - * @mp *d@ = destination for search start point - * @pfilt *f@ = where to store filter jump context - * @unsigned nbits@ = number of bits wanted - * @grand *r@ = random number source - * @unsigned n@ = number of attempts to make - * @pgen_proc *event@ = event handler function - * @void *ectx@ = argument for the event handler - * - * Returns: A starting point for a `strong' prime search, or zero. - * - * Use: Sets up for a strong prime search, so that primes with - * particular properties can be found. It's probably important - * to note that the number left in the filter context @f@ is - * congruent to 2 (mod 4). - */ - -extern mp *strongprime_setup(const char */*name*/, mp */*d*/, pfilt */*f*/, - unsigned /*nbits*/, grand */*r*/, - unsigned /*n*/, pgen_proc */*event*/, - void */*ectx*/); - -/* --- @strongprime@ --- * - * - * Arguments: @const char *name@ = pointer to name root - * @mp *d@ = destination integer - * @unsigned nbits@ = number of bits wanted - * @grand *r@ = random number source - * @unsigned n@ = number of attempts to make - * @pgen_proc *event@ = event handler function - * @void *ectx@ = argument for the event handler - * - * Returns: A `strong' prime, or zero. - * - * Use: Finds `strong' primes. A strong prime %$p$% is such that - * - * * %$p - 1$% has a large prime factor %$r$%, - * * %$p + 1$% has a large prime factor %$s$%, and - * * %$r - 1$% has a large prime factor %$t$%. - * - * The numbers produced may be slightly larger than requested, - * by a few bits. - */ - -extern mp *strongprime(const char */*name*/, mp */*d*/, unsigned /*nbits*/, - grand */*r*/, unsigned /*n*/, - pgen_proc */*event*/, void */*ectx*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/symm/Makefile.am b/symm/Makefile.am new file mode 100644 index 0000000..9c2895b --- /dev/null +++ b/symm/Makefile.am @@ -0,0 +1,401 @@ +### -*-makefile-*- +### +### Build script for symmetric cryptography +### +### (c) 2013 Straylight/Edgeware +### + +###----- Licensing notice --------------------------------------------------- +### +### This file is part of Catacomb. +### +### Catacomb is free software; you can redistribute it and/or modify +### it under the terms of the GNU Library General Public License as +### published by the Free Software Foundation; either version 2 of the +### License, or (at your option) any later version. +### +### Catacomb is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU Library General Public License for more details. +### +### You should have received a copy of the GNU Library General Public +### License along with Catacomb; if not, write to the Free +### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +### MA 02111-1307, USA. + +include $(top_srcdir)/vars.am + +noinst_LTLIBRARIES = libsymm.la +libsymm_la_SOURCES = +nodist_libsymm_la_SOURCES = + +TEST_LIBS = libsymm.la + +VPATH += modes + +###-------------------------------------------------------------------------- +### Autogenerated lists. + +## Fancy template substitutions. +multigen = $(PYTHON) $(srcdir)/multigen +EXTRA_DIST += multigen + +## The heart of this is an enormous cross-product of crypto primitives and +## the corresponding modes of operation. Rather than write it out longhand, +## we generate it using `multigen'. Unfortunately, this needs to be done +## at the Automake level, which causes some interesting bootstrapping +## problems. +include modes.am + +EXTRA_DIST += modes.am.in modes.am +MAINTAINERCLEANFILES += $(srcdir)/modes.am + +## Generate the lists. +$(srcdir)/modes.am: modes.am.in + $(AM_V_GEN)$(multigen) -g $(srcdir)/modes.am.in $(srcdir)/modes.am \ + blkc="$(BLKCS)" \ + blkcmode="$(BLKCMODES)" \ + blkcciphermode="$(BLKCCIPHERMODES)" \ + hash="$(HASHES)" \ + hashmode="$(HASHMODES)" \ + hashciphermode="$(HASHCIPHERMODES)" \ + hashmacmode="$(HASHMACMODES)" + +## Initialize lists of known classes. +ALL_CIPHERS = $(CIPHER_MODES) +ALL_HASHES = $(HASHES) +ALL_MACS = $(MAC_MODES) + +###-------------------------------------------------------------------------- +### Block ciphers. + +BLKCS = +BLKCMODES = + +BLKCCIPHERMODES = +BLKCMODES += $(BLKCCIPHERMODES) + +## A tool for translating the AES-contest test vectors into a form our test +## rigs understand. +EXTRA_DIST += aes-trans + +## Block cipher utility macros, mainly used in mode implementations. +pkginclude_HEADERS += blkc.h + +## Source code and headers for the block ciphers. +libsymm_la_SOURCES += $(BLKC_C) +pkginclude_HEADERS += $(BLKC_H) + +## Schneier's `Blowfish' block cipher. +BLKCS += blowfish +blowfish.lo: blowfish-tab.h +CLEANFILES += blowfish-tab.h +noinst_PROGRAMS += blowfish-mktab +blowfish_mktab_CPPFLAGS = $(AM_CPPFLAGS) -DQUIET +blowfish-tab.h: blowfish-mktab$e + $(AM_V_GEN)./blowfish-mktab >blowfish-tab.h.new && \ + mv blowfish-tab.h.new blowfish-tab.h + +## Adams and Tavares' `CAST' block ciphers. +BLKCS += cast128 cast256 +libsymm_la_SOURCES += cast-s.c cast-sk.c cast-base.h cast-tab.h +cast256.$t: t/cast256 +EXTRA_DIST += t/cast256.aes +MAINTAINERCLEANFILES += $(srcdir)/t/cast256 +t/cast256: t/cast256.aes + $(AM_V_GEN)$(srcdir)/aes-trans CAST256 \ + <$(srcdir)/t/cast256.aes \ + >$(srcdir)/t/cast256.new && \ + mv $(srcdir)/t/cast256.new $(srcdir)/t/cast256 + +## IBM's `DES' block cipher, by Feistel, Coppersmith, and others. +BLKCS += des des3 +libsymm_la_SOURCES += des-base.h des-base.c desx-tab.h +des-base.lo: des-tab.h +CLEANFILES += des-tab.h +noinst_PROGRAMS += des-mktab +des-tab.h: des-mktab$e + $(AM_V_GEN)./des-mktab >des-tab.h.new && \ + mv des-tab.h.new des-tab.h + +## Rivest's `DESX' variant, with pre- and post-whitening. +BLKCS += desx +libsymm_la_SOURCES += desx-tab.h + +## Lai and Massey's IDEA. +BLKCS += idea + +## IBM's `MARS' block cipher. +BLKCS += mars +mars.lo: mars-tab.h +CLEANFILES += mars-tab.h +noinst_PROGRAMS += mars-mktab +mars-tab.h: mars-mktab$e + $(AM_V_GEN)./mars-mktab >mars-tab.h.new && \ + mv mars-tab.h.new mars-tab.h +mars.$t: t/mars +EXTRA_DIST += t/mars.aes +MAINTAINERCLEANFILES += $(srcdir)/t/mars +t/mars: t/mars.aes + $(AM_V_GEN)$(srcdir)/aes-trans Mars \ + <$(srcdir)/t/mars.aes \ + >$(srcdir)/t/mars.new && \ + mv $(srcdir)/t/mars.new $(srcdir)/t/mars + +## Daemen, Peeters, Van Assche and Rijmen's `Noekeon'. +BLKCS += noekeon + +## Rivest's `RC2' block cipher. +BLKCS += rc2 +libsymm_la_SOURCES += rc2-tab.h + +## Rivest's `RC5'. +BLKCS += rc5 + +## Daemen and Rijmen's `Rijndael' block cipher, selected as AES. +BLKCS += rijndael rijndael192 rijndael256 +libsymm_la_SOURCES += rijndael-base.h rijndael-base.c +rijndael-base.lo: rijndael-tab.h +CLEANFILES += rijndael-tab.h +noinst_PROGRAMS += rijndael-mktab +rijndael-tab.h: rijndael-mktab$e + $(AM_V_GEN)./rijndael-mktab >rijndael-tab.h.new && \ + mv rijndael-tab.h.new rijndael-tab.h +rijndael.$t: t/rijndael +EXTRA_DIST += t/rijndael.aes +MAINTAINERCLEANFILES += $(srcdir)/t/rijndael +t/rijndael: t/rijndael.aes + $(AM_V_GEN)$(srcdir)/aes-trans Rijndael \ + <$(srcdir)/t/rijndael.aes \ + >$(srcdir)/t/rijndael.new && \ + mv $(srcdir)/t/rijndael.new $(srcdir)/t/rijndael + +## Massey's `SAFER' block ciphers. +BLKCS += safer safersk +safer.lo: safer-tab.h +CLEANFILES += safer-tab.h +noinst_PROGRAMS += safer-mktab +safer-tab.h: safer-mktab$e + $(AM_V_GEN)./safer-mktab >safer-tab.h.new && \ + mv safer-tab.h.new safer-tab.h + +## Anderson, Biham and Knudsen's `Serpent' block cipher. +BLKCS += serpent +libsymm_la_SOURCES += serpent-sbox.h +noinst_PROGRAMS += serpent-check +TESTS += serpent-check +serpent.$t: t/serpent +EXTRA_DIST += t/serpent.aes +MAINTAINERCLEANFILES += $(srcdir)/t/serpent +t/serpent: t/serpent.aes + $(AM_V_GEN)$(srcdir)/aes-trans Serpent -v rev=1 \ + <$(srcdir)/t/serpent.aes \ + >$(srcdir)/t/serpent.new && \ + mv $(srcdir)/t/serpent.new $(srcdir)/t/serpent + +## The National Security Agency's `Skipjack' block cipher. You don't want to +## use this. +BLKCS += skipjack +libsymm_la_SOURCES += skipjack-tab.h + +## Daemen and Rijmen's `Square' block cipher. +BLKCS += square +square.lo: square-tab.h +CLEANFILES += square-tab.h +noinst_PROGRAMS += square-mktab +square-tab.h: square-mktab$e + $(AM_V_GEN)./square-mktab >square-tab.h.new && \ + mv square-tab.h.new square-tab.h + +## Wheeler and Needham's `TEA' and `XTEA' block ciphers. +BLKCS += tea xtea + +## Schneier, Kelsey, Whiting, Wagner, Hall and Ferguson's `Twofish' block +## cipher. +BLKCS += twofish +twofish.lo: twofish-tab.h +CLEANFILES += twofish-tab.h +noinst_PROGRAMS += twofish-mktab +twofish-tab.h: twofish-mktab$e + $(AM_V_GEN)./twofish-mktab >twofish-tab.h.new && \ + mv twofish-tab.h.new twofish-tab.h +twofish.$t: t/twofish +EXTRA_DIST += t/twofish.aes +MAINTAINERCLEANFILES += $(srcdir)/t/twofish +t/twofish: t/twofish.aes + $(AM_V_GEN)$(srcdir)/aes-trans Twofish \ + <$(srcdir)/t/twofish.aes \ + >$(srcdir)/t/twofish.new && \ + mv $(srcdir)/t/twofish.new $(srcdir)/t/twofish + +## The old NIST modes for DES. +BLKCCIPHERMODES += cbc cfb ecb ofb + +## Counter mode. +BLKCCIPHERMODES += counter + +###-------------------------------------------------------------------------- +### Hash functions. + +HASHES = +HASHMODES = + +HASHCIPHERMODES = +HASHMODES += $(HASHCIPHERMODES) + +HASHMACMODES = +HASHMODES += $(HASHMACMODES) + +## Common definitions for hash functions. +pkginclude_HEADERS += hash.h + +## Source code and headers for the hash functions. +libsymm_la_SOURCES += $(HASH_C) +pkginclude_HEADERS += $(HASH_H) + +## Lim and KISA's `HAS-160', recommended for use with KCDSA. +HASHES += has160 + +## Rivest's `MD' series of hash functions +HASHES += md2 md4 md5 +libsymm_la_SOURCES += md2-tab.h + +## Dobbertin, Bosselaers and Preneel's `RIPEMD' suite. +HASHES += rmd128 rmd160 rmd256 rmd320 + +## The National Security Agency's `SHA-1' hash function. +HASHES += sha + +## The National Security Agency's `SHA-2' suite. +HASHES += sha224 sha256 +HASHES += sha384 sha512 + +## Anderson and Biham's `Tiger' hash function. +HASHES += tiger +libsymm_la_SOURCES += tiger-base.h +tiger.lo: tiger-tab.h +CLEANFILES += tiger-tab.h +noinst_PROGRAMS += tiger-mktab +tiger-tab.h: tiger-mktab$e + $(AM_V_GEN)./tiger-mktab >tiger-tab.h.new && \ + mv tiger-tab.h.new tiger-tab.h + +## Barreto and Rijmen's `Whirlpool' hash function. +HASHES += whirlpool whirlpool256 +whirlpool.lo: whirlpool-tab.h +CLEANFILES += whirlpool-tab.h +noinst_PROGRAMS += whirlpool-mktab +whirlpool-tab.h: whirlpool-mktab$e + $(AM_V_GEN)./whirlpool-mktab >whirlpool-tab.h.new && \ + mv whirlpool-tab.h.new whirlpool-tab.h + +## Bellare, Canetti and Krawczyk's `HMAC' mode for message authentication. +HASHMACMODES += hmac + +## MGF1, used in OAEP and PSS. +HASHCIPHERMODES += mgf + +###-------------------------------------------------------------------------- +### Other symmetric primitives. + +## The CRC32 algorithm, which is useful, but has no worthwhile security. +pkginclude_HEADERS += crc32.h +libsymm_la_SOURCES += crc32.c +ALL_HASHES += crc32=gcrc32 + +## Rivest's `RC4' stream cipher. +pkginclude_HEADERS += rc4.h +libsymm_la_SOURCES += rc4.c +TESTS += rc4.$t +EXTRA_DIST += t/rc4 +ALL_CIPHERS += rc4 + +## Coppersmith and Rogaway's `SEAL' pseudorandom function. +pkginclude_HEADERS += seal.h +libsymm_la_SOURCES += seal.c +TESTS += seal.$t +EXTRA_DIST += t/seal +ALL_CIPHERS += seal + +###-------------------------------------------------------------------------- +### Autogenerated mode implementations. + +## The master stamp file, indicating that we generated all of the sources. +CLEANFILES += modes/gen-stamp +EXTRA_DIST += mode.h.in mode.c.in +modes/gen-stamp: + $(AM_V_at)$(MKDIR_P) modes + $(AM_V_GEN)$(multigen) -g $(srcdir)/mode.c.in \ + modes/@base-@mode.c \ + base="$(BLKCS)" mode="$(BLKCMODES)" + $(AM_V_at)$(multigen) -g $(srcdir)/mode.h.in \ + modes/@base-@mode.h \ + base="$(BLKCS)" mode="$(BLKCMODES)" + $(AM_V_at)$(multigen) -g $(srcdir)/mode.c.in \ + modes/@base-@mode.c \ + base="$(HASHES)" mode="$(HASHMODES)" + $(AM_V_at)$(multigen) -g $(srcdir)/mode.h.in \ + modes/@base-@mode.h \ + base="$(HASHES)" mode="$(HASHMODES)" + $(AM_V_at)touch modes/gen-stamp + +## The individual mode interfaces and implementations. +pkginclude_HEADERS += $(MODE_H) + +## Generated implementations. +BUILT_SOURCES += $(GENMODES_C) +CLEANFILES += $(GENMODES_C) +nodist_libsymm_la_SOURCES += $(GENMODES_C) +$(GENMODES_C): modes/gen-stamp + +## Generated interfaces. +BUILT_SOURCES += $(GENMODES_H) +CLEANFILES += $(GENMODES_H) +nodist_pkginclude_HEADERS += $(GENMODES_H) +$(GENMODES_H): modes/gen-stamp + +###-------------------------------------------------------------------------- +### Tables of classes for encryption, hashing, and message authentication. + +## The skeleton for the class tables. +EXTRA_DIST += gthingtab.c.in + +## Table of cipher classes. +pkginclude_HEADERS += gcipher.h +CLEANFILES += gciphertab.c +nodist_libsymm_la_SOURCES += gciphertab.c +gciphertab.c: gthingtab.c.in + $(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in gciphertab.c \ + what=gcipher cls=gccipher thing="$(ALL_CIPHERS)" + +## Table of hash classes. +pkginclude_HEADERS += ghash.h ghash-def.h +CLEANFILES += ghashtab.c +nodist_libsymm_la_SOURCES += ghashtab.c +ghashtab.c: gthingtab.c.in + $(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in ghashtab.c \ + what=ghash cls=gchash thing="$(ALL_HASHES)" + +## Table of MAC classes. +pkginclude_HEADERS += gmac.h +CLEANFILES += gmactab.c +nodist_libsymm_la_SOURCES += gmactab.c +gmactab.c: gthingtab.c.in + $(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in gmactab.c \ + what=gmac cls=gcmac thing="$(ALL_MACS)" + +###-------------------------------------------------------------------------- +### Testing. + +## Run the test programs. +TESTS += $(SYMM_TESTS) +EXTRA_DIST += $(SYMM_TEST_FILES) + +## A piece of sample text for round-trip testing encryption modes. +EXTRA_DIST += daftstory.h + +## Clean the debris from the `modes' subdirectory. +CLEANFILES += modes/*.to modes/*.$t + +###----- That's all, folks -------------------------------------------------- diff --git a/tests/aes-trans b/symm/aes-trans similarity index 100% rename from tests/aes-trans rename to symm/aes-trans diff --git a/symm/blkc.h b/symm/blkc.h new file mode 100644 index 0000000..d6e3da0 --- /dev/null +++ b/symm/blkc.h @@ -0,0 +1,345 @@ +/* -*-c-*- + * + * Common definitions for block ciphers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_BLKC_H +#define CATACOMB_BLKC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Theory of operation -----------------------------------------------* + * + * A block cipher has associated with it a triple, called PRE_CLASS, of the + * form `(TYPE, ENDIAN, BITS)', where TYPE is either `N' (representing an + * implemented bit size) or `X' (representing an unimplemented bit size, + * causing loops to be compiled rather than unrolled code), ENDIAN is `B' + * (big) or `L' (little), and BITS is the block size of the cipher in bits. + */ + +/*----- Data movement macros ----------------------------------------------*/ + +/* + * `The C preprocessor. You will never find a more wretched hive of bogus + * hackery. We must be cautious.' + */ + +/* --- General dispatch macros --- */ + +#define BLKC_DOGLUE(x, y) x ## y +#define BLKC_GLUE(x, y) BLKC_DOGLUE(x, y) +#define BLKC_APPLY(f, x) f x +#define BLKC_FIRST(x, y, z) x +#define BLKC_SECOND(x, y, z) y +#define BLKC_THIRD(x, y, z) z +#define BLKC_TYPE(PRE) BLKC_APPLY(BLKC_FIRST, PRE##_CLASS) +#define BLKC_ENDIAN(PRE) BLKC_APPLY(BLKC_SECOND, PRE##_CLASS) +#define BLKC_BITS(PRE) BLKC_APPLY(BLKC_THIRD, PRE##_CLASS) + +#define BLKC_STORE_E(PRE) BLKC_GLUE(STORE32_, BLKC_ENDIAN(PRE)) +#define BLKC_LOAD_E(PRE) BLKC_GLUE(LOAD32_, BLKC_ENDIAN(PRE)) + +/* --- Interface macros --- */ + +#define BLKC_STORE(PRE, b, w) \ + BLKC_GLUE(BLKC_STORE_, BLKC_TYPE(PRE)) \ + (PRE, b, w, BLKC_STORE_E(PRE), BLKC_BITS(PRE)) + +#define BLKC_XSTORE(PRE, b, w, wx) \ + BLKC_GLUE(BLKC_XSTORE_, BLKC_TYPE(PRE)) \ + (PRE, b, w, wx, BLKC_STORE_E(PRE), BLKC_BITS(PRE)) + +#define BLKC_LOAD(PRE, w, b) \ + BLKC_GLUE(BLKC_LOAD_, BLKC_TYPE(PRE)) \ + (PRE, w, b, BLKC_LOAD_E(PRE), BLKC_BITS(PRE)) + +#define BLKC_XLOAD(PRE, w, b) \ + BLKC_GLUE(BLKC_XLOAD_, BLKC_TYPE(PRE)) \ + (PRE, w, b, BLKC_LOAD_E(PRE), BLKC_BITS(PRE)) + +#define BLKC_MOVE(PRE, w, wx) \ + BLKC_GLUE(BLKC_MOVE_, BLKC_TYPE(PRE)) \ + (PRE, w, wx, BLKC_BITS(PRE)) + +#define BLKC_XMOVE(PRE, w, wx) \ + BLKC_GLUE(BLKC_XMOVE_, BLKC_TYPE(PRE)) \ + (PRE, w, wx, BLKC_BITS(PRE)) + +#define BLKC_STEP(PRE, w) \ + BLKC_GLUE(BLKC_STEP_X_, BLKC_ENDIAN(PRE)) \ + (PRE, w) + +#define BLKC_ZERO(PRE, w) \ + BLKC_GLUE(BLKC_ZERO_, BLKC_TYPE(PRE)) \ + (PRE, w, BLKC_BITS(PRE)) + +#define BLKC_SET(PRE, w, x) \ + BLKC_GLUE(BLKC_SET_X_, BLKC_ENDIAN(PRE)) \ + (PRE, w, x) + +#define BLKC_SHOW(PRE, tag, w) do { \ + fputs(tag ": ", stdout); \ + BLKC_SKEL_X(PRE, BLKC_W(w);, printf("%08x ", *_w++);); \ + fputc('\n', stdout); \ +} while (0) + +/* --- General implementation skeleton --- */ + +#define BLKC_SKEL(PRE, decl, guts) do { \ + decl \ + guts \ +} while (0) + +#define BLKC_P(p) register octet *_p = (octet *)(p) +#define BLKC_W(w) register uint32 *_w = (w) +#define BLKC_WX(wx) register uint32 *_wx = (wx) + +/* --- Implementation for unusual block sizes --- */ + +#define BLKC_SKEL_X(PRE, decl, guts) \ + BLKC_SKEL(PRE, unsigned _i; decl, \ + for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) { \ + guts \ + }) + +#define BLKC_STORE_X(PRE, b, w, op, n) \ + BLKC_SKEL_X(PRE, BLKC_P(b); const BLKC_W(w);, \ + op(_p, *_w); _p += 4; _w++; ) + +#define BLKC_XSTORE_X(PRE, b, w, wx, op, n) \ + BLKC_SKEL_X(PRE, BLKC_P(b); const BLKC_W(w); const BLKC_WX(wx);, \ + op(_p, *_w ^ *_wx); _p += 4; _w++; _wx++; ) + +#define BLKC_LOAD_X(PRE, w, b, op, n) \ + BLKC_SKEL_X(PRE, const BLKC_P(b); BLKC_W(w);, \ + *_w = op(_p); _p += 4; _w++; ) + +#define BLKC_XLOAD_X(PRE, w, b, op, n) \ + BLKC_SKEL_X(PRE, const BLKC_P(b); BLKC_W(w);, \ + *_w ^= op(_p); _p += 4; _w++; ) + +#define BLKC_MOVE_X(PRE, w, wx, n) \ + BLKC_SKEL_X(PRE, BLKC_W(w); const BLKC_WX(wx);, \ + *_w = *_wx; _w++; _wx++; ) \ + +#define BLKC_XMOVE_X(PRE, w, wx, n) \ + BLKC_SKEL_X(PRE, BLKC_W(w); const BLKC_WX(wx);, \ + *_w ^= *_wx; _w++; _wx++; ) \ + +#define BLKC_ZERO_X(PRE, w, n) \ + BLKC_SKEL_X(PRE, BLKC_W(w);, *_w++ = 0;) + +#define BLKC_STEP_X_B(PRE, w) do { \ + unsigned _i = PRE##_BLKSZ / 4; BLKC_W(w); uint32 _x = 0; \ + while (_i && !_x) { _i--; _w[_i] = _x = U32(_w[_i] + 1); } \ +} while (0) + +#define BLKC_STEP_X_L(PRE, w) do { \ + unsigned _i = 0; BLKC_W(w); uint32 _x = 0; \ + while (_i < PRE##_BLKSZ / 4 && !_x) \ + { _w[_i] = _x = U32(_w[_i] + 1); _i++; } \ +} while (0) + +#define BLKC_SET_X_B(PRE, w, x) do { \ + unsigned _i; BLKC_W(w); unsigned long _x = x; \ + for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) { \ + *_w++ = U32(_x); \ + _x = ((_x & ~MASK32) >> 16) >> 16; \ + } \ +} while (0) + +#define BLKC_SET_X_L(PRE, w, x) do { \ + unsigned _i; BLKC_W(w); unsigned long _x = x; _w += PRE##_BLKSZ / 4; \ + for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) { \ + *--_w = U32(_x); \ + _x = ((_x & ~MASK32) >> 16) >> 16; \ + } \ +} while (0) + +/* --- Implementation for known block sizes --- */ + +#define BLKC_SKEL_64(PRE, decl, op, guts) \ + BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1);) + +#define BLKC_SKEL_96(PRE, decl, op, guts) \ + BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1); guts(op, 2);) + +#define BLKC_SKEL_128(PRE, decl, op, guts) \ + BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3);) + +#define BLKC_SKEL_192(PRE, decl, op, guts) \ + BLKC_SKEL(PRE, decl, \ + guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3); \ + guts(op, 4); guts(op, 5);) + +#define BLKC_SKEL_256(PRE, decl, op, guts) \ + BLKC_SKEL(PRE, decl, \ + guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3); \ + guts(op, 4); guts(op, 5); guts(op, 6); guts(op, 7);) + +#define BLKC_STORE_GUTS(op, i) op(_p + 4 * i, _w[i]) +#define BLKC_XSTORE_GUTS(op, i) op(_p + 4 * i, _w[i] ^ _wx[i]) +#define BLKC_LOAD_GUTS(op, i) _w[i] = op(_p + 4 * i) +#define BLKC_XLOAD_GUTS(op, i) _w[i] ^= op(_p + 4 * i) +#define BLKC_MOVE_GUTS(op, i) _w[i] = _wx[i] +#define BLKC_XMOVE_GUTS(op, i) _w[i] ^= _wx[i] +#define BLKC_ZERO_GUTS(op, i) _w[i] = 0 + +#define BLKC_STORE_N(PRE, b, w, op, n) \ + BLKC_GLUE(BLKC_SKEL_, n) \ + (PRE, BLKC_P(b); const BLKC_W(w);, op, BLKC_STORE_GUTS) + +#define BLKC_XSTORE_N(PRE, b, w, wx, op, n) \ + BLKC_GLUE(BLKC_SKEL_, n) \ + (PRE, BLKC_P(b); const BLKC_W(w); const BLKC_WX(wx);, \ + op, BLKC_XSTORE_GUTS) + +#define BLKC_LOAD_N(PRE, w, b, op, n) \ + BLKC_GLUE(BLKC_SKEL_, n) \ + (PRE, const BLKC_P(b); BLKC_W(w);, op, BLKC_LOAD_GUTS) + +#define BLKC_XLOAD_N(PRE, w, b, op, n) \ + BLKC_GLUE(BLKC_SKEL_, n) \ + (PRE, const BLKC_P(b); BLKC_W(w);, op, BLKC_XLOAD_GUTS) + +#define BLKC_MOVE_N(PRE, w, wx, n) \ + BLKC_GLUE(BLKC_SKEL_, n) \ + (PRE, BLKC_W(w); const BLKC_WX(wx);, op, BLKC_MOVE_GUTS) + +#define BLKC_ZERO_N(PRE, w, n) \ + BLKC_GLUE(BLKC_SKEL_, n) \ + (PRE, BLKC_W(w); , op, BLKC_ZERO_GUTS) + +#define BLKC_XMOVE_N(PRE, w, wx, n) \ + BLKC_GLUE(BLKC_SKEL_, n) \ + (PRE, BLKC_W(w); const BLKC_WX(wx);, op, BLKC_XMOVE_GUTS) + +/*----- Test rig for block ciphers ----------------------------------------*/ + +/* --- @BLKC_TEST@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for cipher-specific definitions + * + * Use: Standard test rig for block ciphers. + */ + +#ifdef TEST_RIG + +#include + +#include +#include + +#define BLKC_VERIFY(PRE, pre) \ + \ +static int pre##_verify(dstr *v) \ +{ \ + pre##_ctx k; \ + uint32 p[PRE##_BLKSZ / 4]; \ + uint32 c[PRE##_BLKSZ / 4]; \ + uint32 d[PRE##_BLKSZ / 4]; \ + dstr b = DSTR_INIT; \ + int ok = 1; \ + \ + /* --- Initialize the key buffer --- */ \ + \ + dstr_ensure(&b, PRE##_BLKSZ); \ + b.len = PRE##_BLKSZ; \ + pre##_init(&k, v[0].buf, v[0].len); \ + BLKC_LOAD(PRE, p, v[1].buf); \ + BLKC_LOAD(PRE, c, v[2].buf); \ + \ + /* --- Test encryption --- */ \ + \ + BLKC_MOVE(PRE, d, p); \ + pre##_eblk(&k, d, d); \ + BLKC_STORE(PRE, b.buf, d); \ + if (memcmp(b.buf, v[2].buf, PRE##_BLKSZ)) { \ + ok = 0; \ + printf("\nfail encryption:" \ + "\n\tkey = "); \ + type_hex.dump(&v[0], stdout); \ + printf("\n\tplaintext = "); type_hex.dump(&v[1], stdout); \ + printf("\n\texpected = "); type_hex.dump(&v[2], stdout); \ + printf("\n\tcalculated = "); type_hex.dump(&b, stdout); \ + putchar('\n'); \ + } \ + \ + /* --- Test decryption --- */ \ + \ + BLKC_MOVE(PRE, d, c); \ + pre##_dblk(&k, d, d); \ + BLKC_STORE(PRE, b.buf, d); \ + if (memcmp(b.buf, v[1].buf, PRE##_BLKSZ)) { \ + ok = 0; \ + printf("\nfail decryption:" \ + "\n\tkey = "); \ + type_hex.dump(&v[0], stdout); \ + printf("\n\tciphertext = "); type_hex.dump(&v[2], stdout); \ + printf("\n\texpected = "); type_hex.dump(&v[1], stdout); \ + printf("\n\tcalculated = "); type_hex.dump(&b, stdout); \ + putchar('\n'); \ + } \ + \ + /* --- Return --- */ \ + \ + return (ok); \ +} + +#define BLKC_TEST(PRE, pre) \ + \ +BLKC_VERIFY(PRE, pre) \ + \ +static const test_chunk defs[] = { \ + { #pre, pre##_verify, { &type_hex, &type_hex, &type_hex, 0 } }, \ + { 0, 0, { 0 } } \ +}; \ + \ +int main(int argc, char *argv[]) \ +{ \ + test_run(argc, argv, defs, SRCDIR"/t/" #pre); \ + return (0); \ +} + +#else +# define BLKC_VERIFY(PRE, pre) +# define BLKC_TEST(PRE, pre) +#endif + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/blowfish-mktab.c b/symm/blowfish-mktab.c new file mode 100644 index 0000000..752fb32 --- /dev/null +++ b/symm/blowfish-mktab.c @@ -0,0 +1,190 @@ +/* -*-c-*- + * + * Build Blowfish key table + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @spigot@ --- * + * + * Arguments: @uint32 *buf@ = pointer to the output buffer + * @size_t n@ = number of output digits wanted + * + * Returns: --- + * + * Use: Writes digits of %$\pi$% to the given array. The algorithm + * is based on the Spigot algorithm by Stanley Rabinowitz and + * Stan Wagon, published in Amer.Math.Monthly, March 1995, with + * bug fixes by C. Haenel. I then bodged it to output hex + * digits rather than decimal ones, and to leave off the initial + * `3'. + * + * I've not analysed the algorithm very much. + */ + +#define SPIGOT_WORDS (18 + 4 * 256ul) +#define SPIGOT_BITS 8 +#define SPIGOT_RADIX (1ul << SPIGOT_BITS) +#define SPIGOT_BUFLEN (SPIGOT_WORDS * 32) + +#ifdef QUIET +# define Q(x) +#else +# define Q(x) x +#endif + +static void spigot(uint32 *buf, size_t n) +{ + uint32 acc = 0; + int b = -1; + unsigned a[SPIGOT_BUFLEN] = { 0 }; + uint32 p = 0; + unsigned f = 0; + unsigned max = 32 * n; + Q( size_t step = n / 60; ) + + Q( fputs("[ ]\r[", + stderr); ) + +#define EMIT(z) do { \ + if (b == -1) \ + b = 0; \ + else { \ + acc = (acc << SPIGOT_BITS) | (z); \ + b += SPIGOT_BITS; \ + if (b == 32) { \ + *buf++ = acc; \ + acc = 0; \ + b = 0; \ + n--; \ + if (!n) \ + goto done; \ + Q( if (n % step == 0) \ + fputc('.', stderr); ) \ + } \ + } \ +} while (0) + + while (n) { + uint32 q = 0; + uint32 i; + uint32 x = 0; + uint32 k = max * 2 - 1; + + for (i = max; i; i--) { + x = (b == -1 ? SPIGOT_RADIX * 2 : a[i - 1] << SPIGOT_BITS) + q * i; + q = x / k; + a[i - 1] = x - q * k; + k -= 2; + } + + k = x & (SPIGOT_RADIX - 1); + if (k == SPIGOT_RADIX - 1) + f++; + else { + EMIT(p + (x >> SPIGOT_BITS)); + if (f) { + unsigned d = (x >= SPIGOT_RADIX ? 0 : SPIGOT_RADIX - 1); + while (f) { + EMIT(d); + f--; + } + } + p = k; + } + } + +done:; + Q( fputc('\n', stderr); ) + +#undef EMIT +} + +/* --- @main@ --- */ + +int main(void) +{ + uint32 dbuf[SPIGOT_WORDS]; + int i, j; + uint32 *d = dbuf; + + spigot(d, SPIGOT_WORDS); + + fputs("\ +/* -*-c-*-\n\ + *\n\ + * Blowfish initial key table [generated]\n\ + */\n\ +\n\ +#ifndef CATACOMB_BLOWFISH_TAB_H\n\ +#define CATACOMB_BLOWFISH_TAB_H\n\ +\n\ +#define BLOWFISH_IKEY { \\\n\ + { ", stdout); + + for (i = 0; i < 18; i++) { + printf("0x%08x", *d++); + if (i == 17) + fputs(" }, \\\n\ + \\\n\ + { ", stdout); + else if (i % 4 == 3) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + for (j = 0; j < 4; j++) { + for (i = 0; i < 256; i++) { + printf("0x%08x", *d++); + if (i == 255) { + if (j == 3) + fputs(" } \\\n}\n\n#endif\n", stdout); + else + fputs(" }, \\\n\ + \\\n\ + { ", stdout); + } else if (i % 4 == 3) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + } + + if (fclose(stdout)) { + fprintf(stderr, "error writing data\n"); + exit(EXIT_FAILURE); + } + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/blowfish.c b/symm/blowfish.c new file mode 100644 index 0000000..4bfb84d --- /dev/null +++ b/symm/blowfish.c @@ -0,0 +1,206 @@ +/* -*-c-*- + * + * The Blowfish block cipher + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "blowfish.h" +#include "blowfish-tab.h" +#include "blkc.h" +#include "gcipher.h" +#include "paranoia.h" + +/*----- Global variables --------------------------------------------------*/ + +static const blowfish_ctx ikey = BLOWFISH_IKEY; + +const octet blowfish_keysz[] = { KSZ_RANGE, BLOWFISH_KEYSZ, 1, 56, 1 }; + +/*----- Macros ------------------------------------------------------------*/ + +#define ROUND(k, x, y, r) do { \ + x ^= *r; \ + y ^= ((k->s0[U8(x >> 24)] + \ + k->s1[U8(x >> 16)]) ^ \ + k->s2[U8(x >> 8)]) + \ + k->s3[U8(x >> 0)]; \ +} while (0) + +#define EBLK(k, a, b, c, d) do { \ + const uint32 *_r = k->p; \ + uint32 _x = a; \ + uint32 _y = b; \ + ROUND(k, _x, _y, _r++); \ + ROUND(k, _y, _x, _r++); \ + ROUND(k, _x, _y, _r++); \ + ROUND(k, _y, _x, _r++); \ + ROUND(k, _x, _y, _r++); \ + ROUND(k, _y, _x, _r++); \ + ROUND(k, _x, _y, _r++); \ + ROUND(k, _y, _x, _r++); \ + ROUND(k, _x, _y, _r++); \ + ROUND(k, _y, _x, _r++); \ + ROUND(k, _x, _y, _r++); \ + ROUND(k, _y, _x, _r++); \ + ROUND(k, _x, _y, _r++); \ + ROUND(k, _y, _x, _r++); \ + ROUND(k, _x, _y, _r++); \ + ROUND(k, _y, _x, _r++); \ + c = _y ^ k->p[17]; \ + d = _x ^ k->p[16]; \ +} while (0) + +#define DBLK(k, a, b, c, d) do { \ + const uint32 *_r = k->p + 18; \ + uint32 _x = a; \ + uint32 _y = b; \ + ROUND(k, _x, _y, --_r); \ + ROUND(k, _y, _x, --_r); \ + ROUND(k, _x, _y, --_r); \ + ROUND(k, _y, _x, --_r); \ + ROUND(k, _x, _y, --_r); \ + ROUND(k, _y, _x, --_r); \ + ROUND(k, _x, _y, --_r); \ + ROUND(k, _y, _x, --_r); \ + ROUND(k, _x, _y, --_r); \ + ROUND(k, _y, _x, --_r); \ + ROUND(k, _x, _y, --_r); \ + ROUND(k, _y, _x, --_r); \ + ROUND(k, _x, _y, --_r); \ + ROUND(k, _y, _x, --_r); \ + ROUND(k, _x, _y, --_r); \ + ROUND(k, _y, _x, --_r); \ + c = _y ^ k->p[0]; \ + d = _x ^ k->p[1]; \ +} while (0) + +/*----- Low-level encryption interface ------------------------------------*/ + +/* --- @blowfish_init@ --- * + * + * Arguments: @blowfish_ctx *k@ = pointer to key block to fill in + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a Blowfish key buffer. Blowfish accepts + * a more-or-less arbitrary size key. + */ + +void blowfish_init(blowfish_ctx *k, const void *buf, size_t sz) +{ + KSZ_ASSERT(blowfish, sz); + + /* --- Copy the initial value over --- */ + + memcpy(k, &ikey, sizeof(ikey)); + + /* --- Initialize the %$P$% array --- */ + + { + const octet *p = buf; + const octet *q = p + sz; + int i = 0, j = 0; + uint32 x = 0; + + while (i < 18) { + x = (x << 8) | U8(*p++); + if (p >= q) + p = buf; + if (++j >= 4) { + k->p[i++] ^= x; + x = 0; + j = 0; + } + } + + x = 0; + } + + /* --- Now mangle the complete array of keys --- */ + + { + uint32 b[2]; + int i; + + b[0] = b[1] = 0; + + for (i = 0; i < 18; i += 2) { + blowfish_eblk(k, b, b); + k->p[i] = b[0]; k->p[i + 1] = b[1]; + } + + for (i = 0; i < 256; i += 2) { + blowfish_eblk(k, b, b); + k->s0[i] = b[0]; k->s0[i + 1] = b[1]; + } + + for (i = 0; i < 256; i += 2) { + blowfish_eblk(k, b, b); + k->s1[i] = b[0]; k->s1[i + 1] = b[1]; + } + + for (i = 0; i < 256; i += 2) { + blowfish_eblk(k, b, b); + k->s2[i] = b[0]; k->s2[i + 1] = b[1]; + } + + for (i = 0; i < 256; i += 2) { + blowfish_eblk(k, b, b); + k->s3[i] = b[0]; k->s3[i + 1] = b[1]; + } + + BURN(b); + } +} + +/* --- @blowfish_eblk@, @blowfish_dblk@ --- * + * + * Arguments: @const blowfish_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +void blowfish_eblk(const blowfish_ctx *k, const uint32 *s, uint32 *d) +{ + EBLK(k, s[0], s[1], d[0], d[1]); +} + +void blowfish_dblk(const blowfish_ctx *k, const uint32 *s, uint32 *d) +{ + DBLK(k, s[0], s[1], d[0], d[1]); +} + +BLKC_TEST(BLOWFISH, blowfish) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/blowfish.h b/symm/blowfish.h new file mode 100644 index 0000000..eedf820 --- /dev/null +++ b/symm/blowfish.h @@ -0,0 +1,105 @@ +/* -*-c-*- + * + * The Blowfish block cipher + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the Blowfish block cipher --------------------------------* + * + * Blowfish was invented by Bruce Schneier. The algorithm is unpatented and + * free for anyone to use. It's fast, simple, offers a big key, and is + * looking relatively bulletproof. It's also this author's block cipher of + * choice, for what little that's worth. The disadvantage is that Blowfish + * has a particularly heavyweight key schedule. + */ + +#ifndef CATACOMB_BLOWFISH_H +#define CATACOMB_BLOWFISH_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magical numbers ---------------------------------------------------*/ + +#define BLOWFISH_BLKSZ 8 +#define BLOWFISH_KEYSZ 32 +#define BLOWFISH_CLASS (N, B, 64) + +extern const octet blowfish_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct blowfish_ctx { + uint32 p[18]; + uint32 s0[256], s1[256], s2[256], s3[256]; +} blowfish_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @blowfish_init@ --- * + * + * Arguments: @blowfish_ctx *k@ = pointer to key block to fill in + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a Blowfish key buffer. Blowfish accepts + * a more-or-less arbitrary size key. + */ + +extern void blowfish_init(blowfish_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @blowfish_eblk@, @blowfish_dblk@ --- * + * + * Arguments: @const blowfish_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void blowfish_eblk(const blowfish_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +extern void blowfish_dblk(const blowfish_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/cast-base.h b/symm/cast-base.h new file mode 100644 index 0000000..8a8dcc6 --- /dev/null +++ b/symm/cast-base.h @@ -0,0 +1,65 @@ +/* -*-c-*- + * + * Basic macros and definitions for CAST-128 and CAST-256 + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_CAST_BASE_H +#define CATACOMB_CAST_BASE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +/*----- Round functions ---------------------------------------------------*/ + +#define CAST_R_guts(km, kr, xx, yy, aop, bop, cop) do { \ + uint32 i = km aop yy; \ + unsigned _r = kr; \ + i = ROL32(i, _r); \ + xx ^= ((cast_s[0][U8(i >> 24)] bop \ + cast_s[1][U8(i >> 16)]) cop \ + cast_s[2][U8(i >> 8)]) aop \ + cast_s[3][U8(i >> 0)]; \ +} while (0) + +#define CAST_R1(km, kr, xx, yy) CAST_R_guts(km, kr, xx, yy, +, ^, -) +#define CAST_R2(km, kr, xx, yy) CAST_R_guts(km, kr, xx, yy, ^, -, +) +#define CAST_R3(km, kr, xx, yy) CAST_R_guts(km, kr, xx, yy, -, +, ^) + +/*----- Global variables --------------------------------------------------*/ + +extern const uint32 cast_s[4][256], cast_sk[4][256]; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/cast-s.c b/symm/cast-s.c new file mode 100644 index 0000000..968d888 --- /dev/null +++ b/symm/cast-s.c @@ -0,0 +1,39 @@ +/* -*-c-*- + * + * Basic S-boxes for CAST-128 and CAST-256 + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "cast-base.h" +#include "cast-tab.h" + +/*----- Global variables --------------------------------------------------*/ + +const uint32 cast_s[4][256] = CAST_S; + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/cast-sk.c b/symm/cast-sk.c new file mode 100644 index 0000000..d1620ee --- /dev/null +++ b/symm/cast-sk.c @@ -0,0 +1,39 @@ +/* -*-c-*- + * + * Key-schedule S-boxes for CAST-128 + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "cast-base.h" +#include "cast-tab.h" + +/*----- Global variables --------------------------------------------------*/ + +const uint32 cast_sk[4][256] = CAST_SK; + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/cast-tab.h b/symm/cast-tab.h new file mode 100644 index 0000000..b6e2f9f --- /dev/null +++ b/symm/cast-tab.h @@ -0,0 +1,567 @@ +/* -*-c-*- + * + * S-boxes for CAST-128 and CAST-256 + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_CAST_TAB_H +#define CATACOMB_CAST_TAB_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- S-box tables ------------------------------------------------------*/ + +#define CAST_S { \ + { 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, \ + 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, \ + 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, \ + 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, \ + 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, \ + 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, \ + 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, \ + 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, \ + 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, \ + 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, \ + 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, \ + 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, \ + 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, \ + 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, \ + 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, \ + 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, \ + 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, \ + 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, \ + 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, \ + 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, \ + 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, \ + 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, \ + 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, \ + 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, \ + 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, \ + 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, \ + 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, \ + 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, \ + 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, \ + 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, \ + 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, \ + 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, \ + 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, \ + 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, \ + 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, \ + 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, \ + 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, \ + 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, \ + 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, \ + 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, \ + 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, \ + 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, \ + 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, \ + 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, \ + 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, \ + 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, \ + 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, \ + 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, \ + 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, \ + 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, \ + 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, \ + 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, \ + 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, \ + 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, \ + 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, \ + 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, \ + 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, \ + 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, \ + 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, \ + 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, \ + 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, \ + 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, \ + 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, \ + 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf }, \ + \ + { 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, \ + 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, \ + 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, \ + 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, \ + 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, \ + 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, \ + 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, \ + 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, \ + 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, \ + 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, \ + 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, \ + 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, \ + 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, \ + 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, \ + 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, \ + 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, \ + 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, \ + 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, \ + 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, \ + 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, \ + 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, \ + 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, \ + 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, \ + 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, \ + 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, \ + 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, \ + 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, \ + 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, \ + 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, \ + 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, \ + 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, \ + 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, \ + 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, \ + 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, \ + 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, \ + 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, \ + 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, \ + 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, \ + 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, \ + 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, \ + 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, \ + 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, \ + 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, \ + 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, \ + 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, \ + 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, \ + 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, \ + 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, \ + 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, \ + 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, \ + 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, \ + 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, \ + 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, \ + 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, \ + 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, \ + 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, \ + 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, \ + 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, \ + 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, \ + 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, \ + 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, \ + 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, \ + 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, \ + 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 }, \ + \ + { 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, \ + 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, \ + 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, \ + 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, \ + 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, \ + 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, \ + 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, \ + 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, \ + 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, \ + 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, \ + 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, \ + 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, \ + 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, \ + 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, \ + 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, \ + 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, \ + 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, \ + 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, \ + 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, \ + 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, \ + 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, \ + 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, \ + 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, \ + 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, \ + 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, \ + 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, \ + 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, \ + 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, \ + 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, \ + 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, \ + 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, \ + 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, \ + 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, \ + 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, \ + 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, \ + 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, \ + 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, \ + 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, \ + 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, \ + 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, \ + 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, \ + 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, \ + 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, \ + 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, \ + 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, \ + 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, \ + 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, \ + 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, \ + 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, \ + 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, \ + 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, \ + 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, \ + 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, \ + 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, \ + 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, \ + 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, \ + 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, \ + 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, \ + 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, \ + 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, \ + 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, \ + 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, \ + 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, \ + 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 }, \ + \ + { 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, \ + 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, \ + 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, \ + 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, \ + 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, \ + 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, \ + 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, \ + 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, \ + 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, \ + 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, \ + 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, \ + 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, \ + 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, \ + 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, \ + 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, \ + 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, \ + 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, \ + 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, \ + 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, \ + 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, \ + 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, \ + 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, \ + 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, \ + 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, \ + 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, \ + 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, \ + 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, \ + 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, \ + 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, \ + 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, \ + 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, \ + 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, \ + 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, \ + 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, \ + 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, \ + 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, \ + 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, \ + 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, \ + 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, \ + 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, \ + 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, \ + 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, \ + 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, \ + 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, \ + 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, \ + 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, \ + 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, \ + 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, \ + 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, \ + 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, \ + 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, \ + 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, \ + 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, \ + 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, \ + 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, \ + 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, \ + 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, \ + 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, \ + 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, \ + 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, \ + 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, \ + 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, \ + 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, \ + 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 } \ +} + +#define CAST_SK { \ + { 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, \ + 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, \ + 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, \ + 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, \ + 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, \ + 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, \ + 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, \ + 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, \ + 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, \ + 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, \ + 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, \ + 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, \ + 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, \ + 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, \ + 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, \ + 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, \ + 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, \ + 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, \ + 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, \ + 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, \ + 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, \ + 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, \ + 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, \ + 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, \ + 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, \ + 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, \ + 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, \ + 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, \ + 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, \ + 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, \ + 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, \ + 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, \ + 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, \ + 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, \ + 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, \ + 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, \ + 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, \ + 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, \ + 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, \ + 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, \ + 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, \ + 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, \ + 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, \ + 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, \ + 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, \ + 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, \ + 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, \ + 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, \ + 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, \ + 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, \ + 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, \ + 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, \ + 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, \ + 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, \ + 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, \ + 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, \ + 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, \ + 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, \ + 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, \ + 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, \ + 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, \ + 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, \ + 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, \ + 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 }, \ + \ + { 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, \ + 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, \ + 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, \ + 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, \ + 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, \ + 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, \ + 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, \ + 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, \ + 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, \ + 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, \ + 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, \ + 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, \ + 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, \ + 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, \ + 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, \ + 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, \ + 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, \ + 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, \ + 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, \ + 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, \ + 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, \ + 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, \ + 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, \ + 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, \ + 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, \ + 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, \ + 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, \ + 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, \ + 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, \ + 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, \ + 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, \ + 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, \ + 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, \ + 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, \ + 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, \ + 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, \ + 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, \ + 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, \ + 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, \ + 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, \ + 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, \ + 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, \ + 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, \ + 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, \ + 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, \ + 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, \ + 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, \ + 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, \ + 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, \ + 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, \ + 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, \ + 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, \ + 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, \ + 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, \ + 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, \ + 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, \ + 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, \ + 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, \ + 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, \ + 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, \ + 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, \ + 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, \ + 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, \ + 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f }, \ + \ + { 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, \ + 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, \ + 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, \ + 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, \ + 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, \ + 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, \ + 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, \ + 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, \ + 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, \ + 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, \ + 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, \ + 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, \ + 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, \ + 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, \ + 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, \ + 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, \ + 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, \ + 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, \ + 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, \ + 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, \ + 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, \ + 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, \ + 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, \ + 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, \ + 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, \ + 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, \ + 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, \ + 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, \ + 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, \ + 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, \ + 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, \ + 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, \ + 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, \ + 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, \ + 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, \ + 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, \ + 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, \ + 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, \ + 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, \ + 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, \ + 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, \ + 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, \ + 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, \ + 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, \ + 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, \ + 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, \ + 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, \ + 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, \ + 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, \ + 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, \ + 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, \ + 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, \ + 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, \ + 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, \ + 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, \ + 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, \ + 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, \ + 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, \ + 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, \ + 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, \ + 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, \ + 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, \ + 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, \ + 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 }, \ + \ + { 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, \ + 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, \ + 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, \ + 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, \ + 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, \ + 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, \ + 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, \ + 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, \ + 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, \ + 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, \ + 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, \ + 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, \ + 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, \ + 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, \ + 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, \ + 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, \ + 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, \ + 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, \ + 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, \ + 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, \ + 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, \ + 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, \ + 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, \ + 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, \ + 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, \ + 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, \ + 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, \ + 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, \ + 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, \ + 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, \ + 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, \ + 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, \ + 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, \ + 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, \ + 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, \ + 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, \ + 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, \ + 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, \ + 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, \ + 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, \ + 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, \ + 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, \ + 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, \ + 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, \ + 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, \ + 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, \ + 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, \ + 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, \ + 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, \ + 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, \ + 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, \ + 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, \ + 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, \ + 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, \ + 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, \ + 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, \ + 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, \ + 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, \ + 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, \ + 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, \ + 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, \ + 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, \ + 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, \ + 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e } \ +} + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/cast128.c b/symm/cast128.c new file mode 100644 index 0000000..cbff8d1 --- /dev/null +++ b/symm/cast128.c @@ -0,0 +1,300 @@ +/* -*-c-*- + * + * The CAST-128 block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include + +#include "blkc.h" +#include "cast-base.h" +#include "cast128.h" +#include "gcipher.h" +#include "paranoia.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet cast128_keysz[] = { KSZ_RANGE, CAST128_KEYSZ, 0, 16, 1 }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @cast128_init@ --- * + * + * Arguments: @cast128_ctx *k@ = pointer to key block to fill in + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a CAST-128 key buffer. CAST-128 accepts + * 128-bit keys or shorter. + */ + +void cast128_init(cast128_ctx *k, const void *buf, size_t sz) +{ + const octet *p = buf; + uint32 kk[4]; + unsigned i; + uint32 a, b, c, d, aa, bb, cc, dd; + + /* --- Fiddle with the key size a bit --- */ + + KSZ_ASSERT(cast128, sz); + + if (sz > 10) + k->r = 16; + else + k->r = 12; + + /* --- Read the key into the array --- */ + + i = 0; + b = 32; aa = 0; + for (;;) { + if (!sz) + break; + b -= 8; + aa |= ((uint32)*p++ << b); + sz--; + if (b == 0) { + kk[i++] = aa; + if (i == 4) + break; + aa = 0; + b = 32; + } + } + + for (; i < 4; i++) { + kk[i] = aa; + aa = 0; + } + + /* --- Read the key words out --- */ + + a = kk[0]; b = kk[1]; c = kk[2]; d = kk[3]; + +#define X_0123 a +#define X_4567 b +#define X_89ab c +#define X_cdef d + +#define X_0 U8(X_0123 >> 24) +#define X_1 U8(X_0123 >> 16) +#define X_2 U8(X_0123 >> 8) +#define X_3 U8(X_0123 >> 0) +#define X_4 U8(X_4567 >> 24) +#define X_5 U8(X_4567 >> 16) +#define X_6 U8(X_4567 >> 8) +#define X_7 U8(X_4567 >> 0) +#define X_8 U8(X_89ab >> 24) +#define X_9 U8(X_89ab >> 16) +#define X_a U8(X_89ab >> 8) +#define X_b U8(X_89ab >> 0) +#define X_c U8(X_cdef >> 24) +#define X_d U8(X_cdef >> 16) +#define X_e U8(X_cdef >> 8) +#define X_f U8(X_cdef >> 0) + +#define Z_0123 aa +#define Z_4567 bb +#define Z_89ab cc +#define Z_cdef dd + +#define Z_0 U8(Z_0123 >> 24) +#define Z_1 U8(Z_0123 >> 16) +#define Z_2 U8(Z_0123 >> 8) +#define Z_3 U8(Z_0123 >> 0) +#define Z_4 U8(Z_4567 >> 24) +#define Z_5 U8(Z_4567 >> 16) +#define Z_6 U8(Z_4567 >> 8) +#define Z_7 U8(Z_4567 >> 0) +#define Z_8 U8(Z_89ab >> 24) +#define Z_9 U8(Z_89ab >> 16) +#define Z_a U8(Z_89ab >> 8) +#define Z_b U8(Z_89ab >> 0) +#define Z_c U8(Z_cdef >> 24) +#define Z_d U8(Z_cdef >> 16) +#define Z_e U8(Z_cdef >> 8) +#define Z_f U8(Z_cdef >> 0) + +#define SK(w, x, y, z) \ + cast_sk[0][w] ^ cast_sk[1][x] ^ cast_sk[2][y] ^ cast_sk[3][z] + + i = 0; + Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8]; + Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a]; + Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9]; + Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b]; + k->km[i++] = SK(Z_8, Z_9, Z_7, Z_6) ^ cast_sk[0][Z_2]; + k->km[i++] = SK(Z_a, Z_b, Z_5, Z_4) ^ cast_sk[1][Z_6]; + k->km[i++] = SK(Z_c, Z_d, Z_3, Z_2) ^ cast_sk[2][Z_9]; + k->km[i++] = SK(Z_e, Z_f, Z_1, Z_0) ^ cast_sk[3][Z_c]; + X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0]; + X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2]; + X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1]; + X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3]; + k->km[i++] = SK(X_3, X_2, X_c, X_d) ^ cast_sk[0][X_8]; + k->km[i++] = SK(X_1, X_0, X_e, X_f) ^ cast_sk[1][X_d]; + k->km[i++] = SK(X_7, X_6, X_8, X_9) ^ cast_sk[2][X_3]; + k->km[i++] = SK(X_5, X_4, X_a, X_b) ^ cast_sk[3][X_7]; + Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8]; + Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a]; + Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9]; + Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b]; + k->km[i++] = SK(Z_3, Z_2, Z_c, Z_d) ^ cast_sk[0][Z_9]; + k->km[i++] = SK(Z_1, Z_0, Z_e, Z_f) ^ cast_sk[1][Z_c]; + k->km[i++] = SK(Z_7, Z_6, Z_8, Z_9) ^ cast_sk[2][Z_2]; + k->km[i++] = SK(Z_5, Z_4, Z_a, Z_b) ^ cast_sk[3][Z_6]; + X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0]; + X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2]; + X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1]; + X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3]; + k->km[i++] = SK(X_8, X_9, X_7, X_6) ^ cast_sk[0][X_3]; + k->km[i++] = SK(X_a, X_b, X_5, X_4) ^ cast_sk[1][X_7]; + k->km[i++] = SK(X_c, X_d, X_3, X_2) ^ cast_sk[2][X_8]; + k->km[i++] = SK(X_e, X_f, X_1, X_0) ^ cast_sk[3][X_d]; + + i = 0; + Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8]; + Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a]; + Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9]; + Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b]; + k->kr[i++] = (SK(Z_8, Z_9, Z_7, Z_6) ^ cast_sk[0][Z_2]) & 0x1f; + k->kr[i++] = (SK(Z_a, Z_b, Z_5, Z_4) ^ cast_sk[1][Z_6]) & 0x1f; + k->kr[i++] = (SK(Z_c, Z_d, Z_3, Z_2) ^ cast_sk[2][Z_9]) & 0x1f; + k->kr[i++] = (SK(Z_e, Z_f, Z_1, Z_0) ^ cast_sk[3][Z_c]) & 0x1f; + X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0]; + X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2]; + X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1]; + X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3]; + k->kr[i++] = (SK(X_3, X_2, X_c, X_d) ^ cast_sk[0][X_8]) & 0x1f; + k->kr[i++] = (SK(X_1, X_0, X_e, X_f) ^ cast_sk[1][X_d]) & 0x1f; + k->kr[i++] = (SK(X_7, X_6, X_8, X_9) ^ cast_sk[2][X_3]) & 0x1f; + k->kr[i++] = (SK(X_5, X_4, X_a, X_b) ^ cast_sk[3][X_7]) & 0x1f; + Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8]; + Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a]; + Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9]; + Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b]; + k->kr[i++] = (SK(Z_3, Z_2, Z_c, Z_d) ^ cast_sk[0][Z_9]) & 0x1f; + k->kr[i++] = (SK(Z_1, Z_0, Z_e, Z_f) ^ cast_sk[1][Z_c]) & 0x1f; + k->kr[i++] = (SK(Z_7, Z_6, Z_8, Z_9) ^ cast_sk[2][Z_2]) & 0x1f; + k->kr[i++] = (SK(Z_5, Z_4, Z_a, Z_b) ^ cast_sk[3][Z_6]) & 0x1f; + X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0]; + X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2]; + X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1]; + X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3]; + k->kr[i++] = (SK(X_8, X_9, X_7, X_6) ^ cast_sk[0][X_3]) & 0x1f; + k->kr[i++] = (SK(X_a, X_b, X_5, X_4) ^ cast_sk[1][X_7]) & 0x1f; + k->kr[i++] = (SK(X_c, X_d, X_3, X_2) ^ cast_sk[2][X_8]) & 0x1f; + k->kr[i++] = (SK(X_e, X_f, X_1, X_0) ^ cast_sk[3][X_d]) & 0x1f; + + BURN(kk); +} + +/* --- @cast128_eblk@, @cast128_dblk@ --- * + * + * Arguments: @const cast128_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +void cast128_eblk(const cast128_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 a = s[0], b = s[1]; + const uint32 *km = k->km; + const octet *kr = k->kr; + + switch (k->r) { + default: + CAST_R1(*km++, *kr++, a, b); + CAST_R2(*km++, *kr++, b, a); + CAST_R3(*km++, *kr++, a, b); + CAST_R1(*km++, *kr++, b, a); + CAST_R2(*km++, *kr++, a, b); + CAST_R3(*km++, *kr++, b, a); + CAST_R1(*km++, *kr++, a, b); + CAST_R2(*km++, *kr++, b, a); + CAST_R3(*km++, *kr++, a, b); + CAST_R1(*km++, *kr++, b, a); + CAST_R2(*km++, *kr++, a, b); + CAST_R3(*km++, *kr++, b, a); + if (k->r == 12) + break; + CAST_R1(*km++, *kr++, a, b); + CAST_R2(*km++, *kr++, b, a); + CAST_R3(*km++, *kr++, a, b); + CAST_R1(*km++, *kr++, b, a); + break; + } + + d[0] = b; d[1] = a; +} + +void cast128_dblk(const cast128_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 a = s[0], b = s[1]; + const uint32 *km = k->km + k->r; + const octet *kr = k->kr + k->r; + + switch (k->r) { + case 16: + default: + CAST_R1(*--km, *--kr, a, b); + CAST_R3(*--km, *--kr, b, a); + CAST_R2(*--km, *--kr, a, b); + CAST_R1(*--km, *--kr, b, a); + case 12: + CAST_R3(*--km, *--kr, a, b); + CAST_R2(*--km, *--kr, b, a); + CAST_R1(*--km, *--kr, a, b); + CAST_R3(*--km, *--kr, b, a); + CAST_R2(*--km, *--kr, a, b); + CAST_R1(*--km, *--kr, b, a); + CAST_R3(*--km, *--kr, a, b); + CAST_R2(*--km, *--kr, b, a); + CAST_R1(*--km, *--kr, a, b); + CAST_R3(*--km, *--kr, b, a); + CAST_R2(*--km, *--kr, a, b); + CAST_R1(*--km, *--kr, b, a); + break; + } + + d[0] = b; d[1] = a; +} + +BLKC_TEST(CAST128, cast128) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/cast128.h b/symm/cast128.h new file mode 100644 index 0000000..01ba6c6 --- /dev/null +++ b/symm/cast128.h @@ -0,0 +1,114 @@ +/* -*-c-*- + * + * The CAST-128 block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the CAST-128 block cipher --------------------------------* + * + * CAST, designed by Carlisle Adams and Stafford Tavares, is a method for + * designing block ciphers, based around the concept of `bent functions'. It + * is described in the paper `Constructing Symmetric Ciphers using the CAST + * Design Procedure' by Carlisle Adams. + * + * CAST-128, defined in RFC2144, is a particular instance of the CAST design + * procedure, The cipher seems strong and fairly quick. The design procedure + * itself is patented, although the cipher CAST-128 is free to use. + * + * Although CAST ciphers are resistant to differential and linear + * cryptanalysis, some instances have been broken by more advanced techniques + * -- the CAST procedure does not guarantee a strong cipher. However, + * CAST-128 has so far resisted all attacks against it, and has now been + * accepted by the Canadian government for protection of all `Designated' + * material. + */ + +#ifndef CATACOMB_CAST128_H +#define CATACOMB_CAST128_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +/*----- Magic numbers -----------------------------------------------------*/ + +#define CAST128_BLKSZ 8 +#define CAST128_KEYSZ 16 +#define CAST128_CLASS (N, B, 64) + +extern const octet cast128_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct cast128_ctx { + unsigned r; + uint32 km[16]; + octet kr[16]; +} cast128_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @cast128_init@ --- * + * + * Arguments: @cast128_ctx *k@ = pointer to key block to fill in + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a CAST-128 key buffer. CAST-128 accepts + * 128-bit keys or shorter. + */ + +extern void cast128_init(cast128_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @cast128_eblk@, @cast128_dblk@ --- * + * + * Arguments: @const cast128_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void cast128_eblk(const cast128_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +extern void cast128_dblk(const cast128_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/cast256.c b/symm/cast256.c new file mode 100644 index 0000000..38aec60 --- /dev/null +++ b/symm/cast256.c @@ -0,0 +1,203 @@ +/* -*-c-*- + * + * The CAST-256 block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include + +#include "blkc.h" +#include "cast-base.h" +#include "cast256.h" +#include "gcipher.h" +#include "paranoia.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet cast256_keysz[] = { KSZ_RANGE, CAST256_KEYSZ, 0, 32, 1 }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @cast256_init@ --- * + * + * Arguments: @cast128_ctx *k@ = pointer to key block to fill in + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a CAST-256 key buffer. CAST-256 accepts + * 256-bit keys or shorter. + */ + +void cast256_init(cast256_ctx *k, const void *buf, size_t sz) +{ + const octet *p = buf; + uint32 kk[8]; + uint32 *km; + octet *kr; + unsigned i, j; + uint32 a, b, c, d, e, f, g, h; + uint32 m; + unsigned r; + + /* --- Fiddle with the key size --- */ + + KSZ_ASSERT(cast256, sz); + + /* --- Read the key into the array --- */ + + i = 0; + b = 32; a = 0; + for (;;) { + if (!sz) + break; + b -= 8; + a |= ((uint32)*p++ << b); + sz--; + if (b == 0) { + kk[i++] = a; + if (i == 8) + break; + a = 0; + b = 32; + } + } + + for (; i < 8; i++) { + kk[i] = a; + a = 0; + } + + /* --- Read the key words out --- */ + + a = kk[0]; b = kk[1]; c = kk[2]; d = kk[3]; + e = kk[4]; f = kk[5]; g = kk[6]; h = kk[7]; + +#define ROOT2 0x5a827999 +#define ROOT3 0x6ed9eba1 + + m = ROOT2; + r = 19; + + km = k->km; + kr = k->kr; + for (i = 0; i < 12; i++) { + for (j = 0; j < 2; j++) { + CAST_R1(m, r, g, h); m += ROOT3; r = (r + 17) & 0x1f; + CAST_R2(m, r, f, g); m += ROOT3; r = (r + 17) & 0x1f; + CAST_R3(m, r, e, f); m += ROOT3; r = (r + 17) & 0x1f; + CAST_R1(m, r, d, e); m += ROOT3; r = (r + 17) & 0x1f; + CAST_R2(m, r, c, d); m += ROOT3; r = (r + 17) & 0x1f; + CAST_R3(m, r, b, c); m += ROOT3; r = (r + 17) & 0x1f; + CAST_R1(m, r, a, b); m += ROOT3; r = (r + 17) & 0x1f; + CAST_R2(m, r, h, a); m += ROOT3; r = (r + 17) & 0x1f; + } + km[0] = h; km[1] = f; km[2] = d; km[3] = b; + kr[0] = a & 0x1f; kr[1] = c & 0x1f; kr[2] = e & 0x1f; kr[3] = g & 0x1f; + km += 4; kr += 4; + } +} + +/* --- @cast256_eblk@, @cast256_dblk@ --- * + * + * Arguments: @const cast256_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +#define Q0(k, r, a, b, c, d) do { \ + CAST_R1(k[0], r[0], c, d); \ + CAST_R2(k[1], r[1], b, c); \ + CAST_R3(k[2], r[2], a, b); \ + CAST_R1(k[3], r[3], d, a); \ +} while (0) + +#define Q1(k, r, a, b, c, d) do { \ + CAST_R1(k[3], r[3], d, a); \ + CAST_R3(k[2], r[2], a, b); \ + CAST_R2(k[1], r[1], b, c); \ + CAST_R1(k[0], r[0], c, d); \ +} while (0) + +void cast256_eblk(const cast256_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3]; + const uint32 *km = k->km; + const octet *kr = k->kr; + + Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4; + Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4; + Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4; + Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4; + Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4; + Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4; + + Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4; + Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4; + Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4; + Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4; + Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4; + Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4; + + d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd; +} + +void cast256_dblk(const cast256_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3]; + const uint32 *km = k->km + 48; + const octet *kr = k->kr + 48; + + km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd); + km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd); + km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd); + km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd); + km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd); + km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd); + + km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd); + km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd); + km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd); + km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd); + km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd); + km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd); + + d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd; +} + +BLKC_TEST(CAST256, cast256) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/cast256.h b/symm/cast256.h new file mode 100644 index 0000000..dd96460 --- /dev/null +++ b/symm/cast256.h @@ -0,0 +1,109 @@ +/* -*-c-*- + * + * The CAST-128 block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the CAST-256 block cipher --------------------------------* + * + * CAST, designed by Carlisle Adams and Stafford Tavares, is a method for + * designing block ciphers, based around the concept of `bent functions'. It + * is described in the paper `Constructing Symmetric Ciphers using the CAST + * Design Procedure' by Carlisle Adams. + * + * CAST-256, defined in RFC2612, is a particular instance of the CAST design + * procedure. It is an `incomplete' Feistel network. It uses the same + * S-boxes and round functions as CAST-128. + * + * CAST-256 was submitted to the AES contest, but was not selected as one of + * the five `finalist' algorithms. + */ + +#ifndef CATACOMB_CAST256_H +#define CATACOMB_CAST256_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +/*----- Magic numbers -----------------------------------------------------*/ + +#define CAST256_BLKSZ 16 +#define CAST256_KEYSZ 32 +#define CAST256_CLASS (N, B, 128) + +extern const octet cast256_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct cast256_ctx { + uint32 km[48]; + octet kr[48]; +} cast256_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @cast256_init@ --- * + * + * Arguments: @cast256_ctx *k@ = pointer to key block to fill in + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a CAST-256 key buffer. CAST-256 accepts + * 256-bit keys or shorter. + */ + +extern void cast256_init(cast256_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @cast256_eblk@, @cast256_dblk@ --- * + * + * Arguments: @const cast256_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void cast256_eblk(const cast256_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +extern void cast256_dblk(const cast256_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/cbc-def.h b/symm/cbc-def.h new file mode 100644 index 0000000..f48ee46 --- /dev/null +++ b/symm/cbc-def.h @@ -0,0 +1,547 @@ +/* -*-c-*- + * + * Definitions for cipher block chaining mode + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_CBC_DEF_H +#define CATACOMB_CBC_DEF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include +#include + +#ifndef CATACOMB_ARENA_H +# include "arena.h" +#endif + +#ifndef CATACOMB_BLKC_H +# include "blkc.h" +#endif + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +#ifndef CATACOMB_PARANOIA_H +# include "paranoia.h" +#endif + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @CBC_DEF@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher + * + * Use: Creates an implementation for CBC stealing mode. + */ + +#define CBC_DEF(PRE, pre) \ + \ +/* --- @pre_cbcgetiv@ --- * \ + * \ + * Arguments: @const pre_cbcctx *ctx@ = pointer to CBC context block \ + * @void *iv@ = pointer to output data block \ + * \ + * Returns: --- \ + * \ + * Use: Reads the currently set IV. Reading and setting an IV \ + * is transparent to the CBC encryption or decryption \ + * process. \ + */ \ + \ +void pre##_cbcgetiv(const pre##_cbcctx *ctx, void *iv) \ +{ \ + BLKC_STORE(PRE, iv, ctx->iv); \ +} \ + \ +/* --- @pre_cbcsetiv@ --- * \ + * \ + * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ + * @cnost void *iv@ = pointer to IV to set \ + * \ + * Returns: --- \ + * \ + * Use: Sets the IV to use for subsequent encryption. \ + */ \ + \ +void pre##_cbcsetiv(pre##_cbcctx *ctx, const void *iv) \ +{ \ + BLKC_LOAD(PRE, ctx->iv, iv); \ +} \ + \ +/* --- @pre_cbcsetkey@ --- * \ + * \ + * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ + * @const pre_ctx *k@ = pointer to cipher context \ + * \ + * Returns: --- \ + * \ + * Use: Sets the CBC context to use a different cipher key. \ + */ \ + \ +void pre##_cbcsetkey(pre##_cbcctx *ctx, const pre##_ctx *k) \ +{ \ + ctx->ctx = *k; \ +} \ + \ +/* --- @pre_cbcinit@ --- * \ + * \ + * Arguments: @pre_cbcctx *ctx@ = pointer to cipher context \ + * @const void *key@ = pointer to the key buffer \ + * @size_t sz@ = size of the key \ + * @const void *iv@ = pointer to initialization vector \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a CBC context ready for use. The @iv@ \ + * argument may be passed as a null pointer to set a zero \ + * IV. Apart from that, this call is equivalent to calls \ + * to @pre_init@, @pre_cbcsetkey@ and @pre_cbcsetiv@. \ + */ \ + \ +void pre##_cbcinit(pre##_cbcctx *ctx, \ + const void *key, size_t sz, \ + const void *iv) \ +{ \ + static const octet zero[PRE##_BLKSZ] = { 0 }; \ + pre##_init(&ctx->ctx, key, sz); \ + BLKC_LOAD(PRE, ctx->iv, iv ? iv : zero); \ +} \ + \ +/* --- @pre_cbcencrypt@ --- * \ + * \ + * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Encrypts a block with a block cipher in CBC mode, with \ + * ciphertext stealing and other clever tricks. \ + * Essentially, data can be encrypted in arbitrary sized \ + * chunks, although decryption must use the same chunks. \ + */ \ + \ +void pre##_cbcencrypt(pre##_cbcctx *ctx, \ + const void *src, void *dest, \ + size_t sz) \ +{ \ + const octet *s = src; \ + octet *d = dest; \ + \ + /* --- Empty blocks are trivial --- */ \ + \ + if (!sz) \ + return; \ + \ + /* --- Extra magical case for a short block --- * \ + * \ + * Encrypt the IV, then exclusive-or the plaintext with the octets \ + * of the encrypted IV, shifting ciphertext octets in instead. This \ + * basically switches over to CFB. \ + */ \ + \ + if (sz < PRE##_BLKSZ) { \ + octet b[PRE##_BLKSZ]; \ + unsigned i; \ + \ + pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \ + BLKC_STORE(PRE, b, ctx->iv); \ + if (d) { \ + for (i = 0; i < sz; i++) \ + d[i] = b[i] ^ (s ? s[i] : 0); \ + } \ + memmove(b, b + sz, PRE##_BLKSZ - sz); \ + memcpy(b + PRE##_BLKSZ - sz, d, sz); \ + BLKC_LOAD(PRE, ctx->iv, b); \ + return; \ + } \ + \ + /* --- Do the main chunk of encryption --- * \ + * \ + * This will do the whole lot if it's a whole number of blocks. For \ + * each block, XOR it with the previous ciphertext in @iv@, encrypt, \ + * and keep a copy of the ciphertext for the next block. \ + */ \ + \ + while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \ + if (s) { \ + BLKC_XLOAD(PRE, ctx->iv, s); \ + s += PRE##_BLKSZ; \ + } \ + pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \ + if (d) { \ + BLKC_STORE(PRE, d, ctx->iv); \ + d += PRE##_BLKSZ; \ + } \ + sz -= PRE##_BLKSZ; \ + } \ + \ + /* --- Do the tail-end block and bit-left-over --- * \ + * \ + * This isn't very efficient. That shouldn't matter much. \ + */ \ + \ + if (sz) { \ + octet b[PRE##_BLKSZ]; \ + unsigned i; \ + \ + /* --- Let @sz@ be the size of the partial block --- */ \ + \ + sz -= PRE##_BLKSZ; \ + \ + /* --- First stage --- * \ + * \ + * XOR the complete block with the current IV, and encrypt it. The \ + * first part of the result is the partial ciphertext block. Don't \ + * write that out yet, because I've not read the partial plaintext \ + * block. \ + */ \ + \ + if (s) BLKC_XLOAD(PRE, ctx->iv, s); \ + pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \ + BLKC_STORE(PRE, b, ctx->iv); \ + \ + /* --- Second stage --- * \ + * \ + * Now XOR in the partial plaintext block, writing out the \ + * ciphertext as I go. Then encrypt, and write the complete \ + * ciphertext block. \ + */ \ + \ + if (s) s += PRE##_BLKSZ; \ + if (d) d += PRE##_BLKSZ; \ + for (i = 0; i < sz; i++) { \ + register octet x = b[i]; \ + if (s) b[i] ^= s[i]; \ + if (d) d[i] = x; \ + } \ + BLKC_LOAD(PRE, ctx->iv, b); \ + pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \ + if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, ctx->iv); \ + } \ + \ + /* --- Done --- */ \ + \ + return; \ +} \ + \ +/* --- @pre_cbcdecrypt@ --- * \ + * \ + * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Decrypts a block with a block cipher in CBC mode, with \ + * ciphertext stealing and other clever tricks. \ + * Essentially, data can be encrypted in arbitrary sized \ + * chunks, although decryption must use the same chunks. \ + */ \ + \ +void pre##_cbcdecrypt(pre##_cbcctx *ctx, \ + const void *src, void *dest, \ + size_t sz) \ +{ \ + const octet *s = src; \ + octet *d = dest; \ + \ + /* --- Empty blocks are trivial --- */ \ + \ + if (!sz) \ + return; \ + \ + /* --- Extra magical case for a short block --- * \ + * \ + * Encrypt the IV, then exclusive-or the ciphertext with the octets \ + * of the encrypted IV, shifting ciphertext octets in instead. This \ + * basically switches over to CFB. \ + */ \ + \ + if (sz < PRE##_BLKSZ) { \ + octet b[PRE##_BLKSZ], c[PRE##_BLKSZ]; \ + unsigned i; \ + \ + pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \ + BLKC_STORE(PRE, b, ctx->iv); \ + for (i = 0; i < sz; i++) { \ + register octet x = s[i]; \ + d[i] = b[i] ^ x; \ + c[i] = x; \ + } \ + memmove(b, b + sz, PRE##_BLKSZ - sz); \ + memcpy(b + PRE##_BLKSZ - sz, c, sz); \ + BLKC_LOAD(PRE, ctx->iv, b); \ + return; \ + } \ + \ + /* --- Do the main chunk of decryption --- * \ + * \ + * This will do the whole lot if it's a whole number of blocks. For \ + * each block, decrypt, XOR it with the previous ciphertext in @iv@, \ + * and keep a copy of the ciphertext for the next block. \ + */ \ + \ + while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \ + uint32 b[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4]; \ + BLKC_LOAD(PRE, niv, s); \ + pre##_dblk(&ctx->ctx, niv, b); \ + BLKC_XSTORE(PRE, d, b, ctx->iv); \ + BLKC_MOVE(PRE, ctx->iv, niv); \ + s += PRE##_BLKSZ; \ + d += PRE##_BLKSZ; \ + sz -= PRE##_BLKSZ; \ + } \ + \ + /* --- Do the tail-end block and bit-left-over --- * \ + * \ + * This isn't very efficient. That shouldn't matter much. \ + */ \ + \ + if (sz) { \ + octet b[PRE##_BLKSZ]; \ + uint32 bk[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4]; \ + unsigned i; \ + \ + /* --- Let @sz@ be the size of the partial block --- */ \ + \ + sz -= PRE##_BLKSZ; \ + \ + /* --- First stage --- * \ + * \ + * Take the complete ciphertext block, and decrypt it. This block \ + * is carried over for the next encryption operation. \ + */ \ + \ + BLKC_LOAD(PRE, niv, s); \ + pre##_dblk(&ctx->ctx, niv, bk); \ + \ + /* --- Second stage --- * \ + * \ + * XORing the first few bytes of this with the partial ciphertext \ + * block recovers the partial plaintext block. At the same time, \ + * write the partial ciphertext block's contents in ready for stage \ + * three. \ + */ \ + \ + BLKC_STORE(PRE, b, bk); \ + s += PRE##_BLKSZ; \ + d += PRE##_BLKSZ; \ + for (i = 0; i < sz; i++) { \ + register octet x = s[i]; \ + d[i] = b[i] ^ x; \ + b[i] = x; \ + } \ + \ + /* --- Third stage --- * \ + * \ + * Decrypt the block we've got left, and XOR with the initial IV to \ + * recover the complete plaintext block. \ + */ \ + \ + BLKC_LOAD(PRE, bk, b); \ + pre##_dblk(&ctx->ctx, bk, bk); \ + BLKC_XSTORE(PRE, d - PRE##_BLKSZ, bk, ctx->iv); \ + BLKC_MOVE(PRE, ctx->iv, niv); \ + } \ + \ + /* --- Done --- */ \ + \ + return; \ +} \ + \ +/* --- Generic cipher interface --- */ \ + \ +static const gcipher_ops gops; \ + \ +typedef struct gctx { \ + gcipher c; \ + pre##_cbcctx k; \ +} gctx; \ + \ +static gcipher *ginit(const void *k, size_t sz) \ +{ \ + gctx *g = S_CREATE(gctx); \ + g->c.ops = &gops; \ + pre##_cbcinit(&g->k, k, sz, 0); \ + return (&g->c); \ +} \ + \ +static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_cbcencrypt(&g->k, s, t, sz); \ +} \ + \ +static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_cbcdecrypt(&g->k, s, t, sz); \ +} \ + \ +static void gdestroy(gcipher *c) \ +{ \ + gctx *g = (gctx *)c; \ + BURN(*g); \ + S_DESTROY(g); \ +} \ + \ +static void gsetiv(gcipher *c, const void *iv) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_cbcsetiv(&g->k, iv); \ +} \ + \ +static const gcipher_ops gops = { \ + &pre##_cbc, \ + gencrypt, gdecrypt, gdestroy, gsetiv, 0 \ +}; \ + \ +const gccipher pre##_cbc = { \ + #pre "-cbc", pre##_keysz, PRE##_BLKSZ, \ + ginit \ +}; \ + \ +CBC_TEST(PRE, pre) + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +#include "daftstory.h" + +/* --- @CBC_TEST@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions + * + * Use: Standard test rig for CBC functions. + */ + +#define CBC_TEST(PRE, pre) \ + \ +/* --- Initial plaintext for the test --- */ \ + \ +static const octet text[] = TEXT; \ + \ +/* --- Key and IV to use --- */ \ + \ +static const octet key[] = KEY; \ +static const octet iv[] = IV; \ + \ +/* --- Buffers for encryption and decryption output --- */ \ + \ +static octet ct[sizeof(text)]; \ +static octet pt[sizeof(text)]; \ + \ +static void hexdump(const octet *p, size_t sz) \ +{ \ + const octet *q = p + sz; \ + for (sz = 0; p < q; p++, sz++) { \ + printf("%02x", *p); \ + if ((sz + 1) % PRE##_BLKSZ == 0) \ + putchar(':'); \ + } \ +} \ + \ +int main(void) \ +{ \ + size_t sz = 0, rest; \ + pre##_cbcctx ctx; \ + pre##_ctx k; \ + int status = 0; \ + int done = 0; \ + \ + size_t keysz = PRE##_KEYSZ ? \ + PRE##_KEYSZ : strlen((const char *)key); \ + \ + fputs(#pre "-cbc: ", stdout); \ + \ + pre##_init(&k, key, keysz); \ + pre##_cbcsetkey(&ctx, &k); \ + \ + while (sz <= sizeof(text)) { \ + rest = sizeof(text) - sz; \ + memcpy(ct, text, sizeof(text)); \ + pre##_cbcsetiv(&ctx, iv); \ + pre##_cbcencrypt(&ctx, ct, ct, sz); \ + pre##_cbcencrypt(&ctx, ct + sz, ct + sz, rest); \ + memcpy(pt, ct, sizeof(text)); \ + pre##_cbcsetiv(&ctx, iv); \ + pre##_cbcdecrypt(&ctx, pt, pt, sz); \ + pre##_cbcdecrypt(&ctx, pt + sz, pt + sz, rest); \ + if (memcmp(pt, text, sizeof(text)) == 0) { \ + done++; \ + if (sizeof(text) < 40 || done % 8 == 0) \ + fputc('.', stdout); \ + if (done % 480 == 0) \ + fputs("\n\t", stdout); \ + fflush(stdout); \ + } else { \ + printf("\nError (sz = %lu)\n", (unsigned long)sz); \ + status = 1; \ + printf("\tplaintext = "); hexdump(text, sz); \ + printf(", "); hexdump(text + sz, rest); \ + fputc('\n', stdout); \ + printf("\tciphertext = "); hexdump(ct, sz); \ + printf(", "); hexdump(ct + sz, rest); \ + fputc('\n', stdout); \ + printf("\trecovered text = "); hexdump(pt, sz); \ + printf(", "); hexdump(pt + sz, rest); \ + fputc('\n', stdout); \ + fputc('\n', stdout); \ + } \ + if (sz < 63) \ + sz++; \ + else \ + sz += 9; \ + } \ + \ + fputs(status ? " failed\n" : " ok\n", stdout); \ + return (status); \ +} + +#else +# define CBC_TEST(PRE, pre) +#endif + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/cbc.h b/symm/cbc.h new file mode 100644 index 0000000..5f1f22a --- /dev/null +++ b/symm/cbc.h @@ -0,0 +1,171 @@ +/* -*-c-*- + * + * Ciphertext block chaining for block ciphers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_CBC_H +#define CATACOMB_CBC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @CBC_DECL@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher + * + * Use: Creates declarations for CBC stealing mode. + */ + +#define CBC_DECL(PRE, pre) \ + \ +/* --- Cipher block chaining context --- */ \ + \ +typedef struct pre##_cbcctx { \ + pre##_ctx ctx; /* Underlying cipher context */ \ + uint32 iv[PRE##_BLKSZ / 4]; /* Previous ciphertext or IV */ \ +} pre##_cbcctx; \ + \ +/* --- @pre_cbcgetiv@ --- * \ + * \ + * Arguments: @const pre_cbcctx *ctx@ = pointer to CBC context block \ + * @void *iv@ = pointer to output data block \ + * \ + * Returns: --- \ + * \ + * Use: Reads the currently set IV. Reading and setting an IV \ + * is transparent to the CBC encryption or decryption \ + * process. \ + */ \ + \ +extern void pre##_cbcgetiv(const pre##_cbcctx */*ctx*/, \ + void */*iv*/); \ + \ +/* --- @pre_cbcsetiv@ --- * \ + * \ + * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ + * @cnost void *iv@ = pointer to IV to set \ + * \ + * Returns: --- \ + * \ + * Use: Sets the IV to use for subsequent encryption. \ + */ \ + \ +extern void pre##_cbcsetiv(pre##_cbcctx */*ctx*/, \ + const void */*iv*/); \ + \ +/* --- @pre_cbcsetkey@ --- * \ + * \ + * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ + * @const pre_ctx *k@ = pointer to cipher context \ + * \ + * Returns: --- \ + * \ + * Use: Sets the CBC context to use a different cipher key. \ + */ \ + \ +extern void pre##_cbcsetkey(pre##_cbcctx */*ctx*/, \ + const pre##_ctx */*k*/); \ + \ +/* --- @pre_cbcinit@ --- * \ + * \ + * Arguments: @pre_cbcctx *ctx@ = pointer to cipher context \ + * @const void *key@ = pointer to the key buffer \ + * @size_t sz@ = size of the key \ + * @const void *iv@ = pointer to initialization vector \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a CBC context ready for use. The @iv@ \ + * argument may be passed as a null pointer to set a zero \ + * IV. Apart from that, this call is equivalent to calls \ + * to @pre_init@, @pre_cbcsetkey@ and @pre_cbcsetiv@. \ + */ \ + \ +extern void pre##_cbcinit(pre##_cbcctx */*ctx*/, \ + const void */*key*/, size_t /*sz*/, \ + const void */*iv*/); \ + \ +/* --- @pre_cbcencrypt@ --- * \ + * \ + * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Encrypts a block with a block cipher in CBC mode, with \ + * ciphertext stealing and other clever tricks. \ + * Essentially, data can be encrypted in arbitrary sized \ + * chunks, although decryption must use the same chunks. \ + */ \ + \ +extern void pre##_cbcencrypt(pre##_cbcctx */*ctx*/, \ + const void */*src*/, void */*dest*/, \ + size_t /*sz*/); \ + \ +/* --- @pre_cbcdecrypt@ --- * \ + * \ + * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Decrypts a block with a block cipher in CBC mode, with \ + * ciphertext stealing and other clever tricks. \ + * Essentially, data can be encrypted in arbitrary sized \ + * chunks, although decryption must use the same chunks. \ + */ \ + \ +extern void pre##_cbcdecrypt(pre##_cbcctx */*ctx*/, \ + const void */*src*/, void */*dest*/, \ + size_t /*sz*/); \ + \ +/* --- Generic cipher interface --- */ \ + \ +extern const gccipher pre##_cbc; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/cfb-def.h b/symm/cfb-def.h new file mode 100644 index 0000000..767f4c4 --- /dev/null +++ b/symm/cfb-def.h @@ -0,0 +1,506 @@ +/* -*-c-*- + * + * Definitions for ciphertext feedback mode + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_CFB_DEF_H +#define CATACOMB_CFB_DEF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include +#include + +#ifndef CATACOMB_ARENA_H +# include "arena.h" +#endif + +#ifndef CATACOMB_BLKC_H +# include "blkc.h" +#endif + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +#ifndef CATACOMB_PARANOIA_H +# include "paranoia.h" +#endif + +#ifndef CATACOMB_PARANOIA_H +# include "paranoia.h" +#endif + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @CFB_DEF@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher + * + * Use: Creates an implementation for CFB mode. + */ + +#define CFB_DEF(PRE, pre) \ + \ +/* --- @pre_cfbgetiv@ --- * \ + * \ + * Arguments: @const pre_cfbctx *ctx@ = pointer to CFB context block \ + * @void *iv@ = pointer to output data block \ + * \ + * Returns: --- \ + * \ + * Use: Reads the currently set IV. Reading and setting an IV \ + * is not transparent to the cipher. It will add a `step' \ + * which must be matched by a similar operation during \ + * decryption. \ + */ \ + \ +void pre##_cfbgetiv(const pre##_cfbctx *ctx, void *iv) \ +{ \ + octet *p = iv; \ + unsigned off = ctx->off; \ + unsigned rest = PRE##_BLKSZ - off; \ + memcpy(p, ctx->iv + off, rest); \ + memcpy(p + rest, ctx->iv, off); \ +} \ + \ +/* --- @pre_cfbsetiv@ --- * \ + * \ + * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ + * @cnost void *iv@ = pointer to IV to set \ + * \ + * Returns: --- \ + * \ + * Use: Sets the IV to use for subsequent encryption. \ + */ \ + \ +void pre##_cfbsetiv(pre##_cfbctx *ctx, const void *iv) \ +{ \ + memcpy(ctx->iv, iv, PRE##_BLKSZ); \ + ctx->off = PRE##_BLKSZ; \ +} \ + \ +/* --- @pre_cfbbdry@ --- * \ + * \ + * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ + * \ + * Returns: --- \ + * \ + * Use: Inserts a boundary during encryption. Successful \ + * decryption must place a similar boundary. \ + */ \ + \ +void pre##_cfbbdry(pre##_cfbctx *ctx) \ +{ \ + uint32 niv[PRE##_BLKSZ / 4]; \ + BLKC_LOAD(PRE, niv, ctx->iv); \ + pre##_eblk(&ctx->ctx, niv, niv); \ + BLKC_STORE(PRE, ctx->iv, niv); \ + ctx->off = PRE##_BLKSZ; \ + BURN(niv); \ +} \ + \ +/* --- @pre_cfbsetkey@ --- * \ + * \ + * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ + * @const pre_ctx *k@ = pointer to cipher context \ + * \ + * Returns: --- \ + * \ + * Use: Sets the CFB context to use a different cipher key. \ + */ \ + \ +void pre##_cfbsetkey(pre##_cfbctx *ctx, const pre##_ctx *k) \ +{ \ + ctx->ctx = *k; \ + ctx->off = PRE##_BLKSZ; \ +} \ + \ +/* --- @pre_cfbinit@ --- * \ + * \ + * Arguments: @pre_cfbctx *ctx@ = pointer to cipher context \ + * @const void *key@ = pointer to the key buffer \ + * @size_t sz@ = size of the key \ + * @const void *iv@ = pointer to initialization vector \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a CFB context ready for use. You should \ + * ensure that the IV chosen is unique: reusing an IV will \ + * compromise the security of at least the first block \ + * encrypted. This is equivalent to calls to @pre_init@, \ + * @pre_cfbsetkey@ and @pre_cfbsetiv@. \ + */ \ + \ +void pre##_cfbinit(pre##_cfbctx *ctx, \ + const void *key, size_t sz, \ + const void *iv) \ +{ \ + static const octet zero[PRE##_BLKSZ] = { 0 }; \ + pre##_init(&ctx->ctx, key, sz); \ + pre##_cfbsetiv(ctx, iv ? iv : zero); \ +} \ + \ +/* --- @pre_cfbencrypt@ --- * \ + * \ + * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Encrypts a block with a block cipher in CFB mode. The \ + * input block may be arbitrary in size. CFB mode is not \ + * sensitive to block boundaries. \ + */ \ + \ +void pre##_cfbencrypt(pre##_cfbctx *ctx, \ + const void *src, void *dest, \ + size_t sz) \ +{ \ + const octet *s = src; \ + octet *d = dest; \ + unsigned off = ctx->off; \ + \ + /* --- Empty blocks are trivial --- */ \ + \ + if (!sz) \ + return; \ + \ + /* --- If I can deal with the block from my buffer, do that --- */ \ + \ + if (sz < PRE##_BLKSZ - off) \ + goto small; \ + \ + /* --- Finish off what's left in my buffer --- */ \ + \ + while (off < PRE##_BLKSZ) { \ + register octet x = *s++; \ + ctx->iv[off] ^= x; \ + if (d) *d++ = ctx->iv[off]; \ + off++; \ + sz--; \ + } \ + \ + /* --- Main encryption loop --- */ \ + \ + { \ + uint32 iv[PRE##_BLKSZ / 4]; \ + BLKC_LOAD(PRE, iv, ctx->iv); \ + \ + for (;;) { \ + pre##_eblk(&ctx->ctx, iv, iv); \ + if (sz < PRE##_BLKSZ) \ + break; \ + if (s) { \ + BLKC_XLOAD(PRE, iv, s); \ + s += PRE##_BLKSZ; \ + } \ + if (d) { \ + BLKC_STORE(PRE, d, iv); \ + d += PRE##_BLKSZ; \ + } \ + sz -= PRE##_BLKSZ; \ + } \ + off = 0; \ + BLKC_STORE(PRE, ctx->iv, iv); \ + } \ + \ + /* --- Tidying up the tail end --- */ \ + \ + if (sz) { \ + small: \ + do { \ + register octet x = *s++; \ + ctx->iv[off] ^= x; \ + if (d) *d++ = ctx->iv[off]; \ + off++; \ + sz--; \ + } while (sz); \ + } \ + \ + /* --- Done --- */ \ + \ + ctx->off = off; \ + return; \ +} \ + \ +/* --- @pre_cfbdecrypt@ --- * \ + * \ + * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Decrypts a block with a block cipher in CFB mode. The \ + * input block may be arbitrary in size. CFB mode is not \ + * sensitive to block boundaries. \ + */ \ + \ +void pre##_cfbdecrypt(pre##_cfbctx *ctx, \ + const void *src, void *dest, \ + size_t sz) \ +{ \ + const octet *s = src; \ + octet *d = dest; \ + unsigned off = ctx->off; \ + \ + /* --- Empty blocks are trivial --- */ \ + \ + if (!sz) \ + return; \ + \ + /* --- If I can deal with the block from my buffer, do that --- */ \ + \ + if (sz < PRE##_BLKSZ - off) \ + goto small; \ + \ + /* --- Finish off what's left in my buffer --- */ \ + \ + while (off < PRE##_BLKSZ) { \ + register octet x = *s++; \ + *d++ = ctx->iv[off] ^ x; \ + ctx->iv[off++] = x; \ + sz--; \ + } \ + \ + /* --- Main encryption loop --- */ \ + \ + { \ + uint32 iv[PRE##_BLKSZ / 4]; \ + BLKC_LOAD(PRE, iv, ctx->iv); \ + \ + for (;;) { \ + uint32 x[PRE##_BLKSZ / 4]; \ + pre##_eblk(&ctx->ctx, iv, iv); \ + if (sz < PRE##_BLKSZ) \ + break; \ + BLKC_LOAD(PRE, x, s); \ + BLKC_XSTORE(PRE, d, iv, x); \ + BLKC_MOVE(PRE, iv, x); \ + s += PRE##_BLKSZ; \ + d += PRE##_BLKSZ; \ + sz -= PRE##_BLKSZ; \ + } \ + off = 0; \ + BLKC_STORE(PRE, ctx->iv, iv); \ + } \ + \ + /* --- Tidying up the tail end --- */ \ + \ + if (sz) { \ + small: \ + do { \ + register octet x = *s++; \ + *d++ = ctx->iv[off] ^ x; \ + ctx->iv[off++] = x; \ + sz--; \ + } while (sz); \ + } \ + \ + /* --- Done --- */ \ + \ + ctx->off = off; \ + return; \ +} \ + \ +/* --- Generic cipher interface --- */ \ + \ +static const gcipher_ops gops; \ + \ +typedef struct gctx { \ + gcipher c; \ + pre##_cfbctx k; \ +} gctx; \ + \ +static gcipher *ginit(const void *k, size_t sz) \ +{ \ + gctx *g = S_CREATE(gctx); \ + g->c.ops = &gops; \ + pre##_cfbinit(&g->k, k, sz, 0); \ + return (&g->c); \ +} \ + \ +static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_cfbencrypt(&g->k, s, t, sz); \ +} \ + \ +static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_cfbdecrypt(&g->k, s, t, sz); \ +} \ + \ +static void gdestroy(gcipher *c) \ +{ \ + gctx *g = (gctx *)c; \ + BURN(*g); \ + S_DESTROY(g); \ +} \ + \ +static void gsetiv(gcipher *c, const void *iv) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_cfbsetiv(&g->k, iv); \ +} \ + \ +static void gbdry(gcipher *c) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_cfbbdry(&g->k); \ +} \ + \ +static const gcipher_ops gops = { \ + &pre##_cfb, \ + gencrypt, gdecrypt, gdestroy, gsetiv, gbdry \ +}; \ + \ +const gccipher pre##_cfb = { \ + #pre "-cfb", pre##_keysz, PRE##_BLKSZ, \ + ginit \ +}; \ + \ +CFB_TEST(PRE, pre) + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +#include "daftstory.h" + +/* --- @CFB_TEST@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions + * + * Use: Standard test rig for CFB functions. + */ + +#define CFB_TEST(PRE, pre) \ + \ +/* --- Initial plaintext for the test --- */ \ + \ +static const octet text[] = TEXT; \ + \ +/* --- Key and IV to use --- */ \ + \ +static const octet key[] = KEY; \ +static const octet iv[] = IV; \ + \ +/* --- Buffers for encryption and decryption output --- */ \ + \ +static octet ct[sizeof(text)]; \ +static octet pt[sizeof(text)]; \ + \ +static void hexdump(const octet *p, size_t sz) \ +{ \ + const octet *q = p + sz; \ + for (sz = 0; p < q; p++, sz++) { \ + printf("%02x", *p); \ + if ((sz + 1) % PRE##_BLKSZ == 0) \ + putchar(':'); \ + } \ +} \ + \ +int main(void) \ +{ \ + size_t sz = 0, rest; \ + pre##_cfbctx ctx; \ + int status = 0; \ + int done = 0; \ + pre##_ctx k; \ + \ + size_t keysz = PRE##_KEYSZ ? \ + PRE##_KEYSZ : strlen((const char *)key); \ + \ + fputs(#pre "-cfb: ", stdout); \ + \ + pre##_init(&k, key, keysz); \ + pre##_cfbsetkey(&ctx, &k); \ + \ + while (sz <= sizeof(text)) { \ + rest = sizeof(text) - sz; \ + memcpy(ct, text, sizeof(text)); \ + pre##_cfbsetiv(&ctx, iv); \ + pre##_cfbencrypt(&ctx, ct, ct, sz); \ + pre##_cfbencrypt(&ctx, ct + sz, ct + sz, rest); \ + memcpy(pt, ct, sizeof(text)); \ + pre##_cfbsetiv(&ctx, iv); \ + pre##_cfbdecrypt(&ctx, pt, pt, rest); \ + pre##_cfbdecrypt(&ctx, pt + rest, pt + rest, sz); \ + if (memcmp(pt, text, sizeof(text)) == 0) { \ + done++; \ + if (sizeof(text) < 40 || done % 8 == 0) \ + fputc('.', stdout); \ + if (done % 480 == 0) \ + fputs("\n\t", stdout); \ + fflush(stdout); \ + } else { \ + printf("\nError (sz = %lu)\n", (unsigned long)sz); \ + status = 1; \ + printf("\tplaintext = "); hexdump(text, sz); \ + printf(", "); hexdump(text + sz, rest); \ + fputc('\n', stdout); \ + printf("\tciphertext = "); hexdump(ct, sz); \ + printf(", "); hexdump(ct + sz, rest); \ + fputc('\n', stdout); \ + printf("\trecovered text = "); hexdump(pt, sz); \ + printf(", "); hexdump(pt + sz, rest); \ + fputc('\n', stdout); \ + fputc('\n', stdout); \ + } \ + if (sz < 63) \ + sz++; \ + else \ + sz += 9; \ + } \ + \ + fputs(status ? " failed\n" : " ok\n", stdout); \ + return (status); \ +} + +#else +# define CFB_TEST(PRE, pre) +#endif + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/cfb.h b/symm/cfb.h new file mode 100644 index 0000000..c357115 --- /dev/null +++ b/symm/cfb.h @@ -0,0 +1,184 @@ +/* -*-c-*- + * + * Ciphertext feedback for block ciphers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_CFB_H +#define CATACOMB_CFB_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- @CFB_DECL@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher + * + * Use: Creates declarations for CFB mode. + */ + +#define CFB_DECL(PRE, pre) \ + \ +/* --- Ciphertext feedback context --- */ \ + \ +typedef struct pre##_cfbctx { \ + pre##_ctx ctx; /* Underlying cipher context */ \ + unsigned off; /* Offset into @iv@ buffer */ \ + octet iv[PRE##_BLKSZ]; /* Previous ciphertext or IV */ \ +} pre##_cfbctx; \ + \ +/* --- @pre_cfbgetiv@ --- * \ + * \ + * Arguments: @const pre_cfbctx *ctx@ = pointer to CFB context block \ + * @void *iv@ = pointer to output data block \ + * \ + * Returns: --- \ + * \ + * Use: Reads the currently set IV. Reading and setting an IV \ + * is not transparent to the cipher. It will add a `step' \ + * which must be matched by a similar operation during \ + * decryption. \ + */ \ + \ +extern void pre##_cfbgetiv(const pre##_cfbctx */*ctx*/, \ + void */*iv*/); \ + \ +/* --- @pre_cfbsetiv@ --- * \ + * \ + * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ + * @cnost void *iv@ = pointer to IV to set \ + * \ + * Returns: --- \ + * \ + * Use: Sets the IV to use for subsequent encryption. \ + */ \ + \ +extern void pre##_cfbsetiv(pre##_cfbctx */*ctx*/, \ + const void */*iv*/); \ + \ +/* --- @pre_cfbbdry@ --- * \ + * \ + * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ + * \ + * Returns: --- \ + * \ + * Use: Inserts a boundary during encryption. Successful \ + * decryption must place a similar boundary. \ + */ \ + \ +extern void pre##_cfbbdry(pre##_cfbctx */*ctx*/); \ + \ +/* --- @pre_cfbsetkey@ --- * \ + * \ + * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ + * @const pre_ctx *k@ = pointer to cipher context \ + * \ + * Returns: --- \ + * \ + * Use: Sets the CFB context to use a different cipher key. \ + */ \ + \ +extern void pre##_cfbsetkey(pre##_cfbctx */*ctx*/, \ + const pre##_ctx */*k*/); \ + \ +/* --- @pre_cfbinit@ --- * \ + * \ + * Arguments: @pre_cfbctx *ctx@ = pointer to cipher context \ + * @const void *key@ = pointer to the key buffer \ + * @size_t sz@ = size of the key \ + * @const void *iv@ = pointer to initialization vector \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a CFB context ready for use. You should \ + * ensure that the IV chosen is unique: reusing an IV will \ + * compromise the security of at least the first block \ + * encrypted. This is equivalent to calls to @pre_init@, \ + * @pre_cfbsetkey@ and @pre_cfbsetiv@. \ + */ \ + \ +extern void pre##_cfbinit(pre##_cfbctx */*ctx*/, \ + const void */*key*/, size_t /*sz*/, \ + const void */*iv*/); \ + \ +/* --- @pre_cfbencrypt@ --- * \ + * \ + * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Encrypts a block with a block cipher in CFB mode. The \ + * input block may be arbitrary in size. CFB mode is not \ + * sensitive to block boundaries. \ + */ \ + \ +extern void pre##_cfbencrypt(pre##_cfbctx */*ctx*/, \ + const void */*src*/, void */*dest*/, \ + size_t /*sz*/); \ + \ +/* --- @pre_cfbencrypt@ --- * \ + * \ + * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Decrypts a block with a block cipher in CFB mode. The \ + * input block may be arbitrary in size. CFB mode is not \ + * sensitive to block boundaries. \ + */ \ + \ +extern void pre##_cfbdecrypt(pre##_cfbctx */*ctx*/, \ + const void */*src*/, void */*dest*/, \ + size_t /*sz*/); \ + \ +/* --- Generic cipher interface --- */ \ + \ +extern const gccipher pre##_cfb; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/counter-def.h b/symm/counter-def.h new file mode 100644 index 0000000..2f35323 --- /dev/null +++ b/symm/counter-def.h @@ -0,0 +1,533 @@ +/* -*-c-*- + * + * Block cipher counter mode (or long cycle mode) + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_COUNTER_DEF_H +#define CATACOMB_COUNTER_DEF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include +#include + +#ifndef CATACOMB_ARENA_H +# include "arena.h" +#endif + +#ifndef CATACOMB_BLKC_H +# include "blkc.h" +#endif + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +#ifndef CATACOMB_PARANOIA_H +# include "paranoia.h" +#endif + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @COUNTER_DEF@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher + * + * Use: Creates definitions for counter mode. + */ + +#define COUNTER_DEF(PRE, pre) \ + \ +/* --- @pre_countergetiv@ --- * \ + * \ + * Arguments: @const pre_counterctx *ctx@ = pointer to counter \ + * context \ + * @void *iv@ = pointer to output data block \ + * \ + * Returns: --- \ + * \ + * Use: Reads the currently set IV. Reading and setting an IV \ + * is not transparent to the cipher. It will add a `step' \ + * which must be matched by a similar operation during \ + * decryption. \ + */ \ + \ +void pre##_countergetiv(const pre##_counterctx *ctx, void *iv) \ +{ \ + BLKC_STORE(PRE, iv, ctx->n); \ +} \ + \ +/* --- @pre_countersetiv@ --- * \ + * \ + * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ + * @cnost void *iv@ = pointer to IV to set \ + * \ + * Returns: --- \ + * \ + * Use: Sets the IV to use for subsequent encryption. \ + */ \ + \ +void pre##_countersetiv(pre##_counterctx *ctx, const void *iv) \ +{ \ + BLKC_LOAD(PRE, ctx->n, iv); \ + ctx->off = PRE##_BLKSZ; \ +} \ + \ +/* --- @pre_counterbdry@ --- * \ + * \ + * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ + * \ + * Returns: --- \ + * \ + * Use: Inserts a boundary during encryption. Successful \ + * decryption must place a similar boundary. \ + */ \ + \ +void pre##_counterbdry(pre##_counterctx *ctx) \ +{ \ + BLKC_STEP(PRE, ctx->n); \ + ctx->off = PRE##_BLKSZ; \ +} \ + \ +/* --- @pre_countersetkey@ --- * \ + * \ + * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ + * @const pre_ctx *k@ = pointer to cipher context \ + * \ + * Returns: --- \ + * \ + * Use: Sets the counter context to use a different cipher key. \ + */ \ + \ +void pre##_countersetkey(pre##_counterctx *ctx, const pre##_ctx *k) \ +{ \ + ctx->ctx = *k; \ +} \ + \ +/* --- @pre_counterinit@ --- * \ + * \ + * Arguments: @pre_counterctx *ctx@ = pointer to cipher context \ + * @const void *key@ = pointer to the key buffer \ + * @size_t sz@ = size of the key \ + * @const void *iv@ = pointer to initialization vector \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a counter context ready for use. You \ + * should ensure that the IV chosen is unique: reusing an \ + * IV will compromise the security of the entire \ + * plaintext. This is equivalent to calls to @pre_init@, \ + * @pre_countersetkey@ and @pre_countersetiv@. \ + */ \ + \ +void pre##_counterinit(pre##_counterctx *ctx, \ + const void *key, size_t sz, \ + const void *iv) \ +{ \ + static const octet zero[PRE##_BLKSZ] = { 0 }; \ + pre##_init(&ctx->ctx, key, sz); \ + pre##_countersetiv(ctx, iv ? iv : zero); \ +} \ + \ +/* --- @pre_counterencrypt@ --- * \ + * \ + * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Encrypts or decrypts a block with a block cipher in \ + * counter mode: encryption and decryption are the same in \ + * counter. The destination may be null to just churn the \ + * feedback round for a bit. The source may be null to \ + * use the cipher as a random data generator. \ + */ \ + \ +void pre##_counterencrypt(pre##_counterctx *ctx, \ + const void *src, void *dest, \ + size_t sz) \ +{ \ + const octet *s = src; \ + octet *d = dest; \ + unsigned off = ctx->off; \ + \ + /* --- Empty blocks are trivial --- */ \ + \ + if (!sz) \ + return; \ + \ + /* --- If I can deal with the block from my buffer, do that --- */ \ + \ + if (sz < PRE##_BLKSZ - off) \ + goto small; \ + \ + /* --- Finish off what's left in my buffer --- */ \ + \ + if (!d) \ + sz -= PRE##_BLKSZ - off; \ + else { \ + while (off < PRE##_BLKSZ) { \ + register octet x = s ? *s++ : 0; \ + *d++ = ctx->buf[off++] ^ x; \ + sz--; \ + } \ + } \ + \ + /* --- Main encryption loop --- */ \ + \ + { \ + uint32 n[PRE##_BLKSZ / 4]; \ + \ + for (;;) { \ + pre##_eblk(&ctx->ctx, ctx->n, n); \ + BLKC_STEP(PRE, ctx->n); \ + if (sz < PRE##_BLKSZ) \ + break; \ + if (d) { \ + if (!s) \ + BLKC_STORE(PRE, d, n); \ + else { \ + uint32 x[PRE##_BLKSZ / 4]; \ + BLKC_LOAD(PRE, x, s); \ + BLKC_XSTORE(PRE, d, n, x); \ + s += PRE##_BLKSZ; \ + } \ + d += PRE##_BLKSZ; \ + } \ + sz -= PRE##_BLKSZ; \ + } \ + \ + BLKC_STORE(PRE, ctx->buf, n); \ + off = 0; \ + } \ + \ + /* --- Tidying up the tail end --- */ \ + \ + if (sz) { \ + small: \ + if (!d) \ + off += sz; \ + else do { \ + register octet x = s ? *s++ : 0; \ + *d++ = ctx->buf[off++] ^ x; \ + sz--; \ + } while (sz); \ + } \ + \ + /* --- Done --- */ \ + \ + ctx->off = off; \ + return; \ +} \ + \ +/* --- Generic cipher interface --- */ \ + \ +static const gcipher_ops gops; \ + \ +typedef struct gctx { \ + gcipher c; \ + pre##_counterctx k; \ +} gctx; \ + \ +static gcipher *ginit(const void *k, size_t sz) \ +{ \ + gctx *g = S_CREATE(gctx); \ + g->c.ops = &gops; \ + pre##_counterinit(&g->k, k, sz, 0); \ + return (&g->c); \ +} \ + \ +static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_counterencrypt(&g->k, s, t, sz); \ +} \ + \ +static void gdestroy(gcipher *c) \ +{ \ + gctx *g = (gctx *)c; \ + BURN(*g); \ + S_DESTROY(g); \ +} \ + \ +static void gsetiv(gcipher *c, const void *iv) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_countersetiv(&g->k, iv); \ +} \ + \ +static void gbdry(gcipher *c) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_counterbdry(&g->k); \ +} \ + \ +static const gcipher_ops gops = { \ + &pre##_counter, \ + gencrypt, gencrypt, gdestroy, gsetiv, gbdry \ +}; \ + \ +const gccipher pre##_counter = { \ + #pre "-counter", pre##_keysz, PRE##_BLKSZ, \ + ginit \ +}; \ + \ +/* --- Generic random number generator interface --- */ \ + \ +typedef struct grctx { \ + grand r; \ + pre##_counterctx k; \ +} grctx; \ + \ +static void grdestroy(grand *r) \ +{ \ + grctx *g = (grctx *)r; \ + BURN(*g); \ + S_DESTROY(g); \ +} \ + \ +static int grmisc(grand *r, unsigned op, ...) \ +{ \ + grctx *g = (grctx *)r; \ + va_list ap; \ + int rc = 0; \ + octet buf[PRE##_BLKSZ]; \ + va_start(ap, op); \ + \ + switch (op) { \ + case GRAND_CHECK: \ + switch (va_arg(ap, unsigned)) { \ + case GRAND_CHECK: \ + case GRAND_SEEDINT: \ + case GRAND_SEEDUINT32: \ + case GRAND_SEEDBLOCK: \ + case GRAND_SEEDRAND: \ + rc = 1; \ + break; \ + default: \ + rc = 0; \ + break; \ + } \ + break; \ + case GRAND_SEEDINT: \ + BLKC_SET(PRE, g->k.n, va_arg(ap, unsigned)); \ + g->k.off = PRE##_BLKSZ; \ + break; \ + case GRAND_SEEDUINT32: \ + BLKC_SET(PRE, g->k.n, va_arg(ap, uint32)); \ + g->k.off = PRE##_BLKSZ; \ + break; \ + case GRAND_SEEDBLOCK: { \ + const void *p = va_arg(ap, const void *); \ + size_t sz = va_arg(ap, size_t); \ + if (sz < sizeof(buf)) { \ + memset(buf, 0, sizeof(buf)); \ + memcpy(buf, p, sz); \ + p = buf; \ + } \ + pre##_countersetiv(&g->k, p); \ + } break; \ + case GRAND_SEEDRAND: { \ + grand *rr = va_arg(ap, grand *); \ + rr->ops->fill(rr, buf, sizeof(buf)); \ + pre##_countersetiv(&g->k, buf); \ + } break; \ + default: \ + GRAND_BADOP; \ + break; \ + } \ + \ + va_end(ap); \ + return (rc); \ +} \ + \ +static octet grbyte(grand *r) \ +{ \ + grctx *g = (grctx *)r; \ + octet o; \ + pre##_counterencrypt(&g->k, 0, &o, 1); \ + return (o); \ +} \ + \ +static uint32 grword(grand *r) \ +{ \ + grctx *g = (grctx *)r; \ + octet b[4]; \ + pre##_counterencrypt(&g->k, 0, b, sizeof(b)); \ + return (LOAD32(b)); \ +} \ + \ +static void grfill(grand *r, void *p, size_t sz) \ +{ \ + grctx *g = (grctx *)r; \ + pre##_counterencrypt(&g->k, 0, p, sz); \ +} \ + \ +static const grand_ops grops = { \ + #pre "-counter", \ + GRAND_CRYPTO, 0, \ + grmisc, grdestroy, \ + grword, grbyte, grword, grand_range, grfill \ +}; \ + \ +/* --- @pre_counterrand@ --- * \ + * \ + * Arguments: @const void *k@ = pointer to key material \ + * @size_t sz@ = size of key material \ + * \ + * Returns: Pointer to generic random number generator interface. \ + * \ + * Use: Creates a random number interface wrapper around an \ + * counter-mode block cipher. \ + */ \ + \ +grand *pre##_counterrand(const void *k, size_t sz) \ +{ \ + grctx *g = S_CREATE(grctx); \ + g->r.ops = &grops; \ + pre##_counterinit(&g->k, k, sz, 0); \ + return (&g->r); \ +} \ + \ +COUNTER_TEST(PRE, pre) + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +#include "daftstory.h" + +/* --- @COUNTER_TEST@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions + * + * Use: Standard test rig for counter functions. + */ + +#define COUNTER_TEST(PRE, pre) \ + \ +/* --- Initial plaintext for the test --- */ \ + \ +static const octet text[] = TEXT; \ + \ +/* --- Key and IV to use --- */ \ + \ +static const octet key[] = KEY; \ +static const octet iv[] = IV; \ + \ +/* --- Buffers for encryption and decryption output --- */ \ + \ +static octet ct[sizeof(text)]; \ +static octet pt[sizeof(text)]; \ + \ +static void hexdump(const octet *p, size_t sz) \ +{ \ + const octet *q = p + sz; \ + for (sz = 0; p < q; p++, sz++) { \ + printf("%02x", *p); \ + if ((sz + 1) % PRE##_BLKSZ == 0) \ + putchar(':'); \ + } \ +} \ + \ +int main(void) \ +{ \ + size_t sz = 0, rest; \ + pre##_counterctx ctx; \ + int status = 0; \ + int done = 0; \ + pre##_ctx k; \ + \ + size_t keysz = PRE##_KEYSZ ? \ + PRE##_KEYSZ : strlen((const char *)key); \ + \ + fputs(#pre "-counter: ", stdout); \ + \ + pre##_init(&k, key, keysz); \ + pre##_countersetkey(&ctx, &k); \ + \ + while (sz <= sizeof(text)) { \ + rest = sizeof(text) - sz; \ + memcpy(ct, text, sizeof(text)); \ + pre##_countersetiv(&ctx, iv); \ + pre##_counterencrypt(&ctx, ct, ct, sz); \ + pre##_counterencrypt(&ctx, ct + sz, ct + sz, rest); \ + memcpy(pt, ct, sizeof(text)); \ + pre##_countersetiv(&ctx, iv); \ + pre##_counterencrypt(&ctx, pt, pt, rest); \ + pre##_counterencrypt(&ctx, pt + rest, pt + rest, sz); \ + if (memcmp(pt, text, sizeof(text)) == 0) { \ + done++; \ + if (sizeof(text) < 40 || done % 8 == 0) \ + fputc('.', stdout); \ + if (done % 480 == 0) \ + fputs("\n\t", stdout); \ + fflush(stdout); \ + } else { \ + printf("\nError (sz = %lu)\n", (unsigned long)sz); \ + status = 1; \ + printf("\tplaintext = "); hexdump(text, sz); \ + printf(", "); hexdump(text + sz, rest); \ + fputc('\n', stdout); \ + printf("\tciphertext = "); hexdump(ct, sz); \ + printf(", "); hexdump(ct + sz, rest); \ + fputc('\n', stdout); \ + printf("\trecovered text = "); hexdump(pt, sz); \ + printf(", "); hexdump(pt + sz, rest); \ + fputc('\n', stdout); \ + fputc('\n', stdout); \ + } \ + if (sz < 63) \ + sz++; \ + else \ + sz += 9; \ + } \ + \ + fputs(status ? " failed\n" : " ok\n", stdout); \ + return (status); \ +} + +#else +# define COUNTER_TEST(PRE, pre) +#endif + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/counter.h b/symm/counter.h new file mode 100644 index 0000000..7e07b3c --- /dev/null +++ b/symm/counter.h @@ -0,0 +1,187 @@ +/* -*-c-*- + * + * Block cipher counter mode (or long cycle mode) + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_COUNTER_H +#define CATACOMB_COUNTER_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @COUNTER_DECL@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions + * + * Use: Makes declarations for counter mode. + */ + +#define COUNTER_DECL(PRE, pre) \ + \ +/* --- Counter mode context --- */ \ + \ +typedef struct pre##_counterctx { \ + pre##_ctx ctx; /* Underlying cipher context */ \ + unsigned off; /* Current offset in buffer */ \ + octet buf[PRE##_BLKSZ]; /* Output buffer */ \ + uint32 n[PRE##_BLKSZ / 4]; /* Counter */ \ +} pre##_counterctx; \ + \ +/* --- @pre_countergetiv@ --- * \ + * \ + * Arguments: @const pre_counterctx *ctx@ = pointer to counter \ + * context \ + * @void *iv@ = pointer to output data block \ + * \ + * Returns: --- \ + * \ + * Use: Reads the currently set IV. Reading and setting an IV \ + * is not transparent to the cipher. It will add a `step' \ + * which must be matched by a similar operation during \ + * decryption. \ + */ \ + \ +extern void pre##_countergetiv(const pre##_counterctx */*ctx*/, \ + void */*iv*/); \ + \ +/* --- @pre_countersetiv@ --- * \ + * \ + * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ + * @cnost void *iv@ = pointer to IV to set \ + * \ + * Returns: --- \ + * \ + * Use: Sets the IV to use for subsequent encryption. \ + */ \ + \ +extern void pre##_countersetiv(pre##_counterctx */*ctx*/, \ + const void */*iv*/); \ + \ +/* --- @pre_counterbdry@ --- * \ + * \ + * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ + * \ + * Returns: --- \ + * \ + * Use: Inserts a boundary during encryption. Successful \ + * decryption must place a similar boundary. \ + */ \ + \ +extern void pre##_counterbdry(pre##_counterctx */*ctx*/); \ + \ +/* --- @pre_countersetkey@ --- * \ + * \ + * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ + * @const pre_ctx *k@ = pointer to cipher context \ + * \ + * Returns: --- \ + * \ + * Use: Sets the counter context to use a different cipher key. \ + */ \ + \ +extern void pre##_countersetkey(pre##_counterctx */*ctx*/, \ + const pre##_ctx */*k*/); \ + \ +/* --- @pre_counterinit@ --- * \ + * \ + * Arguments: @pre_counterctx *ctx@ = pointer to cipher context \ + * @const void *key@ = pointer to the key buffer \ + * @size_t sz@ = size of the key \ + * @const void *iv@ = pointer to initialization vector \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a counter context ready for use. You \ + * should ensure that the IV chosen is unique: reusing an \ + * IV will compromise the security of the entire \ + * plaintext. This is equivalent to calls to @pre_init@, \ + * @pre_countersetkey@ and @pre_countersetiv@. \ + */ \ + \ +extern void pre##_counterinit(pre##_counterctx */*ctx*/, \ + const void */*key*/, size_t /*sz*/, \ + const void */*iv*/); \ + \ +/* --- @pre_counterencrypt@ --- * \ + * \ + * Arguments: @pre_counterctx *ctx@ = pointer to counter context \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Encrypts or decrypts a block with a block cipher in \ + * counter mode: encryption and decryption are the same in \ + * counter. The destination may be null to just churn the \ + * feedback round for a bit. The source may be null to \ + * use the cipher as a random data generator. \ + */ \ + \ +extern void pre##_counterencrypt(pre##_counterctx */*ctx*/, \ + const void */*src*/, void */*dest*/, \ + size_t /*sz*/); \ + \ +/* --- @pre_counterrand@ --- * \ + * \ + * Arguments: @const void *k@ = pointer to key material \ + * @size_t sz@ = size of key material \ + * \ + * Returns: Pointer to generic random number generator interface. \ + * \ + * Use: Creates a random number interface wrapper around an \ + * counter-mode block cipher. \ + */ \ + \ +extern grand *pre##_counterrand(const void */*k*/, size_t /*sz*/); \ + \ +/* --- Generic cipher interface --- */ \ + \ +extern const gccipher pre##_counter; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/crc32.c b/symm/crc32.c new file mode 100644 index 0000000..4b6f27b --- /dev/null +++ b/symm/crc32.c @@ -0,0 +1,89 @@ +/* -*-c-*- + * + * Generic hash wrapper for CRC32 + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include "arena.h" +#include "crc32.h" +#include "ghash.h" +#include "paranoia.h" + +/*----- Main code ---------------------------------------------------------*/ + +typedef struct gctx { + ghash h; + uint32 c; + octet buf[4]; +} gctx; + +static const ghash_ops gops; + +static ghash *ghinit(void) +{ + gctx *g = S_CREATE(gctx); + g->h.ops = &gops; + g->c = 0; + return (&g->h); +} + +static void ghhash(ghash *h, const void *p, size_t sz) +{ + gctx *g = (gctx *)h; + CRC32(g->c, g->c, p, sz); +} + +static octet *ghdone(ghash *h, void *buf) +{ + gctx *g = (gctx *)h; + if (!buf) + buf = g->buf; + STORE32(buf, g->c); + return (buf); +} + +static void ghdestroy(ghash *h) +{ + gctx *g = (gctx *)h; + BURN(*g); + S_DESTROY(g); +} + +static ghash *ghcopy(ghash *h) +{ + gctx *g = (gctx *)h; + gctx *gg = S_CREATE(gctx); + memcpy(gg, g, sizeof(gctx)); + return (&gg->h); +} + +static const ghash_ops gops = { &gcrc32, ghhash, ghdone, ghdestroy, ghcopy }; +const gchash gcrc32 = { "crc32", 4, ghinit }; + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/crc32.h b/symm/crc32.h new file mode 100644 index 0000000..a242273 --- /dev/null +++ b/symm/crc32.h @@ -0,0 +1,53 @@ +/* -*-c-*- + * + * Generic hash wrapper for CRC32 + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_CRC32_H +#define CATACOMB_CRC32_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Generic interface -------------------------------------------------*/ + +extern const gchash gcrc32; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/daftstory.h b/symm/daftstory.h new file mode 100644 index 0000000..b4d6b58 --- /dev/null +++ b/symm/daftstory.h @@ -0,0 +1,76 @@ +/* -*-c-*- + * + * Daft story for use in test encryptions + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_DAFTSTORY_H +#define CATACOMB_DAFTSTORY_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Macros ------------------------------------------------------------*/ + +/* --- Don't ask --- */ + +#ifdef SMALL_TEST +# define TEXT "A small piece of text for testing encryption." +#else +# define STORY "\ +Once upon a time there were a beautiful princess, a slightly nutty wizard,\n\ +and a watermelon. Now, the watermelon had decided that it probably wasn't\n\ +going to get very far with the princess unless it did something pretty\n\ +drastic. So it asked the wizard to turn it into a handsome prince.\n\ +\n\ +At least, this is the way that the wizard viewed the situation. He might\n\ +have just hallucinated it all; those mushrooms had looked ever so nice.\n\ +\n\ +Back to the point. The watermelon had expressed its desire not to be a\n\ +watermelon any more. And the wizard was probably tripping something quite\n\ +powerful. He hunted around a bit for his staff, and mumbled something\n\ +that film directors would think of as sounding appropriately arcane and\n\ +mystical (but was, in fact, just the ingredients list for an ancient\n\ +remedy for athlete's foot) and *pop*. Cooked watermelon. Yuk.\n\ +\n\ +Later in the year, the princess tripped over the hem of her dress, fell\n\ +down a spiral staircase, and died. The king ordered dressmakers to attach\n\ +safety warnings to long dresses.\n\ +\n\ +And the wizard? Who cares?\n\ +" +# define TEXT STORY STORY +#endif + +#define KEY "Penguins rule OK, rhubarb cauliflower" +#define IV "EdgewareCatacomb, parsley, sage, rosemary and thyme" + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/des-base.c b/symm/des-base.c new file mode 100644 index 0000000..4d55881 --- /dev/null +++ b/symm/des-base.c @@ -0,0 +1,39 @@ +/* -*-c-*- + * + * Common features for DES implementation + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "des-base.h" +#include "des-tab.h" + +/*----- Global variables --------------------------------------------------*/ + +const uint32 des_sp[8][64] = DES_SP; + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/des-base.h b/symm/des-base.h new file mode 100644 index 0000000..49bbed7 --- /dev/null +++ b/symm/des-base.h @@ -0,0 +1,156 @@ +/* -*-c-*- + * + * Common features for DES implementation + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_DES_BASE_H +#define CATACOMB_DES_BASE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +/*----- External data -----------------------------------------------------*/ + +extern const uint32 des_sp[8][64]; + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @DES_ROUND@ --- * + * + * This is the basic DES round function. The inputs are the two subkey + * halves, and the left and right block halves. Note that the block halves + * are rotated left one place at this point. This wraps what's meant to be + * the top bit around to the bottom, so I get a clear run at the S-boxes. + */ + +#define DES_ROUND(ka, kb, x, y) do { \ + uint32 _t = (y) ^ (ka); \ + (x) ^= des_sp[7][(_t >> 0) & 0x3f] ^ \ + des_sp[5][(_t >> 8) & 0x3f] ^ \ + des_sp[3][(_t >> 16) & 0x3f] ^ \ + des_sp[1][(_t >> 24) & 0x3f]; \ + _t = ROR32((y), 4) ^ (kb); \ + (x) ^= des_sp[6][(_t >> 0) & 0x3f] ^ \ + des_sp[4][(_t >> 8) & 0x3f] ^ \ + des_sp[2][(_t >> 16) & 0x3f] ^ \ + des_sp[0][(_t >> 24) & 0x3f]; \ +} while (0) + +/* --- @DES_IP@, @DES_IPINV@ --- * + * + * The cryptographically useless initial and final permutations. The initial + * permutation also rotates the two block halves left by one place. This is + * undone by the inverse permutation at the end. + */ + +#define DES_IP(x, y) do { \ + uint32 _t; \ + _t = (y ^ (x >> 4)) & 0x0f0f0f0f; y ^= _t; x ^= _t << 4; \ + _t = (x ^ (x >> 18)) & 0x00003333; x ^= _t; x ^= _t << 18; \ + _t = (y ^ (y >> 18)) & 0x00003333; y ^= _t; y ^= _t << 18; \ + _t = (x ^ (x >> 9)) & 0x00550055; x ^= _t; x ^= _t << 9; \ + _t = (y ^ (y >> 9)) & 0x00550055; y ^= _t; y ^= _t << 9; \ + _t = (x ^ (x >> 24)) & 0x000000ff; x ^= _t; x ^= _t << 24; \ + _t = (y ^ (y >> 24)) & 0x000000ff; y ^= _t; y ^= _t << 24; \ + _t = (y ^ (x >> 16)) & 0x0000ffff; y ^= _t; x ^= _t << 16; \ + x = ROL32(x, 1); y = ROL32(y, 1); \ +} while (0) + +#define DES_IPINV(x, y) do { \ + uint32 _t; \ + x = ROR32(x, 1); y = ROR32(y, 1); \ + _t = (y ^ (x >> 16)) & 0x0000ffff; y ^= _t; x ^= _t << 16; \ + _t = (x ^ (x >> 24)) & 0x000000ff; x ^= _t; x ^= _t << 24; \ + _t = (y ^ (y >> 24)) & 0x000000ff; y ^= _t; y ^= _t << 24; \ + _t = (y ^ (x >> 4)) & 0x0f0f0f0f; y ^= _t; x ^= _t << 4; \ + _t = (x ^ (x >> 18)) & 0x00003333; x ^= _t; x ^= _t << 18; \ + _t = (y ^ (y >> 18)) & 0x00003333; y ^= _t; y ^= _t << 18; \ + _t = (x ^ (x >> 9)) & 0x00550055; x ^= _t; x ^= _t << 9; \ + _t = (y ^ (y >> 9)) & 0x00550055; y ^= _t; y ^= _t << 9; \ +} while (0) + +/* --- @DES_EBLK@, @DES_DBLK@ --- * + * + * Whole block encryption and decryption. + */ + +#define DES_EBLK(k, a, b, c, d) do { \ + const uint32 *_k = (k); \ + uint32 _x = (a), _y = (b); \ + DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ + DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ + DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ + DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ + DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ + DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ + DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ + DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ + DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ + DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ + DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ + DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ + DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ + DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ + DES_ROUND(_k[0], _k[1], _x, _y); _k += 2; \ + DES_ROUND(_k[0], _k[1], _y, _x); _k += 2; \ + (c) = _y; \ + (d) = _x; \ +} while (0) + +#define DES_DBLK(k, a, b, c, d) do { \ + const uint32 *_k = (k) + 32; \ + uint32 _x = (a), _y = (b); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y); \ + _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x); \ + (c) = _y; \ + (d) = _x; \ +} while (0) + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/des-mktab.c b/symm/des-mktab.c new file mode 100644 index 0000000..5dc8c4a --- /dev/null +++ b/symm/des-mktab.c @@ -0,0 +1,285 @@ +/* -*-c-*- + * + * Build combined S-P tables for DES + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include + +/*----- Static variables --------------------------------------------------*/ + +/* --- S boxes --- */ + +static const char s[8][4][16] = { + + /* --- S1 --- */ + + { { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 }, + { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 }, + { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 }, + { 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } }, + + /* --- S2 --- */ + + { { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 }, + { 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 }, + { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 }, + { 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } }, + + /* --- S3 --- */ + + { { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 }, + { 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 }, + { 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 }, + { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } }, + + /* --- S4 --- */ + + { { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 }, + { 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 }, + { 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 }, + { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } }, + + /* --- S5 --- */ + + { { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 }, + { 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 }, + { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 }, + { 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } }, + + /* --- S6 --- */ + + { { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 }, + { 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 }, + { 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 }, + { 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } }, + + /* --- S7 --- */ + + { { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 }, + { 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 }, + { 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 }, + { 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } }, + + /* --- S8 --- */ + + { { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 }, + { 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 }, + { 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 }, + { 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } } +}; + +/* --- P table --- */ + +static char p[32] = { + 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, + 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 +}; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @unique@ --- * + * + * Arguments: @const char *t@ = pointer to table + * @int base@ = base of the data + * @int sz@ = number of elements + * @const char *name@ = name of this table + * @...@ = things to fill in + * + * Returns: Zero if it failed, nonzero if it didn't. + * + * Use: Validates a table. All the elements must be in range and + * unique. + */ + +static int unique(const char *t, int base, int sz, const char *name, ...) +{ + char u[32]; + char nbuf[128]; + int i; + int ok = 1; + + { + va_list ap; + va_start(ap, name); + vsprintf(nbuf, name, ap); + va_end(ap); + } + + if (sz > sizeof(u)) { + fprintf(stderr, "internal error: table `%s' too large\n", nbuf); + exit(EXIT_FAILURE); + } + memset(u, 0, sizeof(u)); + for (i = 0; i < sz; i++) { + int x = t[i] - base; + if (x >= sz) { + fprintf(stderr, "validation error: %i too big (index %i) in %s\n", + x + base, i, nbuf); + ok = 0; + } else if (u[x]) { + fprintf(stderr, "validation error: duplicate %i (index %i) in %s\n", + x + base, i, nbuf); + ok = 0; + } + u[x] = 1; + } + for (i = 0; i < sz; i++) { + if (!u[i]) { + fprintf(stderr, "validation error: missing %i in %s\n", + i + base, nbuf); + ok = 0; + } + } + + return (ok); +} + +/* --- @validate@ --- * + * + * Arguments: --- + * + * Returns: Only if everything's OK. + * + * Use: Validates the tables. A bit. Not much at all... + */ + +static void validate(void) +{ + int i, j; + int ok = 1; + + for (i = 0; i < 8; i++) for (j = 0; j < 4; j++) + if (!unique(s[i][j], 0, 16, "sbox %i, row %i", i, j)) ok = 0; + if (!unique(p, 1, 32, "p")) ok = 0; + if (!ok) + exit(EXIT_FAILURE); +} + +/* --- @permute@ --- * + * + * Arguments: @unsigned long x@ = value to permute + * + * Returns: Permuted version of @x@. + * + * Use: Permutes a number. The result is the input value after + * having been spewed through the @P@ permutation, and then + * (and this is important) rotated left one place. + */ + +static unsigned long permute(unsigned long x) +{ + unsigned long y = 0; + unsigned i; + + for (i = 0; i < 32; i++) { + if (x & (1 << (32 - p[i]))) + y |= (1 << (31 - i)); + } + return (ROL32(y, 1)); +} + +/* --- @mangle@ --- * + * + * Arguments: @const char s[4][16]@ = an s-box + * @unsigned long ss[64]@ = output buffer + * @int bitoff@ = bit offset to use + * + * Returns: --- + * + * Use: Mangles the s-box. Specifically, the bizarre indexing is + * transformed into something sensible, and the result is + * permuted according to the @p@ table. + */ + +static void mangle(const char s[4][16], unsigned long *ss, int bitoff) +{ + unsigned i; + for (i = 0; i < 64; i++) { + unsigned row = ((i & 0x20) >> 4) | (i & 0x01); + unsigned col = (i & 0x1e) >> 1; + ss[i] = permute(s[row][col] << bitoff); + } +} + +/* --- @main@ --- */ + +int main(void) +{ + int i, j; + unsigned long ss[64]; + const char *sep; + + validate(); + + fputs("\ +/* -*-c-*-\n\ + *\n\ + * DES tables [generated]\n\ + */\n\ +\n\ +#ifndef CATACOMB_DES_TAB_H\n\ +#define CATACOMB_DES_TAB_H\n\ +\n\ +#define DES_SP { \\\n\ +", stdout); + for (i = 0; i < 8; i++) { + mangle(s[i], ss, 28 - 4 * i); + printf("\ + \\\n\ + /* --- SP[%i] --- */ \\\n\ + \\\n\ +", i); + sep = " { "; + for (j = 0; j < 64; j++) { + printf("%s0x%08lx", sep, ss[j]); + if (j % 4 == 3) + sep = ", \\\n "; + else + sep = ", "; + } + printf(" }%s \\\n", i == 7 ? "" : ","); + } + fputs("\ +}\n\ +\n\ +#endif\n\ +", stdout); + + if (fclose(stdout)) { + fprintf(stderr, "error writing data\n"); + exit(EXIT_FAILURE); + } + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/des.c b/symm/des.c new file mode 100644 index 0000000..06400a1 --- /dev/null +++ b/symm/des.c @@ -0,0 +1,279 @@ +/* -*-c-*- + * + * The Data Encryption Standard + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include + +#include "blkc.h" +#include "des-base.h" +#include "des.h" +#include "gcipher.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet des_keysz[] = { KSZ_SET, 7, 8, 0 }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @permute@ --- * + * + * Arguments: @const char *p@ = pointer to permutation table + * @uint32 a, b@ = source value to permute + * @uint32 *d@ = destination for value + * + * Returns: --- + * + * Use: Performs a 64-bit permutation. The table is given in the + * normal (but bizarre) DES bit numbering system. That's not to + * say that the tables in this source file are like the normal + * DES tables, because they're not. + */ + +static void permute(const char *p, uint32 a, uint32 b, uint32 *d) +{ + uint32 x = 0, y = 0; + int i; + + for (i = 0; i < 32; i++) { + int q = p[i]; + uint32 t; + if (!q) + continue; + else if (q <= 32) + t = a; + else { + t = b; + q -= 32; + } + if (t & (1 << (32 - q))) + x |= (1 << (31 - i)); + } + + p += 32; + + for (i = 0; i < 32; i++) { + int q = p[i]; + uint32 t; + if (!q) + continue; + else if (q <= 32) + t = a; + else { + t = b; + q -= 32; + } + if (t & (1 << (32 - q))) + y |= (1 << (31 - i)); + } + + d[0] = x; + d[1] = y; +} + +/* --- @des_expand@ --- * + * + * Arguments: @const octet *k@ = pointer to key material + * @size_t n@ = number of octets of key material (7 or 8) + * @uint32 *xx, *yy@ = where to put the results + * + * Returns: --- + * + * Use: Extracts 64 bits of key material from the given buffer, + * possibly expanding it from 56 to 64 bits on the way. + * Parity is set correctly if the key is expanded. + */ + +void des_expand(const octet *k, size_t n, uint32 *xx, uint32 *yy) +{ + uint32 x, y, z; + + if (n == 8) { + x = LOAD32(k + 0); + y = LOAD32(k + 4); + } else { + x = LOAD32(k + 0); + x = (x & 0xfe000000) | ((x & 0x01fffff0) >> 1); + x = (x & 0xfffe0000) | ((x & 0x0001fff8) >> 1); + x = (x & 0xfffffe00) | ((x & 0x000001fc) >> 1); + z = x; z ^= z >> 4; z ^= z >> 2; z ^= z >> 1; + x |= (z & 0x01010101) ^ 0x01010101; + y = LOAD32(k + 3) << 1; /* Note: misaligned */ + y = (y & 0x000000fe) | ((y & 0x1fffff00) << 1); + y = (y & 0x0000fefe) | ((y & 0x3fff0000) << 1); + y = (y & 0x00fefefe) | ((y & 0x7f000000) << 1); + z = y; z ^= z >> 4; z ^= z >> 2; z ^= z >> 1; + y |= (z & 0x01010101) ^ 0x01010101; + } + *xx = x; *yy = y; +} + +/* --- @des_init@ --- * + * + * Arguments: @des_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a DES key buffer. The key buffer may be either 7 + * or 8 bytes long. If it's 8 bytes, the key is assumed to be + * padded with parity bits in the low order bit of each octet. + * These are stripped out without checking prior to the actual + * key scheduling. + */ + +void des_init(des_ctx *k, const void *buf, size_t sz) +{ + uint32 x, y; + uint32 *kp = k->k; + uint32 ka[2]; + int i; + + /* --- @pc1@ --- * + * + * This cryptographically useless permutation is used to mangle the key + * before it's subjected to the key schedule proper. I've not actually + * messed it about much except for inserting padding at the beginning of + * the two halves of the key. + */ + + static const char pc1[] = { + 0, 0, 0, 0, + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + 0, 0, 0, 0, + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 + }; + + /* --- @pc2@ --- * + * + * This irritating but necessary permutation mangles the key between the + * simple rotation-based schedule and the actual XOR with which it modifies + * the behaviour of the cipher. + * + * This version of the table doesn't look much like the original. This is + * because some parts of the world have been permuted in order to make + * things simpler for the round function. In particular, everything is + * rotated left one place to avoid problems with the wraparound of the + * expansion permutation, and the key is split between odd and even S-boxes + * rather than high and low ones. That's without the complication of the + * padding bits in the representation of the 56-bit proto-key. + */ + + static const char pc2[] = { + 0, 0, 3 + 4, 28 + 4, 15 + 4, 6 + 4, 21 + 4, 10 + 4, /* S-box 2 */ + 0, 0, 16 + 4, 7 + 4, 27 + 4, 20 + 4, 13 + 4, 2 + 4, /* S-box 4 */ + 0, 0, 30 + 8, 40 + 8, 51 + 8, 45 + 8, 33 + 8, 48 + 8, /* S-box 6 */ + 0, 0, 46 + 8, 42 + 8, 50 + 8, 36 + 8, 29 + 8, 32 + 8, /* S-box 8 */ + 0, 0, 14 + 4, 17 + 4, 11 + 4, 24 + 4, 1 + 4, 5 + 4, /* S-box 1 */ + 0, 0, 23 + 4, 19 + 4, 12 + 4, 4 + 4, 26 + 4, 8 + 4, /* S-box 3 */ + 0, 0, 41 + 8, 52 + 8, 31 + 8, 37 + 8, 47 + 8, 55 + 8, /* S-box 5 */ + 0, 0, 44 + 8, 49 + 8, 39 + 8, 56 + 8, 34 + 8, 53 + 8 /* S-box 7 */ + }; + + /* --- @v@ --- * + * + * Contains the rotation amounts for the key halves. + */ + + static const char v[] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 + }; + + /* --- Extract the key into my registers --- * + * + * The 7 byte case is rather horrible. It expands the key to the 8 byte + * case before going any further. It could probably do with its own @pc1@ + * table. + */ + + KSZ_ASSERT(des, sz); + des_expand(buf, sz, &x, &y); + + /* --- Permute using the pointless PC1 --- */ + + permute(pc1, x, y, ka); + x = ka[0]; y = ka[1]; + + /* --- Now for the key schedule proper --- */ + + for (i = 0; i < 16; i++) { + if (v[i] == 1) { + x = ((x << 1) | (x >> 27)) & 0x0fffffff; + y = ((y << 1) | (y >> 27)) & 0x0fffffff; + } else { + x = ((x << 2) | (x >> 26)) & 0x0fffffff; + y = ((y << 2) | (y >> 26)) & 0x0fffffff; + } + permute(pc2, x, y, kp); + kp += 2; + } +} + +/* --- @des_eblk@, @des_dblk@ --- * + * + * Arguments: @const des_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +void des_eblk(const des_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 x = s[0], y = s[1]; + DES_IP(x, y); + DES_EBLK(k->k, x, y, x, y); + DES_IPINV(x, y); + d[0] = x, d[1] = y; +} + +void des_dblk(const des_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 x = s[0], y = s[1]; + DES_IP(x, y); + DES_DBLK(k->k, x, y, x, y); + DES_IPINV(x, y); + d[0] = x, d[1] = y; +} + +BLKC_TEST(DES, des) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/des.h b/symm/des.h new file mode 100644 index 0000000..682be6b --- /dev/null +++ b/symm/des.h @@ -0,0 +1,124 @@ +/* -*-c-*- + * + * The Data Encryption Standard + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the Data Encryption Standard -----------------------------* + * + * Almost twenty years after it was first accepted, DES is still the standard + * block cipher. It's showing its age in its small key size and poor + * optimiziation for software implementations, but it's not really been badly + * dented by the intensive analysis thrown at it. + * + * This interface is here for compatibility with existing protocols, and + * because it's a trivial veneer over the base DES code which is used by the + * @des3@ interface which implements proper strong triple-DES. + */ + +#ifndef CATACOMB_DES_H +#define CATACOMB_DES_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magical numbers ---------------------------------------------------*/ + +#define DES_BLKSZ 8 +#define DES_KEYSZ 7 +#define DES_CLASS (N, B, 64) + +extern const octet des_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct des_ctx { + uint32 k[32]; +} des_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @des_expand@ --- * + * + * Arguments: @const octet *k@ = pointer to key material + * @size_t n@ = number of octets of key material (7 or 8) + * @uint32 *xx, *yy@ = where to put the results + * + * Returns: --- + * + * Use: Extracts 64 bits of key material from the given buffer, + * possibly expanding it from 56 to 64 bits on the way. + * Parity is set correctly if the key is expanded. + */ + +extern void des_expand(const octet */*k*/, size_t /*n*/, + uint32 */*xx*/, uint32 */*yy*/); + +/* --- @des_init@ --- * + * + * Arguments: @des_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a DES key buffer. The key buffer may be either 7 + * or 8 bytes long. If it's 8 bytes, the key is assumed to be + * padded with parity bits in the low order bit of each octet. + * These are stripped out without checking prior to the actual + * key scheduling. + */ + +extern void des_init(des_ctx */*k*/, const void */*buf*/, size_t /*sz*/); + +/* --- @des_eblk@, @des_dblk@ --- * + * + * Arguments: @const des_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void des_eblk(const des_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); +extern void des_dblk(const des_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/des3.c b/symm/des3.c new file mode 100644 index 0000000..dedd9f2 --- /dev/null +++ b/symm/des3.c @@ -0,0 +1,117 @@ +/* -*-c-*- + * + * Implementation of double- and triple-DES + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include + +#include "blkc.h" +#include "des-base.h" +#include "des.h" +#include "des3.h" +#include "gcipher.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet des3_keysz[] = { KSZ_SET, 21, 7, 8, 14, 16, 24, 0 }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @des3_init@ --- * + * + * Arguments: @des3_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a DES key buffer. The key buffer may have length + * 7, 8, 14, 16, 21, or 24. These correspond to one, two or + * three DES keys, either packed or unpacked (i.e., still + * containing parity bits). + */ + +void des3_init(des3_ctx *k, const void *buf, size_t sz) +{ + size_t step; + const octet *p = buf; + + KSZ_ASSERT(des3, sz); + + if (sz % 7 == 0) + step = 7; + else + step = 8; + + des_init(&k->a, p, step); + if (sz > 8) p += step; + des_init(&k->b, p, step); + if (sz > 16) p += step; else p = buf; + des_init(&k->c, p, step); +} + +/* --- @des3_eblk@, @des3_dblk@ --- * + * + * Arguments: @const des3_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +void des3_eblk(const des3_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 x = s[0], y = s[1]; + DES_IP(x, y); + DES_EBLK(k->a.k, x, y, x, y); + DES_DBLK(k->b.k, x, y, x, y); + DES_EBLK(k->c.k, x, y, x, y); + DES_IPINV(x, y); + d[0] = x, d[1] = y; +} + +void des3_dblk(const des3_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 x = s[0], y = s[1]; + DES_IP(x, y); + DES_DBLK(k->c.k, x, y, x, y); + DES_EBLK(k->b.k, x, y, x, y); + DES_DBLK(k->a.k, x, y, x, y); + DES_IPINV(x, y); + d[0] = x, d[1] = y; +} + +BLKC_TEST(DES3, des3) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/des3.h b/symm/des3.h new file mode 100644 index 0000000..881f558 --- /dev/null +++ b/symm/des3.h @@ -0,0 +1,108 @@ +/* -*-c-*- + * + * Implementation of double- and triple-DES + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_DES3_H +#define CATACOMB_DES3_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Notes on double- and triple-DES -----------------------------------* + * + * The normal recommendation for using DES now is `triple DES'. + * Conventionally, this involves an encrypt-decrypt-encrypt sequence, + * although whether the first and last operations use the same key is + * unfortunately not agreed upon. This interface handles both cases (and the + * single-key one too, although the simple @des@ calls are quicker for that). + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#ifndef CATACOMB_DES_H +# include "des.h" +#endif + +/*----- Magical numbers ---------------------------------------------------*/ + +#define DES3_BLKSZ 8 +#define DES3_KEYSZ 21 +#define DES3_CLASS (N, B, 64) + +extern const octet des3_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct des3_ctx { + des_ctx a, b, c; +} des3_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @des3_init@ --- * + * + * Arguments: @des3_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a DES key buffer. The key buffer may have length + * 7, 8, 14, 16, 21, or 24. These correspond to one, two or + * three DES keys, either packed or unpacked (i.e., still + * containing parity bits). + */ + +extern void des3_init(des3_ctx */*k*/, const void */*buf*/, size_t /*sz*/); + +/* --- @des3_eblk@, @des_dblk@ --- * + * + * Arguments: @const des3_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void des3_eblk(const des3_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); +extern void des3_dblk(const des3_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/desx-tab.h b/symm/desx-tab.h new file mode 100644 index 0000000..f1b54d4 --- /dev/null +++ b/symm/desx-tab.h @@ -0,0 +1,78 @@ +/* -*-c-*- + * + * Tables for DESX + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_DESX_TAB_H +#define CATACOMB_DESX_TAB_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- S-box table -------------------------------------------------------*/ + +#define DESX_S { \ + 0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, \ + 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0, \ + 0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, \ + 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a, \ + 0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda, \ + 0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36, \ + 0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8, \ + 0x34, 0xa9, 0x13, 0xf0, 0xa6, 0x3f, 0xd8, 0x0c, \ + 0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17, \ + 0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x07, 0xb8, 0x60, \ + 0x48, 0xe6, 0x1e, 0x53, 0xf3, 0x92, 0xa4, 0x72, \ + 0x8c, 0x08, 0x15, 0x6e, 0x86, 0x00, 0x84, 0xfa, \ + 0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd, \ + 0x14, 0x8d, 0x50, 0x12, 0xba, 0x3c, 0x06, 0x4e, \ + 0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b, \ + 0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf, \ + 0x3a, 0xde, 0x96, 0x0e, 0xbc, 0x0a, 0xed, 0x77, \ + 0xfc, 0x37, 0x6b, 0x03, 0x79, 0x89, 0x62, 0xc6, \ + 0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3, \ + 0x5b, 0x05, 0x5d, 0x02, 0x75, 0xd5, 0x61, 0xe3, \ + 0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0x0b, 0x5e, \ + 0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c, \ + 0xb4, 0xc5, 0xcc, 0x70, 0xb2, 0x91, 0x59, 0x0d, \ + 0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x01, 0xe2, \ + 0x16, 0x38, 0xc4, 0x6f, 0x3b, 0x0f, 0x65, 0x46, \ + 0xbe, 0x7e, 0x2d, 0x7b, 0x82, 0xf9, 0x40, 0xb5, \ + 0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97, \ + 0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5, \ + 0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, \ + 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f, \ + 0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, \ + 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab, \ +} + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/desx.c b/symm/desx.c new file mode 100644 index 0000000..d65ffa7 --- /dev/null +++ b/symm/desx.c @@ -0,0 +1,149 @@ +/* -*-c-*- + * + * Implementation of DESX + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include + +#include "blkc.h" +#include "des-base.h" +#include "des.h" +#include "desx.h" +#include "desx-tab.h" +#include "gcipher.h" + +/*----- Tables ------------------------------------------------------------*/ + +static const octet s[256] = DESX_S; + +/*----- Global variables --------------------------------------------------*/ + +const octet desx_keysz[] = { KSZ_SET, 23, 7, 8, 15, 16, 24, 0 }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @desx_init@ --- * + * + * Arguments: @desx_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a DESX key buffer. The key buffer contains, in + * order, a single-DES key (either 7 or 8 bytes), an optional + * 8-byte pre-whitening key, and an optional 8-byte + * port-whitening key. If no whitening keys are specified, the + * algorithm becomes the same as single-DES. + */ + +static void mangle(octet *b, const octet *p) +{ + unsigned i; + + for (i = 0; i < 8; i++) + b[i] = *p++ ^ s[b[i] ^ b[(i + 1) & 7u]]; +} + +void desx_init(desx_ctx *k, const void *buf, size_t sz) +{ + const octet *p = buf, *kk = buf; + size_t n; + + KSZ_ASSERT(desx, sz); + + n = sz % 8 == 7 ? 7 : 8; + des_init(&k->k, p, n); + p += n; + sz -= n; + if (!sz) + k->prea = k->preb = k->posta = k->postb = 0; + else { + const octet *q = p; + k->prea = LOAD32(q + 0); + k->preb = LOAD32(q + 4); + p += 8; + sz -= 8; + if (sz) { + k->posta = LOAD32(p + 0); + k->postb = LOAD32(p + 4); + } else { + octet b[16]; + uint32 x, y; + + des_expand(kk, n, &x, &y); + STORE32(b + 8, x); STORE32(b + 12, y); + memset(b, 0, 8); + mangle(b, b + 8); + mangle(b, q); + k->posta = LOAD32(b + 0); + k->postb = LOAD32(b + 4); + } + } +} + +/* --- @desx_eblk@, @desx_dblk@ --- * + * + * Arguments: @const desx_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +void desx_eblk(const desx_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 x = s[0], y = s[1]; + x ^= k->prea; y ^= k->preb; + DES_IP(x, y); + DES_EBLK(k->k.k, x, y, x, y); + DES_IPINV(x, y); + x ^= k->posta; y ^= k->postb; + d[0] = x, d[1] = y; +} + +void desx_dblk(const desx_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 x = s[0], y = s[1]; + x ^= k->posta; y ^= k->postb; + DES_IP(x, y); + DES_DBLK(k->k.k, x, y, x, y); + DES_IPINV(x, y); + x ^= k->prea; y ^= k->preb; + d[0] = x, d[1] = y; +} + +BLKC_TEST(DESX, desx) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/desx.h b/symm/desx.h new file mode 100644 index 0000000..62e8300 --- /dev/null +++ b/symm/desx.h @@ -0,0 +1,109 @@ +/* -*-c-*- + * + * The DESX algorithm + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on DESX -----------------------------------------------------* + * + * DESX was designed by Ron Rivest in 1986 as a simple and cheap way to + * strengthen DES against exhaustive search. It also increases the + * difficulty of differential and linear attacks. + */ + +#ifndef CATACOMB_DESX_H +#define CATACOMB_DESX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#ifndef CATACOMB_DES_H +# include "des.h" +#endif + +/*----- Magical numbers ---------------------------------------------------*/ + +#define DESX_BLKSZ 8 +#define DESX_KEYSZ 23 +#define DESX_CLASS (N, B, 64) + +extern const octet desx_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct desx_ctx { + des_ctx k; + uint32 prea, preb; + uint32 posta, postb; +} desx_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @desx_init@ --- * + * + * Arguments: @desx_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a DESX key buffer. The key buffer contains, in + * order, an optional 8-byte pre-whitening key, a single-DES key + * (either 7 or 8 bytes), and an optional 8-byte port-whitening + * key. If no whitening keys are specified, the algorithm + * becomes the same as single-DES. + */ + +extern void desx_init(desx_ctx */*k*/, const void */*buf*/, size_t /*sz*/); + +/* --- @desx_eblk@, @desx_dblk@ --- * + * + * Arguments: @const desx_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void desx_eblk(const desx_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); +extern void desx_dblk(const desx_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/ecb-def.h b/symm/ecb-def.h new file mode 100644 index 0000000..ea153a2 --- /dev/null +++ b/symm/ecb-def.h @@ -0,0 +1,471 @@ +/* -*-c-*- + * + * Definitions electronic code book mode + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_ECB_DEF_H +#define CATACOMB_ECB_DEF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include +#include + +#ifndef CATACOMB_ARENA_H +# include "arena.h" +#endif + +#ifndef CATACOMB_BLKC_H +# include "blkc.h" +#endif + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +#ifndef CATACOMB_PARANOIA_H +# include "paranoia.h" +#endif + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @ECB_DEF@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher + * + * Use: Creates an implementation for ECB stealing mode. + */ + +#define ECB_DEF(PRE, pre) \ + \ +/* --- @pre_ecbsetkey@ --- * \ + * \ + * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \ + * @const pre_ctx *k@ = pointer to cipher context \ + * \ + * Returns: --- \ + * \ + * Use: Sets the ECB context to use a different cipher key. \ + */ \ + \ +void pre##_ecbsetkey(pre##_ecbctx *ctx, const pre##_ctx *k) \ +{ \ + ctx->ctx = *k; \ +} \ + \ +/* --- @pre_ecbinit@ --- * \ + * \ + * Arguments: @pre_ecbctx *ctx@ = pointer to cipher context \ + * @const void *key@ = pointer to the key buffer \ + * @size_t sz@ = size of the key \ + * @const void *iv@ = pointer to initialization vector \ + * \ + * Returns: --- \ + * \ + * Use: Initializes an ECB context ready for use. This is \ + * equivalent to calls to @pre_init@ and @pre_setkey@. \ + */ \ + \ +void pre##_ecbinit(pre##_ecbctx *ctx, \ + const void *key, size_t sz, \ + const void *iv) \ +{ \ + pre##_init(&ctx->ctx, key, sz); \ +} \ + \ +/* --- @pre_ecbencrypt@ --- * \ + * \ + * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Encrypts a block with a block cipher in ECB mode, with \ + * ciphertext stealing and other clever tricks. \ + * Essentially, data can be encrypted in arbitrary sized \ + * chunks, although decryption must use the same chunks. \ + */ \ + \ +void pre##_ecbencrypt(pre##_ecbctx *ctx, \ + const void *src, void *dest, \ + size_t sz) \ +{ \ + const octet *s = src; \ + octet *d = dest; \ + \ + /* --- Empty blocks are trivial --- */ \ + \ + if (!sz) \ + return; \ + \ + /* --- Short blocks aren't allowed in ECB --- * \ + * \ + * There's absolutely nothing secure I can do with them. \ + */ \ + \ + assert(((void)"ECB must have at least one whole block to work with", \ + sz >= PRE##_BLKSZ)); \ + \ + /* --- Do the main chunk of encryption --- * \ + * \ + * This will do the whole lot if it's a whole number of blocks. Just \ + * give each block to the cipher in turn. This is trivial. \ + * Hopefully... \ + */ \ + \ + while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \ + uint32 x[PRE##_BLKSZ / 4]; \ + if (!s) \ + BLKC_ZERO(PRE, x); \ + else { \ + BLKC_LOAD(PRE, x, s); \ + s += PRE##_BLKSZ; \ + } \ + pre##_eblk(&ctx->ctx, x, x); \ + if (d) { \ + BLKC_STORE(PRE, d, x); \ + d += PRE##_BLKSZ; \ + } \ + sz -= PRE##_BLKSZ; \ + } \ + \ + /* --- Do the tail-end block and bit-left-over --- * \ + * \ + * This isn't very efficient. That shouldn't matter much. \ + */ \ + \ + if (sz) { \ + uint32 x[PRE##_BLKSZ / 4]; \ + octet b[PRE##_BLKSZ]; \ + unsigned i; \ + \ + /* --- Let @sz@ be the size of the partial block --- */ \ + \ + sz -= PRE##_BLKSZ; \ + \ + /* --- First stage --- * \ + * \ + * Read in the current block, and encrypt it. The first part of \ + * the result is the partial ciphertext block. Don't write that \ + * out yet, because I've not read the partial plaintext block. \ + */ \ + \ + if (!s) \ + BLKC_ZERO(PRE, x); \ + else { \ + BLKC_LOAD(PRE, x, s); \ + s += PRE##_BLKSZ; \ + } \ + pre##_eblk(&ctx->ctx, x, x); \ + BLKC_STORE(PRE, b, x); \ + \ + /* --- Second stage --- * \ + * \ + * Now move in the partial plaintext block, writing out the \ + * ciphertext as I go. Then encrypt, and write the complete \ + * ciphertext block. \ + */ \ + \ + if (d) d += PRE##_BLKSZ; \ + for (i = 0; i < sz; i++) { \ + register octet y = b[i]; \ + b[i] = s[i]; \ + if (d) d[i] = y; \ + } \ + BLKC_LOAD(PRE, x, b); \ + pre##_eblk(&ctx->ctx, x, x); \ + if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, x); \ + } \ + \ + /* --- Done --- */ \ + \ + return; \ +} \ + \ +/* --- @pre_ecbdecrypt@ --- * \ + * \ + * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Decrypts a block with a block cipher in ECB mode, with \ + * ciphertext stealing and other clever tricks. \ + * Essentially, data can be encrypted in arbitrary sized \ + * chunks, although decryption must use the same chunks. \ + */ \ + \ +void pre##_ecbdecrypt(pre##_ecbctx *ctx, \ + const void *src, void *dest, \ + size_t sz) \ +{ \ + const octet *s = src; \ + octet *d = dest; \ + \ + /* --- Empty blocks are trivial --- */ \ + \ + if (!sz) \ + return; \ + \ + /* --- Short blocks aren't allowed in ECB --- * \ + * \ + * There's absolutely nothing secure I can do with them. \ + */ \ + \ + assert(((void)"ECB must have at least one whole block to work with", \ + sz >= PRE##_BLKSZ)); \ + \ + /* --- Do the main chunk of decryption --- * \ + * \ + * This will do the whole lot if it's a whole number of blocks. \ + * Each block is just handed to the block cipher in turn. \ + */ \ + \ + while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \ + uint32 x[PRE##_BLKSZ / 4]; \ + BLKC_LOAD(PRE, x, s); \ + pre##_dblk(&ctx->ctx, x, x); \ + BLKC_STORE(PRE, d, x); \ + s += PRE##_BLKSZ; \ + d += PRE##_BLKSZ; \ + sz -= PRE##_BLKSZ; \ + } \ + \ + /* --- Do the tail-end block and bit-left-over --- * \ + * \ + * This isn't very efficient. That shouldn't matter much. \ + */ \ + \ + if (sz) { \ + uint32 x[PRE##_BLKSZ / 4]; \ + octet b[PRE##_BLKSZ]; \ + unsigned i; \ + \ + /* --- Let @sz@ be the size of the partial block --- */ \ + \ + sz -= PRE##_BLKSZ; \ + \ + /* --- First stage --- * \ + * \ + * Take the complete ciphertext block, and decrypt it. This block \ + * is carried over for the next encryption operation. \ + */ \ + \ + BLKC_LOAD(PRE, x, s); \ + pre##_dblk(&ctx->ctx, x, x); \ + BLKC_STORE(PRE, b, x); \ + \ + /* --- Second stage --- * \ + * \ + * The first few bytes are the partial plaintext block. Write that \ + * and replace with the partial ciphertext block. Then decrypt \ + * what's left as the complete plaintext. \ + */ \ + \ + s += PRE##_BLKSZ; \ + d += PRE##_BLKSZ; \ + for (i = 0; i < sz; i++) { \ + register octet y = s[i]; \ + d[i] = b[i]; \ + b[i] = y; \ + } \ + BLKC_LOAD(PRE, x, b); \ + pre##_dblk(&ctx->ctx, x, x); \ + BLKC_STORE(PRE, d - PRE##_BLKSZ, x); \ + } \ + \ + /* --- Done --- */ \ + \ + return; \ +} \ + \ +/* --- Generic cipher interface --- */ \ + \ +static const gcipher_ops gops; \ + \ +typedef struct gctx { \ + gcipher c; \ + pre##_ecbctx k; \ +} gctx; \ + \ +static gcipher *ginit(const void *k, size_t sz) \ +{ \ + gctx *g = S_CREATE(gctx); \ + g->c.ops = &gops; \ + pre##_ecbinit(&g->k, k, sz, 0); \ + return (&g->c); \ +} \ + \ +static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_ecbencrypt(&g->k, s, t, sz); \ +} \ + \ +static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_ecbdecrypt(&g->k, s, t, sz); \ +} \ + \ +static void gdestroy(gcipher *c) \ +{ \ + gctx *g = (gctx *)c; \ + BURN(*g); \ + S_DESTROY(g); \ +} \ + \ +static const gcipher_ops gops = { \ + &pre##_ecb, \ + gencrypt, gdecrypt, gdestroy, 0, 0 \ +}; \ + \ +const gccipher pre##_ecb = { \ + #pre "-ecb", pre##_keysz, PRE##_BLKSZ, \ + ginit \ +}; \ + \ +ECB_TEST(PRE, pre) + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +#include "daftstory.h" + +/* --- @ECB_TEST@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions + * + * Use: Standard test rig for ECB functions. + */ + +#define ECB_TEST(PRE, pre) \ + \ +/* --- Initial plaintext for the test --- */ \ + \ +static const octet text[] = TEXT; \ + \ +/* --- Key and IV to use --- */ \ + \ +static const octet key[] = KEY; \ +static const octet iv[] = IV; \ + \ +/* --- Buffers for encryption and decryption output --- */ \ + \ +static octet ct[sizeof(text)]; \ +static octet pt[sizeof(text)]; \ + \ +static void hexdump(const octet *p, size_t sz) \ +{ \ + const octet *q = p + sz; \ + for (sz = 0; p < q; p++, sz++) { \ + printf("%02x", *p); \ + if ((sz + 1) % PRE##_BLKSZ == 0) \ + putchar(':'); \ + } \ +} \ + \ +int main(void) \ +{ \ + size_t sz = 0, rest; \ + pre##_ecbctx ctx; \ + int status = 0; \ + int done = 0; \ + \ + size_t keysz = PRE##_KEYSZ ? \ + PRE##_KEYSZ : strlen((const char *)key); \ + \ + fputs(#pre "-ecb: ", stdout); \ + \ + pre##_ecbinit(&ctx, key, keysz, iv); \ + \ + while (sz <= sizeof(text)) { \ + rest = sizeof(text) - sz; \ + if ((sz != 0 && sz < PRE##_BLKSZ) || \ + (rest != 0 && rest < PRE##_BLKSZ)) \ + goto next; \ + memcpy(ct, text, sizeof(text)); \ + pre##_ecbencrypt(&ctx, ct, ct, sz); \ + pre##_ecbencrypt(&ctx, ct + sz, ct + sz, rest); \ + memcpy(pt, ct, sizeof(text)); \ + pre##_ecbdecrypt(&ctx, pt, pt, sz); \ + pre##_ecbdecrypt(&ctx, pt + sz, pt + sz, rest); \ + if (memcmp(pt, text, sizeof(text)) == 0) { \ + done++; \ + if (sizeof(text) < 40 || done % 8 == 0) \ + fputc('.', stdout); \ + if (done % 480 == 0) \ + fputs("\n\t", stdout); \ + fflush(stdout); \ + } else { \ + printf("\nError (sz = %lu)\n", (unsigned long)sz); \ + status = 1; \ + printf("\tplaintext = "); hexdump(text, sz); \ + printf(", "); hexdump(text + sz, rest); \ + fputc('\n', stdout); \ + printf("\tciphertext = "); hexdump(ct, sz); \ + printf(", "); hexdump(ct + sz, rest); \ + fputc('\n', stdout); \ + printf("\trecovered text = "); hexdump(pt, sz); \ + printf(", "); hexdump(pt + sz, rest); \ + fputc('\n', stdout); \ + fputc('\n', stdout); \ + } \ + next: \ + if (sz < 63) \ + sz++; \ + else \ + sz += 9; \ + } \ + \ + fputs(status ? " failed\n" : " ok\n", stdout); \ + return (status); \ +} + +#else +# define ECB_TEST(PRE, pre) +#endif + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/ecb.h b/symm/ecb.h new file mode 100644 index 0000000..4f5d525 --- /dev/null +++ b/symm/ecb.h @@ -0,0 +1,138 @@ +/* -*-c-*- + * + * Electronic code book for block ciphers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_ECB_H +#define CATACOMB_ECB_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @ECB_DECL@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher + * + * Use: Creates declarations for ECB stealing mode. + */ + +#define ECB_DECL(PRE, pre) \ + \ +/* --- Electronic codebook context --- */ \ + \ +typedef struct pre##_ecbctx { \ + pre##_ctx ctx; /* Underlying cipher context */ \ +} pre##_ecbctx; \ + \ +/* --- @pre_ecbsetkey@ --- * \ + * \ + * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \ + * @const pre_ctx *k@ = pointer to cipher context \ + * \ + * Returns: --- \ + * \ + * Use: Sets the ECB context to use a different cipher key. \ + */ \ + \ +extern void pre##_ecbsetkey(pre##_ecbctx */*ctx*/, \ + const pre##_ctx */*k*/); \ + \ +/* --- @pre_ecbinit@ --- * \ + * \ + * Arguments: @pre_ecbctx *ctx@ = pointer to cipher context \ + * @const void *key@ = pointer to the key buffer \ + * @size_t sz@ = size of the key \ + * @const void *iv@ = pointer to initialization vector \ + * \ + * Returns: --- \ + * \ + * Use: Initializes an ECB context ready for use. This is \ + * equivalent to calls to @pre_init@ and @pre_setkey@. \ + */ \ + \ +extern void pre##_ecbinit(pre##_ecbctx */*ctx*/, \ + const void */*key*/, size_t /*sz*/, \ + const void */*iv*/); \ + \ +/* --- @pre_ecbencrypt@ --- * \ + * \ + * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Encrypts a block with a block cipher in ECB mode, with \ + * ciphertext stealing and other clever tricks. \ + * Essentially, data can be encrypted in arbitrary sized \ + * chunks, although decryption must use the same chunks. \ + */ \ + \ +extern void pre##_ecbencrypt(pre##_ecbctx */*ctx*/, \ + const void */*src*/, void */*dest*/, \ + size_t /*sz*/); \ + \ +/* --- @pre_ecbdecrypt@ --- * \ + * \ + * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Decrypts a block with a block cipher in ECB mode, with \ + * ciphertext stealing and other clever tricks. \ + * Essentially, data can be encrypted in arbitrary sized \ + * chunks, although decryption must use the same chunks. \ + */ \ + \ +extern void pre##_ecbdecrypt(pre##_ecbctx */*ctx*/, \ + const void */*src*/, void */*dest*/, \ + size_t /*sz*/); \ + \ +/* --- Generic cipher interface --- */ \ + \ +extern const gccipher pre##_ecb; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/gcipher.h b/symm/gcipher.h new file mode 100644 index 0000000..efe9f51 --- /dev/null +++ b/symm/gcipher.h @@ -0,0 +1,96 @@ +/* -*-c-*- + * + * Generic symmetric cipher interface + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GCIPHER_H +#define CATACOMB_GCIPHER_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#ifndef CATACOMB_KEYSZ_H +# include "keysz.h" +#endif + +/*----- Generic symmetric cipher interface --------------------------------*/ + +typedef struct gcipher { + const struct gcipher_ops *ops; /* Pointer to cipher operations */ +} gcipher; + +typedef struct gcipher_ops { + const struct gccipher *c; /* Pointer to cipher class */ + void (*encrypt)(gcipher */*c*/, const void */*s*/, + void */*t*/, size_t /*sz*/); + void (*decrypt)(gcipher */*c*/, const void */*s*/, + void */*t*/, size_t /*sz*/); + void (*destroy)(gcipher */*c*/); + void (*setiv)(gcipher */*c*/, const void */*iv*/); + void (*bdry)(gcipher */*c*/); +} gcipher_ops; + +typedef struct gccipher { + const char *name; /* Cipher name */ + const octet *keysz; /* Preferred key size table */ + size_t blksz; /* Block size or zero if none */ + gcipher *(*init)(const void */*k*/, size_t /*sz*/); +} gccipher; + +#define GC_INIT(cc, k, sz) (cc)->init((k), (sz)) +#define GC_CLASS(cc) (cc)->ops->c +#define GC_ENCRYPT(c, s, t, sz) (c)->ops->encrypt((c), (s), (t), (sz)) +#define GC_DECRYPT(c, s, t, sz) (c)->ops->decrypt((c), (s), (t), (sz)) +#define GC_DESTROY(c) (c)->ops->destroy((c)) +#define GC_SETIV(c, iv) (c)->ops->setiv((c), (iv)) +#define GC_BDRY(c) (c)->ops->bdry((c)) + +/*----- Tables ------------------------------------------------------------*/ + +extern const gccipher *const gciphertab[]; + +/* --- @gcipher_byname@ --- * + * + * Arguments: @const char *p@ = pointer to name string + * + * Returns: The named cipher class, or null. + */ + +extern const gccipher *gcipher_byname(const char */*p*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/ghash-def.h b/symm/ghash-def.h new file mode 100644 index 0000000..2ede96f --- /dev/null +++ b/symm/ghash-def.h @@ -0,0 +1,119 @@ +/* -*-c-*- + * + * Definitions for generic hash interface + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GHASH_DEF_H +#define CATACOMB_GHASH_DEF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#ifndef CATACOMB_ARENA_H +# include "arena.h" +#endif + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +#ifndef CATACOMB_PARANOIA_H +# include "paranoia.h" +#endif + +/*----- Generic hash function interface -----------------------------------*/ + +/* --- @GHASH_DEF@ --- * + * + * Arguments: @PRE, pre@ = prefixes for hash function + * + * Use: Defines the generic hash instance. + */ + +#define GHASH_DEF(PRE, pre) \ + \ +static const ghash_ops gops; \ + \ +typedef struct gctx { \ + ghash h; \ + pre##_ctx c; \ + octet buf[PRE##_HASHSZ]; \ +} gctx; \ + \ +static ghash *ghinit(void) \ +{ \ + gctx *g = S_CREATE(gctx); \ + g->h.ops = &gops; \ + pre##_init(&g->c); \ + return (&g->h); \ +} \ + \ +static void ghhash(ghash *h, const void *p, size_t sz) \ +{ \ + gctx *g = (gctx *)h; \ + pre##_hash(&g->c, p, sz); \ +} \ + \ +static octet *ghdone(ghash *h, void *buf) \ +{ \ + gctx *g = (gctx *)h; \ + if (!buf) \ + buf = g->buf; \ + pre##_done(&g->c, buf); \ + return (buf); \ +} \ + \ +static void ghdestroy(ghash *h) \ +{ \ + gctx *g = (gctx *)h; \ + BURN(*g); \ + S_DESTROY(g); \ +} \ + \ +static ghash *ghcopy(ghash *h) \ +{ \ + gctx *g = (gctx *)h; \ + gctx *gg = S_CREATE(gctx); \ + memcpy(gg, g, sizeof(gctx)); \ + return (&gg->h); \ +} \ + \ +static const ghash_ops gops = \ + { &pre, ghhash, ghdone, ghdestroy, ghcopy }; \ +const gchash pre = { #pre, PRE##_HASHSZ, ghinit, PRE##_BUFSZ }; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/ghash.h b/symm/ghash.h new file mode 100644 index 0000000..2f6a6cd --- /dev/null +++ b/symm/ghash.h @@ -0,0 +1,154 @@ +/* -*-c-*- + * + * Generic hash function interface + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GHASH_H +#define CATACOMB_GHASH_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Generic hash function interface -----------------------------------*/ + +typedef struct ghash { + const struct ghash_ops *ops; /* Pointer to hash operations */ +} ghash; + +typedef struct ghash_ops { + const struct gchash *c; /* Pointer to hash class */ + void (*hash)(ghash */*h*/, const void */*p*/, size_t /*sz*/); /* Hash */ + octet *(*done)(ghash */*h*/, void */*buf*/); /* Write result */ + void (*destroy)(ghash */*h*/); /* Destroy hash block */ + ghash *(*copy)(ghash */*h*/); /* Make a copy of the hash context */ +} ghash_ops; + +#define GH_INIT(ch) (ch)->init() +#define GH_CLASS(h) (h)->ops->c +#define GH_HASH(h, p, sz) (h)->ops->hash((h), (p), (sz)) +#define GH_DONE(h, buf) (h)->ops->done((h), (buf)) +#define GH_DESTROY(h) (h)->ops->destroy((h)) +#define GH_COPY(h) (h)->ops->copy((h)) + +#define GH_HASHU_(h, n, W) do { \ + TY_U##W n_ = (n); octet b_[SZ_##W]; \ + STORE##W(b_, n_); GH_HASH((h), b_, SZ_##W); \ +} while (0) +#define GH_HASHU8(h, n) GH_HASHU_((h), (n), 8) +#define GH_HASHU16(h, n) GH_HASHU_((h), (n), 16) +#define GH_HASHU16_B(h, n) GH_HASHU_((h), (n), 16_B) +#define GH_HASHU16_L(h, n) GH_HASHU_((h), (n), 16_L) +#define GH_HASHU24(h, n) GH_HASHU_((h), (n), 24) +#define GH_HASHU24_B(h, n) GH_HASHU_((h), (n), 24_B) +#define GH_HASHU24_L(h, n) GH_HASHU_((h), (n), 24_L) +#define GH_HASHU32(h, n) GH_HASHU_((h), (n), 32) +#define GH_HASHU32_B(h, n) GH_HASHU_((h), (n), 32_B) +#define GH_HASHU32_L(h, n) GH_HASHU_((h), (n), 32_L) +#ifdef HAVE_UINT64 +# define GH_HASHU64(h, n) GH_HASHU_((h), (n), 64) +# define GH_HASHU64_B(h, n) GH_HASHU_((h), (n), 64_B) +# define GH_HASHU64_L(h, n) GH_HASHU_((h), (n), 64_L) +#endif + +#define GH_HASHBUF_(h, p, sz, W) do { \ + size_t sz_ = (sz); assert(sz_ <= MASK##W); \ + GH_HASHU_(h, sz_, W); GH_HASH(h, (p), sz_); \ +} while (0) +#define GH_HASHBUF8(h, p, sz) GH_HASHBUF_((h), (p), (sz), 8) +#define GH_HASHBUF16(h, p, sz) GH_HASHBUF_((h), (p), (sz), 16) +#define GH_HASHBUF16_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 16_L) +#define GH_HASHBUF16_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 16_B) +#define GH_HASHBUF24(h, p, sz) GH_HASHBUF_((h), (p), (sz), 24) +#define GH_HASHBUF24_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 24_L) +#define GH_HASHBUF24_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 24_B) +#define GH_HASHBUF32(h, p, sz) GH_HASHBUF_((h), (p), (sz), 32) +#define GH_HASHBUF32_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 32_L) +#define GH_HASHBUF32_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 32_B) +#ifdef HAVE_UINT64 +# define GH_HASHBUF64(h, p, sz) GH_HASHBUF_((h), (p), (sz), 64) +# define GH_HASHBUF64_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 64_L) +# define GH_HASHBUF64_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 64_B) +#endif + +#define GH_HASHSTR_(h, p, W) do { \ + const char *p_ = (p); GH_HASHBUF_((h), p_, strlen(p_), W); \ +} while (0) +#define GH_HASHSTR8(h, p) GH_HASHSTR_((h), (p), 8) +#define GH_HASHSTR16(h, p) GH_HASHSTR_((h), (p), 16) +#define GH_HASHSTR16_L(h, p) GH_HASHSTR_((h), (p), 16_L) +#define GH_HASHSTR16_B(h, p) GH_HASHSTR_((h), (p), 16_B) +#define GH_HASHSTR24(h, p) GH_HASHSTR_((h), (p), 24) +#define GH_HASHSTR24_L(h, p) GH_HASHSTR_((h), (p), 24_L) +#define GH_HASHSTR24_B(h, p) GH_HASHSTR_((h), (p), 24_B) +#define GH_HASHSTR32(h, p) GH_HASHSTR_((h), (p), 32) +#define GH_HASHSTR32_L(h, p) GH_HASHSTR_((h), (p), 32_L) +#define GH_HASHSTR32_B(h, p) GH_HASHSTR_((h), (p), 32_B) +#ifdef HAVE_UINT64 +# define GH_HASHSTR64(h, p) GH_HASHSTR_((h), (p), 64) +# define GH_HASHSTR64_L(h, p) GH_HASHSTR_((h), (p), 64_L) +# define GH_HASHSTR64_B(h, p) GH_HASHSTR_((h), (p), 64_B) +#endif + +#define GH_HASHSTRZ(h, p) do { \ + const char *p_ = (p); GH_HASH((h), p_, strlen(p_) + 1); \ +} while (0) +#define GH_HASHSTR(h, p) do { \ + const char *p_ = (p); GH_HASH((h), p_, strlen(p_)); \ +} while (0) + +typedef struct gchash { + const char *name; /* Name of the hash function */ + size_t hashsz; /* Size of output hash */ + ghash *(*init)(void); /* Create a new hash instance */ + size_t bufsz; /* Buffer size, or zero */ +} gchash; + +/*----- Tables ------------------------------------------------------------*/ + +extern const gchash *const ghashtab[]; + +/* --- @ghash_byname@ --- * + * + * Arguments: @const char *p@ = pointer to name string + * + * Returns: The named cipher class, or null. + */ + +extern const gchash *ghash_byname(const char */*p*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/gmac.h b/symm/gmac.h new file mode 100644 index 0000000..efd4a02 --- /dev/null +++ b/symm/gmac.h @@ -0,0 +1,90 @@ +/* -*-c-*- + * + * Generic MAC function interface + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_GMAC_H +#define CATACOMB_GMAC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Generic MAC function interface ------------------------------------*/ + +typedef struct gmac { + const struct gmac_ops *ops; /* Pointer to MAC operations */ +} gmac; + +typedef struct gmac_ops { + const struct gcmac *c; /* Pointer to MAC class */ + ghash *(*init)(gmac */*m*/); /* Create keyed hash instance */ + void (*destroy)(gmac */*m*/); /* Destroy MAC key block */ +} gmac_ops; + +typedef struct gcmac { + const char *name; /* Name of the MAC function */ + size_t hashsz; /* Size of output hash */ + const octet *keysz; /* Key size options */ + gmac *(*key)(const void */*k*/, size_t /*sz*/); /* Create key */ +} gcmac; + +#define GM_KEY(cm, k, ksz) (cm)->key((k), (ksz)) +#define GM_CLASS(km) (km)->ops->c +#define GM_INIT(km) (km)->ops->init((km)) +#define GM_DESTROY(km) (km)->ops->destroy((km)) + +/*----- Tables ------------------------------------------------------------*/ + +extern const gcmac *const gmactab[]; + +/* --- @gmac_byname@ --- * + * + * Arguments: @const char *p@ = pointer to name string + * + * Returns: The named cipher class, or null. + */ + +extern const gcmac *gmac_byname(const char */*p*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/gthingtab.c.in b/symm/gthingtab.c.in similarity index 100% rename from gthingtab.c.in rename to symm/gthingtab.c.in diff --git a/symm/has160.c b/symm/has160.c new file mode 100644 index 0000000..483b9fe --- /dev/null +++ b/symm/has160.c @@ -0,0 +1,246 @@ +/* -*-c-*- + * + * The HAS160 message digest function + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "has160.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @has160_compress@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: HAS160 compression function. + */ + +void has160_compress(has160_ctx *ctx, const void *sbuf) +{ + uint32 a, b, c, d, e; + uint32 buf[16]; + + /* --- Fetch the chaining variables --- */ + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + e = ctx->e; + + /* --- Fetch the buffer contents --- */ + + { + int i; + const octet *p; + + for (i = 0, p = sbuf; i < 16; i++, p += 4) + buf[i] = LOAD32_L(p); + } + + /* --- Definitions for round functions --- */ + +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define G(x, y, z) ((x) ^ (y) ^ (z)) +#define H(x, y, z) ((y) ^ ((x) | ~(z))) + +#define FF(f, a, b, c, d, e, x, s, ss, k) do { \ + e += ROL32(a, s) + f(b, c, d) + (x) + k; \ + b = ROL32(b, ss); \ +} while (0) + + /* --- The actual hashing --- * + * + * Hmm, this is more regular than most. The macros are quite grim, + * though. + */ + +#define ROUND(f, ss, k, \ + i0, i1, i2, i3, i4, i5, i6, i7, \ + i8, i9, i10, i11, i12, i13, i14, i15) do { \ + FF(f, a, b, c, d, e, buf[ i8]^buf[ i9]^buf[i10]^buf[i11], 5, ss, k); \ + FF(f, e, a, b, c, d, buf[ i0], 11, ss, k); \ + FF(f, d, e, a, b, c, buf[ i1], 7, ss, k); \ + FF(f, c, d, e, a, b, buf[ i2], 15, ss, k); \ + FF(f, b, c, d, e, a, buf[ i3], 6, ss, k); \ + FF(f, a, b, c, d, e, buf[i12]^buf[i13]^buf[i14]^buf[i15], 13, ss, k); \ + FF(f, e, a, b, c, d, buf[ i4], 8, ss, k); \ + FF(f, d, e, a, b, c, buf[ i5], 14, ss, k); \ + FF(f, c, d, e, a, b, buf[ i6], 7, ss, k); \ + FF(f, b, c, d, e, a, buf[ i7], 12, ss, k); \ + FF(f, a, b, c, d, e, buf[ i0]^buf[ i1]^buf[ i2]^buf[ i3], 9, ss, k); \ + FF(f, e, a, b, c, d, buf[ i8], 11, ss, k); \ + FF(f, d, e, a, b, c, buf[ i9], 8, ss, k); \ + FF(f, c, d, e, a, b, buf[i10], 15, ss, k); \ + FF(f, b, c, d, e, a, buf[i11], 6, ss, k); \ + FF(f, a, b, c, d, e, buf[ i4]^buf[ i5]^buf[ i6]^buf[ i7], 12, ss, k); \ + FF(f, e, a, b, c, d, buf[i12], 9, ss, k); \ + FF(f, d, e, a, b, c, buf[i13], 14, ss, k); \ + FF(f, c, d, e, a, b, buf[i14], 5, ss, k); \ + FF(f, b, c, d, e, a, buf[i15], 13, ss, k); \ +} while (0) + + ROUND(F, 10, 0x00000000, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + ROUND(G, 17, 0x5a827999, + 3, 6, 9, 12, 15, 2, 5, 8, 11, 14, 1, 4, 7, 10, 13, 0); + ROUND(H, 25, 0x6ed9eba1, + 12, 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3); + ROUND(G, 30, 0x8f1bbcdc, + 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5, 0, 11, 6, 1, 12); + + /* --- Update the chaining variables --- */ + + ctx->a += a; + ctx->b += b; + ctx->c += c; + ctx->d += d; + ctx->e += e; +} + +/* --- @has160_init@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void has160_init(has160_ctx *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + ctx->e = 0xc3d2e1f0; + ctx->off = 0; + ctx->nl = ctx->nh = 0; +} + +/* --- @has160_set@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void has160_set(has160_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + ctx->a = LOAD32_L(p + 0); + ctx->b = LOAD32_L(p + 4); + ctx->c = LOAD32_L(p + 8); + ctx->d = LOAD32_L(p + 12); + ctx->e = LOAD32_L(p + 16); + ctx->off = 0; + ctx->nl = U32(count); + ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); +} + +/* --- @has160_hash@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void has160_hash(has160_ctx *ctx, const void *buf, size_t sz) +{ + HASH_BUFFER(HAS160, has160, ctx, buf, sz); +} + +/* --- @has160_done@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +void has160_done(has160_ctx *ctx, void *hash) +{ + octet *p = hash; + HASH_MD5STRENGTH(HAS160, has160, ctx); + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); + STORE32_L(p + 16, ctx->e); +} + +/* --- @has160_state@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @has160_set@. + */ + +unsigned long has160_state(has160_ctx *ctx, void *state) +{ + octet *p = state; + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); + STORE32_L(p + 16, ctx->e); + return (ctx->nl | ((ctx->nh << 16) << 16)); +} + +/* --- Generic interface --- */ + +GHASH_DEF(HAS160, has160) + +/* --- Test code --- */ + +HASH_TEST(HAS160, has160) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/has160.h b/symm/has160.h new file mode 100644 index 0000000..d3c17f1 --- /dev/null +++ b/symm/has160.h @@ -0,0 +1,157 @@ +/* -*-c-*- + * + * The HAS160 message digest function + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the HAS160 hash function ---------------------------------* + * + * HAS160 was designed by Chae Hoon Lim and the Korean Information Security + * Agency (KISA). It's recommended for use with KCDSA (though I think I'm + * happer with RIPEMD-160 or SHA1). It's here so I can check KCDSA test + * vectors. + */ + +#ifndef CATACOMB_HAS160_H +#define CATACOMB_HAS160_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define HAS160_BUFSZ 64 +#define HAS160_HASHSZ 20 +#define HAS160_STATESZ 20 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct has160_ctx { + uint32 a, b, c, d, e; /* Chaining variables */ + uint32 nl, nh; /* Byte count so far */ + unsigned off; /* Offset into buffer */ + octet buf[HAS160_BUFSZ]; /* Accumulation buffer */ +} has160_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @has160_compress@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: HAS160 compression function. + */ + +extern void has160_compress(has160_ctx */*ctx*/, const void */*sbuf*/); + +/* --- @has160_init@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void has160_init(has160_ctx */*ctx*/); + +/* --- @has160_set@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void has160_set(has160_ctx */*ctx*/, const void */*buf*/, + unsigned long /*count*/); + +/* --- @has160_hash@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void has160_hash(has160_ctx */*ctx*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @has160_done@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void has160_done(has160_ctx */*ctx*/, void */*hash*/); + +/* --- @has160_state@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @has160_set@. + */ + +extern unsigned long has160_state(has160_ctx */*ctx*/, void */*state*/); + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash has160; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/hash.h b/symm/hash.h new file mode 100644 index 0000000..31cf4a8 --- /dev/null +++ b/symm/hash.h @@ -0,0 +1,277 @@ +/* -*-c-*- + * + * Generic handling for message digest functions + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_HASH_H +#define CATACOMB_HASH_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @HASH_BUFFER@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for hash-specific definitions + * @ictx@ = pointer to context block for the hash + * @ibuf@ = pointer to input data to hash + * @isz@ = size of buffer + * + * Use: Handles buffering of input data to a hash function. The + * hash's compression function is called when the buffer is + * full. Note that the compression function can be called on + * data which is at odd alignments; it is expected to cope + * gracefully with this (possibly by copying the data into its + * internal buffer before starting). + */ + +#define HASH_BUFFER(PRE, pre, ictx, ibuf, isz) do { \ + pre##_ctx *_bctx = (ictx); \ + size_t _bsz = (isz); \ + const octet *_bbuf = (octet *)(ibuf); \ + \ + /* --- Add on the size done so far --- * \ + * \ + * Messy, because trapping overflow is difficult when you don't know \ + * how many bits you've actually got. \ + */ \ + \ + { \ + uint32 _l = U32(_bsz); \ + uint32 _h = ((_bsz & ~MASK32) >> 16) >> 16; \ + _bctx->nh += _h; \ + _bctx->nl += _l; \ + if (_bctx->nl < _l || _bctx->nl & ~MASK32) \ + _bctx->nh++; \ + } \ + \ + /* --- Handle very small contributions --- */ \ + \ + if (_bctx->off + _bsz < PRE##_BUFSZ) { \ + memcpy(_bctx->buf + _bctx->off, _bbuf, _bsz); \ + _bctx->off += _bsz; \ + } else { \ + \ + /* --- Handle an initial partial buffer --- */ \ + \ + if (_bctx->off) { \ + size_t s = PRE##_BUFSZ - _bctx->off; \ + memcpy(_bctx->buf + _bctx->off, _bbuf, s); \ + pre##_compress(_bctx, _bctx->buf); \ + _bsz -= s; _bbuf += s; \ + } \ + \ + /* --- Do whole buffers while we can --- */ \ + \ + while (_bsz >= PRE##_BUFSZ) { \ + pre##_compress(_bctx, _bbuf); \ + _bsz -= PRE##_BUFSZ; _bbuf += PRE##_BUFSZ; \ + } \ + \ + /* --- And wrap up at the end --- */ \ + \ + if (_bsz) \ + memcpy(_bctx->buf, _bbuf, _bsz); \ + _bctx->off = _bsz; \ + } \ +} while (0) + +/* --- @HASH_PAD@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for hash-specific definitions + * @ictx@ = pointer to context block for the hash + * @term@ = terminator character to write following the data + * @pad@ = pad character to fill with + * @diff@ = size of space to leave at the end of the last block + * + * Use: Does padding for message digest functions. + */ + +#define HASH_PAD(PRE, pre, ictx, term, pad, diff) do { \ + pre##_ctx *_pctx = (ictx); \ + \ + _pctx->buf[_pctx->off] = term; \ + _pctx->off++; \ + if (_pctx->off > PRE##_BUFSZ - diff) { \ + if (_pctx->off < PRE##_BUFSZ) \ + memset(_pctx->buf + _pctx->off, pad, PRE##_BUFSZ - _pctx->off); \ + pre##_compress(_pctx, _pctx->buf); \ + memset(_pctx->buf, pad, PRE##_BUFSZ - diff); \ + } else \ + memset(_pctx->buf + _pctx->off, pad, \ + PRE##_BUFSZ - _pctx->off - diff); \ +} while (0) + +/* --- @HASH_MD5STRENGTH@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for hash-specific definitions + * @ictx@ = pointer to context block for the hash + * + * Use: Does MD5-style MD strengthening. The data is terminated + * by a single set bit, padded with zero bits, and then a 64- + * bit length is written, little-end first. + */ + +#define HASH_MD5STRENGTH(PRE, pre, ictx) do { \ + pre##_ctx *_mctx = (ictx); \ + HASH_PAD(PRE, pre, _mctx, 0x80u, 0, 8); \ + STORE32_L(_mctx->buf + PRE##_BUFSZ - 8, _mctx->nl << 3); \ + STORE32_L(_mctx->buf + PRE##_BUFSZ - 4, \ + (_mctx->nl >> 29) | (_mctx->nh << 3)); \ + pre##_compress(_mctx, _mctx->buf); \ +} while (0) + +/* --- @HASH_TEST@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for hash-specfic definitions + * + * Use: Standard test rig for hash functions. + */ + +#ifdef TEST_RIG + +#include +#include + +#define HASH_BUFLEN 100000 + +#define HASH_TEST(PRE, pre) \ + \ +static int verify(dstr *v) \ +{ \ + pre##_ctx ctx; \ + int ok = 1; \ + int i; \ + octet *p; \ + int szs[] = { 1, 7, 192, -1, 0 }, *ip; \ + size_t sz; \ + dstr d; \ + \ + dstr_create(&d); \ + dstr_ensure(&d, PRE##_HASHSZ); \ + d.len = PRE##_HASHSZ; \ + \ + for (ip = szs; *ip; ip++) { \ + i = *ip; \ + sz = v[0].len; \ + if (i == -1) \ + i = sz; \ + if (i > sz) \ + continue; \ + p = (octet *)v[0].buf; \ + pre##_init(&ctx); \ + while (sz) { \ + if (i > sz) \ + i = sz; \ + pre##_hash(&ctx, p, i); \ + p += i; \ + sz -= i; \ + } \ + pre##_done(&ctx, d.buf); \ + if (memcmp(d.buf, v[1].buf, PRE##_HASHSZ) != 0) { \ + printf("\nfail:\n\tstep = %i\n\tinput = `%s'\n\texpected = ", \ + *ip, v[0].buf); \ + type_hex.dump(&v[1], stdout); \ + fputs("\n\tcomputed = ", stdout); \ + type_hex.dump(&d, stdout); \ + putchar('\n'); \ + ok = 0; \ + } \ + } \ + \ + dstr_destroy(&d); \ + return (ok); \ +} \ + \ +static int verifyrep(dstr *v) \ +{ \ + pre##_ctx ctx; \ + size_t len = v[0].len; \ + int n = *(int *)v[1].buf; \ + int nd = 0; \ + int nn = len; \ + int ok = 1; \ + octet *p, *q; \ + dstr d = DSTR_INIT; \ + \ + while (nn < HASH_BUFLEN && (n & 1) == 0) { nd++; nn <<= 1; n >>= 1; } \ + p = xmalloc(nn); \ + memcpy(p, v[0].buf, len); \ + q = p + len; \ + while (nd--) { memcpy(q, p, len); q += len; len <<= 1; } \ + \ + dstr_ensure(&d, PRE##_HASHSZ); \ + d.len = PRE##_HASHSZ; \ + pre##_init(&ctx); \ + while (n--) pre##_hash(&ctx, p, len); \ + pre##_done(&ctx, d.buf); \ + \ + if (memcmp(d.buf, v[2].buf, PRE##_HASHSZ) != 0) { \ + printf("\nfail:\n\tinput = `%s'\n\treps = `%i'\n\texpected = ", \ + v[0].buf, *(int *)v[1].buf); \ + type_hex.dump(&v[2], stdout); \ + fputs("\n\tcomputed = ", stdout); \ + type_hex.dump(&d, stdout); \ + putchar('\n'); \ + ok = 0; \ + } \ + xfree(p); \ + dstr_destroy(&d); \ + return (ok); \ +} \ + \ +static test_chunk defs[] = { \ + { #pre, verify, { &type_string, &type_hex, 0 } }, \ + { #pre "-rep", verifyrep, \ + { &type_string, &type_int, &type_hex, 0 } }, \ + { 0, 0, { 0 } } \ +}; \ + \ +int main(int argc, char *argv[]) \ +{ \ + ego(argv[0]); \ + test_run(argc, argv, defs, SRCDIR"/t/" #pre); \ + return (0); \ +} + +#else +# define HASH_TEST(PRE, pre) +#endif + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/hmac-def.h b/symm/hmac-def.h new file mode 100644 index 0000000..032c69f --- /dev/null +++ b/symm/hmac-def.h @@ -0,0 +1,442 @@ +/* -*-c-*- + * + * Definitions for HMAC and NMAC + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_HMAC_DEF_H +#define CATACOMB_HMAC_DEF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include +#include + +#ifndef CATACOMB_ARENA_H +# include "arena.h" +#endif + +#ifndef CATACOMB_GMAC_H +# include "gmac.h" +#endif + +#ifndef CATACOMB_PARANOIA_H +# include "paranoia.h" +#endif + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @HMAC_DEF@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for the underlying hash function + * + * Use: Creates implementations for the HMAC and NMAC functions. + */ + +#define HMAC_DEF(PRE, pre) \ + \ +/* --- Useful constants --- */ \ + \ +const octet pre##_hmackeysz[] = { KSZ_ANY, PRE##_STATESZ }; \ +const octet pre##_sslmackeysz[] = { KSZ_ANY, PRE##_STATESZ }; \ +const octet pre##_nmackeysz[] = { KSZ_SET, 2 * PRE##_STATESZ, 0 }; \ + \ +/* --- @pre_nmacinit@ --- * \ + * \ + * Arguments: @pre_macctx *key@ = pointer to a MAC key object \ + * @const void *ok@ = pointer to outer hash init vector \ + * @const void *ik@ = pointer to inner hash init vector \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a MAC key for doing NMAC hashing. \ + */ \ + \ +void pre##_nmacinit(pre##_mackey *key, const void *ok, const void *ik) \ +{ \ + memcpy(key->ochain, ok, PRE##_STATESZ); \ + memcpy(key->ichain, ik, PRE##_STATESZ); \ + key->ocount = key->icount = 0; \ +} \ + \ +/* --- @pre_hmacinit@ --- * \ + * \ + * Arguments: @pre_mackey *key@ = pointer to MAC key object \ + * @const void *k@ = pointer to key to use \ + * @size_t sz@ = size of key data \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a MAC key for doing HMAC hashing. Keys \ + * longer than the hash function's output size aren't very \ + * useful, but are accepted. Keys longer than the hash's \ + * block size are also accepted; they are hashed before \ + * use, as specified in RFC2104. \ + */ \ + \ +void pre##_hmacinit(pre##_mackey *key, const void *k, size_t sz) \ +{ \ + int i; \ + const octet *kbuf = k; \ + pre##_ctx ctx; \ + octet buf[PRE##_HASHSZ]; \ + \ + if (sz > PRE##_BUFSZ) { \ + pre##_init(&ctx); \ + pre##_hash(&ctx, k, sz); \ + pre##_done(&ctx, buf); \ + kbuf = buf; \ + sz = PRE##_HASHSZ; \ + } \ + \ + pre##_init(&ctx); \ + memset(ctx.buf, 0x5c, PRE##_BUFSZ); \ + for (i = 0; i < sz; i++) \ + ctx.buf[i] ^= kbuf[i]; \ + pre##_compress(&ctx, ctx.buf); \ + pre##_state(&ctx, key->ochain); \ + \ + pre##_init(&ctx); \ + memset(ctx.buf, 0x36, PRE##_BUFSZ); \ + for (i = 0; i < sz; i++) \ + ctx.buf[i] ^= kbuf[i]; \ + pre##_compress(&ctx, ctx.buf); \ + pre##_state(&ctx, key->ichain); \ + \ + key->ocount = key->icount = PRE##_BUFSZ; \ + BURN(ctx); \ +} \ + \ +/* --- @pre_sslmacinit@ --- * \ + * \ + * Arguments: @pre_mackey *key@ = pointer to MAC key object \ + * @const void *k@ = pointer to key to use \ + * @size_t sz@ = size of key data \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a MAC key for doing hasing using the SSL3 \ + * variant of HMAC. \ + */ \ + \ +void pre##_sslmacinit(pre##_mackey *key, const void *k, size_t sz) \ +{ \ + const octet *kbuf = k; \ + pre##_ctx ctx; \ + octet buf[PRE##_HASHSZ]; \ + \ + if (sz > PRE##_BUFSZ) { \ + pre##_init(&ctx); \ + pre##_hash(&ctx, k, sz); \ + pre##_done(&ctx, buf); \ + kbuf = buf; \ + sz = PRE##_HASHSZ; \ + } \ + \ + pre##_init(&ctx); \ + memcpy(ctx.buf, kbuf, sz); \ + memset(ctx.buf + sz, 0x5c, PRE##_BUFSZ - sz); \ + pre##_compress(&ctx, ctx.buf); \ + pre##_state(&ctx, key->ochain); \ + \ + pre##_init(&ctx); \ + memcpy(ctx.buf, kbuf, sz); \ + memset(ctx.buf + sz, 0x36, PRE##_BUFSZ - sz); \ + pre##_compress(&ctx, ctx.buf); \ + pre##_state(&ctx, key->ichain); \ + \ + key->ocount = key->icount = PRE##_BUFSZ; \ + BURN(ctx); \ +} \ + \ +/* --- @pre_macinit@ --- * \ + * \ + * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \ + * @const pre_mackey *key@ = pointer to MAC key block \ + * \ + * Returns: --- \ + * \ + * Use: Instantiates a MAC context from a key block. \ + */ \ + \ +void pre##_macinit(pre##_macctx *ctx, const pre##_mackey *key) \ +{ \ + memcpy(ctx->chain, key->ochain, PRE##_STATESZ); \ + ctx->count = key->ocount; \ + pre##_set(&ctx->ctx, key->ichain, key->icount); \ +} \ + \ +/* --- @pre_machash@ --- * \ + * \ + * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \ + * @const void *buf@ = pointer to buffer \ + * @size_t sz@ = size of the buffer \ + * \ + * Returns: --- \ + * \ + * Use: Hashes a buffer. \ + */ \ + \ +void pre##_machash(pre##_macctx *ctx, const void *buf, size_t sz) \ +{ \ + pre##_hash(&ctx->ctx, buf, sz); \ +} \ + \ +/* --- @pre_macdone@ --- * \ + * \ + * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \ + * @void *mac@ = pointer to buffer to receive MAC \ + * \ + * Returns: --- \ + * \ + * Use: Returns the result of a MAC computation. \ + */ \ + \ +void pre##_macdone(pre##_macctx *ctx, void *mac) \ +{ \ + pre##_done(&ctx->ctx, mac); \ + pre##_set(&ctx->ctx, ctx->chain, ctx->count); \ + pre##_hash(&ctx->ctx, mac, PRE##_HASHSZ); \ + pre##_done(&ctx->ctx, mac); \ +} \ + \ +/* --- Generic MAC interface --- */ \ + \ +static const gmac_ops gkops; \ +static const ghash_ops gops, gnops, gsslops; \ + \ +typedef struct gkctx { \ + gmac m; \ + const ghash_ops *gops; \ + pre##_mackey k; \ +} gkctx; \ + \ +typedef struct gctx { \ + ghash h; \ + pre##_macctx c; \ + octet buf[PRE##_HASHSZ]; \ +} gctx; \ + \ +static ghash *gkinit(gmac *m) \ +{ \ + gkctx *gk = (gkctx *)m; \ + gctx *g = S_CREATE(gctx); \ + g->h.ops = gk->gops; \ + pre##_macinit(&g->c, &gk->k); \ + return (&g->h); \ +} \ + \ +static gmac *gkey(const void *k, size_t sz) \ +{ \ + gkctx *gk = S_CREATE(gkctx); \ + gk->m.ops = &gkops; \ + gk->gops = &gops; \ + pre##_hmacinit(&gk->k, k, sz); \ + return (&gk->m); \ +} \ + \ +static gmac *gnkey(const void *k, size_t sz) \ +{ \ + gkctx *gk = S_CREATE(gkctx); \ + const octet *kk = k; \ + assert(keysz(sz, pre##_nmackeysz) == sz); \ + gk->m.ops = &gkops; \ + gk->gops = &gnops; \ + pre##_nmacinit(&gk->k, kk, kk + PRE##_STATESZ); \ + return (&gk->m); \ +} \ + \ +static gmac *gsslkey(const void *k, size_t sz) \ +{ \ + gkctx *gk = S_CREATE(gkctx); \ + gk->m.ops = &gkops; \ + gk->gops = &gsslops; \ + pre##_sslmacinit(&gk->k, k, sz); \ + return (&gk->m); \ +} \ + \ +static void ghhash(ghash *h, const void *p, size_t sz) \ +{ \ + gctx *g = (gctx *)h; \ + pre##_machash(&g->c, p, sz); \ +} \ + \ +static octet *ghdone(ghash *h, void *buf) \ +{ \ + gctx *g = (gctx *)h; \ + if (!buf) \ + buf = g->buf; \ + pre##_macdone(&g->c, buf); \ + return (buf); \ +} \ + \ +static ghash *ghcopy(ghash *h) \ +{ \ + gctx *g = (gctx *)h; \ + gctx *gg = S_CREATE(gctx); \ + memcpy(gg, g, sizeof(gctx)); \ + return (&gg->h); \ +} \ + \ +static void ghdestroy(ghash *h) \ +{ \ + gctx *g = (gctx *)h; \ + BURN(*g); \ + S_DESTROY(g); \ +} \ + \ +static void gkdestroy(gmac *m) \ +{ \ + gkctx *gk = (gkctx *)m; \ + BURN(*gk); \ + S_DESTROY(gk); \ +} \ + \ +static ghash *ghinit(void) \ +{ \ + assert(((void)"Attempt to instantiate an unkeyed MAC", 0)); \ + return (0); \ +} \ + \ +const gcmac pre##_nmac = \ + { #pre "-nmac", PRE##_HASHSZ, pre##_nmackeysz, gnkey }; \ +const gcmac pre##_hmac = \ + { #pre "-hmac", PRE##_HASHSZ, pre##_hmackeysz, gkey }; \ +const gcmac pre##_sslmac = \ + { #pre "-sslmac", PRE##_HASHSZ, pre##_sslmackeysz, gsslkey }; \ +static const gmac_ops gkops = { &pre##_hmac, gkinit, gkdestroy }; \ +static const gmac_ops gnkops = { &pre##_nmac, gkinit, gkdestroy }; \ +static const gmac_ops gsslkops = { &pre##_sslmac, gkinit, gkdestroy }; \ +static const gchash gch = { #pre "-hmac", PRE##_HASHSZ, ghinit }; \ +static const ghash_ops gops = \ + { &gch, ghhash, ghdone, ghdestroy, ghcopy }; \ +static const gchash gnch = { #pre "-nmac", PRE##_HASHSZ, ghinit }; \ +static const ghash_ops gnops = \ + { &gch, ghhash, ghdone, ghdestroy, ghcopy }; \ +static const gchash gsslch = { #pre "-sslmac", PRE##_HASHSZ, ghinit }; \ +static const ghash_ops gsslops = \ + { &gch, ghhash, ghdone, ghdestroy, ghcopy }; \ + \ +HMAC_TEST(PRE, pre) + +/* --- @HMAC_TEST@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for hash-specfic definitions + * + * Use: Standard test rig for MAC functions. + */ + +#ifdef TEST_RIG + +#include + +#include +#include +#include + +#define HMAC_TEST(PRE, pre) \ + \ +static int macverify(dstr *v) \ +{ \ + pre##_macctx cctx; \ + pre##_mackey ckey; \ + int ok = 1; \ + int i; \ + octet *p; \ + int szs[] = { 1, 7, 192, -1, 0 }, *ip; \ + size_t csz; \ + dstr d; \ + \ + dstr_create(&d); \ + dstr_ensure(&d, PRE##_HASHSZ); \ + d.len = PRE##_HASHSZ; \ + \ + pre##_hmacinit(&ckey, v[1].buf, v[1].len); \ + \ + for (ip = szs; *ip; ip++) { \ + i = *ip; \ + csz = v[0].len; \ + if (i == -1) \ + i = csz; \ + if (i > csz) \ + continue; \ + p = (octet *)v[0].buf; \ + pre##_macinit(&cctx, &ckey); \ + while (csz) { \ + if (i > csz) \ + i = csz; \ + pre##_machash(&cctx, p, i); \ + p += i; \ + csz -= i; \ + } \ + pre##_macdone(&cctx, d.buf); \ + if (memcmp(d.buf, v[2].buf, PRE##_HASHSZ) != 0) { \ + printf("\nfail:\n\tstep = %i\n\tinput = `%s'\n\tkey = ", \ + *ip, v[0].buf); \ + type_hex.dump(&v[1], stdout); \ + fputs("\n\texpected = ", stdout); \ + type_hex.dump(&v[2], stdout); \ + fputs("\n\tcomputed = ", stdout); \ + type_hex.dump(&d, stdout); \ + putchar('\n'); \ + ok = 0; \ + } \ + } \ + \ + dstr_destroy(&d); \ + return (ok); \ +} \ + \ +static test_chunk macdefs[] = { \ + { #pre "-hmac", macverify, \ + { &type_string, &type_hex, &type_hex, 0 } }, \ + { 0, 0, { 0 } } \ +}; \ + \ +int main(int argc, char *argv[]) \ +{ \ + ego(argv[0]); \ + test_run(argc, argv, macdefs, SRCDIR"/t/" #pre); \ + return (0); \ +} + +#else +# define HMAC_TEST(PRE, pre) +#endif + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/hmac.h b/symm/hmac.h new file mode 100644 index 0000000..12da5fd --- /dev/null +++ b/symm/hmac.h @@ -0,0 +1,189 @@ +/* -*-c-*- + * + * Generic code for HMAC and NMAC + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the HMAC and NMAC constructions --------------------------* + * + * Designed by Mihir Bellare, Ran Canetti and Hugo Krawczyk, NMAC is a method + * for constructing keyed message authentication algorithms from unkeyed hash + * functions. It has been proven to provide useful security given reasonable + * assumptions about the underlying hash function. HMAC is an alternative + * formulation which doesn't require low-level access to the hash function's + * implementation. NMAC was designed to allow MD5 has a suitable underlying + * hash function, even though doubts were already being raised about its + * collision resistance. + */ + +#ifndef CATACOMB_HMAC_H +#define CATACOMB_HMAC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#ifndef CATACOMB_GMAC_H +# include "gmac.h" +#endif + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @HMAC_DECL@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for the underlying hash function + * + * Use: Creates declarations for the HMAC and NMAC functions. + */ + +#define HMAC_DECL(PRE, pre) \ + \ +/* --- An HMAC or NMAC key --- */ \ + \ +typedef struct pre##_mackey { \ + octet ochain[PRE##_STATESZ]; /* Chaining for outer hash */ \ + unsigned ocount; /* Byte count for outer hash */ \ + octet ichain[PRE##_STATESZ]; /* Chaining for inner hash */ \ + unsigned icount; /* Byte count for inner hash */ \ +} pre##_mackey; \ + \ +/* --- An HMAC or NMAC hashing context --- */ \ + \ +typedef struct pre##_macctx { \ + pre##_ctx ctx; /* Context for main hashing */ \ + octet chain[PRE##_STATESZ]; /* Chaining for outer hash */ \ + unsigned count; /* Byte count for outer hash */ \ +} pre##_macctx; \ + \ +/* --- Other useful constants --- */ \ + \ +extern const octet pre##_hmackeysz[]; \ +extern const octet pre##_nmackeysz[]; \ +extern const octet pre##_sslmackeysz[]; \ + \ +/* --- @pre_nmacinit@ --- * \ + * \ + * Arguments: @pre_macctx *key@ = pointer to a MAC key object \ + * @const void *ok@ = pointer to outer hash init vector \ + * @const void *ik@ = pointer to inner hash init vector \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a MAC key for doing NMAC hashing. \ + */ \ + \ +extern void pre##_nmacinit(pre##_mackey */*key*/, \ + const void */*ok*/, const void */*ik*/); \ + \ +/* --- @pre_hmacinit@ --- * \ + * \ + * Arguments: @pre_mackey *key@ = pointer to MAC key object \ + * @const void *k@ = pointer to key to use \ + * @size_t sz@ = size of key data \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a MAC key for doing HMAC hashing. Keys \ + * longer than the hash function's output size aren't very \ + * useful, but are accepted. Keys longer than the hash's \ + * block size are also accepted; they are hashed before \ + * use, as specified in RFC2104. \ + */ \ + \ +extern void pre##_hmacinit(pre##_mackey */*key*/, \ + const void */*k*/, size_t /*sz*/); \ + \ +/* --- @pre_sslmacinit@ --- * \ + * \ + * Arguments: @pre_mackey *key@ = pointer to MAC key object \ + * @const void *k@ = pointer to key to use \ + * @size_t sz@ = size of key data \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a MAC key for doing hasing using the SSL3 \ + * variant of HMAC. \ + */ \ + \ +extern void pre##_sslmacinit(pre##_mackey */*key*/, \ + const void */*k*/, size_t /*sz*/); \ + \ +/* --- @pre_macinit@ --- * \ + * \ + * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \ + * @const pre_mackey *key@ = pointer to MAC key block \ + * \ + * Returns: --- \ + * \ + * Use: Instantiates a MAC context from a key block. \ + */ \ + \ +extern void pre##_macinit(pre##_macctx */*ctx*/, \ + const pre##_mackey */*key*/); \ + \ +/* --- @pre_machash@ --- * \ + * \ + * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \ + * @const void *buf@ = pointer to buffer \ + * @size_t sz@ = size of the buffer \ + * \ + * Returns: --- \ + * \ + * Use: Hashes a buffer. \ + */ \ + \ +extern void pre##_machash(pre##_macctx */*ctx*/, \ + const void */*buf*/, size_t /*sz*/); \ + \ +/* --- @pre_macdone@ --- * \ + * \ + * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \ + * @void *mac@ = pointer to buffer to receive MAC \ + * \ + * Returns: --- \ + * \ + * Use: Returns the result of a MAC computation. \ + */ \ + \ +extern void pre##_macdone(pre##_macctx */*ctx*/, void */*mac*/); \ + \ +/* --- Generic MAC interface --- */ \ + \ +extern const gcmac pre##_hmac; \ +extern const gcmac pre##_nmac; \ +extern const gcmac pre##_sslmac; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/idea.c b/symm/idea.c new file mode 100644 index 0000000..51edb2d --- /dev/null +++ b/symm/idea.c @@ -0,0 +1,273 @@ +/* -*-c-*- + * + * Implementation of the IDEA cipher + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "idea.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet idea_keysz[] = { KSZ_SET, IDEA_KEYSZ }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @inv@ --- * + * + * Arguments: @uint16 n@ = number to invert + * + * Returns: Multiplicative inverse of @n@ %$\pmod{2^{16} + 1}$%. + * + * Use: Computes multiplicative inverses. This is handy for the + * decryption key scheduling. + */ + +static uint16 inv(uint16 n) +{ + uint32 m = 0x10001; + uint32 a = 1, b = 0; + uint32 nn = n; + + if (!nn) + nn = 0x10000; + for (;;) { + uint32 q, r, t; + if (!(r = m % nn)) + break; + q = m / nn; + m = nn; nn = r; + t = a; a = b - q * a; b = t; + } + if (a > MASK16) + a += 1; + return (U16(a)); +} + +/* --- @MUL@ --- * + * + * Arguments @x@ and @y@ are two 32-bit values to multiply. On exit, @x@ is + * the product of the two arguments. The result is not normalized back to 16 + * bits; the arguments are not expected to be normalized. + * + * This code is from `Side Channel Attack Hardening of the IDEA Cipher', + * published by Ascom Tech. + */ + +#define MUL(x, y) do { \ + unsigned _t; \ + uint32 _tt; \ + \ + x = U16(x - 1); \ + _t = U16(y - 1); \ + _tt = (uint32)x * (uint32)_t + (uint32)x + (uint32)_t + 1; \ + x = U16(_tt); \ + _t = U16(_tt >> 16); \ + x = x - _t + (x <= _t); \ +} while (0) + +/* --- @idea_init@ --- * + * + * Arguments: @idea_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes an IDEA key buffer. The buffer must be exactly + * 16 bytes in size, because IDEA is only defined with a key + * size of 128 bits. + */ + +void idea_init(idea_ctx *k, const void *buf, size_t sz) +{ + KSZ_ASSERT(idea, sz); + + /* --- Unpack the encryption key --- */ + + { + const octet *p = buf; + uint16 *q = k->e; + uint32 a = LOAD32(p + 0); + uint32 b = LOAD32(p + 4); + uint32 c = LOAD32(p + 8); + uint32 d = LOAD32(p + 12); + int i; + + /* --- Main unpacking loop --- */ + + for (i = 0; i < 6; i++) { + + /* --- Spit out the next 8 subkeys --- */ + + q[0] = U16(a >> 16); + q[1] = U16(a >> 0); + q[2] = U16(b >> 16); + q[3] = U16(b >> 0); + q[4] = U16(c >> 16); + q[5] = U16(c >> 0); + q[6] = U16(d >> 16); + q[7] = U16(d >> 0); + q += 8; + + /* --- Rotate and permute the subkeys --- */ + + { + uint32 t = a; + a = U32((a << 25) | (b >> 7)); + b = U32((b << 25) | (c >> 7)); + c = U32((c << 25) | (d >> 7)); + d = U32((d << 25) | (t >> 7)); + } + } + + /* --- Write out the tail-enders --- */ + + q[0] = U16(a >> 16); + q[1] = U16(a >> 0); + q[2] = U16(b >> 16); + q[3] = U16(b >> 0); + } + + /* --- Convert this into the decryption key --- */ + + { + uint16 *p = k->e + 52; + uint16 *q = k->d; + int i; + + /* --- Translate the main round keys --- */ + + for (i = 0; i < 8; i++) { + p -= 6; + q[4] = p[0]; + q[5] = p[1]; + q[0] = inv(p[2]); + q[3] = inv(p[5]); + if (i) { + q[1] = 0x10000 - p[4]; + q[2] = 0x10000 - p[3]; + } else { + q[1] = 0x10000 - p[3]; + q[2] = 0x10000 - p[4]; + } + q += 6; + } + + /* --- Translate the tail-enders --- */ + + p -= 4; + q[0] = inv(p[0]); + q[1] = 0x10000 - p[1]; + q[2] = 0x10000 - p[2]; + q[3] = inv(p[3]); + } +} + +/* --- @ROUND@ --- */ + +#define MIX(k, a, b, c, d) do { \ + MUL(a, k[0]); \ + b += k[1]; \ + c += k[2]; \ + MUL(d, k[3]); \ +} while (0) + +#define MA(k, a, b, c, d) do { \ + unsigned _u = a ^ c; \ + unsigned _v = b ^ d; \ + MUL(_u, k[4]); \ + _v += _u; \ + MUL(_v, k[5]); \ + _u += _v; \ + a ^= _v; \ + b ^= _u; \ + c ^= _v; \ + d ^= _u; \ +} while (0); + +#define ROUND(k, a, b, c, d) do { \ + MIX(k, a, b, c, d); \ + MA(k, a, b, c, d); \ + (k) += 6; \ +} while (0) + +/* --- Encryption --- */ + +#define EBLK(k, a, b, c, d) do { \ + unsigned _a = U16(a >> 16); \ + unsigned _b = U16(a >> 0); \ + unsigned _c = U16(b >> 16); \ + unsigned _d = U16(b >> 0); \ + const uint16 *_k = (k); \ + \ + ROUND(_k, _a, _b, _c, _d); \ + ROUND(_k, _a, _c, _b, _d); \ + ROUND(_k, _a, _b, _c, _d); \ + ROUND(_k, _a, _c, _b, _d); \ + ROUND(_k, _a, _b, _c, _d); \ + ROUND(_k, _a, _c, _b, _d); \ + ROUND(_k, _a, _b, _c, _d); \ + ROUND(_k, _a, _c, _b, _d); \ + MIX (_k, _a, _c, _b, _d); \ + c = ((uint32)U16(_a) << 16) | (uint32)U16(_c); \ + d = ((uint32)U16(_b) << 16) | (uint32)U16(_d); \ +} while (0) + +#define DBLK(k, a, b) EBLK((k), (a), (b)) + +/* --- @idea_eblk@, @idea_dblk@ --- * + * + * Arguments: @const idea_ctx *k@ = pointer to a key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +void idea_eblk(const idea_ctx *k, const uint32 *s, uint32 *d) +{ + EBLK(k->e, s[0], s[1], d[0], d[1]); +} + +void idea_dblk(const idea_ctx *k, const uint32 *s, uint32 *d) +{ + EBLK(k->d, s[0], s[1], d[0], d[1]); +} + +BLKC_TEST(IDEA, idea) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/idea.h b/symm/idea.h new file mode 100644 index 0000000..a25a82a --- /dev/null +++ b/symm/idea.h @@ -0,0 +1,111 @@ +/* -*-c-*- + * + * Implementation of the IDEA cipher + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the IDEA block cipher ------------------------------------* + * + * IDEA was invented by James Massey and Xuejia Lai. The fundamental idea + * underlying the cipher is combining incompatible group operations. The + * algorithm's main claim to fame is that it is the symmetric cipher in PGP + * version 2. + * + * The IDEA algorithm is allegedly patented by Ascom Tech A.G., even in the + * UK and Europe. Ascom are willing to grant licences for use in software + * which forbids commercial use, but this is not compatible with Free + * Software Foundation ideology. The author recommends against the use of + * the IDEA cipher entirely. Blowfish is conceptually simpler, appears more + * concervative, offers a larger keyspace, runs faster, and is in the public + * domain. + */ + +#ifndef CATACOMB_IDEA_H +#define CATACOMB_IDEA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magical numbers ---------------------------------------------------*/ + +#define IDEA_BLKSZ 8 +#define IDEA_KEYSZ 16 +#define IDEA_CLASS (N, B, 64) + +extern const octet idea_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct idea_ctx { + uint16 e[52]; + uint16 d[52]; +} idea_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @idea_init@ --- * + * + * Arguments: @idea_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes an IDEA key buffer. The buffer must be exactly + * 16 bytes in size, because IDEA is only defined with a key + * size of 128 bits. + */ + +extern void idea_init(idea_ctx */*k*/, const void */*buf*/, size_t /*sz*/); + +/* --- @idea_eblk@, @idea_dblk@ --- * + * + * Arguments: @const idea_ctx *k@ = pointer to a key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void idea_eblk(const idea_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); +extern void idea_dblk(const idea_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/mars-mktab.c b/symm/mars-mktab.c new file mode 100644 index 0000000..750f727 --- /dev/null +++ b/symm/mars-mktab.c @@ -0,0 +1,315 @@ +/* -*-c-*- + * + * Generate the MARS S-box table + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include + +#include "sha.h" + +/*----- SHA-1 (quick version) ---------------------------------------------*/ + +/* --- @sha_compress@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: SHA-1 compression function. + */ + +void sha_compress(sha_ctx *ctx, const void *sbuf) +{ + uint32 a, b, c, d, e; + uint32 buf[80]; + + /* --- Fetch the chaining variables --- */ + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + e = ctx->e; + + /* --- Fetch and expand the buffer contents --- */ + + { + int i; + const octet *p; + + for (i = 0, p = sbuf; i < 16; i++, p += 4) + buf[i] = LOAD32(p); + for (i = 16; i < 80; i++) { + uint32 x = buf[i - 3] ^ buf[i - 8] ^ buf[i - 14] ^ buf[i - 16]; + buf[i] = ROL32(x, 1); + } + } + + /* --- Definitions for round functions --- */ + +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define G(x, y, z) ((x) ^ (y) ^ (z)) +#define H(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) + +#define T(v, w, x, y, z, i, f, k) do { \ + uint32 _x; \ + z = ROL32(v, 5) + f(w, x, y) + z + buf[i] + k; \ + w = ROR32(w, 2); \ + _x = v; v = z; z = y; y = x; x = w; w = _x; \ +} while (0) + +#define FF(v, w, x, y, z, i) T(v, w, x, y, z, i, F, 0x5a827999) +#define GG(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0x6ed9eba1) +#define HH(v, w, x, y, z, i) T(v, w, x, y, z, i, H, 0x8f1bbcdc) +#define II(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0xca62c1d6) + + /* --- The main compression function --- */ + + { + unsigned i; + for (i = 0; i < 20; i++) + FF(a, b, c, d, e, i); + for (i = 20; i < 40; i++) + GG(a, b, c, d, e, i); + for (i = 40; i < 60; i++) + HH(a, b, c, d, e, i); + for (i = 60; i < 80; i++) + II(a, b, c, d, e, i); + } + + ctx->a += a; + ctx->b += b; + ctx->c += c; + ctx->d += d; + ctx->e += e; +} + +/* --- @sha_init@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void sha_init(sha_ctx *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + ctx->e = 0xc3d2e1f0; + ctx->off = 0; + ctx->nl = ctx->nh = 0; +} + +/* --- @sha_hash@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void sha_hash(sha_ctx *ctx, const void *buf, size_t sz) +{ + sha_ctx *_bctx = (ctx); + size_t _bsz = (sz); + const octet *_bbuf = (octet *) (buf); + + { + uint32 _l = ((uint32) ((_bsz) & MASK32)); + uint32 _h = ((_bsz & ~MASK32) >> 16) >> 16; + _bctx->nh += _h; + _bctx->nl += _l; + if (_bctx->nl < _l || _bctx->nl & ~MASK32) + _bctx->nh++; + } + if (_bctx->off + _bsz < SHA_BUFSZ) { + memcpy(_bctx->buf + _bctx->off, _bbuf, _bsz); + _bctx->off += _bsz; + } else { + if (_bctx->off) { + size_t s = SHA_BUFSZ - _bctx->off; + memcpy(_bctx->buf + _bctx->off, _bbuf, s); + sha_compress(_bctx, _bctx->buf); + _bsz -= s; + _bbuf += s; + } + while (_bsz >= SHA_BUFSZ) { + sha_compress(_bctx, _bbuf); + _bsz -= SHA_BUFSZ; + _bbuf += SHA_BUFSZ; + } + if (_bsz) + memcpy(_bctx->buf, _bbuf, _bsz); + _bctx->off = _bsz; + } +} + +/* --- @sha_done@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +void sha_done(sha_ctx *ctx, void *hash) +{ + octet *p = hash; + { + sha_ctx *_pctx = (ctx); + _pctx->buf[_pctx->off] = 0x80; + _pctx->off++; + if (_pctx->off > SHA_BUFSZ - 8) { + if (_pctx->off < SHA_BUFSZ) + memset(_pctx->buf + _pctx->off, 0, SHA_BUFSZ - _pctx->off); + sha_compress(_pctx, _pctx->buf); + memset(_pctx->buf, 0, SHA_BUFSZ - 8); + } else + memset(_pctx->buf + _pctx->off, 0, SHA_BUFSZ - _pctx->off - 8); + } + STORE32(ctx->buf + SHA_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3)); + STORE32(ctx->buf + SHA_BUFSZ - 4, ctx->nl << 3); + sha_compress(ctx, ctx->buf); + STORE32(p + 0, ctx->a); + STORE32(p + 4, ctx->b); + STORE32(p + 8, ctx->c); + STORE32(p + 12, ctx->d); + STORE32(p + 16, ctx->e); +} + +/*----- Main code ---------------------------------------------------------*/ + +static void mks(uint32 c3, uint32 *s) +{ + octet ibuf[16], obuf[20]; + sha_ctx h; + unsigned i, j; + + STORE32_L(ibuf + 4, 0xb7e15162); + STORE32_L(ibuf + 8, 0x243f6a88); + STORE32_L(ibuf + 12, c3); + + for (i = 0; i < 510; i += 5) { + STORE32_L(ibuf, i); + sha_init(&h); + sha_hash(&h, ibuf, sizeof(ibuf)); + sha_done(&h, obuf); + for (j = 0; j < 5; j++) + *s++ = LOAD32_L(obuf + (4 * j)); + } + STORE32_L(ibuf, i); + sha_init(&h); + sha_hash(&h, ibuf, sizeof(ibuf)); + sha_done(&h, obuf); + for (j = 0; i < 512; j++, i++) + *s++ = LOAD32_L(obuf + (4 * j)); +} + +static void fix(uint32 *s) +{ + unsigned i, j, n; + uint32 d; + + for (i = 0; i < 512; i++) { + for (j = i & ~255u; j < ((i + 255) & ~255u); j++) { + if (i == j) + continue; + d = s[i] ^ s[j]; + n = 0; + if (!(d & 0xff000000)) n++; + if (!(d & 0x00ff0000)) n++; + if (!(d & 0x0000ff00)) n++; + if (!(d & 0x000000ff)) n++; + if (n >= 2) { + s[i] = U32(s[i] * 3); + goto fixed; + } + } + fixed:; + } +} + +int main(void) +{ + uint32 s[512]; + unsigned i; + + mks(0x02917d59, s); + fix(s); + + puts("\ +/* -*-c-*-\n\ + *\n\ + * MARS tables [generated]\n\ + */\n\ +\n\ +#ifndef CATACOMB_MARS_TAB_H\n\ +#define CATACOMB_MARS_TAB_H\n\ +"); + + fputs("\ +/* --- The S-box --- */\n\ +\n\ +#define MARS_S { \\\n\ + ", stdout); + for (i = 0; i < 512; i++) { + printf("0x%08lx", (unsigned long)s[i]); + if (i == 511) + fputs(" \\\n}\n\n", stdout); + else if (i % 4 == 3) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + puts("#endif"); + + if (fclose(stdout)) { + fprintf(stderr, "error writing data\n"); + exit(EXIT_FAILURE); + } + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/mars.c b/symm/mars.c new file mode 100644 index 0000000..6f73b42 --- /dev/null +++ b/symm/mars.c @@ -0,0 +1,264 @@ +/* -*-c-*- + * + * The MARS block cipher + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "mars.h" +#include "mars-tab.h" +#include "paranoia.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet mars_keysz[] = { KSZ_RANGE, MARS_KEYSZ, 0, 56, 4 }; + +/*----- Useful tables -----------------------------------------------------*/ + +static const uint32 s[512] = MARS_S; +#define s0 (s + 0) +#define s1 (s + 256) +#define bb (s + 265) + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mars_init@ --- * + * + * Arguments: @mars_ctx *k@ = pointer to key block to fill in + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a MARS key buffer. MARS accepts key sizes + * between 128 and 448 bits which are a multiple of 32 bits. + */ + +void mars_init(mars_ctx *k, const void *buf, size_t sz) +{ + uint32 t[15]; + uint32 *kk = k->k; + const octet *p; + unsigned i, j, ii; + + KSZ_ASSERT(mars, sz); + + /* --- Copy the key into the temporary buffer --- */ + + p = buf; + for (i = 0; i < sz/4; i++) { + t[i] = LOAD32_L(p); + p += 4; + } + t[i++] = sz/4; + for (; i < 15; i++) + t[i] = 0; + + /* --- Now spit out the actual key material --- */ + + for (j = 0; j < 4; j++) { + uint32 x; + + /* --- Do the linear mixing stage --- */ + + for (i = 0; i < 15; i++) { + x = t[(i + 8)%15] ^ t[(i + 13)%15]; + t[i] ^= ROL32(x, 3) ^ ((i << 2) | j); + } + + /* --- Now do the Feistel stirring stage --- */ + + x = t[14]; + for (ii = 0; ii < 4; ii++) { + for (i = 0; i < 15; i++) { + x = t[i] + s[x & 511u]; + t[i] = x = ROL32(x, 9); + } + } + + /* --- And spit out the key material --- */ + + for (i = 0; i < 10; i++) + *kk++ = t[(4 * i)%15]; + } + + /* --- Finally, fix up the multiplicative entries --- */ + + for (i = 5; i < 37; i += 2) { + uint32 w, m, x; + j = k->k[i] & 3u; + w = k->k[i] | 3u; + + /* --- Compute the magic mask value --- */ + + m = 0; + for (ii = 0; ii <= 22; ii++) { + x = w >> ii; + if ((x & 0x3ff) == 0x3ff || (x & 0x3ff) == 0) + m |= 0x3ff << ii; + } + m &= ~(((w ^ (w << 1)) | (w ^ (w >> 1))) | 0x80000003); + + /* --- Add in the bias entry to fix up the key --- */ + + x = ROL32(bb[j], k->k[i - 1]); + k->k[i] = w ^ (x & m); + } +} + +/* --- @mars_eblk@, @mars_dblk@ --- * + * + * Arguments: @const mars_ctx *k@ = pointer to key block + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +#define KADD(k, a, b, c, d) a += *k++, b += *k++, c += *k++, d += *k++ +#define KSUB(k, a, b, c, d) a -= *k++, b -= *k++, c -= *k++, d -= *k++ +#define IKADD(k, a, b, c, d) d += *--k, c += *--k, b += *--k, a += *--k +#define IKSUB(k, a, b, c, d) d -= *--k, c -= *--k, b -= *--k, a -= *--k + +#define MIX(a, b, c, d) do { \ + b ^= s0[(a >> 0) & 0xff]; \ + b += s1[(a >> 8) & 0xff]; \ + c += s0[(a >> 16) & 0xff]; \ + d ^= s1[(a >> 24) & 0xff]; \ + a = ROL32(a, 8); \ +} while (0) + +#define IMIX(a, b, c, d) do { \ + a = ROR32(a, 8); \ + d ^= s1[(a >> 24) & 0xff]; \ + c -= s0[(a >> 16) & 0xff]; \ + b -= s1[(a >> 8) & 0xff]; \ + b ^= s0[(a >> 0) & 0xff]; \ +} while (0) + +#define E(x, y, z, k, a) do { \ + uint32 kx = *k++, ky = *k++; \ + y = a + kx; \ + a = ROL32(a, 13); z = a * ky; z = ROL32(z, 5); \ + x = s[y & 511u] ^ z; y = ROL32(y, z); \ + z = ROL32(z, 5); x ^= z; x = ROL32(x, z); \ +} while (0) + +#define IE(x, y, z, k, a) do { \ + uint32 ky = *--k, kx = *--k; \ + z = a * ky; \ + a = ROR32(a, 13); y = a + kx; z = ROL32(z, 5); \ + x = s[y & 511u] ^ z; y = ROL32(y, z); \ + z = ROL32(z, 5); x ^= z; x = ROL32(x, z); \ +} while (0) + +#define ROUND(k, a, b, c, d) do { \ + uint32 x, y, z; \ + E(x, y, z, k, a); \ + b += x; c += y; d ^= z; \ +} while (0) + +#define IROUND(k, a, b, c, d) do { \ + uint32 x, y, z; \ + IE(x, y, z, k, a); \ + b -= x; c -= y; d ^= z; \ +} while (0) + +void mars_eblk(const mars_ctx *k, const uint32 *src, uint32 *dst) +{ + uint32 a, b, c, d; + const uint32 *kk = k->k; + + a = src[0], b = src[1], c = src[2], d = src[3]; + KADD(kk, a, b, c, d); + + MIX(a, b, c, d); a += d; MIX(b, c, d, a); b += c; + MIX(c, d, a, b); MIX(d, a, b, c); + MIX(a, b, c, d); a += d; MIX(b, c, d, a); b += c; + MIX(c, d, a, b); MIX(d, a, b, c); + + ROUND(kk, a, b, c, d); ROUND(kk, b, c, d, a); + ROUND(kk, c, d, a, b); ROUND(kk, d, a, b, c); + ROUND(kk, a, b, c, d); ROUND(kk, b, c, d, a); + ROUND(kk, c, d, a, b); ROUND(kk, d, a, b, c); + + ROUND(kk, a, d, c, b); ROUND(kk, b, a, d, c); + ROUND(kk, c, b, a, d); ROUND(kk, d, c, b, a); + ROUND(kk, a, d, c, b); ROUND(kk, b, a, d, c); + ROUND(kk, c, b, a, d); ROUND(kk, d, c, b, a); + + IMIX(a, d, c, b); IMIX(b, a, d, c); + c -= b; IMIX(c, b, a, d); d -= a; IMIX(d, c, b, a); + IMIX(a, d, c, b); IMIX(b, a, d, c); + c -= b; IMIX(c, b, a, d); d -= a; IMIX(d, c, b, a); + + KSUB(kk, a, b, c, d); + dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; +} + +void mars_dblk(const mars_ctx *k, const uint32 *src, uint32 *dst) +{ + uint32 a, b, c, d; + const uint32 *kk = k->k + 40; + + a = src[0], b = src[1], c = src[2], d = src[3]; + IKADD(kk, a, b, c, d); + + MIX(d, c, b, a); d += a; MIX(c, b, a, d); c += b; + MIX(b, a, d, c); MIX(a, d, c, b); + MIX(d, c, b, a); d += a; MIX(c, b, a, d); c += b; + MIX(b, a, d, c); MIX(a, d, c, b); + + IROUND(kk, d, c, b, a); IROUND(kk, c, b, a, d); + IROUND(kk, b, a, d, c); IROUND(kk, a, d, c, b); + IROUND(kk, d, c, b, a); IROUND(kk, c, b, a, d); + IROUND(kk, b, a, d, c); IROUND(kk, a, d, c, b); + + IROUND(kk, d, a, b, c); IROUND(kk, c, d, a, b); + IROUND(kk, b, c, d, a); IROUND(kk, a, b, c, d); + IROUND(kk, d, a, b, c); IROUND(kk, c, d, a, b); + IROUND(kk, b, c, d, a); IROUND(kk, a, b, c, d); + + IMIX(d, a, b, c); IMIX(c, d, a, b); + b -= c; IMIX(b, c, d, a); a -= d; IMIX(a, b, c, d); + IMIX(d, a, b, c); IMIX(c, d, a, b); + b -= c; IMIX(b, c, d, a); a -= d; IMIX(a, b, c, d); + + IKSUB(kk, a, b, c, d); + dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; +} + +BLKC_TEST(MARS, mars) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/mars.h b/symm/mars.h new file mode 100644 index 0000000..f13f8a8 --- /dev/null +++ b/symm/mars.h @@ -0,0 +1,104 @@ +/* -*-c-*- + * + * The MARS block cipher + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the MARS block cipher ------------------------------------* + * + * MARS was IBM's submission to the AES contest. It was designed by a number + * of clever people at the T. J. Watson labs, and made it to the second round + * of the contest. Unfortunately, MARS is rather messy. There are some + * awkward corner cases in the key schedule algorithm, for example, that show + * up very rarely. + */ + +#ifndef CATACOMB_MARS_H +#define CATACOMB_MARS_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magical numbers ---------------------------------------------------*/ + +#define MARS_BLKSZ 16 +#define MARS_KEYSZ 32 +#define MARS_CLASS (N, L, 128) + +extern const octet mars_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct mars_ctx { + uint32 k[40]; +} mars_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @mars_init@ --- * + * + * Arguments: @mars_ctx *k@ = pointer to key block to fill in + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a MARS key buffer. MARS accepts key sizes + * between 128 and 448 bits which are a multiple of 32 bits. + */ + +extern void mars_init(mars_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @mars_eblk@, @mars_dblk@ --- * + * + * Arguments: @const mars_ctx *k@ = pointer to key block + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void mars_eblk(const mars_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +extern void mars_dblk(const mars_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/md2-tab.h b/symm/md2-tab.h new file mode 100644 index 0000000..3e1b2e9 --- /dev/null +++ b/symm/md2-tab.h @@ -0,0 +1,78 @@ +/* -*-c-*- + * + * Tables for MD2 + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MD2_TAB_H +#define CATACOMB_MD2_TAB_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- S-box table -------------------------------------------------------*/ + +#define MD2_S { \ + 0x29, 0x2e, 0x43, 0xc9, 0xa2, 0xd8, 0x7c, 0x01, \ + 0x3d, 0x36, 0x54, 0xa1, 0xec, 0xf0, 0x06, 0x13, \ + 0x62, 0xa7, 0x05, 0xf3, 0xc0, 0xc7, 0x73, 0x8c, \ + 0x98, 0x93, 0x2b, 0xd9, 0xbc, 0x4c, 0x82, 0xca, \ + 0x1e, 0x9b, 0x57, 0x3c, 0xfd, 0xd4, 0xe0, 0x16, \ + 0x67, 0x42, 0x6f, 0x18, 0x8a, 0x17, 0xe5, 0x12, \ + 0xbe, 0x4e, 0xc4, 0xd6, 0xda, 0x9e, 0xde, 0x49, \ + 0xa0, 0xfb, 0xf5, 0x8e, 0xbb, 0x2f, 0xee, 0x7a, \ + 0xa9, 0x68, 0x79, 0x91, 0x15, 0xb2, 0x07, 0x3f, \ + 0x94, 0xc2, 0x10, 0x89, 0x0b, 0x22, 0x5f, 0x21, \ + 0x80, 0x7f, 0x5d, 0x9a, 0x5a, 0x90, 0x32, 0x27, \ + 0x35, 0x3e, 0xcc, 0xe7, 0xbf, 0xf7, 0x97, 0x03, \ + 0xff, 0x19, 0x30, 0xb3, 0x48, 0xa5, 0xb5, 0xd1, \ + 0xd7, 0x5e, 0x92, 0x2a, 0xac, 0x56, 0xaa, 0xc6, \ + 0x4f, 0xb8, 0x38, 0xd2, 0x96, 0xa4, 0x7d, 0xb6, \ + 0x76, 0xfc, 0x6b, 0xe2, 0x9c, 0x74, 0x04, 0xf1, \ + 0x45, 0x9d, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, \ + 0x86, 0x5b, 0xcf, 0x65, 0xe6, 0x2d, 0xa8, 0x02, \ + 0x1b, 0x60, 0x25, 0xad, 0xae, 0xb0, 0xb9, 0xf6, \ + 0x1c, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7e, 0x0f, \ + 0x55, 0x47, 0xa3, 0x23, 0xdd, 0x51, 0xaf, 0x3a, \ + 0xc3, 0x5c, 0xf9, 0xce, 0xba, 0xc5, 0xea, 0x26, \ + 0x2c, 0x53, 0x0d, 0x6e, 0x85, 0x28, 0x84, 0x09, \ + 0xd3, 0xdf, 0xcd, 0xf4, 0x41, 0x81, 0x4d, 0x52, \ + 0x6a, 0xdc, 0x37, 0xc8, 0x6c, 0xc1, 0xab, 0xfa, \ + 0x24, 0xe1, 0x7b, 0x08, 0x0c, 0xbd, 0xb1, 0x4a, \ + 0x78, 0x88, 0x95, 0x8b, 0xe3, 0x63, 0xe8, 0x6d, \ + 0xe9, 0xcb, 0xd5, 0xfe, 0x3b, 0x00, 0x1d, 0x39, \ + 0xf2, 0xef, 0xb7, 0x0e, 0x66, 0x58, 0xd0, 0xe4, \ + 0xa6, 0x77, 0x72, 0xf8, 0xeb, 0x75, 0x4b, 0x0a, \ + 0x31, 0x44, 0x50, 0xb4, 0x8f, 0xed, 0x1f, 0x1a, \ + 0xdb, 0x99, 0x8d, 0x33, 0x9f, 0x11, 0x83, 0x14 \ +} + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/md2.c b/symm/md2.c new file mode 100644 index 0000000..180bc65 --- /dev/null +++ b/symm/md2.c @@ -0,0 +1,221 @@ +/* -*-c-*- + * + * The MD2 message digest function + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "md2.h" +#include "md2-tab.h" + +/*----- Tables ------------------------------------------------------------*/ + +static const octet s[256] = MD2_S; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @md2_compress@ --- * + * + * Arguments: @md2_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: MD2 compression and checksum function. + */ + +void md2_compress(md2_ctx *ctx, const void *sbuf) +{ + unsigned i; + unsigned t; + octet x[MD2_BUFSZ]; + octet y[MD2_BUFSZ]; + + /* --- Handy macro for doing something lots of times --- */ + +#define DO(what, where) do { \ + what(where, 0); what(where, 1); what(where, 2); what(where, 3); \ + what(where, 4); what(where, 5); what(where, 6); what(where, 7); \ + what(where, 8); what(where, 9); what(where, 10); what(where, 11); \ + what(where, 12); what(where, 13); what(where, 14); what(where, 15); \ +} while (0) + + /* --- Do the hashing first to avoid corrupting the checksum --- */ + + memcpy(x, sbuf, sizeof(x)); +#define X(z, i) y[i] = z[i] ^ ctx->h[i] + DO(X, x); +#undef X + + t = 0; + for (i = 0; i < 18; i++) { +#define X(z, i) t = z[i] ^= s[t]; + DO(X, ctx->h); + DO(X, x); + DO(X, y); +#undef X + t = U8(t + i); + } + + /* --- Now compute the checksum --- */ + + t = ctx->c[MD2_BUFSZ - 1]; +#define X(z, i) t = ctx->c[i] ^= s[z[i] ^ t] + DO(X, ((const octet *)sbuf)); +#undef X + +#undef DO +} + +/* --- @md2_init@ --- * + * + * Arguments: @md2_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void md2_init(md2_ctx *ctx) +{ + memset(ctx->c, 0, sizeof(ctx->c)); + memset(ctx->h, 0, sizeof(ctx->h)); + ctx->off = 0; +} + +/* --- @md2_set@ --- * + * + * Arguments: @md2_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void md2_set(md2_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + memcpy(ctx->h, p, MD2_BUFSZ); + memcpy(ctx->c, p + MD2_BUFSZ, MD2_BUFSZ); + ctx->off = 0; +} + +/* --- @md2_hash@ --- * + * + * Arguments: @md2_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void md2_hash(md2_ctx *ctx, const void *buf, size_t sz) +{ + const octet *bbuf = (octet *)buf; + + /* --- Code automatically expanded from @HASH_BUFFER@ and tidied --- */ + + if (ctx->off + sz < MD2_BUFSZ) { + memcpy(ctx->buf + ctx->off, bbuf, sz); + ctx->off += sz; + } else { + if (ctx->off) { + size_t s = MD2_BUFSZ - ctx->off; + memcpy(ctx->buf + ctx->off, bbuf, s); + md2_compress(ctx, ctx->buf); + sz -= s; + bbuf += s; + } + while (sz >= MD2_BUFSZ) { + md2_compress(ctx, bbuf); + sz -= MD2_BUFSZ; bbuf += MD2_BUFSZ; + } + if (sz) + memcpy(ctx->buf, bbuf, sz); + ctx->off = sz; + } +} + +/* --- @md2_done@ --- * + * + * Arguments: @md2_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +void md2_done(md2_ctx *ctx, void *hash) +{ + unsigned pad = MD2_BUFSZ - ctx->off; + unsigned i; + for (i = ctx->off; i < MD2_BUFSZ; i++) + ctx->buf[i] = pad; + md2_compress(ctx, ctx->buf); + md2_compress(ctx, ctx->c); + memcpy(hash, ctx->h, MD2_BUFSZ); +} + +/* --- @md2_state@ --- * + * + * Arguments: @md2_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @md2_set@. + */ + +unsigned long md2_state(md2_ctx *ctx, void *state) +{ + octet *p = state; + memcpy(p, ctx->h, MD2_BUFSZ); + memcpy(p + MD2_BUFSZ, ctx->c, MD2_BUFSZ); + return (0); +} + +/* --- Generic interface --- */ + +GHASH_DEF(MD2, md2) + +/* --- Test code --- */ + +HASH_TEST(MD2, md2) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/md2.h b/symm/md2.h new file mode 100644 index 0000000..26a1f2a --- /dev/null +++ b/symm/md2.h @@ -0,0 +1,156 @@ +/* -*-c-*- + * + * The MD2 message digest function + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the MD2 hash function ------------------------------------* + * + * MD2 was designed by Ron Rivest. It's not recommended for new applications + * because only the `checksum' part of the function resists collision-finding + * attacks. It's not very fast either. However, it's still used in + * standards, and having it available can be useful. + */ + +#ifndef CATACOMB_MD2_H +#define CATACOMB_MD2_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define MD2_BUFSZ 16 +#define MD2_HASHSZ 16 +#define MD2_STATESZ 32 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct md2_ctx { + octet c[MD2_BUFSZ]; /* Checksum buffer */ + octet h[MD2_BUFSZ]; /* Hash result buffer */ + octet buf[MD2_BUFSZ]; /* Input buffer */ + unsigned off; /* Offset into buffer */ +} md2_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @md2_compress@ --- * + * + * Arguments: @md2_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: MD2 compression function. + */ + +extern void md2_compress(md2_ctx */*ctx*/, const void */*sbuf*/); + +/* --- @md2_init@ --- * + * + * Arguments: @md2_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void md2_init(md2_ctx */*ctx*/); + +/* --- @md2_set@ --- * + * + * Arguments: @md2_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void md2_set(md2_ctx */*ctx*/, const void */*buf*/, + unsigned long /*count*/); + +/* --- @md2_hash@ --- * + * + * Arguments: @md2_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void md2_hash(md2_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/); + +/* --- @md2_done@ --- * + * + * Arguments: @md2_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void md2_done(md2_ctx */*ctx*/, void */*hash*/); + +/* --- @md2_state@ --- * + * + * Arguments: @md2_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @md2_set@. + */ + +extern unsigned long md2_state(md2_ctx */*ctx*/, void */*state*/); + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash md2; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/md4.c b/symm/md4.c new file mode 100644 index 0000000..eee5d6b --- /dev/null +++ b/symm/md4.c @@ -0,0 +1,257 @@ +/* -*-c-*- + * + * The MD4 message digest function + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "md4.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @md4_compress@ --- * + * + * Arguments: @md4_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: RIPEMD-160 compression function. + */ + +void md4_compress(md4_ctx *ctx, const void *sbuf) +{ + uint32 a, b, c, d; + uint32 buf[16]; + + /* --- Fetch the chaining variables --- */ + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + /* --- Fetch the buffer contents --- */ + + { + int i; + const octet *p; + + for (i = 0, p = sbuf; i < 16; i++, p += 4) + buf[i] = LOAD32_L(p); + } + + /* --- Definitions for round functions --- */ + +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +#define T(w, x, y, z, i, r, k, f) do { \ + uint32 _t = w + f(x, y, z) + buf[i] + k; \ + w = ROL32(_t, r); \ +} while (0) + +#define FF(w, x, y, z, i, r) T(w, x, y, z, i, r, 0x00000000, F) +#define GG(w, x, y, z, i, r) T(w, x, y, z, i, r, 0x5a827999, G) +#define HH(w, x, y, z, i, r) T(w, x, y, z, i, r, 0x6ed9eba1, H) + + /* --- The main compression function --- */ + + FF(a, b, c, d, 0, 3); + FF(d, a, b, c, 1, 7); + FF(c, d, a, b, 2, 11); + FF(b, c, d, a, 3, 19); + FF(a, b, c, d, 4, 3); + FF(d, a, b, c, 5, 7); + FF(c, d, a, b, 6, 11); + FF(b, c, d, a, 7, 19); + FF(a, b, c, d, 8, 3); + FF(d, a, b, c, 9, 7); + FF(c, d, a, b, 10, 11); + FF(b, c, d, a, 11, 19); + FF(a, b, c, d, 12, 3); + FF(d, a, b, c, 13, 7); + FF(c, d, a, b, 14, 11); + FF(b, c, d, a, 15, 19); + + GG(a, b, c, d, 0, 3); + GG(d, a, b, c, 4, 5); + GG(c, d, a, b, 8, 9); + GG(b, c, d, a, 12, 13); + GG(a, b, c, d, 1, 3); + GG(d, a, b, c, 5, 5); + GG(c, d, a, b, 9, 9); + GG(b, c, d, a, 13, 13); + GG(a, b, c, d, 2, 3); + GG(d, a, b, c, 6, 5); + GG(c, d, a, b, 10, 9); + GG(b, c, d, a, 14, 13); + GG(a, b, c, d, 3, 3); + GG(d, a, b, c, 7, 5); + GG(c, d, a, b, 11, 9); + GG(b, c, d, a, 15, 13); + + HH(a, b, c, d, 0, 3); + HH(d, a, b, c, 8, 9); + HH(c, d, a, b, 4, 11); + HH(b, c, d, a, 12, 15); + HH(a, b, c, d, 2, 3); + HH(d, a, b, c, 10, 9); + HH(c, d, a, b, 6, 11); + HH(b, c, d, a, 14, 15); + HH(a, b, c, d, 1, 3); + HH(d, a, b, c, 9, 9); + HH(c, d, a, b, 5, 11); + HH(b, c, d, a, 13, 15); + HH(a, b, c, d, 3, 3); + HH(d, a, b, c, 11, 9); + HH(c, d, a, b, 7, 11); + HH(b, c, d, a, 15, 15); + + /* --- Update the chaining variables --- */ + + ctx->a += a; + ctx->b += b; + ctx->c += c; + ctx->d += d; +} + +/* --- @md4_init@ --- * + * + * Arguments: @md4_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void md4_init(md4_ctx *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + ctx->off = 0; + ctx->nl = ctx->nh = 0; +} + +/* --- @md4_set@ --- * + * + * Arguments: @md4_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void md4_set(md4_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + ctx->a = LOAD32_L(p + 0); + ctx->b = LOAD32_L(p + 4); + ctx->c = LOAD32_L(p + 8); + ctx->d = LOAD32_L(p + 12); + ctx->off = 0; + ctx->nl = U32(count); + ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); +} + +/* --- @md4_hash@ --- * + * + * Arguments: @md4_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void md4_hash(md4_ctx *ctx, const void *buf, size_t sz) +{ + HASH_BUFFER(MD4, md4, ctx, buf, sz); +} + +/* --- @md4_done@ --- * + * + * Arguments: @md4_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +void md4_done(md4_ctx *ctx, void *hash) +{ + octet *p = hash; + HASH_MD5STRENGTH(MD4, md4, ctx); + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); +} + +/* --- @md4_state@ --- * + * + * Arguments: @md4_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @md4_set@. + */ + +unsigned long md4_state(md4_ctx *ctx, void *state) +{ + octet *p = state; + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); + return (ctx->nl | ((ctx->nh >> 16) >> 16)); +} + +/* --- Generic interface --- */ + +GHASH_DEF(MD4, md4) + +/* --- Test rig --- */ + +HASH_TEST(MD4, md4) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/md4.h b/symm/md4.h new file mode 100644 index 0000000..29ca730 --- /dev/null +++ b/symm/md4.h @@ -0,0 +1,157 @@ +/* -*-c-*- + * + * The MD4 message digest function + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the MD4 hash function ------------------------------------* + * + * MD4 was designed by Ron Rivest. It's now well and truly broken: not only + * have collisions been discovered, a slightly cut-down version has been + * shown to be non-preimage-resistant. On the other hand, MD4 is fast and + * makes a good heavy-duty checksum. Just don't rely on it being + * cryptographically strong, 'cos it ain't. + */ + +#ifndef CATACOMB_MD4_H +#define CATACOMB_MD4_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define MD4_BUFSZ 64 +#define MD4_HASHSZ 16 +#define MD4_STATESZ 16 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct md4_ctx { + uint32 a, b, c, d; /* Chaining variables */ + uint32 nl, nh; /* Byte count so far */ + unsigned off; /* Offset into buffer */ + octet buf[MD4_BUFSZ]; /* Accumulation buffer */ +} md4_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @md4_compress@ --- * + * + * Arguments: @md4_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: MD4 compression function. + */ + +extern void md4_compress(md4_ctx */*ctx*/, const void */*sbuf*/); + +/* --- @md4_init@ --- * + * + * Arguments: @md4_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void md4_init(md4_ctx */*ctx*/); + +/* --- @md4_set@ --- * + * + * Arguments: @md4_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void md4_set(md4_ctx */*ctx*/, const void */*buf*/, + unsigned long /*count*/); + +/* --- @md4_hash@ --- * + * + * Arguments: @md4_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void md4_hash(md4_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/); + +/* --- @md4_done@ --- * + * + * Arguments: @md4_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void md4_done(md4_ctx */*ctx*/, void */*hash*/); + +/* --- @md4_state@ --- * + * + * Arguments: @md4_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @md4_set@. + */ + +extern unsigned long md4_state(md4_ctx */*ctx*/, void */*state*/); + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash md4; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/md5.c b/symm/md5.c new file mode 100644 index 0000000..f3b37e1 --- /dev/null +++ b/symm/md5.c @@ -0,0 +1,276 @@ +/* -*-c-*- + * + * The MD5 message digest function + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "md5.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @md5_compress@ --- * + * + * Arguments: @md5_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: MD5 compression function. + */ + +void md5_compress(md5_ctx *ctx, const void *sbuf) +{ + uint32 a, b, c, d; + uint32 buf[16]; + + /* --- Fetch the chaining variables --- */ + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + /* --- Fetch the buffer contents --- */ + + { + int i; + const octet *p; + + for (i = 0, p = sbuf; i < 16; i++, p += 4) + buf[i] = LOAD32_L(p); + } + + /* --- Definitions for round functions --- */ + +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +#define T(w, x, y, z, i, r, k, f) do { \ + uint32 _t = w + f(x, y, z) + buf[i] + k; \ + w = ROL32(_t, r) + x; \ +} while (0) + +#define FF(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, F) +#define GG(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, G) +#define HH(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, H) +#define II(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, I) + + /* --- The main compression function --- */ + + FF(a, b, c, d, 0, 7, 0xd76aa478); + FF(d, a, b, c, 1, 12, 0xe8c7b756); + FF(c, d, a, b, 2, 17, 0x242070db); + FF(b, c, d, a, 3, 22, 0xc1bdceee); + FF(a, b, c, d, 4, 7, 0xf57c0faf); + FF(d, a, b, c, 5, 12, 0x4787c62a); + FF(c, d, a, b, 6, 17, 0xa8304613); + FF(b, c, d, a, 7, 22, 0xfd469501); + FF(a, b, c, d, 8, 7, 0x698098d8); + FF(d, a, b, c, 9, 12, 0x8b44f7af); + FF(c, d, a, b, 10, 17, 0xffff5bb1); + FF(b, c, d, a, 11, 22, 0x895cd7be); + FF(a, b, c, d, 12, 7, 0x6b901122); + FF(d, a, b, c, 13, 12, 0xfd987193); + FF(c, d, a, b, 14, 17, 0xa679438e); + FF(b, c, d, a, 15, 22, 0x49b40821); + + GG(a, b, c, d, 1, 5, 0xf61e2562); + GG(d, a, b, c, 6, 9, 0xc040b340); + GG(c, d, a, b, 11, 14, 0x265e5a51); + GG(b, c, d, a, 0, 20, 0xe9b6c7aa); + GG(a, b, c, d, 5, 5, 0xd62f105d); + GG(d, a, b, c, 10, 9, 0x02441453); + GG(c, d, a, b, 15, 14, 0xd8a1e681); + GG(b, c, d, a, 4, 20, 0xe7d3fbc8); + GG(a, b, c, d, 9, 5, 0x21e1cde6); + GG(d, a, b, c, 14, 9, 0xc33707d6); + GG(c, d, a, b, 3, 14, 0xf4d50d87); + GG(b, c, d, a, 8, 20, 0x455a14ed); + GG(a, b, c, d, 13, 5, 0xa9e3e905); + GG(d, a, b, c, 2, 9, 0xfcefa3f8); + GG(c, d, a, b, 7, 14, 0x676f02d9); + GG(b, c, d, a, 12, 20, 0x8d2a4c8a); + + HH(a, b, c, d, 5, 4, 0xfffa3942); + HH(d, a, b, c, 8, 11, 0x8771f681); + HH(c, d, a, b, 11, 16, 0x6d9d6122); + HH(b, c, d, a, 14, 23, 0xfde5380c); + HH(a, b, c, d, 1, 4, 0xa4beea44); + HH(d, a, b, c, 4, 11, 0x4bdecfa9); + HH(c, d, a, b, 7, 16, 0xf6bb4b60); + HH(b, c, d, a, 10, 23, 0xbebfbc70); + HH(a, b, c, d, 13, 4, 0x289b7ec6); + HH(d, a, b, c, 0, 11, 0xeaa127fa); + HH(c, d, a, b, 3, 16, 0xd4ef3085); + HH(b, c, d, a, 6, 23, 0x04881d05); + HH(a, b, c, d, 9, 4, 0xd9d4d039); + HH(d, a, b, c, 12, 11, 0xe6db99e5); + HH(c, d, a, b, 15, 16, 0x1fa27cf8); + HH(b, c, d, a, 2, 23, 0xc4ac5665); + + II(a, b, c, d, 0, 6, 0xf4292244); + II(d, a, b, c, 7, 10, 0x432aff97); + II(c, d, a, b, 14, 15, 0xab9423a7); + II(b, c, d, a, 5, 21, 0xfc93a039); + II(a, b, c, d, 12, 6, 0x655b59c3); + II(d, a, b, c, 3, 10, 0x8f0ccc92); + II(c, d, a, b, 10, 15, 0xffeff47d); + II(b, c, d, a, 1, 21, 0x85845dd1); + II(a, b, c, d, 8, 6, 0x6fa87e4f); + II(d, a, b, c, 15, 10, 0xfe2ce6e0); + II(c, d, a, b, 6, 15, 0xa3014314); + II(b, c, d, a, 13, 21, 0x4e0811a1); + II(a, b, c, d, 4, 6, 0xf7537e82); + II(d, a, b, c, 11, 10, 0xbd3af235); + II(c, d, a, b, 2, 15, 0x2ad7d2bb); + II(b, c, d, a, 9, 21, 0xeb86d391); + + /* --- Update the chaining variables --- */ + + ctx->a += a; + ctx->b += b; + ctx->c += c; + ctx->d += d; +} + +/* --- @md5_init@ --- * + * + * Arguments: @md5_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void md5_init(md5_ctx *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + ctx->off = 0; + ctx->nl = ctx->nh = 0; +} + +/* --- @md5_set@ --- * + * + * Arguments: @md5_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void md5_set(md5_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + ctx->a = LOAD32_L(p + 0); + ctx->b = LOAD32_L(p + 4); + ctx->c = LOAD32_L(p + 8); + ctx->d = LOAD32_L(p + 12); + ctx->off = 0; + ctx->nl = U32(count); + ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); +} + +/* --- @md5_hash@ --- * + * + * Arguments: @md5_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void md5_hash(md5_ctx *ctx, const void *buf, size_t sz) +{ + HASH_BUFFER(MD5, md5, ctx, buf, sz); +} + +/* --- @md5_done@ --- * + * + * Arguments: @md5_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +void md5_done(md5_ctx *ctx, void *hash) +{ + octet *p = hash; + HASH_MD5STRENGTH(MD5, md5, ctx); + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); +} + +/* --- @md5_state@ --- * + * + * Arguments: @md5_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @md5_set@. + */ + +unsigned long md5_state(md5_ctx *ctx, void *state) +{ + octet *p = state; + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); + return (ctx->nl | ((ctx->nh << 16) << 16)); +} + +/* --- Generic interface --- */ + +GHASH_DEF(MD5, md5) + +/* --- Test code --- */ + +HASH_TEST(MD5, md5) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/md5.h b/symm/md5.h new file mode 100644 index 0000000..4248db2 --- /dev/null +++ b/symm/md5.h @@ -0,0 +1,158 @@ +/* -*-c-*- + * + * The MD5 message digest function + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the MD5 hash function ------------------------------------* + * + * MD5 was designed by Ron Rivest. It was intended to be a more conservative + * design than the slightly earlier MD4, and indeed while MD4 has been pretty + * much demolished by subsequent cryptanalysis, MD5 is still standing + * shakily. It's provided here not because the author recommends its use but + * because it's a common standard, and is often handy in non-cryptographic + * applications. It's also still useful in constructions such as HMAC. + */ + +#ifndef CATACOMB_MD5_H +#define CATACOMB_MD5_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define MD5_BUFSZ 64 +#define MD5_HASHSZ 16 +#define MD5_STATESZ 16 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct md5_ctx { + uint32 a, b, c, d; /* Chaining variables */ + uint32 nl, nh; /* Byte count so far */ + unsigned off; /* Offset into buffer */ + octet buf[MD5_BUFSZ]; /* Accumulation buffer */ +} md5_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @md5_compress@ --- * + * + * Arguments: @md5_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: MD5 compression function. + */ + +extern void md5_compress(md5_ctx */*ctx*/, const void */*sbuf*/); + +/* --- @md5_init@ --- * + * + * Arguments: @md5_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void md5_init(md5_ctx */*ctx*/); + +/* --- @md5_set@ --- * + * + * Arguments: @md5_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void md5_set(md5_ctx */*ctx*/, const void */*buf*/, + unsigned long /*count*/); + +/* --- @md5_hash@ --- * + * + * Arguments: @md5_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void md5_hash(md5_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/); + +/* --- @md5_done@ --- * + * + * Arguments: @md5_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void md5_done(md5_ctx */*ctx*/, void */*hash*/); + +/* --- @md5_state@ --- * + * + * Arguments: @md5_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @md5_set@. + */ + +extern unsigned long md5_state(md5_ctx */*ctx*/, void */*state*/); + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash md5; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/mgf-def.h b/symm/mgf-def.h new file mode 100644 index 0000000..b5105ed --- /dev/null +++ b/symm/mgf-def.h @@ -0,0 +1,458 @@ +/* -*-c-*- + * + * Definitions for the MGF-1 mask generator + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MGF_DEF_H +#define CATACOMB_MGF_DEF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include +#include + +#ifndef CATACOMB_ARENA_H +# include "arena.h" +#endif + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_PARANOIA_H +# include "paranoia.h" +#endif + +/*----- Macros ------------------------------------------------------------*/ + +#define MGF_DEF(PRE, pre) \ + \ +/* --- Useful constants --- */ \ + \ +const octet pre##_mgfkeysz[] = { KSZ_ANY, PRE##_HASHSZ }; \ + \ +/* --- @pre_mgfkeybegin@, @pre_mgfkeyadd@ --- * \ + * \ + * Arguments: @pre_mgfctx *k@ = pointer to context to initialize \ + * @const void *p@ = pointer to data to contribute \ + * \ + * Returns: --- \ + * \ + * Use: A multi-step keying procedure for initializing an MGF \ + * context. The data is contributed to a hashing context \ + * which is then used for mask generation. If you only \ + * have a fixed buffer, you can save a lot of effort by \ + * simply calling @pre_mgfinit@. \ + */ \ + \ +void pre##_mgfkeybegin(pre##_mgfctx *k) \ +{ \ + k->c = 0; \ + k->bsz = 0; \ + pre##_init(&k->k); \ +} \ + \ +void pre##_mgfkeyadd(pre##_mgfctx *k, const void *p, size_t sz) \ +{ \ + pre##_hash(&k->k, p, sz); \ +} \ + \ +/* ---- @pre_mgfinit@ --- * \ + * \ + * Arguments: @pre_mgfctx *k@ = pointer to context to initialize \ + * @const void *p@ = pointer to data to contribute \ + * @size_t sz@ = size of data to contribute \ + * \ + * Returns: --- \ + * \ + * Use: A simpler interface to initialization if all of your \ + * keying material is in one place. \ + */ \ + \ +void pre##_mgfinit(pre##_mgfctx *k, const void *p, size_t sz) \ +{ \ + k->c = 0; \ + k->bsz = 0; \ + pre##_init(&k->k); \ + pre##_hash(&k->k, p, sz); \ +} \ + \ +/* --- @pre_mgfencrypt@ --- * \ + * \ + * Arguments: @pre_mgfctx *k@ = pointer to masking context \ + * @const void *s@ = pointer to source buffer \ + * @void *d@ = pointer to destination buffer \ + * @size_t sz@ = size of buffers \ + * \ + * Returns: --- \ + * \ + * Use: Outputs pseudorandom data, or masks an input buffer. \ + * \ + * If @s@ is nonzero, the source material is exclusive- \ + * orred with the generated mask. If @d@ is zero, the \ + * generator is simply spun around for a while, which \ + * isn't very useful. \ + */ \ + \ +void pre##_mgfencrypt(pre##_mgfctx *k, const void *s, \ + void *d, size_t sz) \ +{ \ + const octet *ss = s; \ + octet *dd = d; \ + \ + /* --- Empty the buffer if there's anything there --- */ \ + \ + if (k->bsz) { \ + const octet *p = k->buf + PRE##_HASHSZ - k->bsz; \ + size_t n = sz > k->bsz ? k->bsz : sz; \ + sz -= n; \ + k->bsz -= n; \ + if (dd) { \ + if (!ss) { \ + memcpy(dd, p, n); \ + dd += n; \ + } else { \ + while (n) { \ + *dd++ = *ss++ ^ *p++; \ + n--; \ + } \ + } \ + } \ + } \ + \ + /* --- While necessary, generate some more mask --- */ \ + \ + while (sz) { \ + pre##_ctx c = k->k; /* Not quick! */ \ + size_t n; \ + \ + STORE32(k->buf, k->c); \ + k->c++; \ + pre##_hash(&c, k->buf, 4); \ + pre##_done(&c, k->buf); \ + n = sz > PRE##_HASHSZ ? PRE##_HASHSZ : sz; \ + k->bsz = PRE##_HASHSZ - n; \ + sz -= n; \ + if (dd) { \ + const octet *p = k->buf; \ + if (!ss) { \ + memcpy(dd, p, n); \ + dd += n; \ + } else { \ + while (n) { \ + *dd++ = *ss++ ^ *p++; \ + n--; \ + } \ + } \ + } \ + } \ +} \ + \ +/* --- @pre_mgfsetindex@ --- * \ + * \ + * Arguments: @pre_mgfctx *k@ = pointer to masking context \ + * @uint32 *c@ = new index to set \ + * \ + * Returns: --- \ + * \ + * Use: Sets a new index. This may be used to step around the \ + * output stream in a rather crude way. \ + */ \ + \ +void pre##_mgfsetindex(pre##_mgfctx *k, uint32 c) \ +{ \ + k->c = c; \ + k->bsz = 0; \ +} \ + \ +/* --- Generic cipher interface --- */ \ + \ +static const gcipher_ops gops; \ + \ +typedef struct gctx { \ + gcipher c; \ + pre##_mgfctx k; \ +} gctx; \ + \ +static gcipher *ginit(const void *k, size_t sz) \ +{ \ + gctx *g = S_CREATE(gctx); \ + g->c.ops = &gops; \ + pre##_mgfinit(&g->k, k, sz); \ + return (&g->c); \ +} \ + \ +static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_mgfencrypt(&g->k, s, t, sz); \ +} \ + \ +static void gdestroy(gcipher *c) \ +{ \ + gctx *g = (gctx *)c; \ + BURN(*g); \ + S_DESTROY(g); \ +} \ + \ +static const gcipher_ops gops = { \ + &pre##_mgf, \ + gencrypt, gencrypt, gdestroy, 0, 0 \ +}; \ + \ +const gccipher pre##_mgf = { \ + #pre "-mgf", pre##_mgfkeysz, 0, \ + ginit \ +}; \ + \ +/* --- Generic random number generator interface --- */ \ + \ +typedef struct grctx { \ + grand r; \ + pre##_mgfctx k; \ +} grctx; \ + \ +static void grdestroy(grand *r) \ +{ \ + grctx *g = (grctx *)r; \ + BURN(*g); \ + S_DESTROY(g); \ +} \ + \ +static int grmisc(grand *r, unsigned op, ...) \ +{ \ + grctx *g = (grctx *)r; \ + va_list ap; \ + int rc = 0; \ + va_start(ap, op); \ + \ + switch (op) { \ + case GRAND_CHECK: \ + switch (va_arg(ap, unsigned)) { \ + case GRAND_CHECK: \ + case GRAND_SEEDINT: \ + case GRAND_SEEDUINT32: \ + case GRAND_SEEDBLOCK: \ + case GRAND_SEEDRAND: \ + rc = 1; \ + break; \ + default: \ + rc = 0; \ + break; \ + } \ + break; \ + case GRAND_SEEDINT: \ + pre##_mgfsetindex(&g->k, va_arg(ap, unsigned)); \ + break; \ + case GRAND_SEEDUINT32: \ + pre##_mgfsetindex(&g->k, va_arg(ap, uint32)); \ + break; \ + case GRAND_SEEDBLOCK: { \ + const void *p = va_arg(ap, const void *); \ + size_t sz = va_arg(ap, size_t); \ + pre##_hash(&g->k.k, p, sz); \ + } break; \ + case GRAND_SEEDRAND: { \ + octet buf[PRE##_BUFSZ]; \ + grand *rr = va_arg(ap, grand *); \ + rr->ops->fill(rr, buf, sizeof(buf)); \ + pre##_hash(&g->k.k, buf, sizeof(buf)); \ + } break; \ + default: \ + GRAND_BADOP; \ + break; \ + } \ + \ + va_end(ap); \ + return (rc); \ +} \ + \ +static octet grbyte(grand *r) \ +{ \ + grctx *g = (grctx *)r; \ + octet o; \ + pre##_mgfencrypt(&g->k, 0, &o, 1); \ + return (o); \ +} \ + \ +static uint32 grword(grand *r) \ +{ \ + grctx *g = (grctx *)r; \ + octet b[4]; \ + pre##_mgfencrypt(&g->k, 0, b, sizeof(b)); \ + return (LOAD32(b)); \ +} \ + \ +static void grfill(grand *r, void *p, size_t sz) \ +{ \ + grctx *g = (grctx *)r; \ + pre##_mgfencrypt(&g->k, 0, p, sz); \ +} \ + \ +static const grand_ops grops = { \ + #pre "-mgf", \ + GRAND_CRYPTO, 0, \ + grmisc, grdestroy, \ + grword, grbyte, grword, grand_range, grfill \ +}; \ + \ +/* --- @pre_mgfrand@ --- * \ + * \ + * Arguments: @const void *k@ = pointer to key material \ + * @size_t sz@ = size of key material \ + * \ + * Returns: Pointer to a generic random number generator instance. \ + * \ + * Use: Creates a random number interface wrapper around an \ + * MGF-1-mode hash function. \ + */ \ + \ +extern grand *pre##_mgfrand(const void *k, size_t sz) \ +{ \ + grctx *g = S_CREATE(grctx); \ + g->r.ops = &grops; \ + pre##_mgfinit(&g->k, k, sz); \ + return (&g->r); \ +} \ + \ +MGF_TEST(PRE, pre) + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +#include "daftstory.h" + +/* --- @MGF_TEST@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions + * + * Use: Standard test rig for MGF functions. + */ + +#define MGF_TEST(PRE, pre) \ + \ +/* --- Initial plaintext for the test --- */ \ + \ +static const octet text[] = TEXT; \ + \ +/* --- Key and IV to use --- */ \ + \ +static const octet key[] = KEY; \ + \ +/* --- Buffers for encryption and decryption output --- */ \ + \ +static octet ct[sizeof(text)]; \ +static octet pt[sizeof(text)]; \ + \ +static void hexdump(const octet *p, size_t sz) \ +{ \ + const octet *q = p + sz; \ + for (sz = 0; p < q; p++, sz++) { \ + printf("%02x", *p); \ + if ((sz + 1) % PRE##_HASHSZ == 0) \ + putchar(':'); \ + } \ +} \ + \ +int main(void) \ +{ \ + size_t sz = 0, rest; \ + pre##_mgfctx ctx; \ + int status = 0; \ + int done = 0; \ + \ + size_t keysz = strlen((const char *)key); \ + \ + fputs(#pre "-mgf: ", stdout); \ + \ + pre##_mgfinit(&ctx, key, keysz); \ + \ + while (sz <= sizeof(text)) { \ + rest = sizeof(text) - sz; \ + memcpy(ct, text, sizeof(text)); \ + pre##_mgfsetindex(&ctx, 0); \ + pre##_mgfencrypt(&ctx, ct, ct, sz); \ + pre##_mgfencrypt(&ctx, ct + sz, ct + sz, rest); \ + memcpy(pt, ct, sizeof(text)); \ + pre##_mgfsetindex(&ctx, 0); \ + pre##_mgfencrypt(&ctx, pt, pt, rest); \ + pre##_mgfencrypt(&ctx, pt + rest, pt + rest, sz); \ + if (memcmp(pt, text, sizeof(text)) == 0) { \ + done++; \ + if (sizeof(text) < 40 || done % 8 == 0) \ + fputc('.', stdout); \ + if (done % 480 == 0) \ + fputs("\n\t", stdout); \ + fflush(stdout); \ + } else { \ + printf("\nError (sz = %lu)\n", (unsigned long)sz); \ + status = 1; \ + printf("\tplaintext = "); hexdump(text, sz); \ + printf(", "); hexdump(text + sz, rest); \ + fputc('\n', stdout); \ + printf("\tciphertext = "); hexdump(ct, sz); \ + printf(", "); hexdump(ct + sz, rest); \ + fputc('\n', stdout); \ + printf("\trecovered text = "); hexdump(pt, sz); \ + printf(", "); hexdump(pt + sz, rest); \ + fputc('\n', stdout); \ + fputc('\n', stdout); \ + } \ + if (sz < 63) \ + sz++; \ + else \ + sz += 9; \ + } \ + \ + fputs(status ? " failed\n" : " ok\n", stdout); \ + return (status); \ +} + +#else +# define MGF_TEST(PRE, pre) +#endif + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/mgf.h b/symm/mgf.h new file mode 100644 index 0000000..d5b0fd1 --- /dev/null +++ b/symm/mgf.h @@ -0,0 +1,162 @@ +/* -*-c-*- + * + * The MGF mask generation function + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the MGF-1 mask generating function -----------------------* + * + * The idea of a mask-generating function is that given an input of arbitrary + * size, it can emit a pseudorandom output `mask' of arbitrary size. This is + * used in PKCS#1 OAEP (RFC2437). My recommendation would be to use a decent + * stream cipher instead, like RC4 or SEAL. MGF-1 isn't very fast. + */ + +#ifndef CATACOMB_MGF_H +#define CATACOMB_MGF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +/*----- Macros ------------------------------------------------------------*/ + +#define MGF_DECL(PRE, pre) \ + \ +/* --- An MGF generation context --- */ \ + \ +typedef struct pre##_mgfctx { \ + pre##_ctx k; /* Underlying key context */ \ + uint32 c; /* Counter */ \ + octet buf[PRE##_HASHSZ]; /* Output buffer */ \ + size_t bsz; /* Size of buffered data */ \ +} pre##_mgfctx; \ + \ +/* --- Other useful constants --- */ \ + \ +extern const octet pre##_mgfkeysz[]; \ + \ +/* --- @pre_mgfkeybegin@, @pre_mgfkeyadd@ --- * \ + * \ + * Arguments: @pre_mgfctx *k@ = pointer to context to initialize \ + * @const void *p@ = pointer to data to contribute \ + * @size_t sz@ = size of data to contribute \ + * \ + * Returns: --- \ + * \ + * Use: A multi-step keying procedure for initializing an MGF \ + * context. The data is contributed to a hashing context \ + * which is then used for mask generation. If you only \ + * have a fixed buffer, you can save a lot of effort by \ + * simply calling @pre_mgfinit@. \ + */ \ + \ +extern void pre##_mgfkeybegin(pre##_mgfctx */*k*/); \ +extern void pre##_mgfkeyadd(pre##_mgfctx */*k*/, \ + const void */*p*/, size_t /*sz*/); \ + \ +/* ---- @pre_mgfinit@ --- * \ + * \ + * Arguments: @pre_mgfctx *k@ = pointer to context to initialize \ + * @const void *p@ = pointer to data to contribute \ + * @size_t sz@ = size of data to contribute \ + * \ + * Returns: --- \ + * \ + * Use: A simpler interface to initialization if all of your \ + * keying material is in one place. \ + */ \ + \ +extern void pre##_mgfinit(pre##_mgfctx */*k*/, \ + const void */*p*/, size_t /*sz*/); \ + \ +/* --- @pre_mgfencrypt@ --- * \ + * \ + * Arguments: @pre_mgfctx *k@ = pointer to masking context \ + * @const void *s@ = pointer to source buffer \ + * @void *d@ = pointer to destination buffer \ + * @size_t sz@ = size of buffers \ + * \ + * Returns: --- \ + * \ + * Use: Outputs pseudorandom data, or masks an input buffer. \ + * \ + * If @s@ is nonzero, the source material is exclusive- \ + * orred with the generated mask. If @d@ is zero, the \ + * generator is simply spun around for a while, which \ + * isn't very useful. \ + */ \ + \ +extern void pre##_mgfencrypt(pre##_mgfctx */*k*/, const void */*s*/, \ + void */*d*/, size_t /*sz*/); \ + \ +/* --- @pre_mgfsetindex@ --- * \ + * \ + * Arguments: @pre_mgfctx *k@ = pointer to masking context \ + * @uint32 *c@ = new index to set \ + * \ + * Returns: --- \ + * \ + * Use: Sets a new index. This may be used to step around the \ + * output stream in a rather crude way. \ + */ \ + \ +extern void pre##_mgfsetindex(pre##_mgfctx */*k*/, uint32 /*c*/); \ + \ +/* --- @pre_mgfrand@ --- * \ + * \ + * Arguments: @const void *k@ = pointer to key material \ + * @size_t sz@ = size of key material \ + * \ + * Returns: Pointer to a generic random number generator instance. \ + * \ + * Use: Creates a random number interface wrapper around an \ + * MGF-1-mode hash function. \ + */ \ + \ +extern grand *pre##_mgfrand(const void */*k*/, size_t /*sz*/); \ + \ +/* --- Generic cipher interface --- */ \ + \ +extern const gccipher pre##_mgf; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/mode.c.in b/symm/mode.c.in similarity index 100% rename from mode.c.in rename to symm/mode.c.in diff --git a/mode.h.in b/symm/mode.h.in similarity index 100% rename from mode.h.in rename to symm/mode.h.in diff --git a/symm/modes.am.in b/symm/modes.am.in new file mode 100644 index 0000000..4cbc88f --- /dev/null +++ b/symm/modes.am.in @@ -0,0 +1,77 @@ +%## -*-makefile-*- +%# +### -*-makefile-*- GENERATED from modes.make.in +### +### Lots of lists of crypto primitives in various modes of operation. + +## Test programs for symmetric primitives. +SYMM_TESTS = + +## Source and header files for primitives under modes of operation. +GENMODES_C = +GENMODES_H = + +## Block cipher modes. +%repeat +GENMODES_C += modes/@blkc-@blkcmode.c +GENMODES_H += modes/@blkc-@blkcmode.h +SYMM_TESTS += @blkc-@blkcmode.$t +%end + +## Hash function modes. +%repeat +GENMODES_C += modes/@hash-@hashmode.c +GENMODES_H += modes/@hash-@hashmode.h +SYMM_TESTS += @hash-@hashmode.$t +%end + +## Interface and implementation headers for the various modes. +MODE_H = +%repeat +MODE_H += @blkcmode.h @blkcmode-def.h +%end +%repeat +MODE_H += @hashmode.h @hashmode-def.h +%end + +## Block cipher interfaces and implementations. +BLKC_C = +BLKC_H = +%repeat +BLKC_C += @blkc.c +BLKC_H += @blkc.h +SYMM_TESTS += @blkc.$t +%end + +## Hash function interfaces and implementations. +HASH_C = +HASH_H = +%repeat +HASH_C += @hash.c +HASH_H += @hash.h +SYMM_TESTS += @hash.$t +%end + +## Modes for symmetric encryption. +CIPHER_MODES = +%repeat +CIPHER_MODES += @blkc-@blkcciphermode +%end +%repeat +CIPHER_MODES += @hash-@hashciphermode +%end + +## Modes for message authentication. +MAC_MODES = +%repeat +MAC_MODES += @hash-@hashmacmode +%end + +## Test input files. +SYMM_TEST_FILES = +%repeat +SYMM_TEST_FILES += t/@blkc +%end +%repeat +SYMM_TEST_FILES += t/@hash +%end diff --git a/multigen b/symm/multigen similarity index 100% rename from multigen rename to symm/multigen diff --git a/symm/noekeon.c b/symm/noekeon.c new file mode 100644 index 0000000..6452091 --- /dev/null +++ b/symm/noekeon.c @@ -0,0 +1,193 @@ +/* -*-c-*- + * + * The Noekeon block cipher + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "noekeon.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet noekeon_keysz[] = { KSZ_SET, NOEKEON_KEYSZ, 0 }; + +/*----- Magic constants ---------------------------------------------------*/ + +/* --- To generate the magic --- * + * + * perl -e'@@r=();$x=0x80;for(0..16){push(@@r,$x);$x<<=1;$x^=0x11b + * if$x&0x100;};print join(", ",map{sprintf"0x%02x",$_}@@r),"\n";' + */ + +static const octet rcon[17] = { + 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, + 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4 +}; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @noekeon_init@--- * + * + * Arguments: @noekeon_ctx *k@ = pointer to key block to fill in + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a Noekeon key buffer. Noekeon accepts a 128-bit + * key. + */ + +void noekeon_init(noekeon_ctx *k, const void *buf, size_t sz) +{ + const octet *p = buf; + static const noekeon_ctx nullkey = { { 0, 0, 0, 0 } }; + + KSZ_ASSERT(noekeon, sz); + k->k[0] = LOAD32(p + 0); + k->k[1] = LOAD32(p + 4); + k->k[2] = LOAD32(p + 8); + k->k[3] = LOAD32(p + 12); + noekeon_eblk(&nullkey, k->k, k->k); +} + +/* --- @noekeon_eblk@, @noekeon_dblk@ --- * + * + * Arguments: @const noekeon_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +#define GAMMA(a, b, c, d) do { \ + uint32 _x; \ + b ^= ~(c | d); a ^= b & c; \ + _x = d; d = a; a = _x; \ + c ^= a ^ b ^ d; \ + b ^= ~(c | d); a ^= b & c; \ +} while (0) + +#define THETA(ka, kb, kc, kd, a, b, c, d) do { \ + uint32 _x; \ + _x = a ^ c; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); b ^= _x; d ^= _x; \ + a ^= ka; b ^= kb; c ^= kc; d ^= kd; \ + _x = b ^ d; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); a ^= _x; c ^= _x; \ +} while (0) + +#define ITHETA(ka, kb, kc, kd, a, b, c, d) do { \ + uint32 _x; \ + _x = b ^ d; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); a ^= _x; c ^= _x; \ + a ^= ka; b ^= kb; c ^= kc; d ^= kd; \ + _x = a ^ c; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); b ^= _x; d ^= _x; \ +} while (0) + +#define PI1(a, b, c, d) do { \ + b = ROL32(b, 1); c = ROL32(c, 5); d = ROL32(d, 2); \ +} while (0) + +#define PI2(a, b, c, d) do { \ + b = ROR32(b, 1); c = ROR32(c, 5); d = ROR32(d, 2); \ +} while (0) + +#define ROUND(r, ka, kb, kc, kd, a, b, c, d) do { \ + a ^= *r++; THETA(ka, kb, kc, kd, a, b, c, d); \ + PI1(a, b, c, d); GAMMA(a, b, c, d); PI2(a, b, c, d); \ +} while (0) + +#define IROUND(r, ka, kb, kc, kd, a, b, c, d) do { \ + ITHETA(ka, kb, kc, kd, a, b, c, d); a ^= *--r; \ + PI1(a, b, c, d); GAMMA(a, b, c, d); PI2(a, b, c, d); \ +} while (0) + +void noekeon_eblk(const noekeon_ctx *k, const uint32 *src, uint32 *dst) +{ + uint32 ka = k->k[0], kb = k->k[1], kc = k->k[2], kd = k->k[3]; + uint32 a = src[0], b = src[1], c = src[2], d = src[3]; + const octet *r = rcon; + + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + ROUND(r, ka, kb, kc, kd, a, b, c, d); + + a ^= *r++; THETA(ka, kb, kc, kd, a, b, c, d); + + dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; +} + +void noekeon_dblk(const noekeon_ctx *k, const uint32 *src, uint32 *dst) +{ + uint32 ka = k->k[0], kb = k->k[1], kc = k->k[2], kd = k->k[3]; + uint32 a = src[0], b = src[1], c = src[2], d = src[3]; + const octet *r = rcon + sizeof(rcon); + + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + IROUND(r, ka, kb, kc, kd, a, b, c, d); + + ITHETA(ka, kb, kc, kd, a, b, c, d); a ^= *--r; + + dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; +} + +BLKC_TEST(NOEKEON, noekeon) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/noekeon.h b/symm/noekeon.h new file mode 100644 index 0000000..744db96 --- /dev/null +++ b/symm/noekeon.h @@ -0,0 +1,103 @@ +/* -*-c-*- + * + * The Noekeon block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the Noekeon block cipher --------------------------------* + * + * A Nessie entry, by Joan Daemen, Michael Peeters, Gilles Van Assche and + * Vincent Rijmen, two of whom were the designers of the AES winner + * Rijndael. It's a simple cipher, based on Serpent-style bit-slicing. + * Speed is about middle-of-the-road -- about as fast as SAFER, faster than + * MARS. + */ + +#ifndef CATACOMB_NOEKEON_H +#define CATACOMB_NOEKEON_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magical numbers ---------------------------------------------------*/ + +#define NOEKEON_BLKSZ 16 +#define NOEKEON_KEYSZ 16 +#define NOEKEON_CLASS (N, B, 128) + +extern const octet noekeon_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct noekeon_ctx { + uint32 k[4]; +} noekeon_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @noekeon_init@ --- * + * + * Arguments: @noekeon_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes a Noekeon context with a particular key. This + * uses indirect keying. The key must be 128 bits long. + */ + +extern void noekeon_init(noekeon_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @noekeon_eblk@, @noekeon_dblk@ --- * + * + * Arguments: @const noekeon_ctx *k@ = pointer to Noekeon context + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void noekeon_eblk(const noekeon_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); +extern void noekeon_dblk(const noekeon_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/ofb-def.h b/symm/ofb-def.h new file mode 100644 index 0000000..6b1357d --- /dev/null +++ b/symm/ofb-def.h @@ -0,0 +1,545 @@ +/* -*-c-*- + * + * Definitions for output feedback mode + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_OFB_DEF_H +#define CATACOMB_OFB_DEF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include +#include + +#ifndef CATACOMB_ARENA_H +# include "arena.h" +#endif + +#ifndef CATACOMB_BLKC_H +# include "blkc.h" +#endif + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +#ifndef CATACOMB_PARANOIA_H +# include "paranoia.h" +#endif + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @OFB_DEF@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher + * + * Use: Creates definitions for output feedback mode. + */ + +#define OFB_DEF(PRE, pre) \ + \ +/* --- @pre_ofbgetiv@ --- * \ + * \ + * Arguments: @const pre_ofbctx *ctx@ = pointer to OFB context block \ + * @void *iv@ = pointer to output data block \ + * \ + * Returns: --- \ + * \ + * Use: Reads the currently set IV. Reading and setting an IV \ + * is not transparent to the cipher. It will add a `step' \ + * which must be matched by a similar operation during \ + * decryption. \ + */ \ + \ +void pre##_ofbgetiv(const pre##_ofbctx *ctx, void *iv) \ +{ \ + octet *p = iv; \ + unsigned off = ctx->off; \ + unsigned rest = PRE##_BLKSZ - off; \ + memcpy(p, ctx->iv + off, rest); \ + memcpy(p + rest, ctx->iv, off); \ +} \ + \ +/* --- @pre_ofbsetiv@ --- * \ + * \ + * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ + * @cnost void *iv@ = pointer to IV to set \ + * \ + * Returns: --- \ + * \ + * Use: Sets the IV to use for subsequent encryption. \ + */ \ + \ +void pre##_ofbsetiv(pre##_ofbctx *ctx, const void *iv) \ +{ \ + memcpy(ctx->iv, iv, PRE##_BLKSZ); \ + ctx->off = PRE##_BLKSZ; \ +} \ + \ +/* --- @pre_ofbbdry@ --- * \ + * \ + * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ + * \ + * Returns: --- \ + * \ + * Use: Inserts a boundary during encryption. Successful \ + * decryption must place a similar boundary. \ + */ \ + \ +void pre##_ofbbdry(pre##_ofbctx *ctx) \ +{ \ + uint32 niv[PRE##_BLKSZ / 4]; \ + BLKC_LOAD(PRE, niv, ctx->iv); \ + pre##_eblk(&ctx->ctx, niv, niv); \ + BLKC_STORE(PRE, ctx->iv, niv); \ + ctx->off = PRE##_BLKSZ; \ + BURN(niv); \ +} \ + \ +/* --- @pre_ofbsetkey@ --- * \ + * \ + * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ + * @const pre_ctx *k@ = pointer to cipher context \ + * \ + * Returns: --- \ + * \ + * Use: Sets the OFB context to use a different cipher key. \ + */ \ + \ +void pre##_ofbsetkey(pre##_ofbctx *ctx, const pre##_ctx *k) \ +{ \ + ctx->ctx = *k; \ +} \ + \ +/* --- @pre_ofbinit@ --- * \ + * \ + * Arguments: @pre_ofbctx *ctx@ = pointer to cipher context \ + * @const void *key@ = pointer to the key buffer \ + * @size_t sz@ = size of the key \ + * @const void *iv@ = pointer to initialization vector \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a OFB context ready for use. You should \ + * ensure that the IV chosen is unique: reusing an IV will \ + * compromise the security of the entire plaintext. This \ + * is equivalent to calls to @pre_init@, @pre_ofbsetkey@ \ + * and @pre_ofbsetiv@. \ + */ \ + \ +void pre##_ofbinit(pre##_ofbctx *ctx, \ + const void *key, size_t sz, \ + const void *iv) \ +{ \ + static const octet zero[PRE##_BLKSZ] = { 0 }; \ + pre##_init(&ctx->ctx, key, sz); \ + pre##_ofbsetiv(ctx, iv ? iv : zero); \ +} \ + \ +/* --- @pre_ofbencrypt@ --- * \ + * \ + * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Encrypts or decrypts a block with a block cipher in OFB \ + * mode: encryption and decryption are the same in OFB. \ + * The destination may be null to just churn the feedback \ + * round for a bit. The source may be null to use the \ + * cipher as a random data generator. \ + */ \ + \ +void pre##_ofbencrypt(pre##_ofbctx *ctx, \ + const void *src, void *dest, \ + size_t sz) \ +{ \ + const octet *s = src; \ + octet *d = dest; \ + unsigned off = ctx->off; \ + \ + /* --- Empty blocks are trivial --- */ \ + \ + if (!sz) \ + return; \ + \ + /* --- If I can deal with the block from my buffer, do that --- */ \ + \ + if (sz < PRE##_BLKSZ - off) \ + goto small; \ + \ + /* --- Finish off what's left in my buffer --- */ \ + \ + if (!d) \ + sz -= PRE##_BLKSZ - off; \ + else { \ + while (off < PRE##_BLKSZ) { \ + register octet x = s ? *s++ : 0; \ + *d++ = ctx->iv[off++] ^ x; \ + sz--; \ + } \ + } \ + \ + /* --- Main encryption loop --- */ \ + \ + { \ + uint32 iv[PRE##_BLKSZ / 4]; \ + BLKC_LOAD(PRE, iv, ctx->iv); \ + \ + for (;;) { \ + pre##_eblk(&ctx->ctx, iv, iv); \ + if (sz < PRE##_BLKSZ) \ + break; \ + if (d) { \ + if (!s) \ + BLKC_STORE(PRE, d, iv); \ + else { \ + uint32 x[PRE##_BLKSZ / 4]; \ + BLKC_LOAD(PRE, x, s); \ + BLKC_XSTORE(PRE, d, iv, x); \ + s += PRE##_BLKSZ; \ + } \ + d += PRE##_BLKSZ; \ + } \ + sz -= PRE##_BLKSZ; \ + } \ + \ + BLKC_STORE(PRE, ctx->iv, iv); \ + off = 0; \ + } \ + \ + /* --- Tidying up the tail end --- */ \ + \ + if (sz) { \ + small: \ + if (!d) \ + off += sz; \ + else do { \ + register octet x = s ? *s++ : 0; \ + *d++ = ctx->iv[off++] ^ x; \ + sz--; \ + } while (sz); \ + } \ + \ + /* --- Done --- */ \ + \ + ctx->off = off; \ + return; \ +} \ + \ +/* --- Generic cipher interface --- */ \ + \ +static const gcipher_ops gops; \ + \ +typedef struct gctx { \ + gcipher c; \ + pre##_ofbctx k; \ +} gctx; \ + \ +static gcipher *ginit(const void *k, size_t sz) \ +{ \ + gctx *g = S_CREATE(gctx); \ + g->c.ops = &gops; \ + pre##_ofbinit(&g->k, k, sz, 0); \ + return (&g->c); \ +} \ + \ +static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_ofbencrypt(&g->k, s, t, sz); \ +} \ + \ +static void gdestroy(gcipher *c) \ +{ \ + gctx *g = (gctx *)c; \ + BURN(*g); \ + S_DESTROY(g); \ +} \ + \ +static void gsetiv(gcipher *c, const void *iv) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_ofbsetiv(&g->k, iv); \ +} \ + \ +static void gbdry(gcipher *c) \ +{ \ + gctx *g = (gctx *)c; \ + pre##_ofbbdry(&g->k); \ +} \ + \ +static const gcipher_ops gops = { \ + &pre##_ofb, \ + gencrypt, gencrypt, gdestroy, gsetiv, gbdry \ +}; \ + \ +const gccipher pre##_ofb = { \ + #pre "-ofb", pre##_keysz, PRE##_BLKSZ, \ + ginit \ +}; \ + \ +/* --- Generic random number generator interface --- */ \ + \ +typedef struct grctx { \ + grand r; \ + pre##_ofbctx k; \ +} grctx; \ + \ +static void grdestroy(grand *r) \ +{ \ + grctx *g = (grctx *)r; \ + BURN(*g); \ + S_DESTROY(g); \ +} \ + \ +static int grmisc(grand *r, unsigned op, ...) \ +{ \ + grctx *g = (grctx *)r; \ + va_list ap; \ + int rc = 0; \ + uint32 i; \ + octet buf[PRE##_BLKSZ]; \ + va_start(ap, op); \ + \ + switch (op) { \ + case GRAND_CHECK: \ + switch (va_arg(ap, unsigned)) { \ + case GRAND_CHECK: \ + case GRAND_SEEDINT: \ + case GRAND_SEEDUINT32: \ + case GRAND_SEEDBLOCK: \ + case GRAND_SEEDRAND: \ + rc = 1; \ + break; \ + default: \ + rc = 0; \ + break; \ + } \ + break; \ + case GRAND_SEEDINT: \ + memset(buf, 0, sizeof(buf)); \ + i = va_arg(ap, unsigned); \ + STORE32(buf, i); \ + pre##_ofbsetiv(&g->k, buf); \ + break; \ + case GRAND_SEEDUINT32: \ + memset(buf, 0, sizeof(buf)); \ + i = va_arg(ap, uint32); \ + STORE32(buf, i); \ + pre##_ofbsetiv(&g->k, buf); \ + break; \ + case GRAND_SEEDBLOCK: { \ + const void *p = va_arg(ap, const void *); \ + size_t sz = va_arg(ap, size_t); \ + if (sz < sizeof(buf)) { \ + memset(buf, 0, sizeof(buf)); \ + memcpy(buf, p, sz); \ + p = buf; \ + } \ + pre##_ofbsetiv(&g->k, p); \ + } break; \ + case GRAND_SEEDRAND: { \ + grand *rr = va_arg(ap, grand *); \ + rr->ops->fill(rr, buf, sizeof(buf)); \ + pre##_ofbsetiv(&g->k, buf); \ + } break; \ + default: \ + GRAND_BADOP; \ + break; \ + } \ + \ + va_end(ap); \ + return (rc); \ +} \ + \ +static octet grbyte(grand *r) \ +{ \ + grctx *g = (grctx *)r; \ + octet o; \ + pre##_ofbencrypt(&g->k, 0, &o, 1); \ + return (o); \ +} \ + \ +static uint32 grword(grand *r) \ +{ \ + grctx *g = (grctx *)r; \ + octet b[4]; \ + pre##_ofbencrypt(&g->k, 0, b, sizeof(b)); \ + return (LOAD32(b)); \ +} \ + \ +static void grfill(grand *r, void *p, size_t sz) \ +{ \ + grctx *g = (grctx *)r; \ + pre##_ofbencrypt(&g->k, 0, p, sz); \ +} \ + \ +static const grand_ops grops = { \ + #pre "-ofb", \ + GRAND_CRYPTO, 0, \ + grmisc, grdestroy, \ + grword, grbyte, grword, grand_range, grfill \ +}; \ + \ +/* --- @pre_ofbrand@ --- * \ + * \ + * Arguments: @const void *k@ = pointer to key material \ + * @size_t sz@ = size of key material \ + * \ + * Returns: Pointer to generic random number generator interface. \ + * \ + * Use: Creates a random number interface wrapper around an \ + * OFB-mode block cipher. \ + */ \ + \ +grand *pre##_ofbrand(const void *k, size_t sz) \ +{ \ + grctx *g = S_CREATE(grctx); \ + g->r.ops = &grops; \ + pre##_ofbinit(&g->k, k, sz, 0); \ + return (&g->r); \ +} \ + \ +OFB_TEST(PRE, pre) + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +#include "daftstory.h" + +/* --- @OFB_TEST@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions + * + * Use: Standard test rig for OFB functions. + */ + +#define OFB_TEST(PRE, pre) \ + \ +/* --- Initial plaintext for the test --- */ \ + \ +static const octet text[] = TEXT; \ + \ +/* --- Key and IV to use --- */ \ + \ +static const octet key[] = KEY; \ +static const octet iv[] = IV; \ + \ +/* --- Buffers for encryption and decryption output --- */ \ + \ +static octet ct[sizeof(text)]; \ +static octet pt[sizeof(text)]; \ + \ +static void hexdump(const octet *p, size_t sz) \ +{ \ + const octet *q = p + sz; \ + for (sz = 0; p < q; p++, sz++) { \ + printf("%02x", *p); \ + if ((sz + 1) % PRE##_BLKSZ == 0) \ + putchar(':'); \ + } \ +} \ + \ +int main(void) \ +{ \ + size_t sz = 0, rest; \ + pre##_ofbctx ctx; \ + int status = 0; \ + int done = 0; \ + pre##_ctx k; \ + \ + size_t keysz = PRE##_KEYSZ ? \ + PRE##_KEYSZ : strlen((const char *)key); \ + \ + fputs(#pre "-ofb: ", stdout); \ + \ + pre##_init(&k, key, keysz); \ + pre##_ofbsetkey(&ctx, &k); \ + \ + while (sz <= sizeof(text)) { \ + rest = sizeof(text) - sz; \ + memcpy(ct, text, sizeof(text)); \ + pre##_ofbsetiv(&ctx, iv); \ + pre##_ofbencrypt(&ctx, ct, ct, sz); \ + pre##_ofbencrypt(&ctx, ct + sz, ct + sz, rest); \ + memcpy(pt, ct, sizeof(text)); \ + pre##_ofbsetiv(&ctx, iv); \ + pre##_ofbencrypt(&ctx, pt, pt, rest); \ + pre##_ofbencrypt(&ctx, pt + rest, pt + rest, sz); \ + if (memcmp(pt, text, sizeof(text)) == 0) { \ + done++; \ + if (sizeof(text) < 40 || done % 8 == 0) \ + fputc('.', stdout); \ + if (done % 480 == 0) \ + fputs("\n\t", stdout); \ + fflush(stdout); \ + } else { \ + printf("\nError (sz = %lu)\n", (unsigned long)sz); \ + status = 1; \ + printf("\tplaintext = "); hexdump(text, sz); \ + printf(", "); hexdump(text + sz, rest); \ + fputc('\n', stdout); \ + printf("\tciphertext = "); hexdump(ct, sz); \ + printf(", "); hexdump(ct + sz, rest); \ + fputc('\n', stdout); \ + printf("\trecovered text = "); hexdump(pt, sz); \ + printf(", "); hexdump(pt + sz, rest); \ + fputc('\n', stdout); \ + fputc('\n', stdout); \ + } \ + if (sz < 63) \ + sz++; \ + else \ + sz += 9; \ + } \ + \ + fputs(status ? " failed\n" : " ok\n", stdout); \ + return (status); \ +} + +#else +# define OFB_TEST(PRE, pre) +#endif + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/ofb.h b/symm/ofb.h new file mode 100644 index 0000000..5eec2ff --- /dev/null +++ b/symm/ofb.h @@ -0,0 +1,185 @@ +/* -*-c-*- + * + * Output feedback for block ciphers + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_OFB_H +#define CATACOMB_OFB_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @OFB_DECL@ --- * + * + * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions + * + * Use: Makes declarations for output feedback mode. + */ + +#define OFB_DECL(PRE, pre) \ + \ +/* --- Output feedback context --- */ \ + \ +typedef struct pre##_ofbctx { \ + pre##_ctx ctx; /* Underlying cipher context */ \ + unsigned off; /* Current offset in buffer */ \ + octet iv[PRE##_BLKSZ]; /* Output buffer and IV */ \ +} pre##_ofbctx; \ + \ +/* --- @pre_ofbgetiv@ --- * \ + * \ + * Arguments: @const pre_ofbctx *ctx@ = pointer to OFB context block \ + * @void *iv@ = pointer to output data block \ + * \ + * Returns: --- \ + * \ + * Use: Reads the currently set IV. Reading and setting an IV \ + * is not transparent to the cipher. It will add a `step' \ + * which must be matched by a similar operation during \ + * decryption. \ + */ \ + \ +extern void pre##_ofbgetiv(const pre##_ofbctx */*ctx*/, \ + void */*iv*/); \ + \ +/* --- @pre_ofbsetiv@ --- * \ + * \ + * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ + * @cnost void *iv@ = pointer to IV to set \ + * \ + * Returns: --- \ + * \ + * Use: Sets the IV to use for subsequent encryption. \ + */ \ + \ +extern void pre##_ofbsetiv(pre##_ofbctx */*ctx*/, \ + const void */*iv*/); \ + \ +/* --- @pre_ofbbdry@ --- * \ + * \ + * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ + * \ + * Returns: --- \ + * \ + * Use: Inserts a boundary during encryption. Successful \ + * decryption must place a similar boundary. \ + */ \ + \ +extern void pre##_ofbbdry(pre##_ofbctx */*ctx*/); \ + \ +/* --- @pre_ofbsetkey@ --- * \ + * \ + * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ + * @const pre_ctx *k@ = pointer to cipher context \ + * \ + * Returns: --- \ + * \ + * Use: Sets the OFB context to use a different cipher key. \ + */ \ + \ +extern void pre##_ofbsetkey(pre##_ofbctx */*ctx*/, \ + const pre##_ctx */*k*/); \ + \ +/* --- @pre_ofbinit@ --- * \ + * \ + * Arguments: @pre_ofbctx *ctx@ = pointer to cipher context \ + * @const void *key@ = pointer to the key buffer \ + * @size_t sz@ = size of the key \ + * @const void *iv@ = pointer to initialization vector \ + * \ + * Returns: --- \ + * \ + * Use: Initializes a OFB context ready for use. You should \ + * ensure that the IV chosen is unique: reusing an IV will \ + * compromise the security of the entire plaintext. This \ + * is equivalent to calls to @pre_init@, @pre_ofbsetkey@ \ + * and @pre_ofbsetiv@. \ + */ \ + \ +extern void pre##_ofbinit(pre##_ofbctx */*ctx*/, \ + const void */*key*/, size_t /*sz*/, \ + const void */*iv*/); \ + \ +/* --- @pre_ofbencrypt@ --- * \ + * \ + * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \ + * @const void *src@ = pointer to source data \ + * @void *dest@ = pointer to destination data \ + * @size_t sz@ = size of block to be encrypted \ + * \ + * Returns: --- \ + * \ + * Use: Encrypts or decrypts a block with a block cipher in OFB \ + * mode: encryption and decryption are the same in OFB. \ + * The destination may be null to just churn the feedback \ + * round for a bit. The source may be null to use the \ + * cipher as a random data generator. \ + */ \ + \ +extern void pre##_ofbencrypt(pre##_ofbctx */*ctx*/, \ + const void */*src*/, void */*dest*/, \ + size_t /*sz*/); \ + \ +/* --- @pre_ofbrand@ --- * \ + * \ + * Arguments: @const void *k@ = pointer to key material \ + * @size_t sz@ = size of key material \ + * \ + * Returns: Pointer to generic random number generator interface. \ + * \ + * Use: Creates a random number interface wrapper around an \ + * OFB-mode block cipher. \ + */ \ + \ +extern grand *pre##_ofbrand(const void */*k*/, size_t /*sz*/); \ + \ +/* --- Generic cipher interface --- */ \ + \ +extern const gccipher pre##_ofb; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/rc2-tab.h b/symm/rc2-tab.h new file mode 100644 index 0000000..48b46e0 --- /dev/null +++ b/symm/rc2-tab.h @@ -0,0 +1,78 @@ +/* -*-c-*- + * + * Substitution table for RC2 + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_RC2_TAB_H +#define CATACOMB_RC2_TAB_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- S-box table -------------------------------------------------------*/ + +#define RC2_PI { \ + 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, \ + 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, \ + 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, \ + 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, \ + 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, \ + 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, \ + 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, \ + 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, \ + 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, \ + 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, \ + 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, \ + 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, \ + 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, \ + 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, \ + 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, \ + 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, \ + 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, \ + 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, \ + 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, \ + 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, \ + 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, \ + 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, \ + 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, \ + 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, \ + 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, \ + 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, \ + 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, \ + 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, \ + 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, \ + 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, \ + 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, \ + 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad \ +} + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/rc2.c b/symm/rc2.c new file mode 100644 index 0000000..4ea85b6 --- /dev/null +++ b/symm/rc2.c @@ -0,0 +1,327 @@ +/* -*-c-*- + * + * The RC2 block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "paranoia.h" +#include "rc2.h" +#include "rc2-tab.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet rc2_keysz[] = { KSZ_RANGE, RC2_KEYSZ, 1, 128, 1 }; + +/*----- Important tables --------------------------------------------------*/ + +static const octet pi[256] = RC2_PI; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rc2_braindamage@ --- * + * + * Arguments: @rc2_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to key material + * @size_t sz@ = size of key material in bytes + * @unsigned eb@ = desired effective key size, in bits + * + * Returns: --- + * + * Use: Initializes an RC2 expanded key, and braindamages it to the + * requested effective key size. This is here for compatibility + * reasons. You should be using @rc2_init@ in normal code, + * which doesn't actually apply braindamage. + */ + +void rc2_braindamage(rc2_ctx *k, const void *buf, size_t sz, unsigned eb) +{ + unsigned t8; + uint16 tm; + unsigned i; + uint16 *kk; + octet l[128]; + + KSZ_ASSERT(rc2, sz); + + /* --- Compute the braindamage parameters --- */ + + t8 = (eb + 7) / 8; + tm = 0xff & ((1 << (8 + eb - 8 * t8)) - 1); + + /* --- Copy and expand the initial key --- */ + + if (sz > sizeof(l)) + sz = sizeof(l); + memcpy(l, buf, sz); + + for (i = sz; i < sizeof(l); i++) + l[i] = pi[U8(l[i - 1] + l[i - sz])]; + + /* --- Braindamage the key --- */ + + i = sizeof(l) - t8; + l[i] = pi[l[i] & tm]; + while (i) { + i--; + l[i] = pi[U8(l[i + 1] ^ l[i + t8])]; + } + + /* --- Write it to the key block --- */ + + kk = k->k; + for (i = 0; i < sizeof(l); i += 2) + *kk++ = LOAD16_L(l + i); + BURN(l); +} + +/* --- @rc2_init@ --- * + * + * Arguments: @rc2_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to key material + * @size_t sz@ = size of key material in bytes + * + * Returns: --- + * + * Use: Initializes an RC2 expanded key. The effective key size is + * set to be equal to the real key size, in bits. + */ + +void rc2_init(rc2_ctx *k, const void *buf, size_t sz) +{ + rc2_braindamage(k, buf, sz, sz * 8); +} + +/*----- Encryption and decryption -----------------------------------------*/ + +#define MIX(a, b, c, d, r, kk) do { \ + a += *kk++ + (d & c) + (~d & b); \ + a = ROL16(a, r); \ +} while (0) + +#define MASH(a, d, k) do { \ + a += k[d & 63]; \ +} while (0) + +#define UNMIX(a, b, c, d, r, kk) do { \ + a = ROR16(a, r); \ + a -= *--kk + (d & c) + (~d & b); \ +} while (0) + +#define UNMASH(a, d, k) do { \ + a -= k[d & 63]; \ +} while (0) + +/* --- @rc2_eblk@, @rc2_dblk@ --- * + * + * Arguments: @const rc2_ctx *k@ = pointer to RC2 context + * @const uint32 s[2]@ = pointer to source block + * @const uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +void rc2_eblk(const rc2_ctx *k, const uint32 *s, uint32 *dst) +{ + uint16 a = U16(s[0] >> 0), b = U16(s[0] >> 16); + uint16 c = U16(s[1] >> 0), d = U16(s[1] >> 16); + const uint16 *kk = k->k; + + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MASH(a, d, k->k); MASH(b, a, k->k); + MASH(c, b, k->k); MASH(d, c, k->k); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MASH(a, d, k->k); MASH(b, a, k->k); + MASH(c, b, k->k); MASH(d, c, k->k); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk); + MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk); + + dst[0] = a | (b << 16); dst[1] = c | (d << 16); +} + +void rc2_dblk(const rc2_ctx *k, const uint32 *s, uint32 *dst) +{ + uint16 a = U16(s[0] >> 0), b = U16(s[0] >> 16); + uint16 c = U16(s[1] >> 0), d = U16(s[1] >> 16); + const uint16 *kk = k->k + 64; + + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMASH(d, c, k->k); UNMASH(c, b, k->k); + UNMASH(b, a, k->k); UNMASH(a, d, k->k); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMASH(d, c, k->k); UNMASH(c, b, k->k); + UNMASH(b, a, k->k); UNMASH(a, d, k->k); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk); + UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk); + + dst[0] = a | (b << 16); dst[1] = c | (d << 16); +} + +/*----- Custom test rig ---------------------------------------------------* + * + * I need to test the braindamage feature. + */ + +#ifdef TEST_RIG + +#include +#include + +static int verify(dstr *v) +{ + rc2_ctx k; + uint32 p[RC2_BLKSZ / 4]; + uint32 c[RC2_BLKSZ / 4]; + uint32 d[RC2_BLKSZ / 4]; + dstr b = DSTR_INIT; + unsigned bd = *(unsigned *)v[1].buf; + int ok = 1; + + /* --- Initialize the key buffer --- */ + + dstr_ensure(&b, RC2_BLKSZ); + b.len = RC2_BLKSZ; + rc2_braindamage(&k, v[0].buf, v[0].len, bd); + BLKC_LOAD(RC2, p, v[2].buf); + BLKC_LOAD(RC2, c, v[3].buf); + + /* --- Test encryption --- */ + + BLKC_MOVE(RC2, d, p); + rc2_eblk(&k, d, d); + BLKC_STORE(RC2, b.buf, d); + if (memcmp(b.buf, v[3].buf, RC2_BLKSZ)) { + ok = 0; + printf("\nfail encryption:" + "\n\tkey = "); + type_hex.dump(&v[0], stdout); + printf("\n\tbraindamage= %u", bd); + printf("\n\tplaintext = "); type_hex.dump(&v[2], stdout); + printf("\n\texpected = "); type_hex.dump(&v[3], stdout); + printf("\n\tcalculated = "); type_hex.dump(&b, stdout); + putchar('\n'); + } + + /* --- Test decryption --- */ + + BLKC_MOVE(RC2, d, c); + rc2_dblk(&k, d, d); + BLKC_STORE(RC2, b.buf, d); + if (memcmp(b.buf, v[2].buf, RC2_BLKSZ)) { + ok = 0; + printf("\nfail decryption:" + "\n\tkey = "); + type_hex.dump(&v[0], stdout); + printf("\n\tbraindamage= %u", bd); + printf("\n\tciphertext = "); type_hex.dump(&v[3], stdout); + printf("\n\texpected = "); type_hex.dump(&v[2], stdout); + printf("\n\tcalculated = "); type_hex.dump(&b, stdout); + putchar('\n'); + } + + /* --- Return --- */ + + return (ok); +} + +static test_chunk defs[] = { + { "rc2", verify, { &type_hex, &type_int, &type_hex, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/t/rc2"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/rc2.h b/symm/rc2.h new file mode 100644 index 0000000..8b72a8b --- /dev/null +++ b/symm/rc2.h @@ -0,0 +1,128 @@ +/* -*-c-*- + * + * The RC2 block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the RC2 block cipher -------------------------------------* + * + * RC2 was designed by Ron Rivest, and for a long time was a trade secret of + * RSA Data Security Inc. Like RC4, it leaked out, and has now been + * described in RFC2268. The RC2 key schedule is known to have some + * weaknesses, although I'm not aware of any major results against the cipher + * itself. I'm also not aware of any legal problems with using the RC2 + * cipher. + * + * The oddest feature in the cipher is the key schedule. It expands the + * initial key material to 128 bytes, and then `brain-damages' it, according + * to a supplied `effective key-bits' parameter, before expanding the + * remaining key material back into the buffer. + * + * The key schedule allows second preimages to be computed trivially. + */ + +#ifndef CATACOMB_RC2_H +#define CATACOMB_RC2_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magical numbers ---------------------------------------------------*/ + +#define RC2_BLKSZ 8 +#define RC2_KEYSZ 16 +#define RC2_CLASS (N, L, 64) + +extern const octet rc2_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct rc2_ctx { + uint16 k[64]; +} rc2_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @rc2_braindamage@ --- * + * + * Arguments: @rc2_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to key material + * @size_t sz@ = size of key material in bytes + * @unsigned eb@ = desired effective key size, in bits + * + * Returns: --- + * + * Use: Initializes an RC2 expanded key, and braindamages it to the + * requested effective key size. This is here for compatibility + * reasons. You should be using @rc2_init@ in normal code, + * which doesn't actually apply braindamage. + */ + +extern void rc2_braindamage(rc2_ctx */*k*/, const void */*buf*/, + size_t /*sz*/, unsigned /*eb*/); + +/* --- @rc2_init@ --- * + * + * Arguments: @rc2_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to key material + * @size_t sz@ = size of key material in bytes + * + * Returns: --- + * + * Use: Initializes an RC2 expanded key. The effective key size is + * set to be equal to the real key size, in bits. + */ + +extern void rc2_init(rc2_ctx */*k*/, const void */*buf*/, size_t /*sz*/); + +/* --- @rc2_eblk@, @rc2_dblk@ --- * + * + * Arguments: @const rc2_ctx *k@ = pointer to RC2 context + * @const uint32 s[2]@ = pointer to source block + * @const uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void rc2_eblk(const rc2_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); +extern void rc2_dblk(const rc2_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/rc4.c b/symm/rc4.c new file mode 100644 index 0000000..0d02062 --- /dev/null +++ b/symm/rc4.c @@ -0,0 +1,367 @@ +/* -*-c-*- + * + * The alleged RC4 stream cipher + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include +#include + +#include "arena.h" +#include "gcipher.h" +#include "grand.h" +#include "paranoia.h" +#include "rc4.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet rc4_keysz[] = { KSZ_RANGE, RC4_KEYSZ, 1, 255, 1 }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rc4_addkey@ --- * + * + * Arguments: @rc4_ctx *ctx@ = pointer to context to key + * @const void *k@ = pointer to key data to use + * @size_t sz@ = size of the key data + * + * Returns: --- + * + * Use: Mixes key data with an RC4 context. The RC4 context is not + * reset before mixing. This may be used to mix new key + * material with an existing RC4 context. + */ + +void rc4_addkey(rc4_ctx *ctx, const void *k, size_t sz) +{ + unsigned i, j; + const octet *p = k, *q = p + sz; + + KSZ_ASSERT(rc4, sz); + + for (i = j = 0; i < 256; i++) { + unsigned si = ctx->s[i]; + j = (j + si + *p++) & 0xff; + ctx->s[i] = ctx->s[j]; + ctx->s[j] = si; + if (p == q) + p = k; + } + + ctx->i = ctx->j = 0; +} + +/* --- @rc4_init@ --- * + * + * Arguments: @rc4_ctx *ctx@ = pointer to context to initialize + * @const void *k@ = pointer to key data to use + * @size_t sz@ = size of the key data + * + * Returns: --- + * + * Use: Initializes an RC4 context ready for use. + */ + +void rc4_init(rc4_ctx *ctx, const void *k, size_t sz) +{ + unsigned i; + + for (i = 0; i < 256; i++) + ctx->s[i] = i; + ctx->f = 0; + rc4_addkey(ctx, k, sz); +} + +/* --- @rc4_encrypt@ --- * + * + * Arguments: @rc4_ctx *ctx@ = pointer to context to use + * @const void *src@ = pointer to the source block + * @void *dest@ = pointer to the destination block + * @size_t sz@ = size of the block + * + * Returns: --- + * + * Use: Encrypts or decrypts a block of data. The destination may + * be null to just grind the generator around for a while. It's + * recommended that you say `@rc4_encrypt(&ctx, 0, 0, 1024)@' + * after initializing a new context, to prevent keystream + * guessing attacks. The source may be null to just extract a + * big lump of data from the generator. + */ + +void rc4_encrypt(rc4_ctx *ctx, const void *src, void *dest, size_t sz) +{ + const octet *s = src; + octet *d = dest; + + if (!d) + RC4_OPEN(ctx, while (sz) { unsigned x; RC4_BYTE(x); sz--; }); + else if (!s) + RC4_OPEN(ctx, while (sz) { RC4_BYTE(*d++); sz--; }); + else + RC4_OPEN(ctx, + while (sz) { unsigned x; RC4_BYTE(x); *d++ = *s++ ^ x; sz--; }); +} + +/*----- Generic cipher interface ------------------------------------------*/ + +typedef struct gctx { + gcipher c; + rc4_ctx rc4; +} gctx; + +static const gcipher_ops gops; + +static gcipher *ginit(const void *k, size_t sz) +{ + gctx *g = S_CREATE(gctx); + g->c.ops = &gops; + rc4_init(&g->rc4, k, sz); + return (&g->c); +} + +static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) +{ + gctx *g = (gctx *)c; + rc4_encrypt(&g->rc4, s, t, sz); +} + +static void gdestroy(gcipher *c) +{ + gctx *g = (gctx *)c; + BURN(*g); + S_DESTROY(g); +} + +static const gcipher_ops gops = { + &rc4, + gencrypt, gencrypt, gdestroy, 0, 0 +}; + +const gccipher rc4 = { + "rc4", rc4_keysz, 0, + ginit +}; + +/*----- Generic random number generator interface -------------------------*/ + +typedef struct grctx { + grand r; + rc4_ctx rc4; +} grctx; + +static void grdestroy(grand *r) +{ + grctx *g = (grctx *)r; + BURN(*g); + S_DESTROY(g); +} + +static int grmisc(grand *r, unsigned op, ...) +{ + grctx *g = (grctx *)r; + va_list ap; + int rc = 0; + uint32 i; + octet buf[4]; + va_start(ap, op); + + switch (op) { + case GRAND_CHECK: + switch (va_arg(ap, unsigned)) { + case GRAND_CHECK: + case GRAND_SEEDINT: + case GRAND_SEEDUINT32: + case GRAND_SEEDBLOCK: + case GRAND_SEEDRAND: + rc = 1; + break; + default: + rc = 0; + break; + } + break; + case GRAND_SEEDINT: + i = va_arg(ap, unsigned); + STORE32(buf, i); + rc4_addkey(&g->rc4, buf, sizeof(buf)); + break; + case GRAND_SEEDUINT32: + i = va_arg(ap, uint32); + STORE32(buf, i); + rc4_addkey(&g->rc4, buf, sizeof(buf)); + break; + case GRAND_SEEDBLOCK: { + const void *p = va_arg(ap, const void *); + size_t sz = va_arg(ap, size_t); + rc4_addkey(&g->rc4, p, sz); + } break; + case GRAND_SEEDRAND: { + grand *rr = va_arg(ap, grand *); + octet buf[16]; + rr->ops->fill(rr, buf, sizeof(buf)); + rc4_addkey(&g->rc4, buf, sizeof(buf)); + } break; + default: + GRAND_BADOP; + break; + } + + va_end(ap); + return (rc); +} + +static octet grbyte(grand *r) +{ + grctx *g = (grctx *)r; + octet o; + RC4_OPEN(&g->rc4, RC4_BYTE(o);); + return (o); +} + +static uint32 grword(grand *r) +{ + grctx *g = (grctx *)r; + octet b[4]; + int i; + RC4_OPEN(&g->rc4, + for (i = 0; i < sizeof(b); i++) + RC4_BYTE(b[i]);); + return (LOAD32(b)); +} + +static void grfill(grand *r, void *p, size_t sz) +{ + grctx *g = (grctx *)r; + rc4_encrypt(&g->rc4, 0, p, sz); +} + +static const grand_ops grops = { + "rc4", + GRAND_CRYPTO, 0, + grmisc, grdestroy, + grword, grbyte, grword, grand_range, grfill +}; + +/* --- @rc4_rand@ --- * + * + * Arguments: @const void *k@ = pointer to key material + * @size_t sz@ = size of key material + * + * Returns: Pointer to generic random number generator interface. + * + * Use: Creates a random number interface wrapper around an + * OFB-mode block cipher. + */ + +grand *rc4_rand(const void *k, size_t sz) +{ + grctx *g = S_CREATE(grctx); + g->r.ops = &grops; + rc4_init(&g->rc4, k, sz); + return (&g->r); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include +#include + +#include +#include + +static int v_encrypt(dstr *v) +{ + rc4_ctx ctx; + dstr d = DSTR_INIT; + int ok = 1; + + rc4_init(&ctx, v[0].buf, v[0].len); + dstr_ensure(&d, v[1].len); + d.len = v[1].len; + rc4_encrypt(&ctx, v[1].buf, d.buf, d.len); + + if (memcmp(v[2].buf, d.buf, d.len) != 0) { + ok = 0; + printf("\nfail encryption:" + "\n\tkey = "); + type_hex.dump(&v[0], stdout); + printf("\n\tplaintext = "); type_hex.dump(&v[1], stdout); + printf("\n\texpected = "); type_hex.dump(&v[2], stdout); + printf("\n\tcalculated = "); type_hex.dump(&d, stdout); + putchar('\n'); + } + + return (ok); +} + +static int v_generate(dstr *v) +{ + rc4_ctx ctx; + dstr d = DSTR_INIT; + int ok = 1; + + rc4_init(&ctx, v[0].buf, v[0].len); + rc4_encrypt(&ctx, 0, 0, *(int *)v[1].buf); + dstr_ensure(&d, v[2].len); + d.len = v[2].len; + rc4_encrypt(&ctx, 0, d.buf, d.len); + + if (memcmp(v[2].buf, d.buf, d.len) != 0) { + ok = 0; + printf("\nfail generation:" + "\n\tkey = "); + type_hex.dump(&v[0], stdout); + printf("\n\tskip len = %i", *(int *)v[1].buf); + printf("\n\texpected = "); type_hex.dump(&v[2], stdout); + printf("\n\tcalculated = "); type_hex.dump(&d, stdout); + putchar('\n'); + } + + return (ok); +} + +static test_chunk defs[] = { + { "rc4-encrypt", v_encrypt, { &type_hex, &type_hex, &type_hex, 0 } }, + { "rc4-generate", v_generate, { &type_hex, &type_int, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/t/rc4"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/rc4.h b/symm/rc4.h new file mode 100644 index 0000000..caeeadb --- /dev/null +++ b/symm/rc4.h @@ -0,0 +1,195 @@ +/* -*-c-*- + * + * The alleged RC4 stream cipher + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on RC4 ------------------------------------------------------* + * + * RC4 is a stream cipher desgigned by Ron Rivest. For a while RC4 was a + * trade secret of RSA Data Security, Inc., but somehow source code for a + * cipher which interworks with RC4 was posted to the Cypherpunks mailing + * list. + */ + +#ifndef CATACOMB_RC4_H +#define CATACOMB_RC4_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct rc4_ctx { + unsigned i, j; /* Indices into the @S@ table */ + unsigned f; /* Flags word */ + octet s[256]; /* The ever-changing @S@ table */ +} rc4_ctx; + +#define RC4F_OPEN 1u + +/*----- Macros ------------------------------------------------------------*/ + +/* --- @RC4_OPEN@ --- * + * + * Arguments: @ctx@ = pointer to an RC4 context + * @guts@ = code to perform within the RC4 context + * + * Use: Performs some code within an RC4 context. Some of the + * parameters are extracted from the context and held in local + * variables for speed. Multiple calls to @RC4_BYTE@ may be + * made within the open context. A context must only be + * opened once at a time. + */ + +#define RC4_OPEN(ctx, guts) do { \ + unsigned _rc4_i = (ctx)->i; \ + unsigned _rc4_j = (ctx)->j; \ + octet *_rc4_s = (ctx)->s; \ + \ + assert(((void)"RC4 context may only be opened once at a time", \ + ((ctx)->f & RC4F_OPEN) == 0)); \ + (ctx)->f |= RC4F_OPEN; \ + \ + guts \ + \ + (ctx)->f &= ~RC4F_OPEN; \ + (ctx)->i = _rc4_i; \ + (ctx)->j = _rc4_j; \ +} while (0) + +/* --- @RC4_BYTE@ --- * + * + * Arguments: @x@ = output variable to set + * + * Use: Extracts an octet from the lexically innermost open RC4 + * context and places it in the variable @x@. + */ + +#define RC4_BYTE(x) do { \ + unsigned _si, _sj; \ + _rc4_i = (_rc4_i + 1) & 0xff; \ + _si = _rc4_s[_rc4_i]; \ + _rc4_j = (_rc4_j + _si) & 0xff; \ + _sj = _rc4_s[_rc4_j]; \ + _rc4_s[_rc4_i] = _sj; \ + _rc4_s[_rc4_j] = _si; \ + (x) = _rc4_s[(_si + _sj) & 0xff]; \ +} while (0) + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @rc4_addkey@ --- * + * + * Arguments: @rc4_ctx *ctx@ = pointer to context to key + * @const void *k@ = pointer to key data to use + * @size_t sz@ = size of the key data + * + * Returns: --- + * + * Use: Mixes key data with an RC4 context. The RC4 context is not + * reset before mixing. This may be used to mix new key + * material with an existing RC4 context. + */ + +extern void rc4_addkey(rc4_ctx */*ctx*/, const void */*k*/, size_t /*sz*/); + +/* --- @rc4_init@ --- * + * + * Arguments: @rc4_ctx *ctx@ = pointer to context to initialize + * @const void *k@ = pointer to key data to use + * @size_t sz@ = size of the key data + * + * Returns: --- + * + * Use: Initializes an RC4 context ready for use. + */ + +extern void rc4_init(rc4_ctx */*ctx*/, const void */*k*/, size_t /*sz*/); + +/* --- @rc4_encrypt@ --- * + * + * Arguments: @rc4_ctx *ctx@ = pointer to context to use + * @const void *src@ = pointer to the source block + * @void *dest@ = pointer to the destination block + * @size_t sz@ = size of the block + * + * Returns: --- + * + * Use: Encrypts or decrypts a block of data. The destination may + * be null to just grind the generator around for a while. It's + * recommended that you say `@rc4_encrypt(&ctx, 0, 0, 1024)@' + * after initializing a new context, to prevent keystream + * guessing attacks. The source may be null to just extract a + * big lump of data from the generator. + */ + +extern void rc4_encrypt(rc4_ctx */*ctx*/, + const void */*src*/, void */*dest*/, + size_t /*sz*/); + +/*----- Generic cipher interface ------------------------------------------*/ + +#define RC4_KEYSZ 16 +extern const octet rc4_keysz[]; + +extern const gccipher rc4; + +/*----- Generic random number generator interface -------------------------*/ + +/* --- @rc4_rand@ --- * + * + * Arguments: @const void *k@ = pointer to key material + * @size_t sz@ = size of key material + * + * Returns: Pointer to generic random number generator interface. + * + * Use: Creates a random number interface wrapper around an + * OFB-mode block cipher. + */ + +extern grand *rc4_rand(const void */*k*/, size_t /*sz*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/rc5.c b/symm/rc5.c new file mode 100644 index 0000000..634f0b7 --- /dev/null +++ b/symm/rc5.c @@ -0,0 +1,230 @@ +/* -*-c-*- + * + * The RC5-32/12 block cipher + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include +#include + +#include "arena.h" +#include "blkc.h" +#include "gcipher.h" +#include "rc5.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet rc5_keysz[] = { KSZ_RANGE, RC5_KEYSZ, 1, 255, 1 }; + +/*----- Internal magical constants ----------------------------------------*/ + +#define T ((RC5_ROUNDS + 1) * 2) +#define P 0xb7e15163 +#define Q 0x9e3779b9 + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rc5_init@ --- * + * + * Arguments: @rc5_ctx *k@ = pointer to a key block + * @const void *sbuf@ = pointer to key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes an RC5 key block. + */ + +void rc5_init(rc5_ctx *k, const void *sbuf, size_t sz) +{ + uint32 *l; + size_t w; + + /* --- Set up the @L@ table --- * + * + * This is slightly unfortunately defined. + */ + + KSZ_ASSERT(rc5, sz); + + { + int i; + const octet *p = sbuf; + + /* --- Create the buffer --- */ + + w = (sz + 3) / 4; + l = XS_ALLOC(w * sizeof(uint32)); + + /* --- Extract the key material --- */ + + for (i = 0; sz > 3; i++) { + l[i] = LOAD32_L(p); + p += 4; + sz -= 4; + } + + /* --- Fix up the tail end --- */ + + if (sz) { + uint32 x = U8(*p++); + if (sz > 1) x |= (U8(*p++) << 8); + if (sz > 2) x |= (U8(*p++) << 16); + l[i] = x; + } + } + + /* --- Initialize the @S@ table --- */ + + { + int i; + + k->s[0] = P; + for (i = 1; i < T; i++) + k->s[i] = k->s[i - 1] + Q; + } + + /* --- Mix in the key --- */ + + { + int m = 3 * (w > T ? w : T); + int i, j, c; + uint32 a, b; + + for (c = i = j = a = b = 0; c < m; c++) { + uint32 x; + + x = k->s[i] + a + b; + k->s[i] = a = ROL32(x, 3); + i++; if (i >= T) i = 0; + + x = l[j] + a + b; + l[j] = b = ROL32(x, a + b); + j++; if (j >= w) j = 0; + } + } + + memset(l, 0, w * sizeof(uint32)); + XS_FREE(l); +} + +/* --- @EROUND@, @DROUND@ --- */ + +#define EROUND(x, y, k) do { \ + uint32 _x; \ + _x = x ^ y; x = ROL32(_x, y) + k[0]; \ + _x = y ^ x; y = ROL32(_x, x) + k[1]; \ + k += 2; \ +} while (0) + +#define DROUND(x, y, k) do { \ + uint32 _x; \ + k -= 2; \ + _x = y - k[1]; y = ROR32(_x, x) ^ x; \ + _x = x - k[0]; x = ROR32(_x, y) ^ y; \ +} while (0) + +/* --- @EBLK@, @DBLK@ --- */ + +#define EBLK(a, b, c, d, k) do { \ + uint32 _l, _r; \ + const uint32 *_k = (k)->s; \ + \ + _l = (a) + _k[0]; \ + _r = (b) + _k[1]; \ + _k += 2; \ + \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + (c) = _l; \ + (d) = _r; \ +} while (0) + +#define DBLK(a, b, c, d, k) do { \ + uint32 _l, _r; \ + const uint32 *_k = (k)->s + T; \ + \ + _l = (a); \ + _r = (b); \ + \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + \ + _k -= 2; \ + (d) = _r - _k[1]; \ + (c) = _l - _k[0]; \ +} while (0) + +/* --- @rc5_eblk@, @rc5_dblk@ --- * + * + * Arguments: @const rc5_ctx *k@ = pointer to RC5 context block + * @const uint32 s[2]@ = pointer to source block + * @uint32 *d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low level block encryption and decryption. + */ + +void rc5_eblk(const rc5_ctx *k, const uint32 *s, uint32 *d) +{ + EBLK(s[0], s[1], d[0], d[1], k); +} + +void rc5_dblk(const rc5_ctx *k, const uint32 *s, uint32 *d) +{ + DBLK(s[0], s[1], d[0], d[1], k); +} + +/* --- Test rig --- */ + +BLKC_TEST(RC5, rc5) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/rc5.h b/symm/rc5.h new file mode 100644 index 0000000..c21b56d --- /dev/null +++ b/symm/rc5.h @@ -0,0 +1,101 @@ +/* -*-c-*- + * + * The RC5-32/12 block cipher + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the RC5 block cipher -------------------------------------* + * + * RC5 was designed by Ron Rivest as a test vehicle for the use of data- + * dependent rotations in cryptographic transformations. The algorithm is + * covered by a patent held by RSA Security Inc. (US Patent# 5,724,428). + * It's vulnerable to some clever differential attacks, which can break it in + * about %$2^{44}$% chosen plaintexts. I don't recommend the use of this + * cipher. + */ + +#ifndef CATACOMB_RC5_H +#define CATACOMB_RC5_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +/*----- Magic numbers -----------------------------------------------------*/ + +#define RC5_ROUNDS 12 +#define RC5_KEYSZ 10 +#define RC5_BLKSZ 8 +#define RC5_CLASS (N, L, 64) + +extern const octet rc5_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct rc5_ctx { + uint32 s[2 * (RC5_ROUNDS + 1)]; +} rc5_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @rc5_init@ --- * + * + * Arguments: @rc5_ctx *k@ = pointer to a key block + * @const void *sbuf@ = pointer to key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes an RC5 key block. + */ + +extern void rc5_init(rc5_ctx */*k*/, const void */*sbuf*/, size_t /*sz*/); + +/* --- @rc5_eblk@, @rc5_dblk@ --- * + * + * Arguments: @const rc5_ctx *k@ = pointer to RC5 context block + * @const uint32 s[2]@ = pointer to source block + * @uint32 *d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low level block encryption and decryption. + */ + +extern void rc5_eblk(const rc5_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); +extern void rc5_dblk(const rc5_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/rijndael-base.c b/symm/rijndael-base.c new file mode 100644 index 0000000..d3ec0d6 --- /dev/null +++ b/symm/rijndael-base.c @@ -0,0 +1,133 @@ +/* -*-c-*- + * + * Low-level stuff for all Rijndael block sizes + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "rijndael.h" +#include "rijndael-base.h" +#include "rijndael-tab.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet rijndael_keysz[] = { KSZ_RANGE, RIJNDAEL_KEYSZ, 4, 32, 4 }; + +/*----- Constant tables ---------------------------------------------------*/ + +const octet rijndael_s[256] = RIJNDAEL_S; +const octet rijndael_si[256] = RIJNDAEL_SI; +const uint32 rijndael_t[4][256] = RIJNDAEL_T; +const uint32 rijndael_ti[4][256] = RIJNDAEL_TI; +const uint32 rijndael_u[4][256] = RIJNDAEL_U; +const octet rijndael_rcon[] = RIJNDAEL_RCON; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rijndael_setup@ --- * + * + * Arguments: @rijndael_ctx *k@ = pointer to context to initialize + * @unsigned nb@ = number of words in the block + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Low-level key-scheduling. + */ + +void rijndael_setup(rijndael_ctx *k, unsigned nb, const void *buf, size_t sz) +{ + unsigned nk, nr, nw; + unsigned i, j, jj; + const octet *p; + uint32 ww; + + /* --- Sort out the key size --- */ + + KSZ_ASSERT(rijndael, sz); + nk = sz / 4; + + /* --- Select the number of rounds --- */ + + nr = (nk > nb ? nk : nb) + 6; + if (nr < 10) + nr = 10; + k->nr = nr; + + /* --- Fetch the first key words out --- */ + + p = buf; + for (i = 0; i < nk; i++) { + k->w[i] = LOAD32_B(p); + p += 4; + } + + /* --- Expand this material to fill the rest of the table --- */ + + nw = (nr + 1) * nb; + ww = k->w[i - 1]; + p = RCON; + for (; i < nw; i++) { + uint32 w = k->w[i - nk]; + if (i % nk == 0) { + ww = ROL32(ww, 8); + w ^= SUB(S, ww, ww, ww, ww) ^ (*p++ << 24); + } else if (nk > 6 && i % nk == 4) + w ^= SUB(S, ww, ww, ww, ww); + else + w ^= ww; + k->w[i] = ww = w; + } + + /* --- Make the decryption keys --- */ + + j = nw; i = 0; + + j -= nb; jj = 0; + for (; i < nb; i++) + k->wi[i] = k->w[j + jj++]; + + for (; i < nw - nb; i += nb) { + j -= nb; + for (jj = 0; jj < nb; jj++) { + uint32 w = k->w[j + jj]; + k->wi[i + jj] = MIX(U, w, w, w, w); + } + } + + j -= nb; jj = 0; + for (; i < nw; i++) + k->wi[i] = k->w[j + jj++]; +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/rijndael-base.h b/symm/rijndael-base.h new file mode 100644 index 0000000..b213b13 --- /dev/null +++ b/symm/rijndael-base.h @@ -0,0 +1,71 @@ +/* -*-c-*- + * + * Internal header for Rijndael implementation + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_RIJNDAEL_BASE_H +#define CATACOMB_RIJNDAEL_BASE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +/*----- Constant tables ---------------------------------------------------*/ + +extern const octet rijndael_s[256]; +extern const octet rijndael_si[256]; +extern const uint32 rijndael_t[4][256]; +extern const uint32 rijndael_ti[4][256]; +extern const uint32 rijndael_u[4][256]; +extern const octet rijndael_rcon[]; + +#define S rijndael_s +#define SI rijndael_si +#define T rijndael_t +#define TI rijndael_ti +#define U rijndael_u +#define RCON rijndael_rcon + +/*----- Handy macros ------------------------------------------------------*/ + +#define SUB(s, a, b, c, d) \ + (s[U8((a) >> 24)] << 24 | s[U8((b) >> 16)] << 16 | \ + s[U8((c) >> 8)] << 8 | s[U8((d) >> 0)] << 0) + +#define MIX(t, a, b, c, d) \ + (t[0][U8((a) >> 24)] ^ t[1][U8((b) >> 16)] ^ \ + t[2][U8((c) >> 8)] ^ t[3][U8((d) >> 0)]) + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/rijndael-mktab.c b/symm/rijndael-mktab.c new file mode 100644 index 0000000..4260de6 --- /dev/null +++ b/symm/rijndael-mktab.c @@ -0,0 +1,368 @@ +/* -*-c-*- + * + * Build precomputed tables for the Rijndael block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include + +/*----- Magic variables ---------------------------------------------------*/ + +static octet s[256], si[256]; +static uint32 t[4][256], ti[4][256]; +static uint32 u[4][256]; +static octet rc[32]; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mul@ --- * + * + * Arguments: @unsigned x, y@ = polynomials over %$\gf{2^8}$% + * @unsigned m@ = modulus + * + * Returns: The product of two polynomials. + * + * Use: Computes a product of polynomials, quite slowly. + */ + +static unsigned mul(unsigned x, unsigned y, unsigned m) +{ + unsigned a = 0; + unsigned i; + + for (i = 0; i < 8; i++) { + if (y & 1) + a ^= x; + y >>= 1; + x <<= 1; + if (x & 0x100) + x ^= m; + } + + return (a); +} + +/* --- @sbox@ --- * + * + * Build the S-box. + * + * This is built from inversion in the multiplicative group of + * %$\gf{2^8}[x]/(p(x))$%, where %$p(x) = x^8 + x^4 + x^3 + x + 1$%, followed + * by an affine transformation treating inputs as vectors over %$\gf{2}$%. + * The result is a horrible function. + * + * The inversion is done slightly sneakily, by building log and antilog + * tables. Let %$a$% be an element of the finite field. If the inverse of + * %$a$% is %$a^{-1}$%, then %$\log a a^{-1} = 0$%. Hence + * %$\log a = -\log a^{-1}$%. This saves fiddling about with Euclidean + * algorithm. + */ + +#define S_MOD 0x11b + +static void sbox(void) +{ + octet log[256], alog[256]; + unsigned x; + unsigned i; + unsigned g; + + /* --- Find a suitable generator, and build log tables --- */ + + log[0] = 0; + for (g = 2; g < 256; g++) { + x = 1; + for (i = 0; i < 256; i++) { + log[x] = i; + alog[i] = x; + x = mul(x, g, S_MOD); + if (x == 1 && i != 254) + goto again; + } + goto done; + again:; + } + fprintf(stderr, "couldn't find generator\n"); + exit(EXIT_FAILURE); +done:; + + /* --- Now grind through and do the affine transform --- * + * + * The matrix multiply is an AND and a parity op. The add is an XOR. + */ + + for (i = 0; i < 256; i++) { + unsigned j; + unsigned m = 0xf8; + unsigned v = i ? alog[255 - log[i]] : 0; + + assert(i == 0 || mul(i, v, S_MOD) == 1); + + x = 0; + for (j = 0; j < 8; j++) { + unsigned r; + r = v & m; + r = (r >> 4) ^ r; + r = (r >> 2) ^ r; + r = (r >> 1) ^ r; + x = (x << 1) | (r & 1); + m = ROR8(m, 1); + } + x ^= 0x63; + s[i] = x; + si[x] = i; + } +} + +/* --- @tbox@ --- * + * + * Construct the t tables for doing the round function efficiently. + */ + +static void tbox(void) +{ + unsigned i; + + for (i = 0; i < 256; i++) { + uint32 a, b, c, d; + uint32 w; + + /* --- Build a forwards t-box entry --- */ + + a = s[i]; + b = a << 1; if (b & 0x100) b ^= S_MOD; + c = a ^ b; + w = (c << 0) | (a << 8) | (a << 16) | (b << 24); + t[0][i] = w; + t[1][i] = ROR32(w, 8); + t[2][i] = ROR32(w, 16); + t[3][i] = ROR32(w, 24); + + /* --- Build a backwards t-box entry --- */ + + a = mul(si[i], 0x0e, S_MOD); + b = mul(si[i], 0x09, S_MOD); + c = mul(si[i], 0x0d, S_MOD); + d = mul(si[i], 0x0b, S_MOD); + w = (d << 0) | (c << 8) | (b << 16) | (a << 24); + ti[0][i] = w; + ti[1][i] = ROR32(w, 8); + ti[2][i] = ROR32(w, 16); + ti[3][i] = ROR32(w, 24); + } +} + +/* --- @ubox@ --- * + * + * Construct the tables for performing the decryption key schedule. + */ + +static void ubox(void) +{ + unsigned i; + + for (i = 0; i < 256; i++) { + uint32 a, b, c, d; + uint32 w; + a = mul(i, 0x0e, S_MOD); + b = mul(i, 0x09, S_MOD); + c = mul(i, 0x0d, S_MOD); + d = mul(i, 0x0b, S_MOD); + w = (d << 0) | (c << 8) | (b << 16) | (a << 24); + u[0][i] = w; + u[1][i] = ROR32(w, 8); + u[2][i] = ROR32(w, 16); + u[3][i] = ROR32(w, 24); + } +} + +/* --- Round constants --- */ + +static void rcon(void) +{ + unsigned r = 1; + int i; + + for (i = 0; i < sizeof(rc); i++) { + rc[i] = r; + r <<= 1; + if (r & 0x100) + r ^= S_MOD; + } +} + +/* --- @main@ --- */ + +int main(void) +{ + int i, j; + + puts("\ +/* -*-c-*-\n\ + *\n\ + * Rijndael tables [generated]\n\ + */\n\ +\n\ +#ifndef CATACOMB_RIJNDAEL_TAB_H\n\ +#define CATACOMB_RIJNDAEL_TAB_H\n\ +"); + + /* --- Write out the S-box --- */ + + sbox(); + fputs("\ +/* --- The byte substitution and its inverse --- */\n\ +\n\ +#define RIJNDAEL_S { \\\n\ + ", stdout); + for (i = 0; i < 256; i++) { + printf("0x%02x", s[i]); + if (i == 255) + fputs(" \\\n}\n\n", stdout); + else if (i % 8 == 7) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + fputs("\ +#define RIJNDAEL_SI { \\\n\ + ", stdout); + for (i = 0; i < 256; i++) { + printf("0x%02x", si[i]); + if (i == 255) + fputs(" \\\n}\n\n", stdout); + else if (i % 8 == 7) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + /* --- Write out the big t tables --- */ + + tbox(); + fputs("\ +/* --- The big round tables --- */\n\ +\n\ +#define RIJNDAEL_T { \\\n\ + { ", stdout); + for (j = 0; j < 4; j++) { + for (i = 0; i < 256; i++) { + printf("0x%08lx", (unsigned long)t[j][i]); + if (i == 255) { + if (j == 3) + fputs(" } \\\n}\n\n", stdout); + else + fputs(" }, \\\n\ + \\\n\ + { ", stdout); + } else if (i % 4 == 3) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + } + + fputs("\ +#define RIJNDAEL_TI { \\\n\ + { ", stdout); + for (j = 0; j < 4; j++) { + for (i = 0; i < 256; i++) { + printf("0x%08lx", (unsigned long)ti[j][i]); + if (i == 255) { + if (j == 3) + fputs(" } \\\n}\n\n", stdout); + else + fputs(" }, \\\n\ + \\\n\ + { ", stdout); + } else if (i % 4 == 3) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + } + + /* --- Write out the big u tables --- */ + + ubox(); + fputs("\ +/* --- The decryption key schedule tables --- */\n\ +\n\ +#define RIJNDAEL_U { \\\n\ + { ", stdout); + for (j = 0; j < 4; j++) { + for (i = 0; i < 256; i++) { + printf("0x%08lx", (unsigned long)u[j][i]); + if (i == 255) { + if (j == 3) + fputs(" } \\\n}\n\n", stdout); + else + fputs(" }, \\\n\ + \\\n\ + { ", stdout); + } else if (i % 4 == 3) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + } + + /* --- Round constants --- */ + + rcon(); + fputs("\ +/* --- The round constants --- */\n\ +\n\ +#define RIJNDAEL_RCON { \\\n\ + ", stdout); + for (i = 0; i < sizeof(rc); i++) { + printf("0x%02x", rc[i]); + if (i == sizeof(rc) - 1) + fputs(" \\\n}\n\n", stdout); + else if (i % 8 == 7) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + /* --- Done --- */ + + puts("#endif"); + + if (fclose(stdout)) { + fprintf(stderr, "error writing data\n"); + exit(EXIT_FAILURE); + } + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/rijndael.c b/symm/rijndael.c new file mode 100644 index 0000000..9d8e739 --- /dev/null +++ b/symm/rijndael.c @@ -0,0 +1,158 @@ +/* -*-c-*- + * + * The Rijndael block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "rijndael.h" +#include "rijndael-base.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rijndael_init@ --- * + * + * Arguments: @rijndael_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes a Rijndael context with a particular key. This + * implementation of Rijndael doesn't impose any particular + * limits on the key size except that it must be multiple of 4 + * bytes long. 256 bits seems sensible, though. + */ + +void rijndael_init(rijndael_ctx *k, const void *buf, size_t sz) +{ + rijndael_setup(k, RIJNDAEL_BLKSZ / 4, buf, sz); +} + +/* --- @rijndael_eblk@, @rijndael_dblk@ --- * + * + * Arguments: @const rijndael_ctx *k@ = pointer to Rijndael context + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +#define DO(what, t, aa, bb, cc, dd, a, b, c, d, w) do { \ + aa = what(t, a, b, c, d) ^ *w++; \ + bb = what(t, b, c, d, a) ^ *w++; \ + cc = what(t, c, d, a, b) ^ *w++; \ + dd = what(t, d, a, b, c) ^ *w++; \ +} while (0) + +#define UNDO(what, t, aa, bb, cc, dd, a, b, c, d, w) do { \ + aa = what(t, a, d, c, b) ^ *w++; \ + bb = what(t, b, a, d, c) ^ *w++; \ + cc = what(t, c, b, a, d) ^ *w++; \ + dd = what(t, d, c, b, a) ^ *w++; \ +} while (0) + +void rijndael_eblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst) +{ + uint32 a = s[0], b = s[1], c = s[2], d = s[3]; + uint32 aa, bb, cc, dd; + const uint32 *w = k->w; + + a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; + aa = a; bb = b; cc = c; dd = d; + + switch (k->nr) { + case 14: + DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); + case 13: + DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); + case 12: + DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); + case 11: + DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); + case 10: + default: + DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); + DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); + DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); + DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); + DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); + DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); + DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); + DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); + DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); + } + DO(SUB, S, a, b, c, d, aa, bb, cc, dd, w); + + dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; +} + +void rijndael_dblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst) +{ + uint32 a = s[0], b = s[1], c = s[2], d = s[3]; + uint32 aa, bb, cc, dd; + const uint32 *w = k->wi; + + a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; + aa = a; bb = b; cc = c; dd = d; + + switch (k->nr) { + case 14: + UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); + case 13: + UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); + case 12: + UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); + case 11: + UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); + case 10: + default: + UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); + UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); + UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); + UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); + UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); + UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); + UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); + UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); + UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); + } + UNDO(SUB, SI, a, b, c, d, aa, bb, cc, dd, w); + + dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; +} + +BLKC_TEST(RIJNDAEL, rijndael) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/rijndael.h b/symm/rijndael.h new file mode 100644 index 0000000..7b93440 --- /dev/null +++ b/symm/rijndael.h @@ -0,0 +1,126 @@ +/* -*-c-*- + * + * The Rijndael block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the Rijndael block cipher --------------------------------* + * + * Invented by Joan Daemen and Vincent Rijmen, Rijndael is a fast, elegant + * and relatively simple 128-bit block cipher. It was chosen by NIST to be + * the new Advanced Encryption Standard (AES) algorithm. + * + * Rijnadel appears to have a low security margin. I recommend waiting + * before using Rijndael for any sensitive applications. + */ + +#ifndef CATACOMB_RIJNDAEL_H +#define CATACOMB_RIJNDAEL_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magical numbers ---------------------------------------------------*/ + +#define RIJNDAEL_BLKSZ 16 +#define RIJNDAEL_KEYSZ 32 +#define RIJNDAEL_CLASS (N, B, 128) + +extern const octet rijndael_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +#define RIJNDAEL_MAXROUNDS 16 +#define RIJNDAEL_KWORDS ((RIJNDAEL_MAXROUNDS + 1) * 8) + +typedef struct rijndael_ctx { + unsigned nr; + uint32 w[RIJNDAEL_KWORDS]; + uint32 wi[RIJNDAEL_KWORDS]; +} rijndael_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @rijndael_setup@ --- * + * + * Arguments: @rijndael_ctx *k@ = pointer to context to initialize + * @unsigned nb@ = number of words in the block + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Low-level key-scheduling. Don't call this directly. + */ + +extern void rijndael_setup(rijndael_ctx */*k*/, unsigned /*nb*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @rijndael_init@ --- * + * + * Arguments: @rijndael_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes a Rijndael context with a particular key. This + * implementation of Rijndael doesn't impose any particular + * limits on the key size except that it must be multiple of 4 + * bytes long. 256 bits seems sensible, though. + */ + +extern void rijndael_init(rijndael_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @rijndael_eblk@, @rijndael_dblk@ --- * + * + * Arguments: @const rijndael_ctx *k@ = pointer to Rijndael context + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void rijndael_eblk(const rijndael_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); +extern void rijndael_dblk(const rijndael_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/rijndael192.c b/symm/rijndael192.c new file mode 100644 index 0000000..424f8f9 --- /dev/null +++ b/symm/rijndael192.c @@ -0,0 +1,159 @@ +/* -*-c-*- + * + * The Rijndael block cipher, 192-bit version + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "rijndael.h" +#include "rijndael192.h" +#include "rijndael-base.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rijndael192_init@ --- * + * + * Arguments: @rijndael_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes a Rijndael context with a particular key. This + * implementation of Rijndael doesn't impose any particular + * limits on the key size except that it must be multiple of 4 + * bytes long. 256 bits seems sensible, though. + */ + +void rijndael192_init(rijndael_ctx *k, const void *buf, size_t sz) +{ + rijndael_setup(k, RIJNDAEL192_BLKSZ / 4, buf, sz); +} + +/* --- @rijndael192_eblk@, @rijndael192_dblk@ --- * + * + * Arguments: @const rijndael_ctx *k@ = pointer to Rijndael context + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +#define DO(what, t, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w) do { \ + aa = what(t, a, b, c, d) ^ *w++; \ + bb = what(t, b, c, d, e) ^ *w++; \ + cc = what(t, c, d, e, f) ^ *w++; \ + dd = what(t, d, e, f, a) ^ *w++; \ + ee = what(t, e, f, a, b) ^ *w++; \ + ff = what(t, f, a, b, c) ^ *w++; \ +} while (0) + +#define UNDO(what, t, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w) do { \ + aa = what(t, a, f, e, d) ^ *w++; \ + bb = what(t, b, a, f, e) ^ *w++; \ + cc = what(t, c, b, a, f) ^ *w++; \ + dd = what(t, d, c, b, a) ^ *w++; \ + ee = what(t, e, d, c, b) ^ *w++; \ + ff = what(t, f, e, d, c) ^ *w++; \ +} while (0) + +void rijndael192_eblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst) +{ + uint32 a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5]; + uint32 aa, bb, cc, dd, ee, ff; + const uint32 *w = k->w; + + a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; e ^= *w++; f ^= *w++; + aa = a; bb = b; cc = c; dd = d; ee = e; ff = f; + + switch (k->nr) { + case 14: + DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + case 13: + DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + case 12: + default: + DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + } + DO(SUB, S, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + + dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; dst[4] = e; dst[5] = f; +} + +void rijndael192_dblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst) +{ + uint32 a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5]; + uint32 aa, bb, cc, dd, ee, ff; + const uint32 *w = k->wi; + + a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; e ^= *w++; f ^= *w++; + aa = a; bb = b; cc = c; dd = d; ee = e; ff = f; + + switch (k->nr) { + case 14: + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + case 13: + UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + case 12: + default: + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w); + } + UNDO(SUB, SI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w); + + dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; dst[4] = e; dst[5] = f; +} + +BLKC_TEST(RIJNDAEL192, rijndael192) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/rijndael192.h b/symm/rijndael192.h new file mode 100644 index 0000000..b9357cd --- /dev/null +++ b/symm/rijndael192.h @@ -0,0 +1,94 @@ +/* -*-c-*- + * + * The Rijndael block cipher, 192-bit version + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_RIJNDAEL192_H +#define CATACOMB_RIJNDAEL192_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_RIJNDAEL_H +# include "rijndael.h" +#endif + +/*----- Magical numbers ---------------------------------------------------*/ + +#define RIJNDAEL192_BLKSZ 24 +#define RIJNDAEL192_KEYSZ 32 +#define RIJNDAEL192_CLASS (N, B, 192) + +#define rijndael192_keysz rijndael_keysz + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct rijndael_ctx rijndael192_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @rijndael192_init@ --- * + * + * Arguments: @rijndael_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes a Rijndael context with a particular key. This + * implementation of Rijndael doesn't impose any particular + * limits on the key size except that it must be multiple of 4 + * bytes long. 256 bits seems sensible, though. + */ + +extern void rijndael192_init(rijndael_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @rijndael_eblk@, @rijndael_dblk@ --- * + * + * Arguments: @const rijndael_ctx *k@ = pointer to Rijndael context + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void rijndael192_eblk(const rijndael_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); +extern void rijndael192_dblk(const rijndael_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/rijndael256.c b/symm/rijndael256.c new file mode 100644 index 0000000..9fb7298 --- /dev/null +++ b/symm/rijndael256.c @@ -0,0 +1,159 @@ +/* -*-c-*- + * + * The Rijndael block cipher, 256-bit version + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "rijndael.h" +#include "rijndael256.h" +#include "rijndael-base.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rijndael256_init@ --- * + * + * Arguments: @rijndael_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes a Rijndael context with a particular key. This + * implementation of Rijndael doesn't impose any particular + * limits on the key size except that it must be multiple of 4 + * bytes long. 256 bits seems sensible, though. + */ + +void rijndael256_init(rijndael_ctx *k, const void *buf, size_t sz) +{ + rijndael_setup(k, RIJNDAEL256_BLKSZ / 4, buf, sz); +} + +/* --- @rijndael256_eblk@, @rijndael256_dblk@ --- * + * + * Arguments: @const rijndael_ctx *k@ = pointer to Rijndael context + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +#define DO(what, t, \ + aa, bb, cc, dd, ee, ff, gg, hh, \ + a, b, c, d, e, f, g, h, w) do { \ + aa = what(t, a, b, d, e) ^ *w++; \ + bb = what(t, b, c, e, f) ^ *w++; \ + cc = what(t, c, d, f, g) ^ *w++; \ + dd = what(t, d, e, g, h) ^ *w++; \ + ee = what(t, e, f, h, a) ^ *w++; \ + ff = what(t, f, g, a, b) ^ *w++; \ + gg = what(t, g, h, b, c) ^ *w++; \ + hh = what(t, h, a, c, d) ^ *w++; \ +} while (0) + +#define UNDO(what, t, \ + aa, bb, cc, dd, ee, ff, gg, hh, \ + a, b, c, d, e, f, g, h, w) do { \ + aa = what(t, a, h, f, e) ^ *w++; \ + bb = what(t, b, a, g, f) ^ *w++; \ + cc = what(t, c, b, h, g) ^ *w++; \ + dd = what(t, d, c, a, h) ^ *w++; \ + ee = what(t, e, d, b, a) ^ *w++; \ + ff = what(t, f, e, c, b) ^ *w++; \ + gg = what(t, g, f, d, c) ^ *w++; \ + hh = what(t, h, g, e, d) ^ *w++; \ +} while (0) + +void rijndael256_eblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst) +{ + uint32 a = s[0], b = s[1], c = s[2], d = s[3]; + uint32 e = s[4], f = s[5], g = s[6], h = s[7]; + uint32 aa, bb, cc, dd, ee, ff, gg, hh; + const uint32 *w = k->w; + + a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; + e ^= *w++; f ^= *w++; g ^= *w++; h ^= *w++; + + DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + DO(SUB, S, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + + dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; + dst[4] = e; dst[5] = f; dst[6] = g; dst[7] = h; +} + +void rijndael256_dblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst) +{ + uint32 a = s[0], b = s[1], c = s[2], d = s[3]; + uint32 e = s[4], f = s[5], g = s[6], h = s[7]; + uint32 aa, bb, cc, dd, ee, ff, gg, hh; + const uint32 *w = k->wi; + + a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; + e ^= *w++; f ^= *w++; g ^= *w++; h ^= *w++; + + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w); + UNDO(SUB, SI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w); + + dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; + dst[4] = e; dst[5] = f; dst[6] = g; dst[7] = h; +} + +BLKC_TEST(RIJNDAEL256, rijndael256) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/rijndael256.h b/symm/rijndael256.h new file mode 100644 index 0000000..fce2d0e --- /dev/null +++ b/symm/rijndael256.h @@ -0,0 +1,94 @@ +/* -*-c-*- + * + * The Rijndael block cipher, 256-bit version + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_RIJNDAEL256_H +#define CATACOMB_RIJNDAEL256_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_RIJNDAEL_H +# include "rijndael.h" +#endif + +/*----- Magical numbers ---------------------------------------------------*/ + +#define RIJNDAEL256_BLKSZ 32 +#define RIJNDAEL256_KEYSZ 32 +#define RIJNDAEL256_CLASS (N, B, 256) + +#define rijndael256_keysz rijndael_keysz + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct rijndael_ctx rijndael256_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @rijndael256_init@ --- * + * + * Arguments: @rijndael_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes a Rijndael context with a particular key. This + * implementation of Rijndael doesn't impose any particular + * limits on the key size except that it must be multiple of 4 + * bytes long. 256 bits seems sensible, though. + */ + +extern void rijndael256_init(rijndael_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @rijndael_eblk@, @rijndael_dblk@ --- * + * + * Arguments: @const rijndael_ctx *k@ = pointer to Rijndael context + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void rijndael256_eblk(const rijndael_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); +extern void rijndael256_dblk(const rijndael_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/rmd128.c b/symm/rmd128.c new file mode 100644 index 0000000..85b6c33 --- /dev/null +++ b/symm/rmd128.c @@ -0,0 +1,356 @@ +/* -*-c-*- + * + * The RIPEMD-128 message digest function + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "rmd128.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rmd128_compress@ --- * + * + * Arguments: @rmd128_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: RIPEMD-128 compression function. + */ + +void rmd128_compress(rmd128_ctx *ctx, const void *sbuf) +{ + uint32 a, b, c, d; + uint32 A, B, C, D; + uint32 buf[16]; + + /* --- Fetch the chaining variables --- */ + + a = A = ctx->a; + b = B = ctx->b; + c = C = ctx->c; + d = D = ctx->d; + + /* --- Fetch the buffer contents --- */ + + { + int i; + const octet *p; + + for (i = 0, p = sbuf; i < 16; i++, p += 4) + buf[i] = LOAD32_L(p); + } + + /* --- Definitions for round functions --- */ + +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) + +#define T(w, x, y, z, i, r, f, k) do { \ + uint32 _t = w + f(x, y, z) + buf[i] + k; \ + w = ROL32(_t, r); \ +} while (0) + +#define F1(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000) +#define G1(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x5a827999) +#define H1(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x6ed9eba1) +#define I1(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x8f1bbcdc) + +#define F2(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x50a28be6) +#define G2(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x5c4dd124) +#define H2(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x6d703ef3) +#define I2(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000) + + /* --- First the left hand side --- */ + + F1(a, b, c, d, 0, 11); + F1(d, a, b, c, 1, 14); + F1(c, d, a, b, 2, 15); + F1(b, c, d, a, 3, 12); + F1(a, b, c, d, 4, 5); + F1(d, a, b, c, 5, 8); + F1(c, d, a, b, 6, 7); + F1(b, c, d, a, 7, 9); + F1(a, b, c, d, 8, 11); + F1(d, a, b, c, 9, 13); + F1(c, d, a, b, 10, 14); + F1(b, c, d, a, 11, 15); + F1(a, b, c, d, 12, 6); + F1(d, a, b, c, 13, 7); + F1(c, d, a, b, 14, 9); + F1(b, c, d, a, 15, 8); + + G1(a, b, c, d, 7, 7); + G1(d, a, b, c, 4, 6); + G1(c, d, a, b, 13, 8); + G1(b, c, d, a, 1, 13); + G1(a, b, c, d, 10, 11); + G1(d, a, b, c, 6, 9); + G1(c, d, a, b, 15, 7); + G1(b, c, d, a, 3, 15); + G1(a, b, c, d, 12, 7); + G1(d, a, b, c, 0, 12); + G1(c, d, a, b, 9, 15); + G1(b, c, d, a, 5, 9); + G1(a, b, c, d, 2, 11); + G1(d, a, b, c, 14, 7); + G1(c, d, a, b, 11, 13); + G1(b, c, d, a, 8, 12); + + H1(a, b, c, d, 3, 11); + H1(d, a, b, c, 10, 13); + H1(c, d, a, b, 14, 6); + H1(b, c, d, a, 4, 7); + H1(a, b, c, d, 9, 14); + H1(d, a, b, c, 15, 9); + H1(c, d, a, b, 8, 13); + H1(b, c, d, a, 1, 15); + H1(a, b, c, d, 2, 14); + H1(d, a, b, c, 7, 8); + H1(c, d, a, b, 0, 13); + H1(b, c, d, a, 6, 6); + H1(a, b, c, d, 13, 5); + H1(d, a, b, c, 11, 12); + H1(c, d, a, b, 5, 7); + H1(b, c, d, a, 12, 5); + + I1(a, b, c, d, 1, 11); + I1(d, a, b, c, 9, 12); + I1(c, d, a, b, 11, 14); + I1(b, c, d, a, 10, 15); + I1(a, b, c, d, 0, 14); + I1(d, a, b, c, 8, 15); + I1(c, d, a, b, 12, 9); + I1(b, c, d, a, 4, 8); + I1(a, b, c, d, 13, 9); + I1(d, a, b, c, 3, 14); + I1(c, d, a, b, 7, 5); + I1(b, c, d, a, 15, 6); + I1(a, b, c, d, 14, 8); + I1(d, a, b, c, 5, 6); + I1(c, d, a, b, 6, 5); + I1(b, c, d, a, 2, 12); + + /* --- And then the right hand side --- */ + + F2(A, B, C, D, 5, 8); + F2(D, A, B, C, 14, 9); + F2(C, D, A, B, 7, 9); + F2(B, C, D, A, 0, 11); + F2(A, B, C, D, 9, 13); + F2(D, A, B, C, 2, 15); + F2(C, D, A, B, 11, 15); + F2(B, C, D, A, 4, 5); + F2(A, B, C, D, 13, 7); + F2(D, A, B, C, 6, 7); + F2(C, D, A, B, 15, 8); + F2(B, C, D, A, 8, 11); + F2(A, B, C, D, 1, 14); + F2(D, A, B, C, 10, 14); + F2(C, D, A, B, 3, 12); + F2(B, C, D, A, 12, 6); + + G2(A, B, C, D, 6, 9); + G2(D, A, B, C, 11, 13); + G2(C, D, A, B, 3, 15); + G2(B, C, D, A, 7, 7); + G2(A, B, C, D, 0, 12); + G2(D, A, B, C, 13, 8); + G2(C, D, A, B, 5, 9); + G2(B, C, D, A, 10, 11); + G2(A, B, C, D, 14, 7); + G2(D, A, B, C, 15, 7); + G2(C, D, A, B, 8, 12); + G2(B, C, D, A, 12, 7); + G2(A, B, C, D, 4, 6); + G2(D, A, B, C, 9, 15); + G2(C, D, A, B, 1, 13); + G2(B, C, D, A, 2, 11); + + H2(A, B, C, D, 15, 9); + H2(D, A, B, C, 5, 7); + H2(C, D, A, B, 1, 15); + H2(B, C, D, A, 3, 11); + H2(A, B, C, D, 7, 8); + H2(D, A, B, C, 14, 6); + H2(C, D, A, B, 6, 6); + H2(B, C, D, A, 9, 14); + H2(A, B, C, D, 11, 12); + H2(D, A, B, C, 8, 13); + H2(C, D, A, B, 12, 5); + H2(B, C, D, A, 2, 14); + H2(A, B, C, D, 10, 13); + H2(D, A, B, C, 0, 13); + H2(C, D, A, B, 4, 7); + H2(B, C, D, A, 13, 5); + + I2(A, B, C, D, 8, 15); + I2(D, A, B, C, 6, 5); + I2(C, D, A, B, 4, 8); + I2(B, C, D, A, 1, 11); + I2(A, B, C, D, 3, 14); + I2(D, A, B, C, 11, 14); + I2(C, D, A, B, 15, 6); + I2(B, C, D, A, 0, 14); + I2(A, B, C, D, 5, 6); + I2(D, A, B, C, 12, 9); + I2(C, D, A, B, 2, 12); + I2(B, C, D, A, 13, 9); + I2(A, B, C, D, 9, 12); + I2(D, A, B, C, 7, 5); + I2(C, D, A, B, 10, 15); + I2(B, C, D, A, 14, 8); + + /* --- Recombine the two halves --- */ + + { + uint32 + tmp = ctx->b + c + D; + ctx->b = ctx->c + d + A; + ctx->c = ctx->d + a + B; + ctx->d = ctx->a + b + C; + ctx->a = tmp; + } +} + +/* --- @rmd128_init@ --- * + * + * Arguments: @rmd128_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void rmd128_init(rmd128_ctx *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + ctx->off = 0; + ctx->nl = ctx->nh = 0; +} + +/* --- @rmd128_set@ --- * + * + * Arguments: @rmd128_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void rmd128_set(rmd128_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + ctx->a = LOAD32_L(p + 0); + ctx->b = LOAD32_L(p + 4); + ctx->c = LOAD32_L(p + 8); + ctx->d = LOAD32_L(p + 12); + ctx->off = 0; + ctx->nl = U32(count); + ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); +} + +/* --- @rmd128_hash@ --- * + * + * Arguments: @rmd128_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void rmd128_hash(rmd128_ctx *ctx, const void *buf, size_t sz) +{ + HASH_BUFFER(RMD128, rmd128, ctx, buf, sz); +} + +/* --- @rmd128_done@ --- * + * + * Arguments: @rmd128_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +void rmd128_done(rmd128_ctx *ctx, void *hash) +{ + octet *p = hash; + HASH_MD5STRENGTH(RMD128, rmd128, ctx); + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); +} + +/* --- @rmd128_state@ --- * + * + * Arguments: @rmd128_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @rmd128_set@. + */ + +unsigned long rmd128_state(rmd128_ctx *ctx, void *state) +{ + octet *p = state; + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); + return (ctx->nl | ((ctx->nh << 16) << 16)); +} + +/* --- Generic interface --- */ + +GHASH_DEF(RMD128, rmd128) + +/* --- Test code --- */ + +HASH_TEST(RMD128, rmd128) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/rmd128.h b/symm/rmd128.h new file mode 100644 index 0000000..c139561 --- /dev/null +++ b/symm/rmd128.h @@ -0,0 +1,156 @@ +/* -*-c-*- + * + * The RIPEMD-128 message digest function + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the RIPEMD-128 hash function -----------------------------* + * + * RIPEMD-128 was invented by Hans Dobbertin, Antoon Bosselaers and Bart + * Preneel, as a drop-in replacement for MD5 (with the same sized output). + * It's a cut-down version of RIPEMD-160, which should be used in preference. + */ + +#ifndef CATACOMB_RMD128_H +#define CATACOMB_RMD128_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define RMD128_BUFSZ 64 +#define RMD128_HASHSZ 16 +#define RMD128_STATESZ 16 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct rmd128_ctx { + uint32 a, b, c, d; /* Chaining variables */ + uint32 nl, nh; /* Byte count so far */ + unsigned off; /* Offset into buffer */ + octet buf[RMD128_BUFSZ]; /* Accumulation buffer */ +} rmd128_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @rmd128_compress@ --- * + * + * Arguments: @rmd128_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: RIPEMD-128 compression function. + */ + +extern void rmd128_compress(rmd128_ctx */*ctx*/, const void */*sbuf*/); + +/* --- @rmd128_init@ --- * + * + * Arguments: @rmd128_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void rmd128_init(rmd128_ctx */*ctx*/); + +/* --- @rmd128_set@ --- * + * + * Arguments: @rmd128_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void rmd128_set(rmd128_ctx */*ctx*/, + const void */*buf*/, unsigned long /*count*/); + +/* --- @rmd128_hash@ --- * + * + * Arguments: @rmd128_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void rmd128_hash(rmd128_ctx */*ctx*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @rmd128_done@ --- * + * + * Arguments: @rmd128_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void rmd128_done(rmd128_ctx */*ctx*/, void */*hash*/); + +/* --- @rmd128_state@ --- * + * + * Arguments: @rmd128_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @rmd128_set@. + */ + +extern unsigned long rmd128_state(rmd128_ctx */*ctx*/, void */*state*/); + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash rmd128; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/rmd160.c b/symm/rmd160.c new file mode 100644 index 0000000..bc7e867 --- /dev/null +++ b/symm/rmd160.c @@ -0,0 +1,399 @@ +/* -*-c-*- + * + * The RIPEMD-160 message digest function + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "rmd160.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rmd160_compress@ --- * + * + * Arguments: @rmd160_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: RIPEMD-160 compression function. + */ + +void rmd160_compress(rmd160_ctx *ctx, const void *sbuf) +{ + uint32 a, b, c, d, e; + uint32 A, B, C, D, E; + uint32 buf[16]; + + /* --- Fetch the chaining variables --- */ + + a = A = ctx->a; + b = B = ctx->b; + c = C = ctx->c; + d = D = ctx->d; + e = E = ctx->e; + + /* --- Fetch the buffer contents --- */ + + { + int i; + const octet *p; + + for (i = 0, p = sbuf; i < 16; i++, p += 4) + buf[i] = LOAD32_L(p); + } + + /* --- Definitions for round functions --- */ + +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define J(x, y, z) ((x) ^ ((y) | ~(z))) + +#define T(v, w, x, y, z, i, r, f, k) do { \ + uint32 _t = v + f(w, x, y) + buf[i] + k; \ + v = ROL32(_t, r) + z; x = ROL32(x, 10); \ +} while (0) + +#define F1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000) +#define G1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x5a827999) +#define H1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6ed9eba1) +#define I1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x8f1bbcdc) +#define J1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0xa953fd4e) + +#define F2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0x50a28be6) +#define G2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x5c4dd124) +#define H2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6d703ef3) +#define I2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x7a6d76e9) +#define J2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000) + + /* --- First the left hand side --- */ + + F1(a, b, c, d, e, 0, 11); + F1(e, a, b, c, d, 1, 14); + F1(d, e, a, b, c, 2, 15); + F1(c, d, e, a, b, 3, 12); + F1(b, c, d, e, a, 4, 5); + F1(a, b, c, d, e, 5, 8); + F1(e, a, b, c, d, 6, 7); + F1(d, e, a, b, c, 7, 9); + F1(c, d, e, a, b, 8, 11); + F1(b, c, d, e, a, 9, 13); + F1(a, b, c, d, e, 10, 14); + F1(e, a, b, c, d, 11, 15); + F1(d, e, a, b, c, 12, 6); + F1(c, d, e, a, b, 13, 7); + F1(b, c, d, e, a, 14, 9); + F1(a, b, c, d, e, 15, 8); + + G1(e, a, b, c, d, 7, 7); + G1(d, e, a, b, c, 4, 6); + G1(c, d, e, a, b, 13, 8); + G1(b, c, d, e, a, 1, 13); + G1(a, b, c, d, e, 10, 11); + G1(e, a, b, c, d, 6, 9); + G1(d, e, a, b, c, 15, 7); + G1(c, d, e, a, b, 3, 15); + G1(b, c, d, e, a, 12, 7); + G1(a, b, c, d, e, 0, 12); + G1(e, a, b, c, d, 9, 15); + G1(d, e, a, b, c, 5, 9); + G1(c, d, e, a, b, 2, 11); + G1(b, c, d, e, a, 14, 7); + G1(a, b, c, d, e, 11, 13); + G1(e, a, b, c, d, 8, 12); + + H1(d, e, a, b, c, 3, 11); + H1(c, d, e, a, b, 10, 13); + H1(b, c, d, e, a, 14, 6); + H1(a, b, c, d, e, 4, 7); + H1(e, a, b, c, d, 9, 14); + H1(d, e, a, b, c, 15, 9); + H1(c, d, e, a, b, 8, 13); + H1(b, c, d, e, a, 1, 15); + H1(a, b, c, d, e, 2, 14); + H1(e, a, b, c, d, 7, 8); + H1(d, e, a, b, c, 0, 13); + H1(c, d, e, a, b, 6, 6); + H1(b, c, d, e, a, 13, 5); + H1(a, b, c, d, e, 11, 12); + H1(e, a, b, c, d, 5, 7); + H1(d, e, a, b, c, 12, 5); + + I1(c, d, e, a, b, 1, 11); + I1(b, c, d, e, a, 9, 12); + I1(a, b, c, d, e, 11, 14); + I1(e, a, b, c, d, 10, 15); + I1(d, e, a, b, c, 0, 14); + I1(c, d, e, a, b, 8, 15); + I1(b, c, d, e, a, 12, 9); + I1(a, b, c, d, e, 4, 8); + I1(e, a, b, c, d, 13, 9); + I1(d, e, a, b, c, 3, 14); + I1(c, d, e, a, b, 7, 5); + I1(b, c, d, e, a, 15, 6); + I1(a, b, c, d, e, 14, 8); + I1(e, a, b, c, d, 5, 6); + I1(d, e, a, b, c, 6, 5); + I1(c, d, e, a, b, 2, 12); + + J1(b, c, d, e, a, 4, 9); + J1(a, b, c, d, e, 0, 15); + J1(e, a, b, c, d, 5, 5); + J1(d, e, a, b, c, 9, 11); + J1(c, d, e, a, b, 7, 6); + J1(b, c, d, e, a, 12, 8); + J1(a, b, c, d, e, 2, 13); + J1(e, a, b, c, d, 10, 12); + J1(d, e, a, b, c, 14, 5); + J1(c, d, e, a, b, 1, 12); + J1(b, c, d, e, a, 3, 13); + J1(a, b, c, d, e, 8, 14); + J1(e, a, b, c, d, 11, 11); + J1(d, e, a, b, c, 6, 8); + J1(c, d, e, a, b, 15, 5); + J1(b, c, d, e, a, 13, 6); + + /* --- And then the right hand side --- */ + + F2(A, B, C, D, E, 5, 8); + F2(E, A, B, C, D, 14, 9); + F2(D, E, A, B, C, 7, 9); + F2(C, D, E, A, B, 0, 11); + F2(B, C, D, E, A, 9, 13); + F2(A, B, C, D, E, 2, 15); + F2(E, A, B, C, D, 11, 15); + F2(D, E, A, B, C, 4, 5); + F2(C, D, E, A, B, 13, 7); + F2(B, C, D, E, A, 6, 7); + F2(A, B, C, D, E, 15, 8); + F2(E, A, B, C, D, 8, 11); + F2(D, E, A, B, C, 1, 14); + F2(C, D, E, A, B, 10, 14); + F2(B, C, D, E, A, 3, 12); + F2(A, B, C, D, E, 12, 6); + + G2(E, A, B, C, D, 6, 9); + G2(D, E, A, B, C, 11, 13); + G2(C, D, E, A, B, 3, 15); + G2(B, C, D, E, A, 7, 7); + G2(A, B, C, D, E, 0, 12); + G2(E, A, B, C, D, 13, 8); + G2(D, E, A, B, C, 5, 9); + G2(C, D, E, A, B, 10, 11); + G2(B, C, D, E, A, 14, 7); + G2(A, B, C, D, E, 15, 7); + G2(E, A, B, C, D, 8, 12); + G2(D, E, A, B, C, 12, 7); + G2(C, D, E, A, B, 4, 6); + G2(B, C, D, E, A, 9, 15); + G2(A, B, C, D, E, 1, 13); + G2(E, A, B, C, D, 2, 11); + + H2(D, E, A, B, C, 15, 9); + H2(C, D, E, A, B, 5, 7); + H2(B, C, D, E, A, 1, 15); + H2(A, B, C, D, E, 3, 11); + H2(E, A, B, C, D, 7, 8); + H2(D, E, A, B, C, 14, 6); + H2(C, D, E, A, B, 6, 6); + H2(B, C, D, E, A, 9, 14); + H2(A, B, C, D, E, 11, 12); + H2(E, A, B, C, D, 8, 13); + H2(D, E, A, B, C, 12, 5); + H2(C, D, E, A, B, 2, 14); + H2(B, C, D, E, A, 10, 13); + H2(A, B, C, D, E, 0, 13); + H2(E, A, B, C, D, 4, 7); + H2(D, E, A, B, C, 13, 5); + + I2(C, D, E, A, B, 8, 15); + I2(B, C, D, E, A, 6, 5); + I2(A, B, C, D, E, 4, 8); + I2(E, A, B, C, D, 1, 11); + I2(D, E, A, B, C, 3, 14); + I2(C, D, E, A, B, 11, 14); + I2(B, C, D, E, A, 15, 6); + I2(A, B, C, D, E, 0, 14); + I2(E, A, B, C, D, 5, 6); + I2(D, E, A, B, C, 12, 9); + I2(C, D, E, A, B, 2, 12); + I2(B, C, D, E, A, 13, 9); + I2(A, B, C, D, E, 9, 12); + I2(E, A, B, C, D, 7, 5); + I2(D, E, A, B, C, 10, 15); + I2(C, D, E, A, B, 14, 8); + + J2(B, C, D, E, A, 12, 8); + J2(A, B, C, D, E, 15, 5); + J2(E, A, B, C, D, 10, 12); + J2(D, E, A, B, C, 4, 9); + J2(C, D, E, A, B, 1, 12); + J2(B, C, D, E, A, 5, 5); + J2(A, B, C, D, E, 8, 14); + J2(E, A, B, C, D, 7, 6); + J2(D, E, A, B, C, 6, 8); + J2(C, D, E, A, B, 2, 13); + J2(B, C, D, E, A, 13, 6); + J2(A, B, C, D, E, 14, 5); + J2(E, A, B, C, D, 0, 15); + J2(D, E, A, B, C, 3, 13); + J2(C, D, E, A, B, 9, 11); + J2(B, C, D, E, A, 11, 11); + + /* --- Recombine the two halves --- */ + + { + uint32 + tmp = ctx->b + c + D; + ctx->b = ctx->c + d + E; + ctx->c = ctx->d + e + A; + ctx->d = ctx->e + a + B; + ctx->e = ctx->a + b + C; + ctx->a = tmp; + } +} + +/* --- @rmd160_init@ --- * + * + * Arguments: @rmd160_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void rmd160_init(rmd160_ctx *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + ctx->e = 0xc3d2e1f0; + ctx->off = 0; + ctx->nl = ctx->nh = 0; +} + +/* --- @rmd160_set@ --- * + * + * Arguments: @rmd160_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void rmd160_set(rmd160_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + ctx->a = LOAD32_L(p + 0); + ctx->b = LOAD32_L(p + 4); + ctx->c = LOAD32_L(p + 8); + ctx->d = LOAD32_L(p + 12); + ctx->e = LOAD32_L(p + 16); + ctx->off = 0; + ctx->nl = U32(count); + ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); +} + +/* --- @rmd160_hash@ --- * + * + * Arguments: @rmd160_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void rmd160_hash(rmd160_ctx *ctx, const void *buf, size_t sz) +{ + HASH_BUFFER(RMD160, rmd160, ctx, buf, sz); +} + +/* --- @rmd160_done@ --- * + * + * Arguments: @rmd160_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +void rmd160_done(rmd160_ctx *ctx, void *hash) +{ + octet *p = hash; + HASH_MD5STRENGTH(RMD160, rmd160, ctx); + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); + STORE32_L(p + 16, ctx->e); +} + +/* --- @rmd160_state@ --- * + * + * Arguments: @rmd160_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @rmd160_set@. + */ + +unsigned long rmd160_state(rmd160_ctx *ctx, void *state) +{ + octet *p = state; + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); + STORE32_L(p + 16, ctx->e); + return (ctx->nl | ((ctx->nh << 16) << 16)); +} + +/* --- Generic interface --- */ + +GHASH_DEF(RMD160, rmd160) + +/* --- Test code --- */ + +HASH_TEST(RMD160, rmd160) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/rmd160.h b/symm/rmd160.h new file mode 100644 index 0000000..fef7112 --- /dev/null +++ b/symm/rmd160.h @@ -0,0 +1,159 @@ +/* -*-c-*- + * + * The RIPEMD-160 message digest function + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the RIPEMD-160 hash function -----------------------------* + * + * RIPEMD-160 was invented by Hans Dobbertin, Antoon Bosselaers and Bart + * Preneel. It's a strengthened version of the original RIPEMD hash + * function, fixing a vulnerability discovered by Hans Dobbertin. The + * RIPEMD-160 design team appears well respected in the cryptographic + * community. The author finds them more plausible than SHA-1, which is the + * best alternative hash function. + */ + +#ifndef CATACOMB_RMD160_H +#define CATACOMB_RMD160_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define RMD160_BUFSZ 64 +#define RMD160_HASHSZ 20 +#define RMD160_STATESZ 20 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct rmd160_ctx { + uint32 a, b, c, d, e; /* Chaining variables */ + uint32 nl, nh; /* Byte count so far */ + unsigned off; /* Offset into buffer */ + octet buf[RMD160_BUFSZ]; /* Accumulation buffer */ +} rmd160_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @rmd160_compress@ --- * + * + * Arguments: @rmd160_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: RIPEMD-160 compression function. + */ + +extern void rmd160_compress(rmd160_ctx */*ctx*/, const void */*sbuf*/); + +/* --- @rmd160_init@ --- * + * + * Arguments: @rmd160_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void rmd160_init(rmd160_ctx */*ctx*/); + +/* --- @rmd160_set@ --- * + * + * Arguments: @rmd160_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void rmd160_set(rmd160_ctx */*ctx*/, + const void */*buf*/, unsigned long /*count*/); + +/* --- @rmd160_hash@ --- * + * + * Arguments: @rmd160_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void rmd160_hash(rmd160_ctx */*ctx*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @rmd160_done@ --- * + * + * Arguments: @rmd160_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void rmd160_done(rmd160_ctx */*ctx*/, void */*hash*/); + +/* --- @rmd160_state@ --- * + * + * Arguments: @rmd160_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @rmd160_set@. + */ + +extern unsigned long rmd160_state(rmd160_ctx */*ctx*/, void */*state*/); + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash rmd160; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/rmd256.c b/symm/rmd256.c new file mode 100644 index 0000000..99648f5 --- /dev/null +++ b/symm/rmd256.c @@ -0,0 +1,374 @@ +/* -*-c-*- + * + * The RIPEMD-256 message digest function + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "rmd256.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rmd256_compress@ --- * + * + * Arguments: @rmd256_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: RIPEMD-256 compression function. + */ + +void rmd256_compress(rmd256_ctx *ctx, const void *sbuf) +{ + uint32 a, b, c, d; + uint32 A, B, C, D; + uint32 buf[16]; + + /* --- Fetch the chaining variables --- */ + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + A = ctx->A; + B = ctx->B; + C = ctx->C; + D = ctx->D; + + /* --- Fetch the buffer contents --- */ + + { + int i; + const octet *p; + + for (i = 0, p = sbuf; i < 16; i++, p += 4) + buf[i] = LOAD32_L(p); + } + + /* --- Definitions for round functions --- */ + +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) + +#define T(w, x, y, z, i, r, f, k) do { \ + uint32 _t = w + f(x, y, z) + buf[i] + k; \ + w = ROL32(_t, r); \ +} while (0) + +#define F1(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000) +#define G1(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x5a827999) +#define H1(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x6ed9eba1) +#define I1(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x8f1bbcdc) + +#define F2(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x50a28be6) +#define G2(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x5c4dd124) +#define H2(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x6d703ef3) +#define I2(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000) + + /* --- We must do both sides together --- */ + + F1(a, b, c, d, 0, 11); + F1(d, a, b, c, 1, 14); + F1(c, d, a, b, 2, 15); + F1(b, c, d, a, 3, 12); + F1(a, b, c, d, 4, 5); + F1(d, a, b, c, 5, 8); + F1(c, d, a, b, 6, 7); + F1(b, c, d, a, 7, 9); + F1(a, b, c, d, 8, 11); + F1(d, a, b, c, 9, 13); + F1(c, d, a, b, 10, 14); + F1(b, c, d, a, 11, 15); + F1(a, b, c, d, 12, 6); + F1(d, a, b, c, 13, 7); + F1(c, d, a, b, 14, 9); + F1(b, c, d, a, 15, 8); + + F2(A, B, C, D, 5, 8); + F2(D, A, B, C, 14, 9); + F2(C, D, A, B, 7, 9); + F2(B, C, D, A, 0, 11); + F2(A, B, C, D, 9, 13); + F2(D, A, B, C, 2, 15); + F2(C, D, A, B, 11, 15); + F2(B, C, D, A, 4, 5); + F2(A, B, C, D, 13, 7); + F2(D, A, B, C, 6, 7); + F2(C, D, A, B, 15, 8); + F2(B, C, D, A, 8, 11); + F2(A, B, C, D, 1, 14); + F2(D, A, B, C, 10, 14); + F2(C, D, A, B, 3, 12); + F2(B, C, D, A, 12, 6); + + G1(A, b, c, d, 7, 7); + G1(d, A, b, c, 4, 6); + G1(c, d, A, b, 13, 8); + G1(b, c, d, A, 1, 13); + G1(A, b, c, d, 10, 11); + G1(d, A, b, c, 6, 9); + G1(c, d, A, b, 15, 7); + G1(b, c, d, A, 3, 15); + G1(A, b, c, d, 12, 7); + G1(d, A, b, c, 0, 12); + G1(c, d, A, b, 9, 15); + G1(b, c, d, A, 5, 9); + G1(A, b, c, d, 2, 11); + G1(d, A, b, c, 14, 7); + G1(c, d, A, b, 11, 13); + G1(b, c, d, A, 8, 12); + + G2(a, B, C, D, 6, 9); + G2(D, a, B, C, 11, 13); + G2(C, D, a, B, 3, 15); + G2(B, C, D, a, 7, 7); + G2(a, B, C, D, 0, 12); + G2(D, a, B, C, 13, 8); + G2(C, D, a, B, 5, 9); + G2(B, C, D, a, 10, 11); + G2(a, B, C, D, 14, 7); + G2(D, a, B, C, 15, 7); + G2(C, D, a, B, 8, 12); + G2(B, C, D, a, 12, 7); + G2(a, B, C, D, 4, 6); + G2(D, a, B, C, 9, 15); + G2(C, D, a, B, 1, 13); + G2(B, C, D, a, 2, 11); + + H1(A, B, c, d, 3, 11); + H1(d, A, B, c, 10, 13); + H1(c, d, A, B, 14, 6); + H1(B, c, d, A, 4, 7); + H1(A, B, c, d, 9, 14); + H1(d, A, B, c, 15, 9); + H1(c, d, A, B, 8, 13); + H1(B, c, d, A, 1, 15); + H1(A, B, c, d, 2, 14); + H1(d, A, B, c, 7, 8); + H1(c, d, A, B, 0, 13); + H1(B, c, d, A, 6, 6); + H1(A, B, c, d, 13, 5); + H1(d, A, B, c, 11, 12); + H1(c, d, A, B, 5, 7); + H1(B, c, d, A, 12, 5); + + H2(a, b, C, D, 15, 9); + H2(D, a, b, C, 5, 7); + H2(C, D, a, b, 1, 15); + H2(b, C, D, a, 3, 11); + H2(a, b, C, D, 7, 8); + H2(D, a, b, C, 14, 6); + H2(C, D, a, b, 6, 6); + H2(b, C, D, a, 9, 14); + H2(a, b, C, D, 11, 12); + H2(D, a, b, C, 8, 13); + H2(C, D, a, b, 12, 5); + H2(b, C, D, a, 2, 14); + H2(a, b, C, D, 10, 13); + H2(D, a, b, C, 0, 13); + H2(C, D, a, b, 4, 7); + H2(b, C, D, a, 13, 5); + + I1(A, B, C, d, 1, 11); + I1(d, A, B, C, 9, 12); + I1(C, d, A, B, 11, 14); + I1(B, C, d, A, 10, 15); + I1(A, B, C, d, 0, 14); + I1(d, A, B, C, 8, 15); + I1(C, d, A, B, 12, 9); + I1(B, C, d, A, 4, 8); + I1(A, B, C, d, 13, 9); + I1(d, A, B, C, 3, 14); + I1(C, d, A, B, 7, 5); + I1(B, C, d, A, 15, 6); + I1(A, B, C, d, 14, 8); + I1(d, A, B, C, 5, 6); + I1(C, d, A, B, 6, 5); + I1(B, C, d, A, 2, 12); + + I2(a, b, c, D, 8, 15); + I2(D, a, b, c, 6, 5); + I2(c, D, a, b, 4, 8); + I2(b, c, D, a, 1, 11); + I2(a, b, c, D, 3, 14); + I2(D, a, b, c, 11, 14); + I2(c, D, a, b, 15, 6); + I2(b, c, D, a, 0, 14); + I2(a, b, c, D, 5, 6); + I2(D, a, b, c, 12, 9); + I2(c, D, a, b, 2, 12); + I2(b, c, D, a, 13, 9); + I2(a, b, c, D, 9, 12); + I2(D, a, b, c, 7, 5); + I2(c, D, a, b, 10, 15); + I2(b, c, D, a, 14, 8); + + /* --- Recombine the two halves --- */ + + ctx->a += A; + ctx->b += B; + ctx->c += C; + ctx->d += D; + ctx->A += a; + ctx->B += b; + ctx->C += c; + ctx->D += d; +} + +/* --- @rmd256_init@ --- * + * + * Arguments: @rmd256_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void rmd256_init(rmd256_ctx *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + ctx->A = 0x76543210; + ctx->B = 0xfedcba98; + ctx->C = 0x89abcdef; + ctx->D = 0x01234567; + ctx->off = 0; + ctx->nl = ctx->nh = 0; +} + +/* --- @rmd256_set@ --- * + * + * Arguments: @rmd256_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void rmd256_set(rmd256_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + ctx->a = LOAD32_L(p + 0); + ctx->b = LOAD32_L(p + 4); + ctx->c = LOAD32_L(p + 8); + ctx->d = LOAD32_L(p + 12); + ctx->A = LOAD32_L(p + 16); + ctx->B = LOAD32_L(p + 20); + ctx->C = LOAD32_L(p + 24); + ctx->D = LOAD32_L(p + 28); + ctx->off = 0; + ctx->nl = U32(count); + ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); +} + +/* --- @rmd256_hash@ --- * + * + * Arguments: @rmd256_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void rmd256_hash(rmd256_ctx *ctx, const void *buf, size_t sz) +{ + HASH_BUFFER(RMD256, rmd256, ctx, buf, sz); +} + +/* --- @rmd256_done@ --- * + * + * Arguments: @rmd256_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +void rmd256_done(rmd256_ctx *ctx, void *hash) +{ + octet *p = hash; + HASH_MD5STRENGTH(RMD256, rmd256, ctx); + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); + STORE32_L(p + 16, ctx->A); + STORE32_L(p + 20, ctx->B); + STORE32_L(p + 24, ctx->C); + STORE32_L(p + 28, ctx->D); +} + +/* --- @rmd256_state@ --- * + * + * Arguments: @rmd256_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @rmd256_set@. + */ + +unsigned long rmd256_state(rmd256_ctx *ctx, void *state) +{ + octet *p = state; + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); + STORE32_L(p + 16, ctx->A); + STORE32_L(p + 20, ctx->B); + STORE32_L(p + 24, ctx->C); + STORE32_L(p + 28, ctx->D); + return (ctx->nl | ((ctx->nh << 16) << 16)); +} + +/* --- Generic interface --- */ + +GHASH_DEF(RMD256, rmd256) + +/* --- Test code --- */ + +HASH_TEST(RMD256, rmd256) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/rmd256.h b/symm/rmd256.h new file mode 100644 index 0000000..9d4d206 --- /dev/null +++ b/symm/rmd256.h @@ -0,0 +1,160 @@ +/* -*-c-*- + * + * The RIPEMD-256 message digest function + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the RIPEMD-256 hash function -----------------------------* + * + * RIPEMD-256 was invented by Hans Dobbertin, Antoon Bosselaers and Bart + * Preneel. It's a double-width version of RIPEMD-128, constructed simply by + * not gluing together the two parallel computations which RIPEMD-128 usually + * does in its compression function. The authors warn that, while its output + * is twice as wide as that of RIPEMD-128, they don't expect it to offer any + * more security. + */ + +#ifndef CATACOMB_RMD256_H +#define CATACOMB_RMD256_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define RMD256_BUFSZ 64 +#define RMD256_HASHSZ 32 +#define RMD256_STATESZ 32 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct rmd256_ctx { + uint32 a, b, c, d; /* Chaining variables */ + uint32 A, B, C, D; /* More chaining variables */ + uint32 nl, nh; /* Byte count so far */ + unsigned off; /* Offset into buffer */ + octet buf[RMD256_BUFSZ]; /* Accumulation buffer */ +} rmd256_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @rmd256_compress@ --- * + * + * Arguments: @rmd256_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: RIPEMD-256 compression function. + */ + +extern void rmd256_compress(rmd256_ctx */*ctx*/, const void */*sbuf*/); + +/* --- @rmd256_init@ --- * + * + * Arguments: @rmd256_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void rmd256_init(rmd256_ctx */*ctx*/); + +/* --- @rmd256_set@ --- * + * + * Arguments: @rmd256_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void rmd256_set(rmd256_ctx */*ctx*/, + const void */*buf*/, unsigned long /*count*/); + +/* --- @rmd256_hash@ --- * + * + * Arguments: @rmd256_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void rmd256_hash(rmd256_ctx */*ctx*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @rmd256_done@ --- * + * + * Arguments: @rmd256_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void rmd256_done(rmd256_ctx */*ctx*/, void */*hash*/); + +/* --- @rmd256_state@ --- * + * + * Arguments: @rmd256_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @rmd256_set@. + */ + +extern unsigned long rmd256_state(rmd256_ctx */*ctx*/, void */*state*/); + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash rmd256; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/rmd320.c b/symm/rmd320.c new file mode 100644 index 0000000..022903e --- /dev/null +++ b/symm/rmd320.c @@ -0,0 +1,424 @@ +/* -*-c-*- + * + * The RIPEMD-320 message digest function + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "rmd320.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rmd320_compress@ --- * + * + * Arguments: @rmd320_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: RIPEMD-320 compression function. + */ + +void rmd320_compress(rmd320_ctx *ctx, const void *sbuf) +{ + uint32 a, b, c, d, e; + uint32 A, B, C, D, E; + uint32 buf[16]; + + /* --- Fetch the chaining variables --- */ + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + e = ctx->e; + + A = ctx->A; + B = ctx->B; + C = ctx->C; + D = ctx->D; + E = ctx->E; + + /* --- Fetch the buffer contents --- */ + + { + int i; + const octet *p; + + for (i = 0, p = sbuf; i < 16; i++, p += 4) + buf[i] = LOAD32_L(p); + } + + /* --- Definitions for round functions --- */ + +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define J(x, y, z) ((x) ^ ((y) | ~(z))) + +#define T(v, w, x, y, z, i, r, f, k) do { \ + uint32 _t = v + f(w, x, y) + buf[i] + k; \ + v = ROL32(_t, r) + z; x = ROL32(x, 10); \ +} while (0) + +#define F1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000) +#define G1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x5a827999) +#define H1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6ed9eba1) +#define I1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x8f1bbcdc) +#define J1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0xa953fd4e) + +#define F2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0x50a28be6) +#define G2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x5c4dd124) +#define H2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6d703ef3) +#define I2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x7a6d76e9) +#define J2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000) + + /* --- We must do both lines together --- */ + + F1(a, b, c, d, e, 0, 11); + F1(e, a, b, c, d, 1, 14); + F1(d, e, a, b, c, 2, 15); + F1(c, d, e, a, b, 3, 12); + F1(b, c, d, e, a, 4, 5); + F1(a, b, c, d, e, 5, 8); + F1(e, a, b, c, d, 6, 7); + F1(d, e, a, b, c, 7, 9); + F1(c, d, e, a, b, 8, 11); + F1(b, c, d, e, a, 9, 13); + F1(a, b, c, d, e, 10, 14); + F1(e, a, b, c, d, 11, 15); + F1(d, e, a, b, c, 12, 6); + F1(c, d, e, a, b, 13, 7); + F1(b, c, d, e, a, 14, 9); + F1(a, b, c, d, e, 15, 8); + + F2(A, B, C, D, E, 5, 8); + F2(E, A, B, C, D, 14, 9); + F2(D, E, A, B, C, 7, 9); + F2(C, D, E, A, B, 0, 11); + F2(B, C, D, E, A, 9, 13); + F2(A, B, C, D, E, 2, 15); + F2(E, A, B, C, D, 11, 15); + F2(D, E, A, B, C, 4, 5); + F2(C, D, E, A, B, 13, 7); + F2(B, C, D, E, A, 6, 7); + F2(A, B, C, D, E, 15, 8); + F2(E, A, B, C, D, 8, 11); + F2(D, E, A, B, C, 1, 14); + F2(C, D, E, A, B, 10, 14); + F2(B, C, D, E, A, 3, 12); + F2(A, B, C, D, E, 12, 6); + + G1(e, A, b, c, d, 7, 7); + G1(d, e, A, b, c, 4, 6); + G1(c, d, e, A, b, 13, 8); + G1(b, c, d, e, A, 1, 13); + G1(A, b, c, d, e, 10, 11); + G1(e, A, b, c, d, 6, 9); + G1(d, e, A, b, c, 15, 7); + G1(c, d, e, A, b, 3, 15); + G1(b, c, d, e, A, 12, 7); + G1(A, b, c, d, e, 0, 12); + G1(e, A, b, c, d, 9, 15); + G1(d, e, A, b, c, 5, 9); + G1(c, d, e, A, b, 2, 11); + G1(b, c, d, e, A, 14, 7); + G1(A, b, c, d, e, 11, 13); + G1(e, A, b, c, d, 8, 12); + + G2(E, a, B, C, D, 6, 9); + G2(D, E, a, B, C, 11, 13); + G2(C, D, E, a, B, 3, 15); + G2(B, C, D, E, a, 7, 7); + G2(a, B, C, D, E, 0, 12); + G2(E, a, B, C, D, 13, 8); + G2(D, E, a, B, C, 5, 9); + G2(C, D, E, a, B, 10, 11); + G2(B, C, D, E, a, 14, 7); + G2(a, B, C, D, E, 15, 7); + G2(E, a, B, C, D, 8, 12); + G2(D, E, a, B, C, 12, 7); + G2(C, D, E, a, B, 4, 6); + G2(B, C, D, E, a, 9, 15); + G2(a, B, C, D, E, 1, 13); + G2(E, a, B, C, D, 2, 11); + + H1(d, e, A, B, c, 3, 11); + H1(c, d, e, A, B, 10, 13); + H1(B, c, d, e, A, 14, 6); + H1(A, B, c, d, e, 4, 7); + H1(e, A, B, c, d, 9, 14); + H1(d, e, A, B, c, 15, 9); + H1(c, d, e, A, B, 8, 13); + H1(B, c, d, e, A, 1, 15); + H1(A, B, c, d, e, 2, 14); + H1(e, A, B, c, d, 7, 8); + H1(d, e, A, B, c, 0, 13); + H1(c, d, e, A, B, 6, 6); + H1(B, c, d, e, A, 13, 5); + H1(A, B, c, d, e, 11, 12); + H1(e, A, B, c, d, 5, 7); + H1(d, e, A, B, c, 12, 5); + + H2(D, E, a, b, C, 15, 9); + H2(C, D, E, a, b, 5, 7); + H2(b, C, D, E, a, 1, 15); + H2(a, b, C, D, E, 3, 11); + H2(E, a, b, C, D, 7, 8); + H2(D, E, a, b, C, 14, 6); + H2(C, D, E, a, b, 6, 6); + H2(b, C, D, E, a, 9, 14); + H2(a, b, C, D, E, 11, 12); + H2(E, a, b, C, D, 8, 13); + H2(D, E, a, b, C, 12, 5); + H2(C, D, E, a, b, 2, 14); + H2(b, C, D, E, a, 10, 13); + H2(a, b, C, D, E, 0, 13); + H2(E, a, b, C, D, 4, 7); + H2(D, E, a, b, C, 13, 5); + + I1(C, d, e, A, B, 1, 11); + I1(B, C, d, e, A, 9, 12); + I1(A, B, C, d, e, 11, 14); + I1(e, A, B, C, d, 10, 15); + I1(d, e, A, B, C, 0, 14); + I1(C, d, e, A, B, 8, 15); + I1(B, C, d, e, A, 12, 9); + I1(A, B, C, d, e, 4, 8); + I1(e, A, B, C, d, 13, 9); + I1(d, e, A, B, C, 3, 14); + I1(C, d, e, A, B, 7, 5); + I1(B, C, d, e, A, 15, 6); + I1(A, B, C, d, e, 14, 8); + I1(e, A, B, C, d, 5, 6); + I1(d, e, A, B, C, 6, 5); + I1(C, d, e, A, B, 2, 12); + + I2(c, D, E, a, b, 8, 15); + I2(b, c, D, E, a, 6, 5); + I2(a, b, c, D, E, 4, 8); + I2(E, a, b, c, D, 1, 11); + I2(D, E, a, b, c, 3, 14); + I2(c, D, E, a, b, 11, 14); + I2(b, c, D, E, a, 15, 6); + I2(a, b, c, D, E, 0, 14); + I2(E, a, b, c, D, 5, 6); + I2(D, E, a, b, c, 12, 9); + I2(c, D, E, a, b, 2, 12); + I2(b, c, D, E, a, 13, 9); + I2(a, b, c, D, E, 9, 12); + I2(E, a, b, c, D, 7, 5); + I2(D, E, a, b, c, 10, 15); + I2(c, D, E, a, b, 14, 8); + + J1(B, C, D, e, A, 4, 9); + J1(A, B, C, D, e, 0, 15); + J1(e, A, B, C, D, 5, 5); + J1(D, e, A, B, C, 9, 11); + J1(C, D, e, A, B, 7, 6); + J1(B, C, D, e, A, 12, 8); + J1(A, B, C, D, e, 2, 13); + J1(e, A, B, C, D, 10, 12); + J1(D, e, A, B, C, 14, 5); + J1(C, D, e, A, B, 1, 12); + J1(B, C, D, e, A, 3, 13); + J1(A, B, C, D, e, 8, 14); + J1(e, A, B, C, D, 11, 11); + J1(D, e, A, B, C, 6, 8); + J1(C, D, e, A, B, 15, 5); + J1(B, C, D, e, A, 13, 6); + + J2(b, c, d, E, a, 12, 8); + J2(a, b, c, d, E, 15, 5); + J2(E, a, b, c, d, 10, 12); + J2(d, E, a, b, c, 4, 9); + J2(c, d, E, a, b, 1, 12); + J2(b, c, d, E, a, 5, 5); + J2(a, b, c, d, E, 8, 14); + J2(E, a, b, c, d, 7, 6); + J2(d, E, a, b, c, 6, 8); + J2(c, d, E, a, b, 2, 13); + J2(b, c, d, E, a, 13, 6); + J2(a, b, c, d, E, 14, 5); + J2(E, a, b, c, d, 0, 15); + J2(d, E, a, b, c, 3, 13); + J2(c, d, E, a, b, 9, 11); + J2(b, c, d, E, a, 11, 11); + + /* --- Write out the result --- */ + + ctx->a += A; + ctx->b += B; + ctx->c += C; + ctx->d += D; + ctx->e += E; + ctx->A += a; + ctx->B += b; + ctx->C += c; + ctx->D += d; + ctx->E += e; +} + +/* --- @rmd320_init@ --- * + * + * Arguments: @rmd320_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void rmd320_init(rmd320_ctx *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + ctx->e = 0xc3d2e1f0; + ctx->A = 0x76543210; + ctx->B = 0xfedcba98; + ctx->C = 0x89abcdef; + ctx->D = 0x01234567; + ctx->E = 0x3c2d1e0f; + ctx->off = 0; + ctx->nl = ctx->nh = 0; +} + +/* --- @rmd320_set@ --- * + * + * Arguments: @rmd320_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void rmd320_set(rmd320_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + ctx->a = LOAD32_L(p + 0); + ctx->b = LOAD32_L(p + 4); + ctx->c = LOAD32_L(p + 8); + ctx->d = LOAD32_L(p + 12); + ctx->e = LOAD32_L(p + 16); + ctx->A = LOAD32_L(p + 20); + ctx->B = LOAD32_L(p + 24); + ctx->C = LOAD32_L(p + 28); + ctx->D = LOAD32_L(p + 32); + ctx->E = LOAD32_L(p + 36); + ctx->off = 0; + ctx->nl = U32(count); + ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); +} + +/* --- @rmd320_hash@ --- * + * + * Arguments: @rmd320_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void rmd320_hash(rmd320_ctx *ctx, const void *buf, size_t sz) +{ + HASH_BUFFER(RMD320, rmd320, ctx, buf, sz); +} + +/* --- @rmd320_done@ --- * + * + * Arguments: @rmd320_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +void rmd320_done(rmd320_ctx *ctx, void *hash) +{ + octet *p = hash; + HASH_MD5STRENGTH(RMD320, rmd320, ctx); + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); + STORE32_L(p + 16, ctx->e); + STORE32_L(p + 20, ctx->A); + STORE32_L(p + 24, ctx->B); + STORE32_L(p + 28, ctx->C); + STORE32_L(p + 32, ctx->D); + STORE32_L(p + 36, ctx->E); +} + +/* --- @rmd320_state@ --- * + * + * Arguments: @rmd320_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @rmd320_set@. + */ + +unsigned long rmd320_state(rmd320_ctx *ctx, void *state) +{ + octet *p = state; + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); + STORE32_L(p + 16, ctx->e); + STORE32_L(p + 20, ctx->A); + STORE32_L(p + 24, ctx->B); + STORE32_L(p + 28, ctx->C); + STORE32_L(p + 32, ctx->D); + STORE32_L(p + 36, ctx->E); + return (ctx->nl | ((ctx->nh << 16) << 16)); +} + +/* --- Generic interface --- */ + +GHASH_DEF(RMD320, rmd320) + +/* --- Test code --- */ + +HASH_TEST(RMD320, rmd320) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/rmd320.h b/symm/rmd320.h new file mode 100644 index 0000000..7fdf388 --- /dev/null +++ b/symm/rmd320.h @@ -0,0 +1,160 @@ +/* -*-c-*- + * + * The RIPEMD-320 message digest function + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the RIPEMD-320 hash function -----------------------------* + * + * RIPEMD-320 was invented by Hans Dobbertin, Antoon Bosselaers and Bart + * Preneel. It's a double-width version of RIPEMD-160, constructed simply by + * not gluing together the two parallel computations which RIPEMD-160 usually + * does in its compression function. The authors warn that, while its output + * is twice as wide as that of RIPEMD-160, they don't expect it to offer any + * more security. + */ + +#ifndef CATACOMB_RMD320_H +#define CATACOMB_RMD320_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define RMD320_BUFSZ 64 +#define RMD320_HASHSZ 40 +#define RMD320_STATESZ 40 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct rmd320_ctx { + uint32 a, b, c, d, e; /* Chaining variables */ + uint32 A, B, C, D, E; /* More chaining variables */ + uint32 nl, nh; /* Byte count so far */ + unsigned off; /* Offset into buffer */ + octet buf[RMD320_BUFSZ]; /* Accumulation buffer */ +} rmd320_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @rmd320_compress@ --- * + * + * Arguments: @rmd320_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: RIPEMD-320 compression function. + */ + +extern void rmd320_compress(rmd320_ctx */*ctx*/, const void */*sbuf*/); + +/* --- @rmd320_init@ --- * + * + * Arguments: @rmd320_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void rmd320_init(rmd320_ctx */*ctx*/); + +/* --- @rmd320_set@ --- * + * + * Arguments: @rmd320_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void rmd320_set(rmd320_ctx */*ctx*/, + const void */*buf*/, unsigned long /*count*/); + +/* --- @rmd320_hash@ --- * + * + * Arguments: @rmd320_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void rmd320_hash(rmd320_ctx */*ctx*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @rmd320_done@ --- * + * + * Arguments: @rmd320_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void rmd320_done(rmd320_ctx */*ctx*/, void */*hash*/); + +/* --- @rmd320_state@ --- * + * + * Arguments: @rmd320_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @rmd320_set@. + */ + +extern unsigned long rmd320_state(rmd320_ctx */*ctx*/, void */*state*/); + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash rmd320; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/safer-mktab.c b/symm/safer-mktab.c new file mode 100644 index 0000000..d9ae784 --- /dev/null +++ b/symm/safer-mktab.c @@ -0,0 +1,102 @@ +/* -*-c-*- + * + * Generate tables for SAFER + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +/*----- Main code ---------------------------------------------------------*/ + +int main(void) +{ + octet s[256], si[256]; + unsigned x, i; + + x = 1; + for (i = 0; i < 256; i++) { + if (x < 256) { + s[i] = x; + si[x] = i; + } + x = (x * 45)%257; + } + s[128] = 0; + si[0] = 128; + + fputs("\ +/* -*-c-*-\n\ + *\n\ + * SAFER tables [generated]\n\ + */\n\ +\n\ +#ifndef CATACOMB_SAFER_TAB_H\n\ +#define CATACOMB_SAFER_TAB_H\n\ +\n\ +", stdout); + + fputs("\ +/* --- S-boxes --- */\n\ +\n\ +#define SAFER_S { \\\n\ + ", stdout); + for (i = 0; i < 256; i++) { + printf("0x%02x", s[i]); + if (i == 255) + fputs(" \\\n}\n\n", stdout); + else if ((i + 1)%8 == 0) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + fputs("\ +#define SAFER_SI { \\\n\ + ", stdout); + for (i = 0; i < 256; i++) { + printf("0x%02x", si[i]); + if (i == 255) + fputs(" \\\n}\n\n", stdout); + else if ((i + 1)%8 == 0) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + puts("#endif"); + + if (fclose(stdout)) { + fprintf(stderr, "error writing data\n"); + exit(EXIT_FAILURE); + } + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/safer.c b/symm/safer.c new file mode 100644 index 0000000..055a5f6 --- /dev/null +++ b/symm/safer.c @@ -0,0 +1,323 @@ +/* -*-c-*- + * + * The SAFER block cipher + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "paranoia.h" +#include "safer.h" +#include "safer-tab.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet safer_keysz[] = { KSZ_SET, 8, 16, 0 }; + +/*----- Important tables --------------------------------------------------*/ + +static const octet s[265] = SAFER_S, si[256] = SAFER_SI; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @safer_setup@ --- * + * + * Arguments: @safer_ctx *k@ = pointer to context to initialize + * @unsigned r@ = number of rounds wanted + * @unsigned f@ = various other flags + * @const void *buf@ = pointer to key material + * @size_t sz@ = size of key material in bytes + * + * Returns: --- + * + * Use: Initializes an SAFER expanded key. A default number of + * rounds is chosen, based on the key length. + */ + +struct ksched { + unsigned i; + octet x[9]; +}; + +static void init(struct ksched *t, const octet *k) +{ + memcpy(t->x, k, 8); + t->i = 1; +} + +static void init_sk(struct ksched *t, const octet *k) +{ + unsigned i; + octet x; + memcpy(t->x, k, 8); + for (x = 0, i = 0; i < 8; x ^= k[i++]) + ; + t->x[8] = x; + t->i = 1; +} + +static void next(struct ksched *t, octet *k) +{ + unsigned i; + if (k) { + memcpy(k, t->x, 8); + if (t->i > 1) { + for (i = 0; i < 8; i++) + k[i] += s[s[U8(9*t->i + i + 1)]]; + } + } + for (i = 0; i < 8; i++) + t->x[i] = ROL8(t->x[i], 3); + t->i++; +} + +static void next_sk(struct ksched *t, octet *k) +{ + unsigned i; + i = (t->i - 1)%9; + if (k) { + if (i < 2) + memcpy(k, t->x + i, 8); + else { + memcpy(k, t->x + i, 9 - i); + memcpy(k + 9 - i, t->x, i - 1); + } + if (t->i > 1) { + for (i = 0; i < 8; i++) + k[i] += s[s[U8(9*t->i + i + 1)]]; + } + } + for (i = 0; i < 9; i++) + t->x[i] = ROL8(t->x[i], 3); + t->i++; +} + +void safer_setup(safer_ctx *k, unsigned r, unsigned f, + const void *buf, size_t sz) +{ + struct ksched ka, kb; + void (*in)(struct ksched *, const octet *); + void (*nx)(struct ksched *, octet *); + octet *kk; + + assert(r <= SAFER_MAXROUNDS); + KSZ_ASSERT(safer, sz); + + if (f & SAFER_SK) { + in = init_sk; + nx = next_sk; + } else { + in = init; + nx = next; + } + + in(&kb, buf); + in(&ka, sz == 8 ? buf : (const octet *)buf + 8); + + k->r = r; + kk = k->k; + while (r) { + nx(&ka, kk); nx(&kb, 0); kk += 8; + nx(&kb, kk); nx(&ka, 0); kk += 8; + r--; + } + nx(&ka, kk); kk += 8; +} + +/* --- @safer_init@, @safersk_init@ --- * + * + * Arguments: @safer_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to key material + * @size_t sz@ = size of key material in bytes + * + * Returns: --- + * + * Use: Initializes an SAFER expanded key. A default number of + * rounds is chosen, based on the key length. + */ + +void safer_init(safer_ctx *k, const void *buf, size_t sz) +{ + safer_setup(k, sz == 8 ? 6 : 10, 0, buf, sz); +} + +void safersk_init(safer_ctx *k, const void *buf, size_t sz) +{ + safer_setup(k, sz == 8 ? 8 : 10, SAFER_SK, buf, sz); +} + +/* --- @safer_eblk@, @safer_dblk@ --- * + * + * Arguments: @const safer_ctx *k@ = pointer to SAFER context + * @const uint32 s[2]@ = pointer to source block + * @const uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +#define UNPACK(src, a, b, c, d, e, f, g, h) do { \ + a = U8(src[0] >> 24); b = U8(src[0] >> 16); \ + c = U8(src[0] >> 8); d = U8(src[0] >> 0); \ + e = U8(src[1] >> 24); f = U8(src[1] >> 16); \ + g = U8(src[1] >> 8); h = U8(src[1] >> 0); \ +} while (0) + +#define PACK(dst, a, b, c, d, e, f, g, h) do { \ + dst[0] = (U8(a) << 24) | (U8(b) << 16) | (U8(c) << 8) | U8(d); \ + dst[1] = (U8(e) << 24) | (U8(f) << 16) | (U8(g) << 8) | U8(h); \ +} while (0) + +#define F(x, y) y += x, x += y +#define G(x, y) x -= y, y -= x + +#define PHT(a, b, c, d, e, f, g, h) do { \ + F(a, b); F(c, d); F(e, f); F(g, h); \ + F(a, c); F(e, g); F(b, d); F(f, h); \ + F(a, e); F(b, f); F(c, g); F(d, h); \ +} while (0) + #define IPHT(a, b, c, d, e, f, g, h) do { \ + G(a, e); G(b, f); G(c, g); G(d, h); \ + G(a, c); G(e, g); G(b, d); G(f, h); \ + G(a, b); G(c, d); G(e, f); G(g, h); \ +} while (0) + +#define KXA(k, a, b, c, d, e, f, g, h) do { \ + a ^= *k++; b += *k++; c += *k++; d ^= *k++; \ + e ^= *k++; f += *k++; g += *k++; h ^= *k++; \ +} while (0) +#define SUB(a, b, c, d, e, f, g, h) do { \ + a = s[U8(a)]; b = si[U8(b)]; c = si[U8(c)]; d = s[U8(d)]; \ + e = s[U8(e)]; f = si[U8(f)]; g = si[U8(g)]; h = s[U8(h)]; \ +} while (0) +#define KAX(k, a, b, c, d, e, f, g, h) do { \ + a += *k++; b ^= *k++; c ^= *k++; d += *k++; \ + e += *k++; f ^= *k++; g ^= *k++; h += *k++; \ +} while (0) + +#define KXS(k, a, b, c, d, e, f, g, h) do { \ + h ^= *--k; g -= *--k; f -= *--k; e ^= *--k; \ + d ^= *--k; c -= *--k; b -= *--k; a ^= *--k; \ +} while (0) +#define ISUB(a, b, c, d, e, f, g, h) do { \ + a = si[U8(a)]; b = s[U8(b)]; c = s[U8(c)]; d = si[U8(d)]; \ + e = si[U8(e)]; f = s[U8(f)]; g = s[U8(g)]; h = si[U8(h)]; \ +} while (0) +#define KSX(k, a, b, c, d, e, f, g, h) do { \ + h -= *--k; g ^= *--k; f ^= *--k; e -= *--k; \ + d -= *--k; c ^= *--k; b ^= *--k; a -= *--k; \ +} while (0) + +#define EROUND(k, a, b, c, d, e, f, g, h) do { \ + KXA(k, a, b, c, d, e, f, g, h); \ + SUB(a, b, c, d, e, f, g, h); \ + KAX(k, a, b, c, d, e, f, g, h); \ + PHT(a, b, c, d, e, f, g, h); \ +} while (0) + +#define DROUND(k, a, b, c, d, e, f, g, h) do { \ + IPHT(a, b, c, d, e, f, g, h); \ + KSX(k, a, b, c, d, e, f, g, h); \ + ISUB(a, b, c, d, e, f, g, h); \ + KXS(k, a, b, c, d, e, f, g, h); \ +} while (0) + + +void safer_eblk(const safer_ctx *k, const uint32 *src, uint32 *dst) +{ + octet a, b, c, d, e, f, g, h; + unsigned r = k->r; + const octet *kk = k->k; + + UNPACK(src, a, b, c, d, e, f, g, h); + while (r >= 3) { + EROUND(kk, a, b, c, d, e, f, g, h); + EROUND(kk, a, e, b, f, c, g, d, h); + EROUND(kk, a, c, e, g, b, d, f, h); + r -= 3; + } + switch (r) { + case 0: + KXA(kk, a, b, c, d, e, f, g, h); + PACK(dst, a, b, c, d, e, f, g ,h); + break; + case 1: + EROUND(kk, a, b, c, d, e, f, g, h); + KXA(kk, a, e, b, f, c, g, d, h); + PACK(dst, a, e, b, f, c, g, d, h); + break; + case 2: + EROUND(kk, a, b, c, d, e, f, g, h); + EROUND(kk, a, e, b, f, c, g, d, h); + KXA(kk, a, c, e, g, b, d, f, h); + PACK(dst, a, c, e, g, b, d, f, h); + break; + } +} + +void safer_dblk(const safer_ctx *k, const uint32 *src, uint32 *dst) +{ + octet a, b, c, d, e, f, g, h; + unsigned r = k->r; + const octet *kk = k->k + 16 * r + 8; + switch (r%3) { + default: + case 0: + UNPACK(src, a, b, c, d, e, f, g, h); + KXS(kk, a, b, c, d, e, f, g, h); + break; + case 1: + UNPACK(src, a, e, b, f, c, g, d, h); + KXS(kk, a, e, b, f, c, g, d, h); + r--; + goto one_round; + case 2: + UNPACK(src, a, c, e, g, b, d, f, h); + KXS(kk, a, c, e, g, b, d, f, h); + r -= 2; + DROUND(kk, a, e, b, f, c, g, d, h); + one_round: + DROUND(kk, a, b, c, d, e, f, g, h); + break; + } + while (r) { + DROUND(kk, a, c, e, g, b, d, f, h); + DROUND(kk, a, e, b, f, c, g, d, h); + DROUND(kk, a, b, c, d, e, f, g, h); + r -= 3; + } + PACK(dst, a, b, c, d, e, f, g, h); +} + +BLKC_TEST(SAFER, safer) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/safer.h b/symm/safer.h new file mode 100644 index 0000000..6186d96 --- /dev/null +++ b/symm/safer.h @@ -0,0 +1,139 @@ +/* -*-c-*- + * + * The SAFER block cipher + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the SAFER block cipher -----------------------------------* + * + * SAFER was designed by James Massey (who also worked on IDEA) for Cylink. + * It's free -- patents or other silliness. The original key schedule had + * some weaknesses, and a new one (the SK version) was added. SAFER has a + * variable number of rounds. The standard interface uses the recommended + * number for the given key schedule algorithm and key size. + * + * SAFER got a bad press in Schneier's book `Applied Cryptography'. I think + * this is undeserved. SAFER is a well-designed cipher which mostly looks + * pretty solid. + */ + +#ifndef CATACOMB_SAFER_H +#define CATACOMB_SAFER_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magical numbers ---------------------------------------------------*/ + +#define SAFER_BLKSZ 8 +#define SAFER_KEYSZ 8 +#define SAFER_CLASS (N, B, 64) + +#define SAFERSK_BLKSZ SAFER_BLKSZ +#define SAFERSK_KEYSZ 16 +#define SAFERSK_CLASS SAFER_CLASS + +#define SAFER_MAXROUNDS 12 + +extern const octet safer_keysz[]; +#define safersk_keysz safer_keysz + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct safer_ctx { + octet k[8 * (2 * SAFER_MAXROUNDS + 1)]; + unsigned r; +} safer_ctx, safersk_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @safer_setup@ --- * + * + * Arguments: @safer_ctx *k@ = pointer to context to initialize + * @unsigned r@ = number of rounds wanted + * @unsigned f@ = various other flags + * @const void *buf@ = pointer to key material + * @size_t sz@ = size of key material in bytes + * + * Returns: --- + * + * Use: Initializes an SAFER expanded key. A default number of + * rounds is chosen, based on the key length. + */ + +#define SAFER_SK 1u + +extern void safer_setup(safer_ctx */*k*/, unsigned /*r*/, unsigned /*f*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @safer_init@, @safersk_init@ --- * + * + * Arguments: @safer_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to key material + * @size_t sz@ = size of key material in bytes + * + * Returns: --- + * + * Use: Initializes an SAFER expanded key. A default number of + * rounds is chosen, based on the key length. + */ + +extern void safer_init(safer_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); +extern void safersk_init(safer_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @safer_eblk@, @safer_dblk@ --- * + * + * Arguments: @const safer_ctx *k@ = pointer to SAFER context + * @const uint32 s[2]@ = pointer to source block + * @const uint32 d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void safer_eblk(const safer_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); +extern void safer_dblk(const safer_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); + +#define safersk_eblk safer_eblk +#define safersk_dblk safer_dblk + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/safersk.c b/symm/safersk.c new file mode 100644 index 0000000..e665410 --- /dev/null +++ b/symm/safersk.c @@ -0,0 +1,14 @@ +/* -*-c-*- + * + * Stub source for SAFER SK + * + * (c) 2001 Straylight/Edgeware + */ + +#include "blkc.h" +#include "safersk.h" + +const char *safersk_magic = "Compile this useless file"; + +BLKC_TEST(SAFERSK, safersk) + diff --git a/symm/safersk.h b/symm/safersk.h new file mode 100644 index 0000000..7087432 --- /dev/null +++ b/symm/safersk.h @@ -0,0 +1,15 @@ +/* -*-c-*- + * + * Stub header for SAFER SK + * + * (c) 2001 Straylight/Edgeware + */ + +#ifndef CATACOMB_SAFERSK_H +#define CATACOMB_SAFERSK_H + +#include "safer.h" + +extern const char *safersk_magic; + +#endif diff --git a/symm/seal.c b/symm/seal.c new file mode 100644 index 0000000..df7cd1b --- /dev/null +++ b/symm/seal.c @@ -0,0 +1,614 @@ +/* -*-c-*- + * + * The SEAL pseudo-random function family + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include + +#include "arena.h" +#include "gcipher.h" +#include "grand.h" +#include "paranoia.h" +#include "seal.h" +#include "sha.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet seal_keysz[] = { KSZ_ANY, SHA_HASHSZ }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gamma@ --- * + * + * Arguments: @uint32 *p@ = output table + * @size_t sz@ = size of the output table + * @const void *k@ = pointer to key material + * @unsigned i@ = integer offset + * + * Returns: --- + * + * Use: Initializes a SEAL key table. + */ + +static void gamma(uint32 *p, size_t sz, const void *k, unsigned i) +{ + uint32 buf[80] = { 0 }; + const octet *kk = k; + uint32 aa = LOAD32(kk); + uint32 bb = LOAD32(kk + 4); + uint32 cc = LOAD32(kk + 8); + uint32 dd = LOAD32(kk + 12); + uint32 ee = LOAD32(kk + 16); + + unsigned skip = i % 5; + i /= 5; + + /* --- While there's hashing to do, do hashing --- */ + + while (sz) { + uint32 a = aa, b = bb, c = cc, d = dd, e = ee; + int j; + + /* --- Initialize and expand the buffer --- */ + + buf[0] = i++; + + for (j = 16; j < 80; j++) { + uint32 x = buf[j - 3] ^ buf[j - 8] ^ buf[j - 14] ^ buf[j - 16]; + buf[j] = ROL32(x, 1); + } + + /* --- Definitions for round functions --- */ + +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define G(x, y, z) ((x) ^ (y) ^ (z)) +#define H(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) + +#define T(v, w, x, y, z, i, f, k) do { \ + uint32 _x; \ + z = ROL32(v, 5) + f(w, x, y) + z + buf[i] + k; \ + w = ROR32(w, 2); \ + _x = v; v = z; z = y; y = x; x = w; w = _x; \ +} while (0) + +#define FF(v, w, x, y, z, i) T(v, w, x, y, z, i, F, 0x5a827999) +#define GG(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0x6ed9eba1) +#define HH(v, w, x, y, z, i) T(v, w, x, y, z, i, H, 0x8f1bbcdc) +#define II(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0xca62c1d6) + + /* --- The main compression function --- * + * + * Since this isn't doing bulk hashing, do it the easy way. + */ + + for (j = 0; j < 20; j++) + FF(a, b, c, d, e, j); + for (j = 20; j < 40; j++) + GG(a, b, c, d, e, j); + for (j = 40; j < 60; j++) + HH(a, b, c, d, e, j); + for (j = 60; j < 80; j++) + II(a, b, c, d, e, j); + + /* --- Do the chaining at the end --- */ + + a += aa; b += bb; c += cc; d += dd; e += ee; + + /* --- Write to the output buffer --- */ + + switch (skip) { + case 0: + if (sz) { *p++ = a; sz--; } + case 1: + if (sz) { *p++ = b; sz--; } + case 2: + if (sz) { *p++ = c; sz--; } + case 3: + if (sz) { *p++ = d; sz--; } + case 4: + if (sz) { *p++ = e; sz--; } + skip = 0; + } + } +} + +/* --- @seal_initkey@ --- * + * + * Arguments: @seal_key *k@ = pointer to key block + * @const void *buf@ = pointer to key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes a SEAL key block. The key material may be any + * size, but if it's not 20 bytes long it's passed to SHA for + * hashing first. + */ + +void seal_initkey(seal_key *k, const void *buf, size_t sz) +{ + /* --- Hash the key if it's the wrong size --- */ + + if (sz == SHA_HASHSZ) + memcpy(k->k, buf, sizeof(k->k)); + else { + sha_ctx c; + sha_init(&c); + sha_hash(&c, buf, sz); + sha_done(&c, k->k); + } + + /* --- Expand the key to fit the various tables --- */ + + gamma(k->t, 512, k->k, 0); + gamma(k->s, 256, k->k, 0x1000); + gamma(k->r, SEAL_R, k->k, 0x2000); +} + +/* --- @seal_reset@ --- * + * + * Arguments: @seal_ctx *c@ = pointer to a SEAL context + * + * Returns: --- + * + * Use: Resets the context so that more data can be extracted from + * it. + */ + +static void seal_reset(seal_ctx *c) +{ + seal_key *k = c->k; + uint32 n = c->n; + uint32 A, B, C, D; + unsigned p; + + /* --- Initialize the new chaining variables --- */ + + if (c->l >= SEAL_R) { + gamma(c->rbuf, SEAL_R, k->k, c->ri); + c->ri += SEAL_R; + c->l = 0; + c->r = c->rbuf; + } + + A = n ^ c->r[0]; + B = ROR32(n, 8) ^ c->r[1]; + C = ROR32(n, 16) ^ c->r[2]; + D = ROR32(n, 24) ^ c->r[3]; + c->l += 4; + c->r += 4; + + /* --- Ensure that everything is sufficiently diffused --- */ + + p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9); + p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9); + p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9); + p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9); + p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9); + p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9); + p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9); + p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9); + + /* --- Write out some context --- */ + + c->n1 = D; c->n2 = B; c->n3 = A; c->n4 = C; + + /* --- Diffuse some more --- */ + + p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9); + p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9); + p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9); + p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9); + + /* --- Write out the magic numbers --- */ + + c->a = A; c->b = B; c->c = C; c->d = D; + c->i = 0; +} + +/* --- @seal_initctx@ --- * + * + * Arguments: @seal_ctx *c@ = pointer to a SEAL context + * @seal_key *k@ = pointer to a SEAL key + * @uint32 n@ = integer sequence number + * + * Returns: --- + * + * Use: Initializes a SEAL context which can be used for random + * number generation or whatever. + */ + +void seal_initctx(seal_ctx *c, seal_key *k, uint32 n) +{ + c->k = k; + c->n = n; + c->l = 0; + c->r = k->r; + c->ri = 0x2000 + SEAL_R; + c->qsz = 0; + seal_reset(c); +} + +/* --- @seal_encrypt@ --- * + * + * Arguments: @seal_ctx *c@ = pointer to a SEAL context + * @const void *src@ = pointer to source data + * @void *dest@ = pointer to destination data + * @size_t sz@ = size of the data + * + * Returns: --- + * + * Use: Encrypts a block of data using SEAL. If @src@ is zero, + * @dest@ is filled with SEAL output. If @dest@ is zero, the + * SEAL generator is just spun around for a bit. This shouldn't + * be necessary, because SEAL isn't RC4. + */ + +void seal_encrypt(seal_ctx *c, const void *src, void *dest, size_t sz) +{ + const octet *s = src; + octet *d = dest; + + /* --- Expect a big dollop of bytes --- */ + + if (sz > c->qsz) { + seal_key *k = c->k; + uint32 A = c->a, B = c->b, C = c->c, D = c->d; + uint32 n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4; + uint32 aa, bb, cc, dd; + unsigned j = c->i; + + /* --- Empty the queue first --- */ + + if (c->qsz) { + if (d) { + unsigned i; + octet *p = c->q + sizeof(c->q) - c->qsz; + for (i = 0; i < c->qsz; i++) + *d++ = (s ? *s++ ^ *p++ : *p++); + } + sz -= c->qsz; + } + + /* --- Main sequence --- */ + + for (;;) { + unsigned P, Q; + + /* --- Reset if we've run out of steam on this iteration --- */ + + if (j == 256) { + seal_reset(c); + A = c->a, B = c->b, C = c->c, D = c->d; + n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4; + j = 0; + } + + /* --- Make some new numbers --- */ + + P = A & 0x7fc; B += k->t[P >> 2]; A = ROR32(A, 9); B ^= A; + Q = B & 0x7fc; C ^= k->t[Q >> 2]; B = ROR32(B, 9); C += B; + P = (P + C) & 0x7fc; D += k->t[P >> 2]; C = ROR32(C, 9); D ^= C; + Q = (Q + D) & 0x7fc; A ^= k->t[Q >> 2]; D = ROR32(D, 9); A += D; + P = (P + A) & 0x7fc; B ^= k->t[P >> 2]; A = ROR32(A, 9); + Q = (Q + B) & 0x7fc; C += k->t[Q >> 2]; B = ROR32(B, 9); + P = (P + C) & 0x7fc; D ^= k->t[P >> 2]; C = ROR32(C, 9); + Q = (Q + D) & 0x7fc; A += k->t[Q >> 2]; D = ROR32(D, 9); + + /* --- Remember the output and set up the next round --- */ + + aa = B + k->s[j + 0]; + bb = C ^ k->s[j + 1]; + cc = D + k->s[j + 2]; + dd = A ^ k->s[j + 3]; + j += 4; + + if (j & 4) + A += n1, B += n2, C ^= n1, D ^= n2; + else + A += n3, B += n4, C ^= n3, D ^= n4; + + /* --- Bail out here if we need to do buffering --- */ + + if (sz < 16) + break; + + /* --- Write the next 16 bytes --- */ + + if (d) { + if (s) { + aa ^= LOAD32_L(s + 0); + bb ^= LOAD32_L(s + 4); + cc ^= LOAD32_L(s + 8); + dd ^= LOAD32_L(s + 12); + s += 16; + } + STORE32_L(d + 0, aa); + STORE32_L(d + 4, bb); + STORE32_L(d + 8, cc); + STORE32_L(d + 12, dd); + d += 16; + } + sz -= 16; + } + + /* --- Write the new queue --- */ + + STORE32_L(c->q + 0, aa); + STORE32_L(c->q + 4, bb); + STORE32_L(c->q + 8, cc); + STORE32_L(c->q + 12, dd); + c->qsz = 16; + + c->a = A; c->b = B; c->c = C; c->d = D; + c->i = j; + } + + /* --- Deal with the rest from the queue --- */ + + if (sz) { + unsigned i; + octet *p = c->q + sizeof(c->q) - c->qsz; + if (d) { + for (i = 0; i < sz; i++) + *d++ = (s ? *s++ ^ *p++ : *p++); + } + c->qsz -= sz; + } +} + +/*----- Generic cipher interface ------------------------------------------*/ + +typedef struct gctx { + gcipher c; + seal_key k; + seal_ctx cc; +} gctx; + +static const gcipher_ops gops; + +static gcipher *ginit(const void *k, size_t sz) +{ + gctx *g = S_CREATE(gctx); + g->c.ops = &gops; + seal_initkey(&g->k, k, sz); + seal_initctx(&g->cc, &g->k, 0); + return (&g->c); +} + +static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) +{ + gctx *g = (gctx *)c; + seal_encrypt(&g->cc, s, t, sz); +} + +static void gsetiv(gcipher *c, const void *iv) +{ + gctx *g = (gctx *)c; + uint32 n = *(const uint32 *)iv; + seal_initctx(&g->cc, &g->k, n); +} + +static void gdestroy(gcipher *c) +{ + gctx *g = (gctx *)c; + BURN(*g); + S_DESTROY(g); +} + +static const gcipher_ops gops = { + &seal, + gencrypt, gencrypt, gdestroy, gsetiv, 0 +}; + +const gccipher seal = { + "seal", seal_keysz, 0, + ginit +}; + +/*----- Generic random number generator interface -------------------------*/ + +typedef struct grctx { + grand r; + seal_key k; + seal_ctx cc; +} grctx; + +static void grdestroy(grand *r) +{ + grctx *g = (grctx *)r; + BURN(*g); + S_DESTROY(g); +} + +static int grmisc(grand *r, unsigned op, ...) +{ + grctx *g = (grctx *)r; + va_list ap; + int rc = 0; + va_start(ap, op); + + switch (op) { + case GRAND_CHECK: + switch (va_arg(ap, unsigned)) { + case GRAND_CHECK: + case GRAND_SEEDINT: + case GRAND_SEEDUINT32: + case GRAND_SEEDBLOCK: + case GRAND_SEEDRAND: + rc = 1; + break; + default: + rc = 0; + break; + } + break; + case GRAND_SEEDINT: + seal_initctx(&g->cc, &g->k, va_arg(ap, int)); + break; + case GRAND_SEEDUINT32: + seal_initctx(&g->cc, &g->k, va_arg(ap, uint32)); + break; + case GRAND_SEEDBLOCK: { + const void *p = va_arg(ap, const void *); + size_t sz = va_arg(ap, size_t); + uint32 n; + if (sz >= 4) + n = LOAD32_L(p); + else { + octet buf[4] = { 0 }; + memcpy(buf, p, sz); + n = LOAD32_L(p); + } + seal_initctx(&g->cc, &g->k, n); + } break; + case GRAND_SEEDRAND: { + grand *rr = va_arg(ap, grand *); + seal_initctx(&g->cc, &g->k, rr->ops->word(rr)); + } break; + default: + GRAND_BADOP; + break; + } + + va_end(ap); + return (rc); +} + +static octet grbyte(grand *r) +{ + grctx *g = (grctx *)r; + octet o; + seal_encrypt(&g->cc, 0, &o, 1); + return (o); +} + +static uint32 grword(grand *r) +{ + grctx *g = (grctx *)r; + octet b[4]; + seal_encrypt(&g->cc, 0, b, 4); + return (LOAD32(b)); +} + +static void grfill(grand *r, void *p, size_t sz) +{ + grctx *g = (grctx *)r; + seal_encrypt(&g->cc, 0, p, sz); +} + +static const grand_ops grops = { + "seal", + GRAND_CRYPTO, 0, + grmisc, grdestroy, + grword, grbyte, grword, grand_range, grfill +}; + +/* --- @seal_rand@ --- * + * + * Arguments: @const void *k@ = pointer to key material + * @size_t sz@ = size of key material + * @uint32 n@ = sequence number + * + * Returns: Pointer to generic random number generator interface. + * + * Use: Creates a random number interface wrapper around a SEAL + * pseudorandom function. + */ + +grand *seal_rand(const void *k, size_t sz, uint32 n) +{ + grctx *g = S_CREATE(grctx); + g->r.ops = &grops; + seal_initkey(&g->k, k, sz); + seal_initctx(&g->cc, &g->k, n); + return (&g->r); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +#include + +static int verify(dstr *v) +{ + seal_key k; + seal_ctx c; + uint32 n = *(uint32 *)v[1].buf; + dstr d = DSTR_INIT; + dstr z = DSTR_INIT; + int i; + int ok = 1; + + DENSURE(&d, v[2].len); + DENSURE(&z, v[2].len); + memset(z.buf, 0, v[2].len); + z.len = d.len = v[2].len; + seal_initkey(&k, v[0].buf, v[0].len); + + for (i = 0; i < v[2].len; i++) { + seal_initctx(&c, &k, n); + seal_encrypt(&c, 0, d.buf, i); + seal_encrypt(&c, z.buf, d.buf + i, d.len - i); + if (memcmp(d.buf, v[2].buf, d.len) != 0) { + ok = 0; + printf("*** seal failure\n"); + printf("*** k = "); type_hex.dump(&v[0], stdout); putchar('\n'); + printf("*** n = %08lx\n", (unsigned long)n); + printf("*** i = %i\n", i); + printf("*** expected = "); type_hex.dump(&v[2], stdout); putchar('\n'); + printf("*** computed = "); type_hex.dump(&d, stdout); putchar('\n'); + } + } + + dstr_destroy(&d); + dstr_destroy(&z); + + return (ok); +} + +static test_chunk defs[] = { + { "seal", verify, { &type_hex, &type_uint32, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/t/seal"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/seal.h b/symm/seal.h new file mode 100644 index 0000000..875994e --- /dev/null +++ b/symm/seal.h @@ -0,0 +1,163 @@ +/* -*-c-*- + * + * The SEAL pseudo-random function family + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the SEAL pseudo-random function family -------------------* + * + * SEAL is a slightly odd cryptographic primitive. It was designed by Phil + * Rogaway and Don Coppersmith at IBM, basically as an exercise in producing + * a really fast symmetric cipher of some kind. They succeeded: SEAL is + * faster than the much simpler RC4. + * + * For each key, it gives you %$2^{32}$% different output streams. This + * implementation imposes no length limits on the size of output streams and + * performs careful buffer handling to allow arbitrary amounts of data to be + * extracted. In practice, extracting more than about 64K is possibly dodgy + * from a security point of view. + * + * SEAL is patented. + */ + +#ifndef CATACOMB_SEAL_H +#define CATACOMB_SEAL_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" +#endif + +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +#define SEAL_R 256 + +typedef struct seal_key { + octet k[20]; /* Copy of the 160-bit key */ + uint32 t[512]; /* Substitution table */ + uint32 s[256]; /* Magic for each iteration */ + uint32 r[SEAL_R]; /* Magic for the first 64K */ +} seal_key; + +typedef struct seal_ctx { + seal_key *k; /* Pointer to the key block */ + uint32 *r, ri; /* Pointer to current magic */ + uint32 n, l; /* Various indices into things */ + uint32 a, b, c, d; /* Current chaining variables */ + uint32 n1, n2, n3, n4; /* Increments for the variables */ + unsigned i; /* Index into current iteration */ + octet q[16]; /* Output buffer */ + unsigned qsz; /* Number of bytes in the buffer */ + uint32 rbuf[SEAL_R]; /* Buffer for later magic */ +} seal_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @seal_initkey@ --- * + * + * Arguments: @seal_key *k@ = pointer to key block + * @const void *buf@ = pointer to key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes a SEAL key block. The key material may be any + * size, but if it's not 20 bytes long it's passed to SHA for + * hashing first. + */ + +extern void seal_initkey(seal_key */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @seal_initctx@ --- * + * + * Arguments: @seal_ctx *c@ = pointer to a SEAL context + * @seal_key *k@ = pointer to a SEAL key + * @uint32 n@ = integer sequence number + * + * Returns: --- + * + * Use: Initializes a SEAL context which can be used for random + * number generation or whatever. + */ + +extern void seal_initctx(seal_ctx */*c*/, seal_key */*k*/, uint32 /*n*/); + +/* --- @seal_encrypt@ --- * + * + * Arguments: @seal_ctx *c@ = pointer to a SEAL context + * @const void *src@ = pointer to source data + * @void *dest@ = pointer to destination data + * @size_t sz@ = size of the data + * + * Returns: --- + * + * Use: Encrypts a block of data using SEAL. If @src@ is zero, + * @dest@ is filled with SEAL output. If @dest@ is zero, the + * SEAL generator is just spun around for a bit. This shouldn't + * be necessary, because SEAL isn't RC4. + */ + +extern void seal_encrypt(seal_ctx */*c*/, const void */*src*/, + void */*dest*/, size_t /*sz*/); + +/*----- Generic cipher interface ------------------------------------------*/ + +#define SEAL_KEYSZ 20 +extern const octet seal_keysz[]; + +extern const gccipher seal; + +/*----- Generic random number generator interface -------------------------*/ + +/* --- @seal_rand@ --- * + * + * Arguments: @const void *k@ = pointer to key material + * @size_t sz@ = size of key material + * @uint32 n@ = sequence number + * + * Returns: Pointer to generic random number generator interface. + * + * Use: Creates a random number interface wrapper around a SEAL + * pseudorandom function. + */ + +extern grand *seal_rand(const void */*k*/, size_t /*sz*/, uint32 /*n*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/serpent-check.c b/symm/serpent-check.c new file mode 100644 index 0000000..7f95ffc --- /dev/null +++ b/symm/serpent-check.c @@ -0,0 +1,99 @@ +/* -*-c-*- + * + * Check the Serpent S-boxes + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include + +#include "serpent-sbox.h" + +/*----- S-box tables ------------------------------------------------------*/ + +static const octet s[8][16] = { + { 3, 8, 15, 1, 10, 6, 5, 11, 14, 13, 4, 2, 7, 0, 9, 12 }, + { 15, 12, 2, 7, 9, 0, 5, 10, 1, 11, 14, 8, 6, 13, 3, 4 }, + { 8, 6, 7, 9, 3, 12, 10, 15, 13, 1, 14, 4, 0, 11, 5, 2 }, + { 0, 15, 11, 8, 12, 9, 6, 3, 13, 1, 2, 4, 10, 7, 5, 14 }, + { 1, 15, 8, 3, 12, 0, 11, 6, 2, 5, 4, 10, 9, 14, 7, 13 }, + { 15, 5, 2, 11, 4, 10, 9, 12, 0, 3, 14, 8, 13, 6, 7, 1 }, + { 7, 2, 12, 5, 8, 4, 6, 11, 14, 9, 1, 15, 13, 3, 10, 0 }, + { 1, 13, 15, 0, 14, 8, 2, 11, 7, 4, 12, 10, 9, 3, 5, 6 } +}; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @check@ --- * + * + * Arguments: @unsigned a, b, c, d@ = four bitslice output registers + * @const octet *p@ = pointer to S-box + * + * Returns: Zero if OK, nonzero on failure. + * + * Use: Checks that an S-box output is correct. + */ + +static int check(unsigned a, unsigned b, unsigned c, unsigned d, + const octet *p) +{ + octet buf[16]; + octet *q = buf; + unsigned i; + + for (i = 0; i < 16; i++) { + *q++ = (a & 1) | ((b & 1) << 1) | ((c & 1) << 2) | ((d & 1) << 3); + a >>= 1; b >>= 1; c >>= 1; d >>= 1; + } + return (memcmp(buf, p, sizeof(buf))); +} + +#define CHECK(i) do { \ + unsigned a = 0xaaaa, b = 0xcccc, c = 0xf0f0, d = 0xff00; \ + S##i(a, b, c, d); \ + if (check(a, b, c, d, s[i])) { \ + fprintf(stderr, "failure in S%i\n", i); \ + rc = EXIT_FAILURE; \ + } \ + IS##i(a, b, c, d); \ + if (a != 0xaaaa || b != 0xcccc || c != 0xf0f0 || d != 0xff00) { \ + fprintf(stderr, "failure in IS%i\n", i); \ + rc = EXIT_FAILURE; \ + } \ +} while (0) + +int main(void) +{ + int rc = 0; + CHECK(0); CHECK(1); CHECK(2); CHECK(3); + CHECK(4); CHECK(5); CHECK(6); CHECK(7); + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/serpent-sbox.h b/symm/serpent-sbox.h new file mode 100644 index 0000000..f59155c --- /dev/null +++ b/symm/serpent-sbox.h @@ -0,0 +1,228 @@ +/* -*-c-*- + * + * Bitslice S-box implementations + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Credit where it's due ---------------------------------------------* + * + * These S-box expressions are taken from the paper `Speeding up Serpent', by + * Dag Arne Osvik, submitted to AES3. + */ + +#ifndef CATACOMB_SERPENT_SBOX_H +#define CATACOMB_SERPENT_SBOX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +/*----- Macros provided ---------------------------------------------------*/ + +/* --- @S0@ --- */ + +#define S0(r0, r1, r2, r3) do { \ + uint32 r4; \ + r3 ^= r0; r4 = r1; r1 &= r3; r4 ^= r2; \ + r1 ^= r0; r0 |= r3; r0 ^= r4; r4 ^= r3; \ + r3 ^= r2; r2 |= r1; r2 ^= r4; r4 = ~r4; \ + r4 |= r1; r1 ^= r3; r1 ^= r4; r3 |= r0; \ + r1 ^= r3; r4 ^= r3; \ + r3 = r0; r0 = r1; r1 = r4; \ +} while (0) + +#define IS0(r0, r1, r2, r3) do { \ + uint32 r4; \ + r2 = ~r2; r4 = r1; r1 |= r0; r4 = ~r4; \ + r1 ^= r2; r2 |= r4; r1 ^= r3; r0 ^= r4; \ + r2 ^= r0; r0 &= r3; r4 ^= r0; r0 |= r1; \ + r0 ^= r2; r3 ^= r4; r2 ^= r1; r3 ^= r0; \ + r3 ^= r1; r2 &= r3; r4 ^= r2; \ + r2 = r1; r1 = r4; \ +} while (0) + +/* --- @S1@ --- */ + +#define S1(r0, r1, r2, r3) do { \ + uint32 r4; \ + r0 = ~r0; r2 = ~r2; r4 = r0; r0 &= r1; \ + r2 ^= r0; r0 |= r3; r3 ^= r2; r1 ^= r0; \ + r0 ^= r4; r4 |= r1; r1 ^= r3; r2 |= r0; \ + r2 &= r4; r0 ^= r1; r1 &= r2; r1 ^= r0; \ + r0 &= r2; r0 ^= r4; \ + r4 = r0; r0 = r2; r2 = r3; r3 = r1; r1 = r4; \ +} while (0) + +#define IS1(r0, r1, r2, r3) do { \ + uint32 r4; \ + r4 = r1; r1 ^= r3; r3 &= r1; r4 ^= r2; \ + r3 ^= r0; r0 |= r1; r2 ^= r3; r0 ^= r4; \ + r0 |= r2; r1 ^= r3; r0 ^= r1; r1 |= r3; \ + r1 ^= r0; r4 = ~r4; r4 ^= r1; r1 |= r0; \ + r1 ^= r0; r1 |= r4; r3 ^= r1; \ + r1 = r0; r0 = r4; r4 = r2; r2 = r3; r3 = r4; \ +} while (0) + +/* --- @S2@ --- */ + +#define S2(r0, r1, r2, r3) do { \ + uint32 r4; \ + r4 = r0; r0 &= r2; r0 ^= r3; r2 ^= r1; \ + r2 ^= r0; r3 |= r4; r3 ^= r1; r4 ^= r2; \ + r1 = r3; r3 |= r4; r3 ^= r0; r0 &= r1; \ + r4 ^= r0; r1 ^= r3; r1 ^= r4; r4 = ~r4; \ + r0 = r2; r2 = r1; r1 = r3; r3 = r4; \ +} while (0) + +#define IS2(r0, r1, r2, r3) do { \ + uint32 r4; \ + r2 ^= r3; r3 ^= r0; r4 = r3; r3 &= r2; \ + r3 ^= r1; r1 |= r2; r1 ^= r4; r4 &= r3; \ + r2 ^= r3; r4 &= r0; r4 ^= r2; r2 &= r1; \ + r2 |= r0; r3 = ~r3; r2 ^= r3; r0 ^= r3; \ + r0 &= r1; r3 ^= r4; r3 ^= r0; \ + r0 = r1; r1 = r4; \ +} while (0) + +/* --- @S3@ --- */ + +#define S3(r0, r1, r2, r3) do { \ + uint32 r4; \ + r4 = r0; r0 |= r3; r3 ^= r1; r1 &= r4; \ + r4 ^= r2; r2 ^= r3; r3 &= r0; r4 |= r1; \ + r3 ^= r4; r0 ^= r1; r4 &= r0; r1 ^= r3; \ + r4 ^= r2; r1 |= r0; r1 ^= r2; r0 ^= r3; \ + r2 = r1; r1 |= r3; r1 ^= r0; \ + r0 = r1; r1 = r2; r2 = r3; r3 = r4; \ +} while (0) + +#define IS3(r0, r1, r2, r3) do { \ + uint32 r4; \ + r4 = r2; r2 ^= r1; r0 ^= r2; r4 &= r2; \ + r4 ^= r0; r0 &= r1; r1 ^= r3; r3 |= r4; \ + r2 ^= r3; r0 ^= r3; r1 ^= r4; r3 &= r2; \ + r3 ^= r1; r1 ^= r0; r1 |= r2; r0 ^= r3; \ + r1 ^= r4; r0 ^= r1; \ + r4 = r0; r0 = r2; r2 = r3; r3 = r4; \ +} while (0) + +/* --- @S4@ --- */ + +#define S4(r0, r1, r2, r3) do { \ + uint32 r4; \ + r1 ^= r3; r3 = ~r3; r2 ^= r3; r3 ^= r0; \ + r4 = r1; r1 &= r3; r1 ^= r2; r4 ^= r3; \ + r0 ^= r4; r2 &= r4; r2 ^= r0; r0 &= r1; \ + r3 ^= r0; r4 |= r1; r4 ^= r0; r0 |= r3; \ + r0 ^= r2; r2 &= r3; r0 = ~r0; r4 ^= r2; \ + r2 = r0; r0 = r1; r1 = r4; \ +} while (0) + +#define IS4(r0, r1, r2, r3) do { \ + uint32 r4; \ + r4 = r2; r2 &= r3; r2 ^= r1; r1 |= r3; \ + r1 &= r0; r4 ^= r2; r4 ^= r1; r1 &= r2; \ + r0 = ~r0; r3 ^= r4; r1 ^= r3; r3 &= r0; \ + r3 ^= r2; r0 ^= r1; r2 &= r0; r3 ^= r0; \ + r2 ^= r4, r2 |= r3; r3 ^= r0; r2 ^= r1; \ + r1 = r3; r3 = r4; \ +} while (0) + +/* --- @S5@ --- */ + +#define S5(r0, r1, r2, r3) do { \ + uint32 r4; \ + r0 ^= r1; r1 ^= r3; r3 = ~r3; r4 = r1; \ + r1 &= r0; r2 ^= r3; r1 ^= r2; r2 |= r4; \ + r4 ^= r3; r3 &= r1; r3 ^= r0; r4 ^= r1; \ + r4 ^= r2; r2 ^= r0; r0 &= r3; r2 = ~r2; \ + r0 ^= r4; r4 |= r3; r2 ^= r4; \ + r4 = r3; r3 = r2; r2 = r0; r0 = r1; r1 = r4; \ +} while (0) + +#define IS5(r0, r1, r2, r3) do { \ + uint32 r4; \ + r1 = ~r1; r4 = r3; r2 ^= r1; r3 |= r0; \ + r3 ^= r2; r2 |= r1; r2 &= r0; r4 ^= r3; \ + r2 ^= r4; r4 |= r0; r4 ^= r1; r1 &= r2; \ + r1 ^= r3; r4 ^= r2; r3 &= r4; r4 ^= r1; \ + r3 ^= r4; r4 = ~r4; r3 ^= r0; \ + r0 = r1; r1 = r4; r4 = r3; r3 = r2; r2 = r4; \ +} while (0) + +/* --- @S6@ --- */ + +#define S6(r0, r1, r2, r3) do { \ + uint32 r4; \ + r2 = ~r2; r4 = r3; r3 &= r0; r0 ^= r4; \ + r3 ^= r2; r2 |= r4; r1 ^= r3; r2 ^= r0; \ + r0 |= r1; r2 ^= r1; r4 ^= r0; r0 |= r3; \ + r0 ^= r2; r4 ^= r3; r4 ^= r0; r3 = ~r3; \ + r2 &= r4; r2 ^= r3; \ + r3 = r2; r2 = r4; \ +} while (0) + +#define IS6(r0, r1, r2, r3) do { \ + uint32 r4; \ + r0 ^= r2; r4 = r2; r2 &= r0; r4 ^= r3; \ + r2 = ~r2; r3 ^= r1; r2 ^= r3; r4 |= r0; \ + r0 ^= r2; r3 ^= r4; r4 ^= r1; r1 &= r3; \ + r1 ^= r0; r0 ^= r3; r0 |= r2; r3 ^= r1; \ + r4 ^= r0; \ + r0 = r1; r1 = r2; r2 = r4; \ +} while (0) + +/* --- @S7@ --- */ + +#define S7(r0, r1, r2, r3) do { \ + uint32 r4; \ + r4 = r1; r1 |= r2; r1 ^= r3; r4 ^= r2; \ + r2 ^= r1; r3 |= r4; r3 &= r0; r4 ^= r2; \ + r3 ^= r1; r1 |= r4; r1 ^= r0; r0 |= r4; \ + r0 ^= r2; r1 ^= r4; r2 ^= r1; r1 &= r0; \ + r1 ^= r4; r2 = ~r2; r2 |= r0; r4 ^= r2; \ + r2 = r1; r1 = r3; r3 = r0; r0 = r4; \ +} while (0) + +#define IS7(r0, r1, r2, r3) do { \ + uint32 r4; \ + r4 = r2; r2 ^= r0; r0 &= r3; r4 |= r3; \ + r2 = ~r2; r3 ^= r1; r1 |= r0; r0 ^= r2; \ + r2 &= r4; r3 &= r4; r1 ^= r2; r2 ^= r0; \ + r0 |= r2; r4 ^= r1; r0 ^= r3; r3 ^= r4; \ + r4 |= r0; r3 ^= r2; r4 ^= r2; \ + r2 = r1; r1 = r0; r0 = r3; r3 = r4; \ +} while (0) + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/serpent.c b/symm/serpent.c new file mode 100644 index 0000000..5ad0fc9 --- /dev/null +++ b/symm/serpent.c @@ -0,0 +1,213 @@ +/* -*-c-*- + * + * The Serpent block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "serpent.h" +#include "serpent-sbox.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet serpent_keysz[] = { KSZ_RANGE, SERPENT_KEYSZ, 0, 32, 1 }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @serpent_init@ --- * + * + * Arguments: @serpent_ctx *k@ = pointer to context block to initialize + * @const void *buf@ = pointer to input buffer + * @size_t sz@ = size of input buffer + * + * Returns: --- + * + * Use: Initializes a Serpent context. The key may be any length of + * up to 32 bytes (256 bits). + */ + +void serpent_init(serpent_ctx *k, const void *buf, size_t sz) +{ + uint32 a; + unsigned b; + const octet *p, *q; + size_t i; + uint32 pk[8 + 132]; + + KSZ_ASSERT(serpent, sz); + + /* --- Read the key into the buffer --- */ + + if (sz > 32) + sz = 32; + i = 0; p = buf; q = p + sz; + a = 0; b = 0; + while (p < q) { + a |= (uint32)*p++ << b; + b += 8; + if (b == 32) { + pk[i++] = a; + a = 0; b = 0; + } + } + + /* --- Pad short keys --- */ + + if (i < 8) { + a |= 0x01 << b; + b += 8; + pk[i++] = a; + for (; i < 8; i++) + pk[i] = 0; + } + + /* --- Expand the prekeys to fill the buffer --- */ + + for (i = 8; i < 8 + 132; i++) { + uint32 x = (pk[i - 8] ^ pk[i - 5] ^ pk[i - 3] ^ pk[i - 1] ^ + (i - 8) ^ 0x9e3779b9); + k->k[i - 8] = pk[i] = ROL32(x, 11); + } + + /* --- Now substitute everything --- */ + + i = 0; + goto midway; + while (i < 132) { +#define KSUB(r) do { \ + uint32 a, b, c, d; \ + a = k->k[i]; b = k->k[i + 1]; c = k->k[i + 2]; d = k->k[i + 3]; \ + S##r(a, b, c, d); \ + k->k[i] = a; k->k[i + 1] = b; k->k[i + 2] = c; k->k[i + 3] = d; \ + i += 4; \ +} while (0) + KSUB(2); KSUB(1); KSUB(0); KSUB(7); + KSUB(6); KSUB(5); KSUB(4); + midway: + KSUB(3); +#undef KSUB + } +} + +/* --- @serpent_eblk@, @serpent_dblk@ --- * + * + * Arguments: @const serpent_ctx *k@ = pointer to key context + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption. + */ + +#define EROUND(a, b, c, d, r, k) do { \ + a ^= *k++; b ^= *k++; c ^= *k++; d ^= *k++; \ + S##r(a, b, c, d); \ + a = ROL32(a, 13); c = ROL32(c, 3); b ^= a ^ c; d ^= c ^ (a << 3); \ + b = ROL32(b, 1); d = ROL32(d, 7); a ^= b ^ d; c ^= d ^ (b << 7); \ + a = ROL32(a, 5); c = ROL32(c, 22); \ +} while (0) + +#define DROUND(a, b, c, d, r, k) do { \ + IS##r(a, b, c, d); \ + d ^= *--k; c ^= *--k; b ^= *--k; a ^= *--k; \ + a = ROR32(a, 5); c = ROR32(c, 22); a ^= b ^ d; c ^= d ^ (b << 7); \ + b = ROR32(b, 1); d = ROR32(d, 7); b ^= a ^ c; d ^= c ^ (a << 3); \ + a = ROR32(a, 13); c = ROR32(c, 3); \ +} while (0) + +void serpent_eblk(const serpent_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3]; + const uint32 *kk = k->k; + + EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk); + EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk); + EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk); + EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk); + + EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk); + EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk); + EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk); + EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk); + + EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk); + EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk); + EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk); + EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk); + + EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk); + EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk); + EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk); + EROUND(aa, bb, cc, dd, 6, kk); + + aa ^= *kk++; bb ^= *kk++; cc ^= *kk++; dd ^= *kk++; + S7(aa, bb, cc, dd); + aa ^= *kk++; bb ^= *kk++; cc ^= *kk++; dd ^= *kk++; + d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd; +} + +void serpent_dblk(const serpent_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3]; + const uint32 *kk = k->k + 132; + + dd ^= *--kk; cc ^= *--kk; bb ^= *--kk; aa ^= *--kk; + + DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk); + DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk); + DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk); + DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk); + + DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk); + DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk); + DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk); + DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk); + + DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk); + DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk); + DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk); + DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk); + + DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk); + DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk); + DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk); + DROUND(aa, bb, cc, dd, 1, kk); + + IS0(aa, bb, cc, dd); + dd ^= *--kk; cc ^= *--kk; bb ^= *--kk; aa ^= *--kk; + d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd; +} + +BLKC_TEST(SERPENT, serpent) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/serpent.h b/symm/serpent.h new file mode 100644 index 0000000..05cc31c --- /dev/null +++ b/symm/serpent.h @@ -0,0 +1,104 @@ +/* -*-c-*- + * + * The Serpent block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the Serpent block cipher ---------------------------------* + * + * Serpent was designed and proposed for the AES contest by Ross Anderson, + * Eli Biham and Lars Knudsen. It's not particularly quick, but is + * stunningly secure. The best differential and linear attacks are + * speculated to require %$2^{256}$% texts (it's a 128-bit block cipher). + * The designers originally intended to file a patent, but failed to persue + * it. Use of the algorithm is completely unencumbered. + */ + +#ifndef CATACOMB_SERPENT_H +#define CATACOMB_SERPENT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magic numbers -----------------------------------------------------*/ + +#define SERPENT_BLKSZ 16 +#define SERPENT_KEYSZ 32 +#define SERPENT_CLASS (N, L, 128) + +extern const octet serpent_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct serpent_ctx { + uint32 k[4 * 33]; +} serpent_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @serpent_init@ --- * + * + * Arguments: @serpent_ctx *k@ = pointer to context block to initialize + * @const void *buf@ = pointer to input buffer + * @size_t sz@ = size of input buffer + * + * Returns: --- + * + * Use: Initializes a Serpent context. The key may be any length of + * up to 32 bytes (256 bits). + */ + +extern void serpent_init(serpent_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @serpent_eblk@, @serpent_dblk@ --- * + * + * Arguments: @const serpent_ctx *k@ = pointer to key context + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption. + */ + +extern void serpent_eblk(const serpent_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); +extern void serpent_dblk(const serpent_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/sha.c b/symm/sha.c new file mode 100644 index 0000000..e4b5023 --- /dev/null +++ b/symm/sha.c @@ -0,0 +1,304 @@ +/* -*-c-*- + * + * Implementation of the SHA-1 hash function + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "sha.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @sha_compress@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: SHA-1 compression function. + */ + +void sha_compress(sha_ctx *ctx, const void *sbuf) +{ + uint32 a, b, c, d, e; + uint32 buf[80]; + + /* --- Fetch the chaining variables --- */ + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + e = ctx->e; + + /* --- Fetch and expand the buffer contents --- */ + + { + int i; + const octet *p; + + for (i = 0, p = sbuf; i < 16; i++, p += 4) + buf[i] = LOAD32(p); + for (i = 16; i < 80; i++) { + uint32 x = buf[i - 3] ^ buf[i - 8] ^ buf[i - 14] ^ buf[i - 16]; + buf[i] = ROL32(x, 1); + } + } + + /* --- Definitions for round functions --- */ + +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define G(x, y, z) ((x) ^ (y) ^ (z)) +#define H(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) + +#define T(v, w, x, y, z, i, f, k) do { \ + z = ROL32(v, 5) + f(w, x, y) + z + buf[i] + k; \ + w = ROR32(w, 2); \ +} while (0) + +#define FF(v, w, x, y, z, i) T(v, w, x, y, z, i, F, 0x5a827999) +#define GG(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0x6ed9eba1) +#define HH(v, w, x, y, z, i) T(v, w, x, y, z, i, H, 0x8f1bbcdc) +#define II(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0xca62c1d6) + + /* --- The main compression function --- */ + + FF(a, b, c, d, e, 0); + FF(e, a, b, c, d, 1); + FF(d, e, a, b, c, 2); + FF(c, d, e, a, b, 3); + FF(b, c, d, e, a, 4); + FF(a, b, c, d, e, 5); + FF(e, a, b, c, d, 6); + FF(d, e, a, b, c, 7); + FF(c, d, e, a, b, 8); + FF(b, c, d, e, a, 9); + FF(a, b, c, d, e, 10); + FF(e, a, b, c, d, 11); + FF(d, e, a, b, c, 12); + FF(c, d, e, a, b, 13); + FF(b, c, d, e, a, 14); + FF(a, b, c, d, e, 15); + FF(e, a, b, c, d, 16); + FF(d, e, a, b, c, 17); + FF(c, d, e, a, b, 18); + FF(b, c, d, e, a, 19); + + GG(a, b, c, d, e, 20); + GG(e, a, b, c, d, 21); + GG(d, e, a, b, c, 22); + GG(c, d, e, a, b, 23); + GG(b, c, d, e, a, 24); + GG(a, b, c, d, e, 25); + GG(e, a, b, c, d, 26); + GG(d, e, a, b, c, 27); + GG(c, d, e, a, b, 28); + GG(b, c, d, e, a, 29); + GG(a, b, c, d, e, 30); + GG(e, a, b, c, d, 31); + GG(d, e, a, b, c, 32); + GG(c, d, e, a, b, 33); + GG(b, c, d, e, a, 34); + GG(a, b, c, d, e, 35); + GG(e, a, b, c, d, 36); + GG(d, e, a, b, c, 37); + GG(c, d, e, a, b, 38); + GG(b, c, d, e, a, 39); + + HH(a, b, c, d, e, 40); + HH(e, a, b, c, d, 41); + HH(d, e, a, b, c, 42); + HH(c, d, e, a, b, 43); + HH(b, c, d, e, a, 44); + HH(a, b, c, d, e, 45); + HH(e, a, b, c, d, 46); + HH(d, e, a, b, c, 47); + HH(c, d, e, a, b, 48); + HH(b, c, d, e, a, 49); + HH(a, b, c, d, e, 50); + HH(e, a, b, c, d, 51); + HH(d, e, a, b, c, 52); + HH(c, d, e, a, b, 53); + HH(b, c, d, e, a, 54); + HH(a, b, c, d, e, 55); + HH(e, a, b, c, d, 56); + HH(d, e, a, b, c, 57); + HH(c, d, e, a, b, 58); + HH(b, c, d, e, a, 59); + + II(a, b, c, d, e, 60); + II(e, a, b, c, d, 61); + II(d, e, a, b, c, 62); + II(c, d, e, a, b, 63); + II(b, c, d, e, a, 64); + II(a, b, c, d, e, 65); + II(e, a, b, c, d, 66); + II(d, e, a, b, c, 67); + II(c, d, e, a, b, 68); + II(b, c, d, e, a, 69); + II(a, b, c, d, e, 70); + II(e, a, b, c, d, 71); + II(d, e, a, b, c, 72); + II(c, d, e, a, b, 73); + II(b, c, d, e, a, 74); + II(a, b, c, d, e, 75); + II(e, a, b, c, d, 76); + II(d, e, a, b, c, 77); + II(c, d, e, a, b, 78); + II(b, c, d, e, a, 79); + + /* --- Update the chaining variables --- */ + + ctx->a += a; + ctx->b += b; + ctx->c += c; + ctx->d += d; + ctx->e += e; +} + +/* --- @sha_init@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void sha_init(sha_ctx *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + ctx->e = 0xc3d2e1f0; + ctx->off = 0; + ctx->nl = ctx->nh = 0; +} + +/* --- @sha_set@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void sha_set(sha_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + ctx->a = LOAD32(p + 0); + ctx->b = LOAD32(p + 4); + ctx->c = LOAD32(p + 8); + ctx->d = LOAD32(p + 12); + ctx->e = LOAD32(p + 16); + ctx->off = 0; + ctx->nl = U32(count); + ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); +} + +/* --- @sha_hash@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void sha_hash(sha_ctx *ctx, const void *buf, size_t sz) +{ + HASH_BUFFER(SHA, sha, ctx, buf, sz); +} + +/* --- @sha_done@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +void sha_done(sha_ctx *ctx, void *hash) +{ + octet *p = hash; + HASH_PAD(SHA, sha, ctx, 0x80, 0, 8); + STORE32(ctx->buf + SHA_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3)); + STORE32(ctx->buf + SHA_BUFSZ - 4, ctx->nl << 3); + sha_compress(ctx, ctx->buf); + STORE32(p + 0, ctx->a); + STORE32(p + 4, ctx->b); + STORE32(p + 8, ctx->c); + STORE32(p + 12, ctx->d); + STORE32(p + 16, ctx->e); +} + +/* --- @sha_state@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @sha_set@. + */ + +unsigned long sha_state(sha_ctx *ctx, void *state) +{ + octet *p = state; + STORE32(p + 0, ctx->a); + STORE32(p + 4, ctx->b); + STORE32(p + 8, ctx->c); + STORE32(p + 12, ctx->d); + STORE32(p + 16, ctx->e); + return (ctx->nl | ((ctx->nh << 16) << 16)); +} + +/* --- Generic interface --- */ + +GHASH_DEF(SHA, sha) + +/* --- Test code --- */ + +HASH_TEST(SHA, sha) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/sha.h b/symm/sha.h new file mode 100644 index 0000000..77f8feb --- /dev/null +++ b/symm/sha.h @@ -0,0 +1,157 @@ +/* -*-c-*- + * + * Implementation of the SHA-1 hash function + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the SHA-1 hash function ----------------------------------* + * + * SHA (Secure Hash Algorithm) was designed by the NSA, for use with the + * Digital Signature Algorithm. It is defined by FIPS 180-1. It has gained + * wide acceptance since its initial publication, and is probably now most + * people's collision-resistant function of choice. The author prefers + * RIPEMD-160, for no particularly good reasons. + */ + +#ifndef CATACOMB_SHA_H +#define CATACOMB_SHA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define SHA_BUFSZ 64 +#define SHA_HASHSZ 20 +#define SHA_STATESZ 20 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct sha_ctx { + uint32 a, b, c, d, e; /* Chaining variables */ + uint32 nl, nh; /* Byte count so far */ + unsigned off; /* Offset into buffer */ + octet buf[SHA_BUFSZ]; /* Accumulation buffer */ +} sha_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @sha_compress@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: SHA compression function. + */ + +extern void sha_compress(sha_ctx */*ctx*/, const void */*sbuf*/); + +/* --- @sha_init@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void sha_init(sha_ctx */*ctx*/); + +/* --- @sha_set@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void sha_set(sha_ctx */*ctx*/, const void */*buf*/, + unsigned long /*count*/); + +/* --- @sha_hash@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void sha_hash(sha_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/); + +/* --- @sha_done@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void sha_done(sha_ctx */*ctx*/, void */*hash*/); + +/* --- @sha_state@ --- * + * + * Arguments: @sha_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @sha_set@. + */ + +extern unsigned long sha_state(sha_ctx */*ctx*/, void */*state*/); + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash sha; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/sha224.c b/symm/sha224.c new file mode 100644 index 0000000..997c51a --- /dev/null +++ b/symm/sha224.c @@ -0,0 +1,12 @@ +/* -*-c-*- + * + * Stub code for SHA-224 + */ + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "sha224.h" + +GHASH_DEF(SHA224, sha224) +HASH_TEST(SHA224, sha224) diff --git a/symm/sha224.h b/symm/sha224.h new file mode 100644 index 0000000..3a49569 --- /dev/null +++ b/symm/sha224.h @@ -0,0 +1,11 @@ +/* -*-c-*- + * + * Stub header for SHA-224 + */ + +#ifndef CATACOMB_SHA224_H +#define CATACOMB_SHA224_H + +#include "sha256.h" + +#endif diff --git a/symm/sha256.c b/symm/sha256.c new file mode 100644 index 0000000..a8796d3 --- /dev/null +++ b/symm/sha256.c @@ -0,0 +1,333 @@ +/* -*-c-*- + * + * Implementation of the SHA-256 hash function + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "sha256.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @sha256_compress@, @sha224_compress@ --- * + * + * Arguments: @sha256_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: SHA-256 compression function. + */ + +void sha256_compress(sha256_ctx *ctx, const void *sbuf) +{ + uint32 a, b, c, d, e, f, g, h; + uint32 buf[64]; + + /* --- Fetch the chaining variables --- */ + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + e = ctx->e; + f = ctx->f; + g = ctx->g; + h = ctx->h; + + /* --- Definitions for round functions --- */ + +#define CH(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define MAJ(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) + +#define S0(x) (ROR32((x), 2) ^ ROR32((x), 13) ^ ROR32((x), 22)) +#define S1(x) (ROR32((x), 6) ^ ROR32((x), 11) ^ ROR32((x), 25)) +#define s0(x) (ROR32((x), 7) ^ ROR32((x), 18) ^ LSR32((x), 3)) +#define s1(x) (ROR32((x), 17) ^ ROR32((x), 19) ^ LSR32((x), 10)) + +#define T(a, b, c, d, e, f, g, h, i, k) do { \ + uint32 t1 = h + S1(e) + CH(e, f, g) + k + buf[i]; \ + uint32 t2 = S0(a) + MAJ(a, b, c); \ + d += t1; h = t1 + t2; \ +} while (0) + + /* --- Fetch and expand the buffer contents --- */ + + { + int i; + const octet *p; + + for (i = 0, p = sbuf; i < 16; i++, p += 4) + buf[i] = LOAD32(p); + for (i = 16; i < 64; i++) + buf[i] = s1(buf[i - 2]) + buf[i - 7] + s0(buf[i - 15]) + buf[i - 16]; + } + + /* --- The main compression function --- */ + + T(a, b, c, d, e, f, g, h, 0, 0x428a2f98); + T(h, a, b, c, d, e, f, g, 1, 0x71374491); + T(g, h, a, b, c, d, e, f, 2, 0xb5c0fbcf); + T(f, g, h, a, b, c, d, e, 3, 0xe9b5dba5); + T(e, f, g, h, a, b, c, d, 4, 0x3956c25b); + T(d, e, f, g, h, a, b, c, 5, 0x59f111f1); + T(c, d, e, f, g, h, a, b, 6, 0x923f82a4); + T(b, c, d, e, f, g, h, a, 7, 0xab1c5ed5); + T(a, b, c, d, e, f, g, h, 8, 0xd807aa98); + T(h, a, b, c, d, e, f, g, 9, 0x12835b01); + T(g, h, a, b, c, d, e, f, 10, 0x243185be); + T(f, g, h, a, b, c, d, e, 11, 0x550c7dc3); + T(e, f, g, h, a, b, c, d, 12, 0x72be5d74); + T(d, e, f, g, h, a, b, c, 13, 0x80deb1fe); + T(c, d, e, f, g, h, a, b, 14, 0x9bdc06a7); + T(b, c, d, e, f, g, h, a, 15, 0xc19bf174); + T(a, b, c, d, e, f, g, h, 16, 0xe49b69c1); + T(h, a, b, c, d, e, f, g, 17, 0xefbe4786); + T(g, h, a, b, c, d, e, f, 18, 0x0fc19dc6); + T(f, g, h, a, b, c, d, e, 19, 0x240ca1cc); + T(e, f, g, h, a, b, c, d, 20, 0x2de92c6f); + T(d, e, f, g, h, a, b, c, 21, 0x4a7484aa); + T(c, d, e, f, g, h, a, b, 22, 0x5cb0a9dc); + T(b, c, d, e, f, g, h, a, 23, 0x76f988da); + T(a, b, c, d, e, f, g, h, 24, 0x983e5152); + T(h, a, b, c, d, e, f, g, 25, 0xa831c66d); + T(g, h, a, b, c, d, e, f, 26, 0xb00327c8); + T(f, g, h, a, b, c, d, e, 27, 0xbf597fc7); + T(e, f, g, h, a, b, c, d, 28, 0xc6e00bf3); + T(d, e, f, g, h, a, b, c, 29, 0xd5a79147); + T(c, d, e, f, g, h, a, b, 30, 0x06ca6351); + T(b, c, d, e, f, g, h, a, 31, 0x14292967); + T(a, b, c, d, e, f, g, h, 32, 0x27b70a85); + T(h, a, b, c, d, e, f, g, 33, 0x2e1b2138); + T(g, h, a, b, c, d, e, f, 34, 0x4d2c6dfc); + T(f, g, h, a, b, c, d, e, 35, 0x53380d13); + T(e, f, g, h, a, b, c, d, 36, 0x650a7354); + T(d, e, f, g, h, a, b, c, 37, 0x766a0abb); + T(c, d, e, f, g, h, a, b, 38, 0x81c2c92e); + T(b, c, d, e, f, g, h, a, 39, 0x92722c85); + T(a, b, c, d, e, f, g, h, 40, 0xa2bfe8a1); + T(h, a, b, c, d, e, f, g, 41, 0xa81a664b); + T(g, h, a, b, c, d, e, f, 42, 0xc24b8b70); + T(f, g, h, a, b, c, d, e, 43, 0xc76c51a3); + T(e, f, g, h, a, b, c, d, 44, 0xd192e819); + T(d, e, f, g, h, a, b, c, 45, 0xd6990624); + T(c, d, e, f, g, h, a, b, 46, 0xf40e3585); + T(b, c, d, e, f, g, h, a, 47, 0x106aa070); + T(a, b, c, d, e, f, g, h, 48, 0x19a4c116); + T(h, a, b, c, d, e, f, g, 49, 0x1e376c08); + T(g, h, a, b, c, d, e, f, 50, 0x2748774c); + T(f, g, h, a, b, c, d, e, 51, 0x34b0bcb5); + T(e, f, g, h, a, b, c, d, 52, 0x391c0cb3); + T(d, e, f, g, h, a, b, c, 53, 0x4ed8aa4a); + T(c, d, e, f, g, h, a, b, 54, 0x5b9cca4f); + T(b, c, d, e, f, g, h, a, 55, 0x682e6ff3); + T(a, b, c, d, e, f, g, h, 56, 0x748f82ee); + T(h, a, b, c, d, e, f, g, 57, 0x78a5636f); + T(g, h, a, b, c, d, e, f, 58, 0x84c87814); + T(f, g, h, a, b, c, d, e, 59, 0x8cc70208); + T(e, f, g, h, a, b, c, d, 60, 0x90befffa); + T(d, e, f, g, h, a, b, c, 61, 0xa4506ceb); + T(c, d, e, f, g, h, a, b, 62, 0xbef9a3f7); + T(b, c, d, e, f, g, h, a, 63, 0xc67178f2); + + /* --- Update the chaining variables --- */ + + ctx->a += a; + ctx->b += b; + ctx->c += c; + ctx->d += d; + ctx->e += e; + ctx->f += f; + ctx->g += g; + ctx->h += h; +} + +/* --- @sha256_init@, @sha224_init@ --- * + * + * Arguments: @sha256_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void sha256_init(sha256_ctx *ctx) +{ + ctx->a = 0x6a09e667; + ctx->b = 0xbb67ae85; + ctx->c = 0x3c6ef372; + ctx->d = 0xa54ff53a; + ctx->e = 0x510e527f; + ctx->f = 0x9b05688c; + ctx->g = 0x1f83d9ab; + ctx->h = 0x5be0cd19; + ctx->off = 0; + ctx->nl = ctx->nh = 0; +} + +void sha224_init(sha256_ctx *ctx) +{ + ctx->a = 0xc1059ed8; + ctx->b = 0x367cd507; + ctx->c = 0x3070dd17; + ctx->d = 0xf70e5939; + ctx->e = 0xffc00b31; + ctx->f = 0x68581511; + ctx->g = 0x64f98fa7; + ctx->h = 0xbefa4fa4; + ctx->off = 0; + ctx->nl = ctx->nh = 0; +} + +/* --- @sha256_set@, @sha224_set@ --- * + * + * Arguments: @sha256_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void sha256_set(sha256_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + ctx->a = LOAD32(p + 0); + ctx->b = LOAD32(p + 4); + ctx->c = LOAD32(p + 8); + ctx->d = LOAD32(p + 12); + ctx->e = LOAD32(p + 16); + ctx->f = LOAD32(p + 20); + ctx->g = LOAD32(p + 24); + ctx->h = LOAD32(p + 28); + ctx->off = 0; + ctx->nl = U32(count); + ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); +} + +/* --- @sha256_hash@, @sha224_hash@ --- * + * + * Arguments: @sha256_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void sha256_hash(sha256_ctx *ctx, const void *buf, size_t sz) +{ + HASH_BUFFER(SHA256, sha256, ctx, buf, sz); +} + +/* --- @sha256_done, @sha224_done@ --- * + * + * Arguments: @sha256_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +static void final(sha256_ctx *ctx) +{ + HASH_PAD(SHA256, sha256, ctx, 0x80, 0, 8); + STORE32(ctx->buf + SHA256_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3)); + STORE32(ctx->buf + SHA256_BUFSZ - 4, ctx->nl << 3); + sha256_compress(ctx, ctx->buf); +} + +void sha256_done(sha256_ctx *ctx, void *hash) +{ + octet *p = hash; + final(ctx); + STORE32(p + 0, ctx->a); + STORE32(p + 4, ctx->b); + STORE32(p + 8, ctx->c); + STORE32(p + 12, ctx->d); + STORE32(p + 16, ctx->e); + STORE32(p + 20, ctx->f); + STORE32(p + 24, ctx->g); + STORE32(p + 28, ctx->h); +} + +void sha224_done(sha224_ctx *ctx, void *hash) +{ + octet *p = hash; + final(ctx); + STORE32(p + 0, ctx->a); + STORE32(p + 4, ctx->b); + STORE32(p + 8, ctx->c); + STORE32(p + 12, ctx->d); + STORE32(p + 16, ctx->e); + STORE32(p + 20, ctx->f); + STORE32(p + 24, ctx->g); +} + +/* --- @sha256_state@, @sha224_state@ --- * + * + * Arguments: @sha256_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @sha256_set@. + */ + +unsigned long sha256_state(sha256_ctx *ctx, void *state) +{ + octet *p = state; + STORE32(p + 0, ctx->a); + STORE32(p + 4, ctx->b); + STORE32(p + 8, ctx->c); + STORE32(p + 12, ctx->d); + STORE32(p + 16, ctx->e); + STORE32(p + 20, ctx->f); + STORE32(p + 24, ctx->g); + STORE32(p + 28, ctx->h); + return (ctx->nl | ((ctx->nh << 16) << 16)); +} + +/* --- Generic interface --- */ + +GHASH_DEF(SHA256, sha256) + +/* --- Test code --- */ + +HASH_TEST(SHA256, sha256) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/sha256.h b/symm/sha256.h new file mode 100644 index 0000000..aab843d --- /dev/null +++ b/symm/sha256.h @@ -0,0 +1,169 @@ +/* -*-c-*- + * + * Implementation of the SHA-256 hash function + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the SHA-256 hash function --------------------------------* + * + * SHA-1 (Secure Hash Algorithm) was designed by the NSA, for use with the + * Digital Signature Algorithm. This is an evolution with a larger output + * size, intended to provide security commensurate with 128-bit AES. At the + * time of writing, SHA-256 is very new, and can't be trusted too far. + */ + +#ifndef CATACOMB_SHA256_H +#define CATACOMB_SHA256_H +#define CATACOMB_SHA224_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define SHA256_BUFSZ 64 +#define SHA256_HASHSZ 32 +#define SHA256_STATESZ 32 + +#define SHA224_BUFSZ 64 +#define SHA224_HASHSZ 28 +#define SHA224_STATESZ 32 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct sha256_ctx { + uint32 a, b, c, d, e, f, g, h; /* Chaining variables */ + uint32 nl, nh; /* Byte count so far */ + unsigned off; /* Offset into buffer */ + octet buf[SHA256_BUFSZ]; /* Accumulation buffer */ +} sha256_ctx, sha224_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @sha256_compress@, @sha224_compress@ --- * + * + * Arguments: @sha256_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: SHA-256 compression function. + */ + +extern void sha256_compress(sha256_ctx */*ctx*/, const void */*sbuf*/); +#define sha224_compress sha256_compress + +/* --- @sha256_init@, @sha224_init@ --- * + * + * Arguments: @sha256_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void sha256_init(sha256_ctx */*ctx*/); +extern void sha224_init(sha256_ctx */*ctx*/); + +/* --- @sha256_set@, @sha224_set@ --- * + * + * Arguments: @sha256_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void sha256_set(sha256_ctx */*ctx*/, const void */*buf*/, + unsigned long /*count*/); +#define sha224_set sha256_set + +/* --- @sha256_hash@, @sha224_hash@ --- * + * + * Arguments: @sha256_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void sha256_hash(sha256_ctx */*ctx*/, + const void */*buf*/, size_t /*sz*/); +#define sha224_hash sha256_hash + +/* --- @sha256_done@, @sha224_done@ --- * + * + * Arguments: @sha256_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void sha256_done(sha256_ctx */*ctx*/, void */*hash*/); +extern void sha224_done(sha256_ctx */*ctx*/, void */*hash*/); + +/* --- @sha256_state@, @sha224_state@ --- * + * + * Arguments: @sha256_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @sha256_set@. + */ + +extern unsigned long sha256_state(sha256_ctx */*ctx*/, void */*state*/); +#define sha224_state sha256_state + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash sha256; +extern const gchash sha224; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/sha384.c b/symm/sha384.c new file mode 100644 index 0000000..e7de7ad --- /dev/null +++ b/symm/sha384.c @@ -0,0 +1,12 @@ +/* -*-c-*- + * + * Stub code for SHA-384 + */ + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "sha384.h" + +GHASH_DEF(SHA384, sha384) +HASH_TEST(SHA384, sha384) diff --git a/symm/sha384.h b/symm/sha384.h new file mode 100644 index 0000000..ed7731f --- /dev/null +++ b/symm/sha384.h @@ -0,0 +1,11 @@ +/* -*-c-*- + * + * Stub header for SHA-384 + */ + +#ifndef CATACOMB_SHA384_H +#define CATACOMB_SHA384_H + +#include "sha512.h" + +#endif diff --git a/symm/sha512.c b/symm/sha512.c new file mode 100644 index 0000000..d4df182 --- /dev/null +++ b/symm/sha512.c @@ -0,0 +1,340 @@ +/* -*-c-*- + * + * Implementation of the SHA-512 hash function + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "sha512.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @sha512_compress@, @sha384_compress@ --- * + * + * Arguments: @sha512_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: SHA-512 compression function. + */ + +void sha512_compress(sha512_ctx *ctx, const void *sbuf) +{ + kludge64 a, b, c, d, e, f, g, h; + kludge64 buf[80]; + int i; + + static const kludge64 K[80] = { + X64(428a2f98, d728ae22), X64(71374491, 23ef65cd), + X64(b5c0fbcf, ec4d3b2f), X64(e9b5dba5, 8189dbbc), + X64(3956c25b, f348b538), X64(59f111f1, b605d019), + X64(923f82a4, af194f9b), X64(ab1c5ed5, da6d8118), + X64(d807aa98, a3030242), X64(12835b01, 45706fbe), + X64(243185be, 4ee4b28c), X64(550c7dc3, d5ffb4e2), + X64(72be5d74, f27b896f), X64(80deb1fe, 3b1696b1), + X64(9bdc06a7, 25c71235), X64(c19bf174, cf692694), + X64(e49b69c1, 9ef14ad2), X64(efbe4786, 384f25e3), + X64(0fc19dc6, 8b8cd5b5), X64(240ca1cc, 77ac9c65), + X64(2de92c6f, 592b0275), X64(4a7484aa, 6ea6e483), + X64(5cb0a9dc, bd41fbd4), X64(76f988da, 831153b5), + X64(983e5152, ee66dfab), X64(a831c66d, 2db43210), + X64(b00327c8, 98fb213f), X64(bf597fc7, beef0ee4), + X64(c6e00bf3, 3da88fc2), X64(d5a79147, 930aa725), + X64(06ca6351, e003826f), X64(14292967, 0a0e6e70), + X64(27b70a85, 46d22ffc), X64(2e1b2138, 5c26c926), + X64(4d2c6dfc, 5ac42aed), X64(53380d13, 9d95b3df), + X64(650a7354, 8baf63de), X64(766a0abb, 3c77b2a8), + X64(81c2c92e, 47edaee6), X64(92722c85, 1482353b), + X64(a2bfe8a1, 4cf10364), X64(a81a664b, bc423001), + X64(c24b8b70, d0f89791), X64(c76c51a3, 0654be30), + X64(d192e819, d6ef5218), X64(d6990624, 5565a910), + X64(f40e3585, 5771202a), X64(106aa070, 32bbd1b8), + X64(19a4c116, b8d2d0c8), X64(1e376c08, 5141ab53), + X64(2748774c, df8eeb99), X64(34b0bcb5, e19b48a8), + X64(391c0cb3, c5c95a63), X64(4ed8aa4a, e3418acb), + X64(5b9cca4f, 7763e373), X64(682e6ff3, d6b2b8a3), + X64(748f82ee, 5defb2fc), X64(78a5636f, 43172f60), + X64(84c87814, a1f0ab72), X64(8cc70208, 1a6439ec), + X64(90befffa, 23631e28), X64(a4506ceb, de82bde9), + X64(bef9a3f7, b2c67915), X64(c67178f2, e372532b), + X64(ca273ece, ea26619c), X64(d186b8c7, 21c0c207), + X64(eada7dd6, cde0eb1e), X64(f57d4f7f, ee6ed178), + X64(06f067aa, 72176fba), X64(0a637dc5, a2c898a6), + X64(113f9804, bef90dae), X64(1b710b35, 131c471b), + X64(28db77f5, 23047d84), X64(32caab7b, 40c72493), + X64(3c9ebe0a, 15c9bebc), X64(431d67c4, 9c100d4c), + X64(4cc5d4be, cb3e42b6), X64(597f299c, fc657e2a), + X64(5fcb6fab, 3ad6faec), X64(6c44198c, 4a475817) + }; + + /* --- Fetch the chaining variables --- */ + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + e = ctx->e; + f = ctx->f; + g = ctx->g; + h = ctx->h; + + /* --- Definitions for round functions --- */ + +#define CH(d, x, y, z) do { \ + kludge64 _x; AND64((d), (x), (y)); CPL64(_x, (x)); \ + AND64(_x, _x, (z)); OR64((d), (d), _x); \ +} while (0) + +#define MAJ(d, x, y, z) do { \ + kludge64 _x; AND64((d), (x), (y)); AND64(_x, (x), (z)); \ + OR64((d), (d), _x); AND64(_x, (y), (z)); OR64((d), (d), _x); \ +} while (0) + +#define SIGMA(d, x, i, j, k, last, what) do { \ + kludge64 _x; ROR64_((d), (x), (i)); ROR64_(_x, (x), (j)); \ + XOR64((d), (d), _x); last##64_(_x, (x), (k)); XOR64((d), (d), _x); \ +} while (0) + +#define S0(d, x) SIGMA(d, x, 28, 34, 39, ROR, S0); +#define S1(d, x) SIGMA(d, x, 14, 18, 41, ROR, S1); +#define s0(d, x) SIGMA(d, x, 1, 8, 7, LSR, s0); +#define s1(d, x) SIGMA(d, x, 19, 61, 6, LSR, s1); + +#define T(a, b, c, d, e, f, g, h, i) do { \ + kludge64 t1, t2, x; \ + ADD64(t1, buf[i], K[i]); ADD64(t1, t1, h); \ + S1(x, e); ADD64(t1, t1, x); CH(x, e, f, g); ADD64(t1, t1, x); \ + S0(t2, a); MAJ(x, a, b, c); ADD64(t2, t2, x); \ + ADD64(d, d, t1); ADD64(h, t1, t2); \ +} while (0) + + /* --- Fetch and expand the buffer contents --- */ + + { + const octet *p; + + for (i = 0, p = sbuf; i < 16; i++, p += 8) + LOAD64_(buf[i], p); + for (i = 16; i < 80; i++) { + kludge64 x; + buf[i] = buf[i - 7]; s1(x, buf[i - 2]); ADD64(buf[i], buf[i], x); + s0(x, buf[i - 15]); ADD64(buf[i], buf[i], x); + ADD64(buf[i], buf[i], buf[i - 16]); + } + } + + /* --- The main compression function --- */ + + for (i = 0; i < 80; i += 8) { + T(a, b, c, d, e, f, g, h, i + 0); + T(h, a, b, c, d, e, f, g, i + 1); + T(g, h, a, b, c, d, e, f, i + 2); + T(f, g, h, a, b, c, d, e, i + 3); + T(e, f, g, h, a, b, c, d, i + 4); + T(d, e, f, g, h, a, b, c, i + 5); + T(c, d, e, f, g, h, a, b, i + 6); + T(b, c, d, e, f, g, h, a, i + 7); + } + + /* --- Update the chaining variables --- */ + + ADD64(ctx->a, ctx->a, a); + ADD64(ctx->b, ctx->b, b); + ADD64(ctx->c, ctx->c, c); + ADD64(ctx->d, ctx->d, d); + ADD64(ctx->e, ctx->e, e); + ADD64(ctx->f, ctx->f, f); + ADD64(ctx->g, ctx->g, g); + ADD64(ctx->h, ctx->h, h); +} + +/* --- @sha512_init@, @sha384_init@ --- * + * + * Arguments: @sha512_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void sha512_init(sha512_ctx *ctx) +{ + SET64(ctx->a, 0x6a09e667, 0xf3bcc908); + SET64(ctx->b, 0xbb67ae85, 0x84caa73b); + SET64(ctx->c, 0x3c6ef372, 0xfe94f82b); + SET64(ctx->d, 0xa54ff53a, 0x5f1d36f1); + SET64(ctx->e, 0x510e527f, 0xade682d1); + SET64(ctx->f, 0x9b05688c, 0x2b3e6c1f); + SET64(ctx->g, 0x1f83d9ab, 0xfb41bd6b); + SET64(ctx->h, 0x5be0cd19, 0x137e2179); + ctx->off = 0; + ctx->nh = ctx->nl = 0; +} + +void sha384_init(sha512_ctx *ctx) +{ + SET64(ctx->a, 0xcbbb9d5d, 0xc1059ed8); + SET64(ctx->b, 0x629a292a, 0x367cd507); + SET64(ctx->c, 0x9159015a, 0x3070dd17); + SET64(ctx->d, 0x152fecd8, 0xf70e5939); + SET64(ctx->e, 0x67332667, 0xffc00b31); + SET64(ctx->f, 0x8eb44a87, 0x68581511); + SET64(ctx->g, 0xdb0c2e0d, 0x64f98fa7); + SET64(ctx->h, 0x47b5481d, 0xbefa4fa4); + ctx->off = 0; + ctx->nh = ctx->nl = 0; +} + +/* --- @sha512_set@, @sha384_set@ --- * + * + * Arguments: @sha512_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void sha512_set(sha512_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + LOAD64_(ctx->a, p + 0); + LOAD64_(ctx->b, p + 8); + LOAD64_(ctx->c, p + 16); + LOAD64_(ctx->d, p + 24); + LOAD64_(ctx->e, p + 32); + LOAD64_(ctx->f, p + 40); + LOAD64_(ctx->g, p + 48); + LOAD64_(ctx->h, p + 56); + ctx->off = 0; + ctx->nl = U32(count); + ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); +} + +/* --- @sha512_hash@, @sha384_hash@ --- * + * + * Arguments: @sha512_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void sha512_hash(sha512_ctx *ctx, const void *buf, size_t sz) +{ + HASH_BUFFER(SHA512, sha512, ctx, buf, sz); +} + +/* --- @sha512_done@, @sha384_done@ --- * + * + * Arguments: @sha512_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +static void final(sha512_ctx *ctx) +{ + HASH_PAD(SHA512, sha512, ctx, 0x80, 0, 16); + memset(ctx->buf + SHA512_BUFSZ - 16, 0, 8); + STORE32(ctx->buf + SHA512_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3)); + STORE32(ctx->buf + SHA512_BUFSZ - 4, ctx->nl << 3); + sha512_compress(ctx, ctx->buf); +} + +void sha512_done(sha512_ctx *ctx, void *hash) +{ + octet *p = hash; + final(ctx); + STORE64_(p + 0, ctx->a); + STORE64_(p + 8, ctx->b); + STORE64_(p + 16, ctx->c); + STORE64_(p + 24, ctx->d); + STORE64_(p + 32, ctx->e); + STORE64_(p + 40, ctx->f); + STORE64_(p + 48, ctx->g); + STORE64_(p + 56, ctx->h); +} + +void sha384_done(sha384_ctx *ctx, void *hash) +{ + octet *p = hash; + final(ctx); + STORE64_(p + 0, ctx->a); + STORE64_(p + 8, ctx->b); + STORE64_(p + 16, ctx->c); + STORE64_(p + 24, ctx->d); + STORE64_(p + 32, ctx->e); + STORE64_(p + 40, ctx->f); +} + +/* --- @sha512_state@, @sha384_state@ --- * + * + * Arguments: @sha512_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @sha512_set@. + */ + +unsigned long sha512_state(sha512_ctx *ctx, void *state) +{ + octet *p = state; + STORE64_(p + 0, ctx->a); + STORE64_(p + 8, ctx->b); + STORE64_(p + 16, ctx->c); + STORE64_(p + 24, ctx->d); + STORE64_(p + 32, ctx->e); + STORE64_(p + 40, ctx->f); + STORE64_(p + 48, ctx->g); + STORE64_(p + 56, ctx->h); + return (ctx->nl | ((ctx->nh << 16) << 16)); +} + +/* --- Generic interface --- */ + +GHASH_DEF(SHA512, sha512) + +/* --- Test code --- */ + +HASH_TEST(SHA512, sha512) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/sha512.h b/symm/sha512.h new file mode 100644 index 0000000..2f3edc2 --- /dev/null +++ b/symm/sha512.h @@ -0,0 +1,171 @@ +/* -*-c-*- + * + * Implementation of the SHA-512 hash function + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the SHA-512 hash function --------------------------------* + * + * SHA-1 (Secure Hash Algorithm) was designed by the NSA, for use with the + * Digital Signature Algorithm. This is an evolution with a larger output + * size, intended to provide security commensurate with 256-bit AES. At the + * time of writing, SHA-512 is very new, and can't be trusted too far. There + * is also a truncated version, SHA-384, which provides security commensurate + * with 192-bit AES. + */ + +#ifndef CATACOMB_SHA512_H +#define CATACOMB_SHA512_H +#define CATACOMB_SHA384_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define SHA512_BUFSZ 128 +#define SHA512_HASHSZ 64 +#define SHA512_STATESZ 64 + +#define SHA384_BUFSZ 128 +#define SHA384_HASHSZ 48 +#define SHA384_STATESZ 64 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct sha512_ctx { + kludge64 a, b, c, d, e, f, g, h; /* Chaining variables */ + uint32 nh, nl; /* Byte count so far */ + unsigned off; /* Offset into buffer */ + octet buf[SHA512_BUFSZ]; /* Accumulation buffer */ +} sha512_ctx, sha384_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @sha512_compress@, @sha384_compress@ --- * + * + * Arguments: @sha512_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: SHA-512 compression function. + */ + +extern void sha512_compress(sha512_ctx */*ctx*/, const void */*sbuf*/); +#define sha384_compress sha512_compress + +/* --- @sha512_init@, @sha384_init@ --- * + * + * Arguments: @sha512_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void sha512_init(sha512_ctx */*ctx*/); +extern void sha384_init(sha512_ctx */*ctx*/); + +/* --- @sha512_set@, @sha384_set@ --- * + * + * Arguments: @sha512_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void sha512_set(sha512_ctx */*ctx*/, const void */*buf*/, + unsigned long /*count*/); +#define sha384_set sha512_set + +/* --- @sha512_hash@, @sha384_hash@ --- * + * + * Arguments: @sha512_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void sha512_hash(sha512_ctx */*ctx*/, + const void */*buf*/, size_t /*sz*/); +#define sha384_hash sha512_hash + +/* --- @sha512_done@, @sha384_done@ --- * + * + * Arguments: @sha512_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void sha512_done(sha512_ctx */*ctx*/, void */*hash*/); +extern void sha384_done(sha512_ctx */*ctx*/, void */*hash*/); + +/* --- @sha512_state@, @sha384_state@ --- * + * + * Arguments: @sha512_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @sha512_set@. + */ + +extern unsigned long sha512_state(sha512_ctx */*ctx*/, void */*state*/); +#define sha384_state sha512_state + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash sha512; +extern const gchash sha384; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/skipjack-tab.h b/symm/skipjack-tab.h new file mode 100644 index 0000000..8994bbb --- /dev/null +++ b/symm/skipjack-tab.h @@ -0,0 +1,78 @@ +/* -*-c-*- + * + * The Skipjack S-box + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_SKIPJACK_TAB_H +#define CATACOMB_SKIPJACK_TAB_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- The S-box ---------------------------------------------------------*/ + +#define SKIPJACK_S { \ + 0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4, \ + 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9, \ + 0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e, \ + 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28, \ + 0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68, \ + 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53, \ + 0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19, \ + 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2, \ + 0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b, \ + 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8, \ + 0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0, \ + 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90, \ + 0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69, \ + 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76, \ + 0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20, \ + 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d, \ + 0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43, \ + 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18, \ + 0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa, \ + 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4, \ + 0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87, \ + 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40, \ + 0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b, \ + 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5, \ + 0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0, \ + 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2, \ + 0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1, \ + 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8, \ + 0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5, \ + 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac, \ + 0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3, \ + 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46 \ +} + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/skipjack.c b/symm/skipjack.c new file mode 100644 index 0000000..bd58ede --- /dev/null +++ b/symm/skipjack.c @@ -0,0 +1,176 @@ +/* -*-c-*- + * + * The Skipjack block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "skipjack.h" +#include "skipjack-tab.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet skipjack_keysz[] = { KSZ_SET, 10, 0 }; + +/*----- The Skipjack S-box ------------------------------------------------*/ + +static const octet f[256] = SKIPJACK_S; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @skipjack_init@ --- * + * + * Arguments: @skipjack_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a Skipjack key buffer. The key buffer must be + * exactly 10 bytes long. + */ + +void skipjack_init(skipjack_ctx *k, const void *buf, size_t sz) +{ + const octet *b = buf; + uint32 crud; + KSZ_ASSERT(skipjack, sz); + k->ka = LOAD32(b); + k->kb = LOAD32(b + 4); + crud = LOAD16(b + 8); + k->kc = U32((crud << 16) | (k->ka >> 16)); + k->kd = U32((k->ka << 16) | (k->kb >> 16)); + k->ke = U32((k->kb << 16) | crud); + crud = 0; +} + +/* --- @skipjack_eblk@, @skipjack_dblk@ --- * + * + * Arguments: @const skipjack_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to skipjacktination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +#define G(x, k) do { \ + octet _x = U8(x >> 8), _y = U8(x); \ + _x ^= f[_y ^ U8(k >> 24)]; \ + _y ^= f[_x ^ U8(k >> 16)]; \ + _x ^= f[_y ^ U8(k >> 8)]; \ + _y ^= f[_x ^ U8(k >> 0)]; \ + x = (_x << 8) | _y; \ +} while (0) + +#define RULE_A(w, x, y, z, n, k) do { \ + G(w, k); z ^= w ^ n++; \ +} while (0) + +#define RULE_B(w, x, y, z, n, k) do { \ + x ^= w ^ n++; G(w, k); \ +} while (0) + +void skipjack_eblk(const skipjack_ctx *k, const uint32 *s, uint32 *d) +{ + unsigned n = 1; + uint16 w = U16(s[0] >> 16), x = U16(s[0]); + uint16 y = U16(s[1] >> 16), z = U16(s[1]); + uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd, ke = k->ke; + + RULE_A(w, x, y, z, n, ka); RULE_A(z, w, x, y, n, kb); + RULE_A(y, z, w, x, n, kc); RULE_A(x, y, z, w, n, kd); + RULE_A(w, x, y, z, n, ke); RULE_A(z, w, x, y, n, ka); + RULE_A(y, z, w, x, n, kb); RULE_A(x, y, z, w, n, kc); + RULE_B(w, x, y, z, n, kd); RULE_B(z, w, x, y, n, ke); + RULE_B(y, z, w, x, n, ka); RULE_B(x, y, z, w, n, kb); + RULE_B(w, x, y, z, n, kc); RULE_B(z, w, x, y, n, kd); + RULE_B(y, z, w, x, n, ke); RULE_B(x, y, z, w, n, ka); + RULE_A(w, x, y, z, n, kb); RULE_A(z, w, x, y, n, kc); + RULE_A(y, z, w, x, n, kd); RULE_A(x, y, z, w, n, ke); + RULE_A(w, x, y, z, n, ka); RULE_A(z, w, x, y, n, kb); + RULE_A(y, z, w, x, n, kc); RULE_A(x, y, z, w, n, kd); + RULE_B(w, x, y, z, n, ke); RULE_B(z, w, x, y, n, ka); + RULE_B(y, z, w, x, n, kb); RULE_B(x, y, z, w, n, kc); + RULE_B(w, x, y, z, n, kd); RULE_B(z, w, x, y, n, ke); + RULE_B(y, z, w, x, n, ka); RULE_B(x, y, z, w, n, kb); + + d[0] = ((uint32)w << 16) | (uint32)x; + d[1] = ((uint32)y << 16) | (uint32)z; +} + +#define G_INV(x, k) do { \ + octet _x = U8(x >> 8), _y = U8(x); \ + _y ^= f[_x ^ U8(k >> 0)]; \ + _x ^= f[_y ^ U8(k >> 8)]; \ + _y ^= f[_x ^ U8(k >> 16)]; \ + _x ^= f[_y ^ U8(k >> 24)]; \ + x = (_x << 8) | _y; \ +} while (0) + +#define RULE_A_INV(w, x, y, z, n, i) do { \ + w ^= x ^ --n; G_INV(x, i); \ +} while (0) + +#define RULE_B_INV(w, x, y, z, n, i) do { \ + G_INV(x, i); y ^= x ^ --n; \ +} while (0) + +void skipjack_dblk(const skipjack_ctx *k, const uint32 *s, uint32 *d) +{ + unsigned n = 33; + uint16 w = U16(s[0] >> 16), x = U16(s[0]); + uint16 y = U16(s[1] >> 16), z = U16(s[1]); + uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd, ke = k->ke; + + RULE_B_INV(w, x, y, z, n, kb); RULE_B_INV(x, y, z, w, n, ka); + RULE_B_INV(y, z, w, x, n, ke); RULE_B_INV(z, w, x, y, n, kd); + RULE_B_INV(w, x, y, z, n, kc); RULE_B_INV(x, y, z, w, n, kb); + RULE_B_INV(y, z, w, x, n, ka); RULE_B_INV(z, w, x, y, n, ke); + RULE_A_INV(w, x, y, z, n, kd); RULE_A_INV(x, y, z, w, n, kc); + RULE_A_INV(y, z, w, x, n, kb); RULE_A_INV(z, w, x, y, n, ka); + RULE_A_INV(w, x, y, z, n, ke); RULE_A_INV(x, y, z, w, n, kd); + RULE_A_INV(y, z, w, x, n, kc); RULE_A_INV(z, w, x, y, n, kb); + RULE_B_INV(w, x, y, z, n, ka); RULE_B_INV(x, y, z, w, n, ke); + RULE_B_INV(y, z, w, x, n, kd); RULE_B_INV(z, w, x, y, n, kc); + RULE_B_INV(w, x, y, z, n, kb); RULE_B_INV(x, y, z, w, n, ka); + RULE_B_INV(y, z, w, x, n, ke); RULE_B_INV(z, w, x, y, n, kd); + RULE_A_INV(w, x, y, z, n, kc); RULE_A_INV(x, y, z, w, n, kb); + RULE_A_INV(y, z, w, x, n, ka); RULE_A_INV(z, w, x, y, n, ke); + RULE_A_INV(w, x, y, z, n, kd); RULE_A_INV(x, y, z, w, n, kc); + RULE_A_INV(y, z, w, x, n, kb); RULE_A_INV(z, w, x, y, n, ka); + + d[0] = ((uint32)w << 16) | (uint32)x; + d[1] = ((uint32)y << 16) | (uint32)z; +} + +BLKC_TEST(SKIPJACK, skipjack) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/skipjack.h b/symm/skipjack.h new file mode 100644 index 0000000..ab43709 --- /dev/null +++ b/symm/skipjack.h @@ -0,0 +1,110 @@ +/* -*-c-*- + * + * The Skipjack block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the Skipjack block cipher --------------------------------* + * + * Skipjack was designed by the NSA, as a type II algorithm to be used in the + * Clipper system. It was initially classified, so that it couldn't be used + * without the key escrow feature, though a team of `respectable' + * cryptographers, including Dorothy Denning, had a quick look at it and + * pronounced it `good', as if this was meant to be convincing. It is + * apparently a particular parameterization of a family which includes type I + * algorithms. Since declassification, Biham has discovered a miss-in-the- + * middle attack which breaks Skipjack with 31 rounds faster than brute + * force. + * + * This implementation is provided for interest's sake, and possibly for + * interoperability, rather than as a good cipher to use. + */ + +#ifndef CATACOMB_SKIPJACK_H +#define CATACOMB_SKIPJACK_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magical numbers ---------------------------------------------------*/ + +#define SKIPJACK_BLKSZ 8 +#define SKIPJACK_KEYSZ 10 +#define SKIPJACK_CLASS (N, B, 64) + +extern const octet skipjack_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct skipjack_ctx { + uint32 ka, kb, kc, kd, ke; +} skipjack_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @skipjack_init@ --- * + * + * Arguments: @skipjack_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a Skipjack key buffer. The key buffer must be + * exactly 10 bytes long. + */ + +extern void skipjack_init(skipjack_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @skipjack_eblk@, @skipjack_dblk@ --- * + * + * Arguments: @const skipjack_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to skipjacktination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void skipjack_eblk(const skipjack_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); +extern void skipjack_dblk(const skipjack_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/square-mktab.c b/symm/square-mktab.c new file mode 100644 index 0000000..a2e90e3 --- /dev/null +++ b/symm/square-mktab.c @@ -0,0 +1,366 @@ +/* -*-c-*- + * + * Build precomputed tables for the Square block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include + +/*----- Magic variables ---------------------------------------------------*/ + +static octet s[256], si[256]; +static uint32 t[4][256], ti[4][256]; +static uint32 u[4][256]; +static octet rc[32]; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @mul@ --- * + * + * Arguments: @unsigned x, y@ = polynomials over %$\gf{2^8}$% + * @unsigned m@ = modulus + * + * Returns: The product of two polynomials. + * + * Use: Computes a product of polynomials, quite slowly. + */ + +static unsigned mul(unsigned x, unsigned y, unsigned m) +{ + unsigned a = 0; + unsigned i; + + for (i = 0; i < 8; i++) { + if (y & 1) + a ^= x; + y >>= 1; + x <<= 1; + if (x & 0x100) + x ^= m; + } + + return (a); +} + +/* --- @sbox@ --- * + * + * Build the S-box. + * + * This is built from inversion in the multiplicative group of + * %$\gf{2^8}[x]/(p(x))$%, where %$p(x) = x^8+x^7+x^6+x^5+x^4+x^2+1$%, + * followed by an affine transformation treating inputs as vectors over + * %$\gf{2}$%. The result is a horrible function. + * + * The inversion is done slightly sneakily, by building log and antilog + * tables. Let %$a$% be an element of the finite field. If the inverse of + * %$a$% is %$a^{-1}$%, then %$\log a a^{-1} = 0$%. Hence + * %$\log a = -\log a^{-1}$%. This saves fiddling about with Euclidean + * algorithm. + */ + +#define S_MOD 0x1f5 + +static void sbox(void) +{ + octet log[256], alog[256]; + unsigned x; + unsigned i; + unsigned g; + + /* --- Find a suitable generator, and build log tables --- */ + + log[0] = 0; + for (g = 2; g < 256; g++) { + x = 1; + for (i = 0; i < 256; i++) { + log[x] = i; + alog[i] = x; + x = mul(x, g, S_MOD); + if (x == 1 && i != 254) + goto again; + } + goto done; + again:; + } + fprintf(stderr, "couldn't find generator\n"); + exit(EXIT_FAILURE); +done:; + + /* --- Now grind through and do the affine transform --- * + * + * The matrix multiply is an AND and a parity op. The add is an XOR. + */ + + for (i = 0; i < 256; i++) { + unsigned j; + octet m[] = { 0xd6, 0x7b, 0x3d, 0x1f, 0x0f, 0x05, 0x03, 0x01 }; + unsigned v = i ? alog[255 - log[i]] : 0; + + assert(i == 0 || mul(i, v, S_MOD) == 1); + + x = 0; + for (j = 0; j < 8; j++) { + unsigned r; + r = v & m[j]; + r = (r >> 4) ^ r; + r = (r >> 2) ^ r; + r = (r >> 1) ^ r; + x = (x << 1) | (r & 1); + } + x ^= 0xb1; + s[i] = x; + si[x] = i; + } +} + +/* --- @tbox@ --- * + * + * Construct the t tables for doing the round function efficiently. + */ + +static void tbox(void) +{ + unsigned i; + + for (i = 0; i < 256; i++) { + uint32 a, b, c, d; + uint32 w; + + /* --- Build a forwards t-box entry --- */ + + a = s[i]; + b = a << 1; if (b & 0x100) b ^= S_MOD; + c = a ^ b; + w = (b << 0) | (a << 8) | (a << 16) | (c << 24); + t[0][i] = w; + t[1][i] = ROL32(w, 8); + t[2][i] = ROL32(w, 16); + t[3][i] = ROL32(w, 24); + + /* --- Build a backwards t-box entry --- */ + + a = mul(si[i], 0x0e, S_MOD); + b = mul(si[i], 0x09, S_MOD); + c = mul(si[i], 0x0d, S_MOD); + d = mul(si[i], 0x0b, S_MOD); + w = (a << 0) | (b << 8) | (c << 16) | (d << 24); + ti[0][i] = w; + ti[1][i] = ROL32(w, 8); + ti[2][i] = ROL32(w, 16); + ti[3][i] = ROL32(w, 24); + } +} + +/* --- @ubox@ --- * + * + * Construct the tables for performing the key schedule. + */ + +static void ubox(void) +{ + unsigned i; + + for (i = 0; i < 256; i++) { + uint32 a, b, c; + uint32 w; + a = i; + b = a << 1; if (b & 0x100) b ^= S_MOD; + c = a ^ b; + w = (b << 0) | (a << 8) | (a << 16) | (c << 24); + u[0][i] = w; + u[1][i] = ROL32(w, 8); + u[2][i] = ROL32(w, 16); + u[3][i] = ROL32(w, 24); + } +} + +/* --- Round constants --- */ + +void rcon(void) +{ + unsigned r = 1; + int i; + + for (i = 0; i < sizeof(rc); i++) { + rc[i] = r; + r <<= 1; + if (r & 0x100) + r ^= S_MOD; + } +} + +/* --- @main@ --- */ + +int main(void) +{ + int i, j; + + puts("\ +/* -*-c-*-\n\ + *\n\ + * Square tables [generated]\n\ + */\n\ +\n\ +#ifndef CATACOMB_SQUARE_TAB_H\n\ +#define CATACOMB_SQUARE_TAB_H\n\ +"); + + /* --- Write out the S-box --- */ + + sbox(); + fputs("\ +/* --- The byte substitution and its inverse --- */\n\ +\n\ +#define SQUARE_S { \\\n\ + ", stdout); + for (i = 0; i < 256; i++) { + printf("0x%02x", s[i]); + if (i == 255) + fputs(" \\\n}\n\n", stdout); + else if (i % 8 == 7) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + fputs("\ +#define SQUARE_SI { \\\n\ + ", stdout); + for (i = 0; i < 256; i++) { + printf("0x%02x", si[i]); + if (i == 255) + fputs(" \\\n}\n\n", stdout); + else if (i % 8 == 7) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + /* --- Write out the big t tables --- */ + + tbox(); + fputs("\ +/* --- The big round tables --- */\n\ +\n\ +#define SQUARE_T { \\\n\ + { ", stdout); + for (j = 0; j < 4; j++) { + for (i = 0; i < 256; i++) { + printf("0x%08x", t[j][i]); + if (i == 255) { + if (j == 3) + fputs(" } \\\n}\n\n", stdout); + else + fputs(" }, \\\n\ + \\\n\ + { ", stdout); + } else if (i % 4 == 3) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + } + + fputs("\ +#define SQUARE_TI { \\\n\ + { ", stdout); + for (j = 0; j < 4; j++) { + for (i = 0; i < 256; i++) { + printf("0x%08x", ti[j][i]); + if (i == 255) { + if (j == 3) + fputs(" } \\\n}\n\n", stdout); + else + fputs(" }, \\\n\ + \\\n\ + { ", stdout); + } else if (i % 4 == 3) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + } + + /* --- Write out the big u tables --- */ + + ubox(); + fputs("\ +/* --- The key schedule tables --- */\n\ +\n\ +#define SQUARE_U { \\\n\ + { ", stdout); + for (j = 0; j < 4; j++) { + for (i = 0; i < 256; i++) { + printf("0x%08x", u[j][i]); + if (i == 255) { + if (j == 3) + fputs(" } \\\n}\n\n", stdout); + else + fputs(" }, \\\n\ + \\\n\ + { ", stdout); + } else if (i % 4 == 3) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + } + + /* --- Round constants --- */ + + rcon(); + fputs("\ +/* --- The round constants --- */\n\ +\n\ +#define SQUARE_RCON { \\\n\ + ", stdout); + for (i = 0; i < sizeof(rc); i++) { + printf("0x%02x", rc[i]); + if (i == sizeof(rc) - 1) + fputs(" \\\n}\n\n", stdout); + else if (i % 8 == 7) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + /* --- Done --- */ + + puts("#endif"); + + if (fclose(stdout)) { + fprintf(stderr, "error writing data\n"); + exit(EXIT_FAILURE); + } + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/square.c b/symm/square.c new file mode 100644 index 0000000..490b917 --- /dev/null +++ b/symm/square.c @@ -0,0 +1,194 @@ +/* -*-c-*- + * + * The Square block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "paranoia.h" +#include "square.h" +#include "square-tab.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet square_keysz[] = { KSZ_RANGE, SQUARE_KEYSZ, 4, 16, 4 }; + +/*----- Constant tables ---------------------------------------------------*/ + +static const octet S[256] = SQUARE_S, SI[256] = SQUARE_SI; +static const uint32 T[4][256] = SQUARE_T, TI[4][256] = SQUARE_TI; +static const uint32 U[4][256] = SQUARE_U; +static const octet rcon[] = SQUARE_RCON; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @square_init@ --- * + * + * Arguments: @square_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes a Square context with a particular key. Square + * keys must be a multiple of 32 bits long, and may be at most + * 128 bits. + */ + +void square_init(square_ctx *k, const void *buf, size_t sz) +{ + unsigned nk, nr, nw; + unsigned i, j, jj; + const octet *p; + uint32 ww; + uint32 kk[SQUARE_KWORDS]; + + /* --- Sort out the key size --- */ + + KSZ_ASSERT(square, sz); + nk = sz / 4; + + /* --- Fetch the first key words out --- */ + + p = buf; + for (i = 0; i < nk; i++) { + kk[i] = LOAD32_L(p); + p += 4; + } + nr = 8; + + /* --- Expand this material to fill the rest of the table --- */ + + nw = (nr + 1) * 4; + ww = kk[i - 1]; + p = rcon; + for (; i < nw; i++) { + uint32 w = kk[i - nk]; + if (i % nk == 0) { + ww = ROR32(ww, 8); + w ^= ww ^ *p++; + } else + w ^= ww; + kk[i] = ww = w; + } + + /* --- Make the encryption and decryption keys --- */ + + for (i = 0; i < nr * 4; i++) { + uint32 w = kk[i]; + k->w[i] = (U[0][U8(w >> 0)] ^ U[1][U8(w >> 8)] ^ + U[2][U8(w >> 16)] ^ U[3][U8(w >> 24)]); + } + for (; i < nw; i++) + k->w[i] = kk[i]; + + jj = nw; + for (i = 0; i < nr * 4; i += 4) { + jj -= 4; + for (j = 0; j < 4; j++) + k->wi[i + j] = kk[jj + j]; + } + for (j = 0; j < 4; j++) + k->wi[i + j] = k->w[j]; + + BURN(kk); +} + +/* --- @square_eblk@, @square_dblk@ --- * + * + * Arguments: @const square_ctx *k@ = pointer to Square context + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +#define SUB(s, sh, a, b, c, d) \ + (s[U8((a) >> sh)] << 0 | s[U8((b) >> sh)] << 8 | \ + s[U8((c) >> sh)] << 16 | s[U8((d) >> sh)] << 24) + +#define MIX(t, sh, a, b, c, d) \ + (t[0][U8((a) >> sh)] ^ t[1][U8((b) >> sh)] ^ \ + t[2][U8((c) >> sh)] ^ t[3][U8((d) >> sh)]) + +#define DO(what, t, aa, bb, cc, dd, a, b, c, d, w) do { \ + aa = what(t, 0, a, b, c, d) ^ *w++; \ + bb = what(t, 8, a, b, c, d) ^ *w++; \ + cc = what(t, 16, a, b, c, d) ^ *w++; \ + dd = what(t, 24, a, b, c, d) ^ *w++; \ +} while (0) + +void square_eblk(const square_ctx *k, const uint32 *s, uint32 *dst) +{ + uint32 a = s[0], b = s[1], c = s[2], d = s[3]; + uint32 aa, bb, cc, dd; + const uint32 *w = k->w; + + a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; + + DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); + DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); + DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); + DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); + DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); + DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w); + DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w); + DO(SUB, S, a, b, c, d, aa, bb, cc, dd, w); + + dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; +} + +void square_dblk(const square_ctx *k, const uint32 *s, uint32 *dst) +{ + uint32 a = s[0], b = s[1], c = s[2], d = s[3]; + uint32 aa, bb, cc, dd; + const uint32 *w = k->wi; + + a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; + + DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); + DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); + DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); + DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); + DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); + DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w); + DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w); + DO(SUB, SI, a, b, c, d, aa, bb, cc, dd, w); + + dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; +} + +BLKC_TEST(SQUARE, square) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/square.h b/symm/square.h new file mode 100644 index 0000000..25671d8 --- /dev/null +++ b/symm/square.h @@ -0,0 +1,112 @@ +/* -*-c-*- + * + * The Square block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the Square block cipher ----------------------------------* + * + * Invented by Joan Daemen and Vincent Rijmen, Square is a fast and + * relatively simple 128-bit block cipher. It is the predecessor to + * Rijndael. I have grave doubts about the security of Square, though: a + * dedicated attack against Square's structure by Knudsen has been extended + * by the Twofish team against Rijndael, and I believe that this extended + * attack is also effective against Square. This is a shame: the structure + * of Square (and Rijndael) is extremely elegant, and has some extremely nice + * properties. + */ + +#ifndef CATACOMB_SQUARE_H +#define CATACOMB_SQUARE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magical numbers ---------------------------------------------------*/ + +#define SQUARE_BLKSZ 16 +#define SQUARE_KEYSZ 16 +#define SQUARE_CLASS (N, L, 128) + +extern const octet square_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +#define SQUARE_MAXROUNDS 8 +#define SQUARE_KWORDS ((SQUARE_MAXROUNDS + 1) * (SQUARE_BLKSZ / 4)) + +typedef struct square_ctx { + uint32 w[SQUARE_KWORDS]; + uint32 wi[SQUARE_KWORDS]; +} square_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @square_init@ --- * + * + * Arguments: @square_ctx *k@ = pointer to context to initialize + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes a Square context with a particular key. This + * implementation of Square doesn't impose any particular + * limits on the key size except that it must be multiple of 4 + * bytes long. 256 bits seems sensible, though. + */ + +extern void square_init(square_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @square_eblk@, @square_dblk@ --- * + * + * Arguments: @const square_ctx *k@ = pointer to Square context + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void square_eblk(const square_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); +extern void square_dblk(const square_ctx */*k*/, + const uint32 */*s*/, uint32 */*dst*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/t/.gitignore b/symm/t/.gitignore new file mode 100644 index 0000000..88cf471 --- /dev/null +++ b/symm/t/.gitignore @@ -0,0 +1,5 @@ +cast256 +mars +rijndael +serpent +twofish diff --git a/symm/t/blowfish b/symm/t/blowfish new file mode 100644 index 0000000..449f967 --- /dev/null +++ b/symm/t/blowfish @@ -0,0 +1,119 @@ +# Test vectors for Blowfish + +blowfish { + + # --- Main block cipher --- + # + # Taken from Bruce Schneier's web pages, I think... + + 0000000000000000 0000000000000000 4ef997456198dd78; + ffffffffffffffff ffffffffffffffff 51866fd5b85ecb8a; + 3000000000000000 1000000000000001 7d856f9a613063f2; + 1111111111111111 1111111111111111 2466dd878b963c9d; + 0123456789abcdef 1111111111111111 61f9c3802281b096; + 1111111111111111 0123456789abcdef 7d0cc630afda1ec7; + 0000000000000000 0000000000000000 4ef997456198dd78; + fedcba9876543210 0123456789abcdef 0aceab0fc6a0a28d; + 7ca110454a1a6e57 01a1d6d039776742 59c68245eb05282b; + 0131d9619dc1376e 5cd54ca83def57da b1b8cc0b250f09a0; + 07a1133e4a0b2686 0248d43806f67172 1730e5778bea1da4; + 3849674c2602319e 51454b582ddf440a a25e7856cf2651eb; + 04b915ba43feb5b6 42fd443059577fa2 353882b109ce8f1a; + 0113b970fd34f2ce 059b5e0851cf143a 48f4d0884c379918; + 0170f175468fb5e6 0756d8e0774761d2 432193b78951fc98; + 43297fad38e373fe 762514b829bf486a 13f04154d69d1ae5; + 07a7137045da2a16 3bdd119049372802 2eedda93ffd39c79; + 04689104c2fd3b2f 26955f6835af609a d887e0393c2da6e3; + 37d06bb516cb7546 164d5e404f275232 5f99d04f5b163969; + 1f08260d1ac2465e 6b056e18759f5cca 4a057a3b24d3977b; + 584023641aba6176 004bd6ef09176062 452031c1e4fada8e; + 025816164629b007 480d39006ee762f2 7555ae39f59b87bd; + 49793ebc79b3258f 437540c8698f3cfa 53c55f9cb49fc019; + 4fb05e1515ab73a7 072d43a077075292 7a8e7bfa937e89a3; + 49e95d6d4ca229bf 02fe55778117f12a cf9c5d7a4986adb5; + 018310dc409b26d6 1d9d5c5018f728c2 d1abb290658bc778; + 1c587f1c13924fef 305532286d6f295a 55cb3774d13ef201; + 0101010101010101 0123456789abcdef fa34ec4847b268b2; + 1f1f1f1f0e0e0e0e 0123456789abcdef a790795108ea3cae; + e0fee0fef1fef1fe 0123456789abcdef c39e072d9fac631d; + 0000000000000000 ffffffffffffffff 014933e0cdaff6e4; + ffffffffffffffff 0000000000000000 f21e9a77b71c49bc; + 0123456789abcdef 0000000000000000 245946885754369a; + fedcba9876543210 ffffffffffffffff 6b5c5a9c5d9e0a5a; + + # --- Key schedule test --- + # + # From wherever the previous tests came from. + + f0 + fedcba9876543210 f9ad597c49db005e; + + f0e1 + fedcba9876543210 e91d21c1d961a6d6; + + f0e1d2 + fedcba9876543210 e9c2b70a1bc65cf3; + + f0e1d2c3 + fedcba9876543210 be1e639408640f05; + + f0e1d2c3b4 + fedcba9876543210 b39e44481bdb1e6e; + + f0e1d2c3b4a5 + fedcba9876543210 9457aa83b1928c0d; + + f0e1d2c3b4a596 + fedcba9876543210 8bb77032f960629d; + + f0e1d2c3b4a59687 + fedcba9876543210 e87a244e2cc85e82; + + f0e1d2c3b4a5968778 + fedcba9876543210 15750e7a4f4ec577; + + f0e1d2c3b4a596877869 + fedcba9876543210 122ba70b3ab64ae0; + + f0e1d2c3b4a5968778695a + fedcba9876543210 3a833c9affc537f6; + + f0e1d2c3b4a5968778695a4b + fedcba9876543210 9409da87a90f6bf2; + + f0e1d2c3b4a5968778695a4b3c + fedcba9876543210 884f80625060b8b4; + + f0e1d2c3b4a5968778695a4b3c2d + fedcba9876543210 1f85031c19e11968; + + f0e1d2c3b4a5968778695a4b3c2d1e + fedcba9876543210 79d9373a714ca34f; + + f0e1d2c3b4a5968778695a4b3c2d1e0f + fedcba9876543210 93142887ee3be15c; + + f0e1d2c3b4a5968778695a4b3c2d1e0f00 + fedcba9876543210 03429e838ce2d14b; + + f0e1d2c3b4a5968778695a4b3c2d1e0f0011 + fedcba9876543210 a4299e27469ff67b; + + f0e1d2c3b4a5968778695a4b3c2d1e0f001122 + fedcba9876543210 afd5aed1c1bc96a8; + + f0e1d2c3b4a5968778695a4b3c2d1e0f00112233 + fedcba9876543210 10851c0e3858da9f; + + f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344 + fedcba9876543210 e6f51ed79b9db21f; + + f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455 + fedcba9876543210 64a6e14afd36b46f; + + f0e1d2c3b4a5968778695a4b3c2d1e0f00112233445566 + fedcba9876543210 80c7d7d45a5479ad; + + f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344556677 + fedcba9876543210 05044b62fa52d080; +} diff --git a/symm/t/cast128 b/symm/t/cast128 new file mode 100644 index 0000000..a456ea0 --- /dev/null +++ b/symm/t/cast128 @@ -0,0 +1,15 @@ +# Test vectors for CAST128 + +cast128 { + 0123456712345678234567893456789a + 0123456789abcdef + 238b4fe5847e44b2; + + 01234567123456782345 + 0123456789abcdef + eb6a711a2c02271b; + + 0123456712 + 0123456789abcdef + 7ac816d16e9b302e; +} diff --git a/tests/cast256.aes b/symm/t/cast256.aes similarity index 100% rename from tests/cast256.aes rename to symm/t/cast256.aes diff --git a/symm/t/des b/symm/t/des new file mode 100644 index 0000000..7b75304 --- /dev/null +++ b/symm/t/des @@ -0,0 +1,62 @@ +# Test vectors for DES + +des { + # --- 7-byte keys --- + + 00451338957377 4e6f772069732074 3fa40e8a984d4815; + b6c74cbf60c1fd 328da675ff5abd2c cd3e9f9b670671d1; + + # --- 8-byte keys --- + + 0123456789abcdef 4e6f772069732074 3fa40e8a984d4815; + 0022446688aaccee 4e6f772069732074 3fa40e8a984d4815; + 0123456789abcdef 68652074696d6520 6a271787ab8883f9; + 0123456789abcdef 666f7220616c6c20 893d51ec4b563b53; + 0123456789abcdef 0123456789abcde7 c95744256a5ed31d; + b763d297f70606fb 328da675ff5abd2c cd3e9f9b670671d1; + + # --- Tests for all DES S-boxes --- + + 7ca110454a1a6e57 01a1d6d039776742 690f5b0d9a26939b; + 0131d9619dc1376e 5cd54ca83def57da 7a389d10354bd271; + 07a1133e4a0b2686 0248d43806f67172 868ebb51cab4599a; + 3849674c2602319e 51454b582ddf440a 7178876e01f19b2a; + 04b915ba43feb5b6 42fd443059577fa2 af37fb421f8c4095; + 0113b970fd34f2ce 059b5e0851cf143a 86a560f10ec6d85b; + 0170f175468fb5e6 0756d8e0774761d2 0cd3da020021dc09; + 43297fad38e373fe 762514b829bf486a ea676b2cb7db2b7a; + 07a7137045da2a16 3bdd119049372802 dfd64a815caf1a0f; + 04689104c2fd3b2f 26955f6835af609a 5c513c9c4886c088; + 37d06bb516cb7546 164d5e404f275232 0a2aeeae3ff4ab77; + 1f08260d1ac2465e 6b056e18759f5cca ef1bf03e5dfa575a; + 584023641aba6176 004bd6ef09176062 88bf0db6d70dee56; + 025816164629b007 480d39006ee762f2 a1f9915541020b56; + 49793ebc79b3258f 437540c8698f3cfa 6fbf1cafcffd0556; + 4fb05e1515ab73a7 072d43a077075292 2f22e49bab7ca1ac; + 49e95d6d4ca229bf 02fe55778117f12a 5a6b612cc26cce4a; + 018310dc409b26d6 1d9d5c5018f728c2 5f4c038ed12b2e41; + 1c587f1c13924fef 305532286d6f295a 63fac0d034d9f793; + + # --- Rivest's test vector set --- + + 9474b8e8c73bca7d 9474b8e8c73bca7d 8da744e0c94e5e17; + 8da744e0c94e5e17 0cdb25e3ba3c6d79 8da744e0c94e5e17; + 0cdb25e3ba3c6d79 0cdb25e3ba3c6d79 4784c4ba5006081f; + 4784c4ba5006081f 1cf1fc126f2ef842 4784c4ba5006081f; + 1cf1fc126f2ef842 1cf1fc126f2ef842 e4be250042098d13; + e4be250042098d13 7bfc5dc6adb5797c e4be250042098d13; + 7bfc5dc6adb5797c 7bfc5dc6adb5797c 1ab3b4d82082fb28; + 1ab3b4d82082fb28 c1576a14de707097 1ab3b4d82082fb28; + c1576a14de707097 c1576a14de707097 739b68cd2e26782a; + 739b68cd2e26782a 2a59f0c464506edb 739b68cd2e26782a; + 2a59f0c464506edb 2a59f0c464506edb a5c39d4251f0a81e; + a5c39d4251f0a81e 7239ac9a6107ddb1 a5c39d4251f0a81e; + 7239ac9a6107ddb1 7239ac9a6107ddb1 070cac8590241233; + 070cac8590241233 78f87b6e3dfecf61 070cac8590241233; + 78f87b6e3dfecf61 78f87b6e3dfecf61 95ec2578c2c433f0; + 95ec2578c2c433f0 1b1a2ddb4c642438 95ec2578c2c433f0; + + # --- The EFF answer to Matt Blaze's challenge --- + + 0e329232ea6d0d73 8787878787878787 0000000000000000; +} diff --git a/symm/t/des3 b/symm/t/des3 new file mode 100644 index 0000000..f1adb1a --- /dev/null +++ b/symm/t/des3 @@ -0,0 +1,41 @@ +# Test vectors for double and triple DES + +des3 { + # --- Some simple single-DES things --- + + 00451338957377 4e6f772069732074 3fa40e8a984d4815; + b6c74cbf60c1fd 328da675ff5abd2c cd3e9f9b670671d1; + + 0123456789abcdef 4e6f772069732074 3fa40e8a984d4815; + 0123456789abcdef 68652074696d6520 6a271787ab8883f9; + 0123456789abcdef 666f7220616c6c20 893d51ec4b563b53; + 0123456789abcdef 0123456789abcde7 c95744256a5ed31d; + + 0045133895737700451338957377 4e6f772069732074 3fa40e8a984d4815; + b6c74cbf60c1fdb6c74cbf60c1fd 328da675ff5abd2c cd3e9f9b670671d1; + + 0123456789abcdef0123456789abcdef 4e6f772069732074 3fa40e8a984d4815; + 0123456789abcdef0123456789abcdef 68652074696d6520 6a271787ab8883f9; + 0123456789abcdef0123456789abcdef 666f7220616c6c20 893d51ec4b563b53; + 0123456789abcdef0123456789abcdef 0123456789abcde7 c95744256a5ed31d; + + 004513389573770045133895737700451338957377 + 4e6f772069732074 3fa40e8a984d4815; + b6c74cbf60c1fdb6c74cbf60c1fdb6c74cbf60c1fd + 328da675ff5abd2c cd3e9f9b670671d1; + + 0123456789abcdef0123456789abcdef0123456789abcdef + 4e6f772069732074 3fa40e8a984d4815; + 0123456789abcdef0123456789abcdef0123456789abcdef + 68652074696d6520 6a271787ab8883f9; + 0123456789abcdef0123456789abcdef0123456789abcdef + 666f7220616c6c20 893d51ec4b563b53; + 0123456789abcdef0123456789abcdef0123456789abcdef + 0123456789abcde7 c95744256a5ed31d; + + # --- Genuine longer keys --- + + 0123456789abcdeffedcba9876543210 0123456789abcde7 7f1d0a77826b8aff; + 0123456789abcdeffedcba987654321089abcdef01234567 + 0123456789abcde7 de0b7c06ae5e0ed5; +} diff --git a/symm/t/desx b/symm/t/desx new file mode 100644 index 0000000..0f64086 --- /dev/null +++ b/symm/t/desx @@ -0,0 +1,22 @@ +# Test vectors for DES + +desx { + # --- From SCAN --- + + 0123456789abcdef1011121314151617 + 4445535864657378 d8fa5084fad4b35c; + 01010101010101010123456789abcdef1011121314151617 + 94dbe082549a14ef 9011121314151617; + + # --- 7-bit key tests --- + + 004513389573771011121314151617 + 4445535864657378 d8fa5084fad4b35c; + 000000000000000123456789abcdef1011121314151617 + 94dbe082549a14ef 9011121314151617; + + # --- Equivalence tests --- + + 00451338957377 4e6f772069732074 3fa40e8a984d4815; + 0123456789abcdef 4e6f772069732074 3fa40e8a984d4815; +} diff --git a/symm/t/has160 b/symm/t/has160 new file mode 100644 index 0000000..e1a3086 --- /dev/null +++ b/symm/t/has160 @@ -0,0 +1,51 @@ +# Test vectors for HAS160 hash function + +# --- Basic hash function --- +# +# Test vectors from `The Revised Version of KCDSA' by Chae Hoon Lim. + +has160 { + "" 307964ef34151d37c8047adec7ab50f4ff89762d; + "a" 4872bcbc4cd0f0a9dc7c2f7045e5b43b6c830db8; + "abc" 975e810488cf2a3d49838478124afce4b1c78804; + "message digest" 2338dbc8638d31225f73086246ba529f96710bc6; + "abcdefghijklmnopqrstuvwxyz" 596185c9ab6703d0d0dbb98702bc0f5729cd1d3c; +} + +has160-rep { + "a" 1000000 d6ad6f0608b878da9b87999c2525cc84f4c9f18d; +} + +# --- HMAC mode --- +# +# Regression catching only. + +has160-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + f5b44115a53f716b6f488de1098ee7c251418623; + + "what do ya want for nothing?" + 4a656665 + a74547c1ef0aa147c7428ab7e71664549be2a412; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + e4c91bc71782fa44a56be1a34aae167e8ffc9734; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + 14d1055da875222053bf1180bbef8892eba3ac30; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 124131a293f1fdf3d6b11e2b7f7a1f5b12e42d58; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 63750d67af40e3fde33526545d300972a1527053; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 1bdb821e399e208352c64f0655f6601e2a8a087c; +} diff --git a/symm/t/idea b/symm/t/idea new file mode 100644 index 0000000..c0b928d --- /dev/null +++ b/symm/t/idea @@ -0,0 +1,26 @@ +# Test vectors for IDEA + +# --- Thin on the ground, these are --- + +idea { + 00010002000300040005000600070008 0000000100020003 11fbed2b01986de5; + 00000000000000000000000000000000 0000000000000000 0001000100000000; + 000027ed8f5c3e8baf16560d14c90b43 0000abbf94ff8b5f cbbb2e6c05ee8c89; + 000027ed8f5c3e8baf16560d14c90b43 6889f5647ab23d59 61d5397046f99637; + 000027ed8f5c3e8baf16560d14c90b43 6c2e3617da2bac35 b2229067630f7045; + 000027ed8f5c3e8baf16560d14c90b43 819440ca2065d112 c88600093b348575; + 000027ed8f5c3e8baf16560d14c90b43 848f836780938169 4821b99f61acebb7; + 000027ed8f5c3e8baf16560d14c90b43 ac4856242b121589 85c6b232294c2f27; + 000027ed8f5c3e8baf16560d14c90b43 cbe465f232f9d85c b67ac767c0c06a55; + 000027ed8f5c3e8baf16560d14c90b43 d53fabbf94ff8b5f 1320f99bfe052804; + 000027ed8f5c3e8baf16560d14c90b43 df8c6fc637e3dad1 ef4899b48de5907c; + 729a27ed8f5c3e8baf16560d14c90b43 0000abbf94ff8b5f 65861be574e1eab6; + 729a27ed8f5c3e8baf16560d14c90b43 6889f5647ab23d59 f963468b52f45d4d; + 729a27ed8f5c3e8baf16560d14c90b43 6c2e3617da2bac35 1569e0627007b12e; + 729a27ed8f5c3e8baf16560d14c90b43 819440ca2065d112 264a8bba66959075; + 729a27ed8f5c3e8baf16560d14c90b43 848f836780938169 d7e0468226d0fc56; + 729a27ed8f5c3e8baf16560d14c90b43 ac4856242b121589 95cd92f44bacb72d; + 729a27ed8f5c3e8baf16560d14c90b43 cbe465f232f9d85c bce24dc8d0961c44; + 729a27ed8f5c3e8baf16560d14c90b43 d53fabbf94ff8b5f 1d0cb2af1654820a; + 729a27ed8f5c3e8baf16560d14c90b43 df8c6fc637e3dad1 29358cc6c83828ae; +} diff --git a/tests/mars.aes b/symm/t/mars.aes similarity index 100% rename from tests/mars.aes rename to symm/t/mars.aes diff --git a/symm/t/md2 b/symm/t/md2 new file mode 100644 index 0000000..e478ae8 --- /dev/null +++ b/symm/t/md2 @@ -0,0 +1,77 @@ +# Test vectors for MD2 hash function + +# --- Basic hash function --- +# +# Test vectors from RFC1319. The last was generated using OpenSSL. + +md2 { + "" 8350e5a3e24c153df2275c9f80692773; + "a" 32ec01ec4a6dac72c0ab96fb34c0b5d1; + "abc" da853b0d3f88d99b30283a69e6ded6bb; + "message digest" ab4f496bfb2a530b219ff33031fe06b0; + "abcdefghijklmnopqrstuvwxyz" + 4e8ddff3650292ab5a4108c3aa47940b; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + da33def2a42df13975352846c30338cd; + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" + d5976f79d83d3a0dc9806c3c66f3efd8; + + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +" 9bc05c2f44930f59882bb885a75b4c95; +} + +# --- HMAC mode --- +# +# These are just regression tests, generated internally. + +md2-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + b524be0196e491ed44823746cd8923af; + + "what do ya want for nothing?" + 4a656665 + 292f9d34f9e311846de86c495d7adfa2; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + ff09238e4bded84b5490bc42cfd5c265; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + ea3181bf1cc387f12ed0637105fb219d; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 7177f2b3e5583078ee122f94fe3c784a; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 615b1c392f5aaeeeab7e82572e6395d5; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + df0b12810892f0c7559802d5c0ce1157; +} diff --git a/symm/t/md4 b/symm/t/md4 new file mode 100644 index 0000000..0b78cc4 --- /dev/null +++ b/symm/t/md4 @@ -0,0 +1,57 @@ +# Test vectors for MD4 hash function + +# --- Basic hash function --- +# +# Test vectors from RFC1186 and some others I generated using the reference +# implementation. + +md4 { + "" 31d6cfe0d16ae931b73c59d7e0c089c0; + "a" bde52cb31de33e46245e05fbdbd6fb24; + "abc" a448017aaf21d8525fc10ae87aa6729d; + "message digest" d9130a8164549fe818874806e1c7014b; + "abcdefghijklmnopqrstuvwxyz" + d79e1c308aa5bbcdeea8ed63df412da9; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + 043f8582f241db351ce627e153e7f0e4; +} + +# --- HMAC mode --- +# +# No test vectors available. The HMAC implementation has not been tested +# against an external reference. However, MD4 isn't strong enough to make +# a realistic MAC anyway, and use of md4-mac is thoroughly deprecated. The +# HMAC code is autogenerated anyway, and ought to be reliable and correct. +# +# These test vectors are here to spot changes in behaviour rather than ensure +# interoperability. + +md4-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + 90a79458f58f437e21f169cdba283da6; + + "what do ya want for nothing?" + 4a656665 + be192c588a8e914d8a59b474a828128f; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 75e5fb6e71ca6dcdd9fca269a9a3cd9c; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + fb14cddf9efe11ad24033fc70f37bb9e; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 6306262f9ba0e83f9ce3f15aafc23be8; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 545b8f2577657042df628fbb98430d5f; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 0192f3442ad5d1ea5268306ab0d4962e; +} diff --git a/symm/t/md5 b/symm/t/md5 new file mode 100644 index 0000000..533c562 --- /dev/null +++ b/symm/t/md5 @@ -0,0 +1,78 @@ +# Test vectors for MD5 hash function + +# --- Basic hash function --- +# +# Test vectors from RFC1321 and some others I generated using the reference +# implementation. + +md5 { + "" d41d8cd98f00b204e9800998ecf8427e; + "a" 0cc175b9c0f1b6a831c399e269772661; + "abc" 900150983cd24fb0d6963f7d28e17f72; + "message digest" f96b697d7cb7938d525a2f31aaf161d0; + "abcdefghijklmnopqrstuvwxyz" + c3fcd3d76192e4007dfb496cca67e13b; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + d174ab98d277d9f5a5611c2c9f419d9f; + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" + 57edf4a22be3c955ac49da2e2107b67a; + + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +" 2b65a7ba4acd105ef2cb9adebd9f0bfa; +} + +# --- HMAC mode --- +# +# Test vectors from RFC2104 and RFC2202. + +md5-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + 9294727a3638bb1c13f48ef8158bfc9d; + + "what do ya want for nothing?" + 4a656665 + 750c783e6ab0b503eaa86e310a5db738; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 56be34521d144c88dbb8c733f0e8b3f6; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + 697eaf0aca3a3aea3a75164746ffaa79; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 56461ef2342edc00f9bab995690efd4c; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 6f630fad67cda0ee1fb1f562db3aa53e; +} diff --git a/symm/t/noekeon b/symm/t/noekeon new file mode 100644 index 0000000..0764732 --- /dev/null +++ b/symm/t/noekeon @@ -0,0 +1,10 @@ +# Test vectors for Noekeon + +noekeon { + 00000000000000000000000000000000 + 00000000000000000000000000000000 ba6933819299c71699a99f08f678178b; + ffffffffffffffffffffffffffffffff + ffffffffffffffffffffffffffffffff 52f88a7b283c1f7bdf7b6faa5011c7d8; + ba6933819299c71699a99f08f678178b + 52f88a7b283c1f7bdf7b6faa5011c7d8 5096f2bfc82ae6e2d9495515c277fa70; +} diff --git a/symm/t/rc2 b/symm/t/rc2 new file mode 100644 index 0000000..ed90d3f --- /dev/null +++ b/symm/t/rc2 @@ -0,0 +1,13 @@ +# Test vectors for RC2 + +rc2 { + 0000000000000000 63 0000000000000000 ebb773f993278eff; + ffffffffffffffff 64 ffffffffffffffff 278b27e42e2f0d49; + 3000000000000000 64 1000000000000001 30649edf9be7d2c2; + 88 64 0000000000000000 61a8a244adacccf0; + 88bca90e90875a 64 0000000000000000 6ccf4308974c267f; + 88bca90e90875a7f0f79c384627bafb2 64 0000000000000000 1a807d272bbe5db1; + 88bca90e90875a7f0f79c384627bafb2 128 0000000000000000 2269552ab0f85ca6; + 88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e 129 + 0000000000000000 5b78d3a43dfff1f1; +} diff --git a/symm/t/rc4 b/symm/t/rc4 new file mode 100644 index 0000000..4e55ba5 --- /dev/null +++ b/symm/t/rc4 @@ -0,0 +1,25 @@ +# Test vectors for RC4 +# +# +# These test vectors come from two places: the Usenet article confirming that +# the alleged RC4 source is interoperable with the BSAFE version, and some +# tests I performed with the RC4-in-a-signature Perl version. Some testing +# with the SSLeay version shows that for an all-zero key I'm compatible, but +# with any other I'm not. Since I pass the Usenet test vectors (which I +# found in the SSLeay sources!), and I'm compatible with at least one other +# implementation, I'm happy that I'm in the right here. + +rc4-encrypt { + 0123456789abcdef 0123456789abcdef 75b7878099e0c596; + 0123456789abcdef + 010101010101010101010101010101010101010101 + 7595c3e6114a09780c4ad452338e1ffd9a1be9498f; +} + +rc4-generate { + 00 0 de188941a3375d3a8a061e67576e926d; + 01fe23dc45ba6798 0 643ded26ae29c15cda4f2b96d66baf2c; + 08192a3b4c5d6e7f 1024 abb3a32a2ba4d409752923aa4032be16; + 0123456789abcdef 0 7494c2e7104b0879; + ef012345 0 d6a141a7ec3c38dfbd61; +} diff --git a/symm/t/rc5 b/symm/t/rc5 new file mode 100644 index 0000000..e7a02c9 --- /dev/null +++ b/symm/t/rc5 @@ -0,0 +1,15 @@ +# Test vectors for RC5-32/12 + +# --- Main cipher test vectors --- +# +# Taken from `The RC5 Encryption Algorithm' by Rivest. Important: the +# test vectors given in the paper are given as 32-bit words, not bytes, so +# since RC5 is little-endian they need to be swapped here. + +rc5 { + 00000000000000000000000000000000 0000000000000000 21a5dbee154b8f6d; + 915f4619be41b2516355a50110a9ce91 21a5dbee154b8f6d f7c013ac5b2b8952; + 783348e75aeb0f2fd7b169bb8dc16787 f7c013ac5b2b8952 2f42b3b70369fc92; + dc49db1375a5584f6485b413b5f12baf 2f42b3b70369fc92 65c178b284d197cc; + 5269f149d41ba0152497574d7f153125 65c178b284d197cc eb44e415da319824; +} diff --git a/tests/rijndael.aes b/symm/t/rijndael.aes similarity index 100% rename from tests/rijndael.aes rename to symm/t/rijndael.aes diff --git a/symm/t/rijndael192 b/symm/t/rijndael192 new file mode 100644 index 0000000..d7732ff --- /dev/null +++ b/symm/t/rijndael192 @@ -0,0 +1,2884 @@ +# Test vectors for Rijndael + +rijndael192 { + 01000000000000000000000000000000 + 023a67f4591abd1dc00c5abebebe0397a3b347451ad3112d + 7ff75c2eeefa7f368c8a8b4520696533bff5aba750f61004; + 02000000000000000000000000000000 + 506a186359362e62a58444f018f882194d728766ca6ff976 + 6288af2dd607059b760ec2ae99287ff4f5f135350c6533b3; + 04000000000000000000000000000000 + ca5c42150025d70706f9df66c6a149878f99b02d80d24af6 + 2740c22885fa7f6979eed72c31254719f75097913d55d089; + 08000000000000000000000000000000 + 03ebd2ad4e4c4b8767eef082e0671b8a40aa83205dd2cd7d + 50d067dfe60008dcff6c8f6011a56b04297a0886b818fdb3; + 10000000000000000000000000000000 + c8b526b380f2b8ddf60ad4527b585b36bc886f915906f34a + ee2550dd5a911da2bb85424687b6d06e18607d9800822a8b; + 20000000000000000000000000000000 + b5fe0634f8cc42cad26dd7448ed44288ff054435747606ac + fabc0ae4d9eb26ed89375f1e24215540b37d106c3f4429b3; + 40000000000000000000000000000000 + 2a8b55370b58585cd5c545065c1236876c25f7227043f697 + 9a2efe9a23f99898519dfc86bd82ac51311356e96a744e4c; + 80000000000000000000000000000000 + 225d2952c570bd85c57b60bdf0d7813cee77f88eb94b9fe0 + 66391730c52594f80fdf06e5da751aad9613767c8a7dbc12; + 00010000000000000000000000000000 + 4ebb41c4aeee673f8a24dca03806b456d7f0371f59ad215d + e20e4d661c9411afca8208e71c2245954316b17d355cc87f; + 00020000000000000000000000000000 + 1ece0d84de9d85f599c043e81ed0d0788b0300dc720806f1 + 8b58730dc35a5b8b679a38662163bbf61f4bcb963d67c0c9; + 00040000000000000000000000000000 + 0acbe6c5eb0b944562a37976acdeaaa343d28c1023805af2 + 77ab5a554203d92b600fe57510c081be22d9a0474158fa0c; + 00080000000000000000000000000000 + 41be3904653a1575e5b06c44aea5d2136df8f9ccd7f42897 + 84ddaa529a9e0c24bb4437fd7c59d126e9f3a2fd144747a8; + 00100000000000000000000000000000 + 1f64e3968eecb4f75248981ee4afe469df2506d85373244e + c0e3387b78dc708656ce32cb56ba8f3a7481db57b2e2f31c; + 00200000000000000000000000000000 + 4aa4faa759d8ae50e22eb0c8d9a35a5ac45d8c321e7945a8 + f912da323759360ab2a17b8903a3995ba1fd286b4f5c0428; + 00400000000000000000000000000000 + ef444349c97db6ced680f42fb6c5be12b6093315d9735c99 + a8e88259daf069ab83caf0827dd8a70aec60763343f1d5e8; + 00800000000000000000000000000000 + 52d311d50f4b8dadb35e14061d24b77128f5fd8f1a4408cc + 830b1649d46496e4e3379c6af09ef3a2db387234e20e0f8a; + 00000100000000000000000000000000 + e7bcd07378c8fa7412cdca4747b825586c1d1db42cb9e3f5 + f646e68c39285ce45d564195ab947cef8f842e83a0039311; + 00000200000000000000000000000000 + 2d6f4c9d74fa658286d89ac21a293b0dbfa23a8b5509d22f + ecab2eb6d811c3c5cbb7ca9697039c0183deba100bd857ef; + 00000400000000000000000000000000 + 553847fabc37d17234bd17f7d9306530bf778143642aaf86 + 6b4c872d23f5e2055dd7b7dfb5e4b7e9e2ca030a4248d033; + 00000800000000000000000000000000 + 940ab6a034bee50736899c4d635156aca5417be2643202a6 + 7518c4af96fa52e3c0b00b874d394c4aa633d0cba04ef54c; + 00001000000000000000000000000000 + fac2d9c5408abd20b4cb620b4e9ae56f94d5c4a1d5875dd1 + cb766e2a037a343083229141d004ba100c4f33de8e064961; + 00002000000000000000000000000000 + b4e037145cfe062329702825eef3c0187602e7c81b196d01 + f307dab2d4b0c4e95024e95bf869da3759038799142e7a4e; + 00004000000000000000000000000000 + faf4093cecf9b49b79ac867cb8eb254f4e6b1cdc0fa8d2e1 + c5a7383e7e51e02872407a34099bffbd43e2369e5b3c4bfb; + 00008000000000000000000000000000 + 13226b07eb7e44d65c4eac727e788fc246c71b7877150716 + 74cd36201eb1e07da6d7f7a922fb4cc9bb76e13b1f770fbe; + 00000001000000000000000000000000 + a4d115e01be2e296dc61104749f5cf13e1b0660b619901da + 6cd992b789f2e6bcae1fc4c54e31983a91cfe80221065d45; + 00000002000000000000000000000000 + c177c0361498f3b8162b8a1e4791d393c90f9be62af73a0d + 8fea60d9cc0b31580e42a55bf633d926458eab2269e284c3; + 00000004000000000000000000000000 + b3fa237d5af3b8b030559f59b22394b94d8b71fe7c499896 + 090181d182605dc6d04734312631193af9ba97a41e36cd6d; + 00000008000000000000000000000000 + d43a7d6e1c6e6bd70ddf057df51171968f135cc628c87aee + a83d729f48beaad53c4703edf669cc3b8172b1f3815826ea; + 00000010000000000000000000000000 + d4a801587858558d74174ec9bf5af46357cb6b509c1cd3c6 + 3c8d553aad2e9e9b57012b8b624864282605a202e770988b; + 00000020000000000000000000000000 + a244142ed94451165b1b284659dd09bf19522d8ede74fa50 + 56a4918a03a03e7522287f2697058a5a4568ee1044abb7a5; + 00000040000000000000000000000000 + 256c7215a7a1f6277efd963ac44f273a67331722a35733a6 + 772bad0f5ba9b17a70db868fa6c94e894332da2be4188990; + 00000080000000000000000000000000 + 0180a9b501ffa92c8d82f9a6841762c0a999f075374ba5ed + b2866da4615cd4dc433537c2946f8892b44f3bd0b2c4dd72; + 00000000010000000000000000000000 + 74094fb2efc7ad295a4e59e6f3cc4bca98f9ca9426f1dc7d + 66e1d8c5b64590a10887d4f30d593e21a988ccc2cb0c56f3; + 00000000020000000000000000000000 + e0f2350c0bc86af716d0e3a4a43f7226642e41247cc365a8 + 47a078702ce531d10d0ee151761fbba5e8b62354fa78b6f2; + 00000000040000000000000000000000 + 422af1fef9c1b8c8a0ef3b62abb1318556ed6fc1f66a9d87 + b334db883014ca79f7822e91203840185153bb845171cf62; + 00000000080000000000000000000000 + 94112b3e064fbe4658252cd678a689e30989d9801f8026bc + 9960c684f52a14396a807b1457b55a6e8805adbd2cad3ea7; + 00000000100000000000000000000000 + 9cdaf684882ddd6dc44fa74b080f6a3b63fa4ddf2a8708f2 + 9640e06263fcdc7f42e8364b6832202026b715b1d604802b; + 00000000200000000000000000000000 + c138345c90c2823c192bb0a347baa310068951f512554d95 + f0b31139a5e0d808349a5897341ceab6d1c92ad0db7efa56; + 00000000400000000000000000000000 + 8ea80f74f49292759317b0b4a1bd488edc883616c04c8920 + 3e2a07a682bf608ec4f94faaac7049323435e17bdf8ce8bf; + 00000000800000000000000000000000 + d170aa41a6e50b8b2738de41f189cf9991eaade3dbd5dec5 + 4b0901022f4449e5fca714fb4a08524c0b33632a704ed726; + 00000000000100000000000000000000 + 9a308261c52d829caacc1b70eb47049a598a4702e22aad0a + 0bcd79778982f5797fb92d16d7e772e624a65e15dde0dcee; + 00000000000200000000000000000000 + 40cff4c8c86429193aa94de96b2719a99f60cbca577980f5 + 47ed4c47df14c5a14290faf23855088bb0fd75d8f209f276; + 00000000000400000000000000000000 + ba4d0f077f721f3939f1389d44a86fcd7f2591b94c9e9080 + adf066342c154cf5c2fb2609be3126b1bfa8098d8be8f1c4; + 00000000000800000000000000000000 + 4c635236910df9d5d1a6ed65c7252a72fb20a716bb64d9b8 + ee98a1c2c6a9c9590f626f4b7f685c8575da477a356d557b; + 00000000001000000000000000000000 + fd3fb55926f16ac3c458669f23a4647fb771ccaa49cafb4b + c3757d955b8944c8dfb62e77cf643f6d8b58261916aec7b6; + 00000000002000000000000000000000 + ab5289cafd68c2bd7facced12251962f7be2b30a99945c9f + 92f2d77a9f0dd409bf737cda459d7d3dce6e407dba592858; + 00000000004000000000000000000000 + 050c239f2157e5355525ffe4557e54b2c8838a68899707cf + c3317fdb7edf02d7b43ff293346977da2a22108748574302; + 00000000008000000000000000000000 + 287c55a9636fd7123dd9851cf5c27c73f3f3a165a4b5ab31 + ef8d185840b9f6f057792cecc2880366dbee7e5b56a38fd5; + 00000000000001000000000000000000 + cc76fb5b7e8316d4c74e1df3f913139e739d9f30e0e320b9 + 9dd58b054a33098f0228bc6b05712e9c7a50add7868a2f96; + 00000000000002000000000000000000 + aa21dae2afdb95ad368f9c1babf2769407cb6d7975d41257 + 3591625006cb3c2bda175be3f715a6ed63d59261a3182f5d; + 00000000000004000000000000000000 + 8cc0d35698def74ded8c1d8222b67e543af62f9627978c80 + 4829e5802b83b5614b58d68305aa94f06aaf37a0c0c4ed5e; + 00000000000008000000000000000000 + da702b5e9b3c7ce13681b3e1a38ae1babd06a0ba46612f63 + 9d162f4850b8b4e4b1a01213138c1f22c863e32c12539a87; + 00000000000010000000000000000000 + 486599f86813923735d14c4308f142eb8a57086a8507255b + 40b857e962dfe1f9d1dd46b69ab4f5ff7faf34b407623c3c; + 00000000000020000000000000000000 + 82f7da5f0379e2cb4e3b58a03ca3de256b282dce73285090 + 1bf3d369ccd413ad0f95a1928715fb8ed55aeb2e9d93f2cc; + 00000000000040000000000000000000 + 3a2ccdf7ca733ef507a485ab20c62cf6fb13cd1281008b49 + 335d30e28232b4bc1dff9de3a4a9faebd4b5accc3cd2eac6; + 00000000000080000000000000000000 + 5129bfb136556242d24c0a69d1b471e39bef4502dcc6ab63 + 0e7f709d8e65ecdeccf0f8f51e1eadd4deb33218ca96133d; + 00000000000000010000000000000000 + bb55b9b172f5102a71d27564fb441ad75ef525e3c7b95569 + 2fe4ac5360626eff86d72d472cff3428f0891f2e708c1fc0; + 00000000000000020000000000000000 + 29e121d9d060b4cb1a8b985514642d2ae657d1bee74622af + 330a0002c3bb7bdd1141085283a2390d50b992667e9c7a2e; + 00000000000000040000000000000000 + 1eab5cf16eaed7787fdca7a4a13f02e89e838e28fee07574 + f351daecc945e7f4fb609f83b30f4a5f96d8d453770235a1; + 00000000000000080000000000000000 + 1d1c207423b291e4faa33ba5511d99fa0a1d6217dfb01503 + f8d4232565a6ec23973b2814fe0d4b0d795df4afb24646bc; + 00000000000000100000000000000000 + 428cd893c5c48447e67a5a78ced4e75b9424d26162396397 + df261879c0edbb80b244a8f95c319bd2f09db2fd24e46664; + 00000000000000200000000000000000 + d559589331a70000a25b0bdcc69edfadacca1a42e26858c8 + 408b5610b79984e6b95c48b6b370c670b054a7f4218bf388; + 00000000000000400000000000000000 + 4b3ae76b7fd6acc18a44eb946daa6bb70d58086904f61243 + 926965c763cbb68699d3e77aa76acebff7be816b27cdae87; + 00000000000000800000000000000000 + c5fb0e875cc5f0d3b8e3056be3c1fef7cb653c2d357de33f + acad4ba4b859549071b491f07e7f90d50ff1e9aaf9d4c566; + 00000000000000000100000000000000 + 50f32b167426251526e8f63bab0d615e016e03058902fe4f + e899b8984e8f6e7203c364181d89439c3bac8e60914d5644; + 00000000000000000200000000000000 + 54418fd49d84a2e725f99459c10454af6e408b945e108275 + cbda143f3ee4dab705f1a91bc941054ffd0ad144d50368b7; + 00000000000000000400000000000000 + 6117166e773302a1b3d21e869407c18a13655033d5ca007b + bbb97e4178dbe65c25ec8002b53ef7932c4ae1cfb947918c; + 00000000000000000800000000000000 + f89ddf74283be908896c62bc18feaa8d305e9ae4278233ce + 2089a78434cf69651c06cf00dbe89bb6b446e4f3db6ce8e5; + 00000000000000001000000000000000 + 03af049da485a4b4ddb468bf3261c38aad2a71c96f990a22 + 46146187446746bbf8dcc71cb5c583506244c1468a015144; + 00000000000000002000000000000000 + aa70df415bd87335969b4fb3c363529061a3da319ef2d890 + a63e67308c4b7f2b33f279bee222a9869446c8c0c250cf06; + 00000000000000004000000000000000 + dad7d93b5a7bff63476de8b3d20190a29f28eecc88495d3d + 9839a4942c8f69283e91eca22ffd198a4a79e68ec07e578f; + 00000000000000008000000000000000 + 59d603166b649e9be642bd3ccbc03f7d9abb3e89aaf0f1c6 + 8686e6909dcd9f787f9fa180a46d1d433bf2721a238faab1; + 00000000000000000001000000000000 + 7bb6311899138ae33f095f79487a8c1ff8efc0a1ba1c0844 + 69e02af433d3d1234a315658f80f6dbad8339e77b894a3bf; + 00000000000000000002000000000000 + 27112725333fed86f93b09ac882e54cc2c625de0970a56c0 + d840315b675f117468782d16dd143961e972a62733ab5b12; + 00000000000000000004000000000000 + 798b2230146a75a46854e26ed0cb07419e79ac176059f223 + f543a2dffe039126eacbb3c5253d3e0656df5886aa7dc934; + 00000000000000000008000000000000 + fdf295ab966e035dc8d9c6a7d378aa1fed50f85e09afc9fd + 1e353b843bfdfb8e04196ebc2a2fba0e6ac7651aec3034a8; + 00000000000000000010000000000000 + 4b9bb076f6e3b227ff27210398252df65e9e2fe255b13992 + e42c1d4b04422a38c1dc7a4bc241ee1f4b9aa5a2aa42047e; + 00000000000000000020000000000000 + f45fa1b841562f0d20769390f1dafd13324bf86216565f5e + 7e96c285bffe97be47ea277140b179e92daa6a13647905b4; + 00000000000000000040000000000000 + de745e5baa6ac8a095898d562c187de0064d23c9b748a115 + 10cf435b1841a119ef753a471f57261af2d137b2eef59c81; + 00000000000000000080000000000000 + ca3c51b2670418b4ec09ffce8f626bbe891b266446f89853 + fb5c6a49a40e79c468ae275331230e37f5e47c3a10159d58; + 00000000000000000000010000000000 + 0a9529d7ca30fca5081c364376c766fa5cb0a488bff9f638 + 149db4dddd0c11aef1e7ffe76286351b2212a17771bb3bba; + 00000000000000000000020000000000 + ac80ed034867425e0482cd34ee6666ff8ed09cad5901c0c9 + 3a4cc4d2888134ad2d77ef262a222c79b66d93226209e6ec; + 00000000000000000000040000000000 + c01846df500d6d9da7755fee30847e2b6e5ef2af29fb768d + 234eee5672c9964bfaeff3d7612ad7796d52630dc86bca96; + 00000000000000000000080000000000 + c15f53accfc0d88ab029139dd65019fa6003b7afe2bd4e54 + a0d7bfcdeb22254d8ea42219368656569742324922a9ee6d; + 00000000000000000000100000000000 + ff213f49aee42eac2aa72d7a29e7ab41aa7f586012e9f97f + f17c2e5990d08495dc94764f8e85c51851a4f413b581584c; + 00000000000000000000200000000000 + 25cae6c9325a23f04d3f14e8c2c2d2e7cf47f4245a813568 + e2f0783438ad7bd9a4f84b1b3a895c05714c514dac819bb1; + 00000000000000000000400000000000 + 22870931c60c3752f5eb3408f4f4f311ecc94d45746334b3 + 6b62d15ad6d4d9a0bcf4f718fa02fcd154922ae0eabb53ba; + 00000000000000000000800000000000 + c08edd588aefb0162ed5a83866b4125c4763187fa2c3a0ec + 06c5641d79eb161bac7db67e4563298fb255ba9d19795081; + 00000000000000000000000100000000 + a27d1bf8dd539451b9c1be660a658551358e0d5e24afc3b9 + 7676d1200c042937af0775b682b8a079e537e09ed0aa4683; + 00000000000000000000000200000000 + 985703a552bf2ef0f0b13cdfdcea1b5f0e8aa26dd0a2df73 + 7c2f3cd5a37195e38378625ba3dcc0331b5f541a8ab99782; + 00000000000000000000000400000000 + 6ec0cf3e2eebe473928c8816aacafa30697d2f1886216355 + 74cd8be145dae8057f60216a73c5facedb9f4e82e0bd65cb; + 00000000000000000000000800000000 + 616f098bebcbf2ed4b706c97bf2515c3b0816deb15de4059 + d15e35c97769885b1a3d35e8e1fe85b693ec2c8744417bfa; + 00000000000000000000001000000000 + e8dd7dbcf07d102c7eaaade8d9024829251e934d0da9d7aa + e3999556264744496ad4d86d445457888419bbe8871d7b4d; + 00000000000000000000002000000000 + 1fa50547af8d9f2d55028008536f066753c17fc8e2d44057 + 4acb79c912d344fae3419ef5700aa6a3d883184f34e5d59e; + 00000000000000000000004000000000 + 92eeebbe20902b4c0a5f890399c32c243e89d8ed91332e3e + e46625fbad57eb9c626e2125cf248e269332527015dcd3e3; + 00000000000000000000008000000000 + cdbf15c739d3fc86f9420eedf6a0956502a4a733217102f4 + 81c056e8176355317af92ba38e40fd5c26f907b285f840ea; + 00000000000000000000000001000000 + 2d349f3bd80ff88f4eee644682b62fd1eb719b9c81b816f6 + 9d44dd091630b3772cb94b8c652a15df0474881371f0b04e; + 00000000000000000000000002000000 + 6c53dac01503d4ea8e2da6e54403fd20c1f5a1f967732cde + 4c17e967bb54e474f3e323d4f0e18ce40e44ea61c2338cd4; + 00000000000000000000000004000000 + 1991e580e4801fc43a1aaef646626306f5b86f93bc114393 + 7237846ab5e292d29a7f115d0b10530720a1d5ea7c5aedf2; + 00000000000000000000000008000000 + 89c2a0916aaf1f36b54c0ac5f74a2cf7ae2d151e9ba39b22 + fdb640c3275ac44815c50f2d872e28060501598e7e9947ea; + 00000000000000000000000010000000 + 5c052c84dea984ffd5703103883523da2208e3bfa1e06649 + 5e97c772783c94a50d288284afa25295f877e5c29d174529; + 00000000000000000000000020000000 + 89dd0a9f15abb0e943d4bd0eb37e9280cb046c88999a5f14 + b8979c6cd28d05d20e4b3ea5ef472ae7d62a2470014f6e7c; + 00000000000000000000000040000000 + fe7ded8a12dcd5bae797cc30cd0596052ef5a56c0924f199 + 30272a00835e69223739d31e66a87ee9810c3181cafa4c5a; + 00000000000000000000000080000000 + 5a856f3220f42525eb711f1895eb09403fddbebfff60851a + ac07c9e6190701a516d89034e9af0229a2ea8bd42ec699aa; + 00000000000000000000000000010000 + ae67448d9fc57e487a4bab448208035dc06ffae8b5e9e8f4 + 693ce9e015e6f445bab0613cf858e152baf438c76bea9239; + 00000000000000000000000000020000 + 349b4b3daff60002fead10f7f11f1ba69a7142c2256214a3 + b24cef9c0a98b607339f148be6af519555fdb8d59237e06f; + 00000000000000000000000000040000 + 0d3724d48fbd0b053b9594042107bd4b91bdcd98a6fa14f9 + ac041956dca2caab9d5e40d344a5ff2e02e48cc638be7058; + 00000000000000000000000000080000 + 29bb7572498bf205d1939c754ba87e3a4f1a2c866bff4377 + c2b627375f0020f1e01df599ccd0c9afef8f72f2fc8c432c; + 00000000000000000000000000100000 + 79898e51f8e2ff9303d2eaf1c113d4be2d7fd73c4f29c1d4 + 02ff562fdf5ba2e325a7daa8e77485d261bf798a70562492; + 00000000000000000000000000200000 + 91ab2704db9e0cb20236885aa1812677767f29887a3825f9 + 945703d5a2ed4c7fbc46641a86b1c4ae52e2b6ae86370b7e; + 00000000000000000000000000400000 + d15999107c2747d3df7e21240b729cafaf32e45ff2e2eb94 + 0621fbacd6f9e17748a251d9ce0f6279c0b4f76de76ca07a; + 00000000000000000000000000800000 + 3022e256e1700e1b38860e08860de7ee7011a471744c4a28 + 5d0cea63850c605346b1bbde1277bd04e9a7ea67dcb95a0c; + 00000000000000000000000000000100 + c41bad6d44d9b3ddb77289d0bc75728ea32d21174989429d + daf7d221677be4c01c524941b43a6583b736f59485c37f9e; + 00000000000000000000000000000200 + c244e345c8771efc91cf85737fbbe0e7f9fe1ad53727bda8 + 0e45be68828f5dbe2cec1eb6631dd455f9f742ec1c6d5734; + 00000000000000000000000000000400 + ea91f3b274796e1a463d3263acf96d8192c927d1fa66b022 + 53a6eb98500423e77e4a17fe1e936500a3411d9d194ee941; + 00000000000000000000000000000800 + b955548cb651e31e94102068eccd141d55333cbb3e34946d + 07af2dbc8c097871dd3ceabb8645a164f445226eac474927; + 00000000000000000000000000001000 + 7f7864177e868e5e4a07a99252eadd43b0529bf5b9b05013 + 2746566baca5f019ff0eea70d3eb82278398c9e9926c3883; + 00000000000000000000000000002000 + 55cafc87e6ce1e903805d23153711dc8c7e8d269e19be3eb + 7946dffc2d8ab6a40a397f81eedb2568c6df9f0b06391d82; + 00000000000000000000000000004000 + 95bd56e986ab583193786c37328d4dde20e62b0d39c19b9c + 1f261cbca6aa0875c3b610990236178251d2865b5033ea5f; + 00000000000000000000000000008000 + 21b185e2c61a750a4dbc47d1af6cf3b47f56ceb362d785b5 + ce8b0dd60ba2d9b6e2582aa6b262cdc674d96848a67641fe; + 00000000000000000000000000000001 + e7d5e316da3127f89538a3b2d24e5f7e8006557dcb03b5e5 + d41ee11b4115c2e2155c0bc35b31d8c38e2282d17ef5ab4b; + 00000000000000000000000000000002 + dc4a61888202b8e52a97af475726e545372aa67912ca8cb1 + c4c595fbf14bd2e4f55acff059c17c243ebbb6e979713bd0; + 00000000000000000000000000000004 + c4306af68bbe3af8b223151aa99c94488c8107fbfdd3b680 + d15a72460ab5a62385c5db730fce1ddd02ca531d250b114d; + 00000000000000000000000000000008 + 5c33a8ad6ca05fc247427b898126e4ab9fd05ed334e14c68 + 8f887594d5f3a14aba879167d605d2ca84abd2aa60ca85dc; + 00000000000000000000000000000010 + d8abe4455e58859d84b0594f2804f77f15ad38887e29d705 + 407f2f3751880efd85de8ba315f222712df2674f20c9baa4; + 00000000000000000000000000000020 + 20b5cc79b89b41aaef175caf0975d6d8f2be320075b8cfbc + 6b366acae30d75bf715a67703cf61e349229015e3587ec05; + 00000000000000000000000000000040 + 3cb706cb93bc33a1fe6b1a68c9c902d187b6c57abee350dc + a1d213280eb276238acf137f2ef7b15216b571f42c9dce58; + 00000000000000000000000000000080 + 7654351a040718ddd3d7fb2cd9af802c17e7db0e7a6cfaf5 + ee3058937fc02624cc4ec6d19a7c8d3a655c6e8fc8c12622; + 0100000000000000000000000000000000000000 + d0b1960db19a85a7a77e46229b9f985139829c3aa120c3ae + c642be9d84e9f449586f6329a6d0783aafc5b9a71d5fdfcf; + 0200000000000000000000000000000000000000 + fbed0648eebac5ad6af9c89f04c759f5b3caaaf2fc77b33a + e2f666ffea4b816c59587f2cc5c4007a6e797c66c20d454d; + 0400000000000000000000000000000000000000 + c5310bb95af7c9a72af7fe845bcfc5944f98606f21d7d414 + 91ddc7e0d5626d0929262a339e488e7b80b59c748b99d96d; + 0800000000000000000000000000000000000000 + 2c22bb4931178c38b575e8a697e774f4b6cc49163b4fc863 + a29c3dfc98b1061718a8b858b582badd3565354c7dfa11e4; + 1000000000000000000000000000000000000000 + 004b667ecd93b6cf8120b4d13f63cc8676f25669cfd54198 + e61ac997edc61a530e21d3fa92597765bf8088eeb044378b; + 2000000000000000000000000000000000000000 + cac87cd9c6a8336a855d7fa479a41348615befe661bccd5f + 3c4de80c174170a85b453b0245b40090c62d7c733e691cd3; + 4000000000000000000000000000000000000000 + 271170c80822719aa7abc308af71bff47220c9c0e1d0af10 + 6adc1a35f39600a3ded1dfa8db6f54d06975f3df17410963; + 8000000000000000000000000000000000000000 + c799a3e1f803ebf7674e82af4e130a1edb80fff06b36913e + 5255a39bc0b3903213e8af99c129481a1a91546435a0b9f4; + 0001000000000000000000000000000000000000 + 7f5dd7178fc11e33e75039cd3b31c3ba715669a2d97fd67d + ea9f8cfdfbf79ffc004244db67a186188761b94dcb680ede; + 0002000000000000000000000000000000000000 + 890342e3bab9d5c12af0eb1147adf72ced3c858a36666765 + fb317078fc5a6f72cd05ed99754244c1d832bce05b495ce9; + 0004000000000000000000000000000000000000 + 4dc89624333568e75ad013d4777641293110c8293a4564eb + 5c215202bce7ac289462ee973b208517a100effc3f045037; + 0008000000000000000000000000000000000000 + eb39a4f0a41388595563ca25220d2ba33e8827e6886dee50 + 6c3cbd45e11b03f217232c6e8f412b2d45626fcbecbbd046; + 0010000000000000000000000000000000000000 + c3768a3a08cde5986f31f19adeb5637c2517e4b793e75c8e + e16c0fd6a2460933f758b736979efb34a9c35df0b58c290c; + 0020000000000000000000000000000000000000 + c4ad863e851697c80ed0607192c54debcf7c66fa38c4a4af + 7907d69fb955ab18bf7c198454c6d8d15e4226b08e322ad6; + 0040000000000000000000000000000000000000 + d2090fd250ba63f3a708140e11ef64f8afcff45dc70cef3f + dd4c891a83c86dd31eb4973dd3948a94d1fbbe6f03fc26c6; + 0080000000000000000000000000000000000000 + 110a9f65db98d165f6d71f8350ab602f4b2039e162744741 + 54d10329bfcb29cd51fbcabda51e28a5d2009694353a43f6; + 0000010000000000000000000000000000000000 + a8c1ba8a548e6f3ed996445f62845dcc078495a6cf9739cc + 6a2fe74b53328830ba707a56c80935b74dec32a312c5f6f2; + 0000020000000000000000000000000000000000 + 94c0028f97319ac431e83414b6c660939b11047f310854b7 + 46a1a901558c6bbb0f8be8662095454d9decbcfa416557da; + 0000040000000000000000000000000000000000 + cb4c1feaab04ab5a6bd70259afafd3bee103ec9f90a5150a + 270e073e9de7d0f5c887b62093e705b6457d0eb070b3c68b; + 0000080000000000000000000000000000000000 + b9d1993a3ea9b0f635d37edcb4c5ce7bdaccf5be5cb7bf02 + 8400b07b3cb30c941e468274b10c77ba3d853c418c2efa15; + 0000100000000000000000000000000000000000 + b4ab6fb85ee6b43cf76adc45644eecee472abcdad771604d + 97133160d397d761ded692085318c15285392e4887563703; + 0000200000000000000000000000000000000000 + 7367a4de601e0bf5244fb989a03fc80ed93d3141424b9477 + c3085f4757b45152825ea9197538a5797bb15b374231992b; + 0000400000000000000000000000000000000000 + 8e97f0e67b27ace30dc30a4ae45670c1378dc2b5bbe12400 + c9a494ceb0d7e51eefc737a9ca0e8af490be4e6a5ed1ce6b; + 0000800000000000000000000000000000000000 + 2713deee079aabbabc432a62e260b8d9291e98595dc86623 + e6ef22a2af39e8cc4415dcf216b7a998b98a7d240e2c3e07; + 0000000100000000000000000000000000000000 + 3dfd7ba2b48e4ffd7c0885552dbab3133c2757683fd817a9 + 7e98b7592893cf2253c1b393e5dacbb233dc803589421eaf; + 0000000200000000000000000000000000000000 + 2ea177197993e7c293ce7a59bd3deef17485c206dd19195d + f1758101cddd487e37c8e5b179cc2d90f15adaa047c61a90; + 0000000400000000000000000000000000000000 + 8fb6036b6580c04c433fb07d0760fef91bba85272739c0c0 + 11c2bc53cfc7fde6fdccefe4f20dba513c465b092194a3a4; + 0000000800000000000000000000000000000000 + 703784863ff9e7e3c09fa9bf128ea31dbd2b8b4f5cb99e36 + 936d221d1f0c14b6f01cb3028873895e5b24d16f0031ab8f; + 0000001000000000000000000000000000000000 + 5a69ea7cc7fa7302fcbd1ac2d07dc7c6621ee0aff1d018a4 + 41c2343b468dcccc3ccfda966cc9ba78d8d57083ae27f29a; + 0000002000000000000000000000000000000000 + c89944b86c5edf216c8a8f8e58eb307bd311e11e66ee4ebe + b38dc49125243cc11781df4559f9d84640a7338403236c85; + 0000004000000000000000000000000000000000 + 3c669450967f16dda82835eaa8cd3877fa8de68ddd5c59b1 + 278e188e35f3c26eb8bff5c03a5b266f0f51aaa4a603081d; + 0000008000000000000000000000000000000000 + 9823a5e5bdb3ca2edc47618be7ba9ca742d5f0d2198047d3 + 21a333410512108c86dc7950ab1abe701a9e3d856e6d9269; + 0000000001000000000000000000000000000000 + 981fa376decb5e95a92b842e2dee03c562d8ebde0c8d6cc6 + 370eb81d50ef15a799ca481521a24966d033da29486007cd; + 0000000002000000000000000000000000000000 + 44b698fa4f4f6bf89fc66a23abb6145d9713908bb03705d5 + fe70a9986d13fbf73500352f742708a29eba0f80d324843d; + 0000000004000000000000000000000000000000 + fee1b9fad13700816390e29880a83233e7b90cf183cd3527 + 0c8ab7fceeeb439397c095de04ae56eb867499360c6033ab; + 0000000008000000000000000000000000000000 + 31defe3570475738ce89f436ab737800c6a59fce561372b7 + d78ea1624b5ed5cce49a46ead9237bbb48b90327db11c74f; + 0000000010000000000000000000000000000000 + 652a17e6b330a95d8237cfa2356e47c295585ba7666fd7f4 + f85f595cc857f48461b889a0ca7f6245866e45946f5c8522; + 0000000020000000000000000000000000000000 + a658d408b3856df66df0e5026173ae70627a649b836c5011 + 38ccb2e915fdfa02fdc9b19a8fa446b538559c6d74af7f97; + 0000000040000000000000000000000000000000 + 84ce7b3fab5d81b85e00681ed7b2ea130c53e405233408f6 + 92d8342bebfc338cec2bb424174d7951ce2ad5407211a53a; + 0000000080000000000000000000000000000000 + 17a24739d92ed5f4f09f886a435af20a3f786bceeb86293c + f51ef9e9d4841d25699f1199bf1b66d3f54e1e1b91e91482; + 0000000000010000000000000000000000000000 + eaa616b384519b85852137c3f4ee61b6b48a2eba21d566d9 + 9e58a0b7cb6d0872f9882cb52abf91ccd7978367ff6228e9; + 0000000000020000000000000000000000000000 + ebd576de80da794a234a8be925c69e88bede65f64d7225bb + aede5cc115eff89d20b3ecde8d4e03a7935d368c20c837c4; + 0000000000040000000000000000000000000000 + 4090b3588edef6e689399495eea36b33fb23104527e353ed + 5295d7a3f7ec90d084282a1a0eb82d6cff90ac2a25f6d3db; + 0000000000080000000000000000000000000000 + 947b834b466d2f3d92ef9512c3e450f0b578e9ac3be212e7 + eff671d27f5e2af474962fa0f66b63276b24e484c66be17b; + 0000000000100000000000000000000000000000 + e611b6a6801fdb802ba7499c39a966bbd8b8410f79ddfada + 357c82dda476be8ad41b40e2269ad52baa9d806c2143f84c; + 0000000000200000000000000000000000000000 + 86e67d84b15f9f40a0fff739679044f91b0ed0376a1095ad + d72da9a06dc17ce4fcb24d51b804262513573c799a57b130; + 0000000000400000000000000000000000000000 + c19000056d359565e51b7a3de313c57ff2bb35d76393acc4 + e5bd4cbffd461144135051d8555128786a9e106d063a6993; + 0000000000800000000000000000000000000000 + 2570f1f193ad3a0d2314158dd137347dd99690a6b886bc5c + 0146f5cc2c6b14652e8aa52d1c4733ba5e367a57109c5bf4; + 0000000000000100000000000000000000000000 + 7526b9f746fbf4396e5663ba52f5bfa682b0501fbd36b5bc + 107ae0fa5444fec8cc7d0f01eafa3eb0fffd7c34ac6869bd; + 0000000000000200000000000000000000000000 + abbd3dbd4a1864fc20f7226f563a7f5098ff273cc8bf6576 + fd12b3b1749e8469a8ec879560b583e2dd88784db4c25879; + 0000000000000400000000000000000000000000 + e281a5fd1b6a7aaeef32e40482d6291aa697cffa21dc27a9 + 0cef0579d12fdce29f96f135be671012502db1f95a55f8f0; + 0000000000000800000000000000000000000000 + abff457652774b07fdc99738bac8ec162a01b73f8a71b126 + 970ff7ab84f483c9f1e73567d7f38163363b14850fad8834; + 0000000000001000000000000000000000000000 + 1d75fbd8451f22a0b0a4a9c62ac6a5716511600bc76e8378 + 6be81dfd6a58e989c4a7d5f1f8fa22f36b079894564434e8; + 0000000000002000000000000000000000000000 + 362b88b73e2cd980d5d78d3b7c591fa0b1e70a9ed5eba7a5 + 7f3c71fecac4105cee4c489c01f975a232402c4635b515fa; + 0000000000004000000000000000000000000000 + a76d84d4eeb86444c3a948c0a798b9dd2778a96e30e61aba + 992557baa0a7dd9a06007681153f98f02c19d6de76d898fd; + 0000000000008000000000000000000000000000 + 667c962b1ba89807b086fa168e80aeee355e825176e212eb + 785d4ed06bcdb3f0fd2cb716ee9a1a3c462fc9b51e305082; + 0000000000000001000000000000000000000000 + c0ce233a95f06506ecc20c9d94ec5c6c757b4c5b0727d492 + 157a5a7d1e8e91495bba18085d26338a3b1463d4e9db858e; + 0000000000000002000000000000000000000000 + 85b69eb5d5b732a8bb0b1a9b3693116f983675785aedff22 + c6fea81b9347c9e7567fbad82d5b8912bbb76dba8f4a29d8; + 0000000000000004000000000000000000000000 + 2795aa156ddfa00c39642ab05e286c964ed00633bd60c5f6 + b7aedfef19724e4782a10536428547040ff7f59c8767f2d3; + 0000000000000008000000000000000000000000 + 86a2b6fb19ca72c2958a6569aaabc0d7d1f2d7dcd2b5b61e + 39130045632a3ee79eca91f2f29056c887192ce4436614ad; + 0000000000000010000000000000000000000000 + 38a0281fc43a1c8719f255c575a9b1dea32a4c81e2d4a934 + 24a434c2d65df7b788bf3bf0664a22928ce07df667017502; + 0000000000000020000000000000000000000000 + 8c8bd4434261667e10c6e5527640e4be2fd50112c27604a4 + 95c7dc7d90348e480db9cef4b640dbc62f4bd76714cbdca5; + 0000000000000040000000000000000000000000 + 7a20a0e0bdc0ce07559e7e247fe27b2e57a3a2bfd1ac0964 + ce680c2c69f4951a45434e164644c36dec6abb246bd4f1b9; + 0000000000000080000000000000000000000000 + cbf7402991a61ead1dfa657b8688ec6b1d3755f1c12d975c + 5bc02ef2adf14ec62187882da764fb4bcd8837eaa3f8014c; + 0000000000000000010000000000000000000000 + e4218125dc4a288d9bcb43710ec3029f0a5d631dfe401b47 + ae21a4b216e530a6ab6c14c8d1c728db79109ec58cf93a0f; + 0000000000000000020000000000000000000000 + 1c7038534568125aac9c0b8f3cf3df6b5c409f47d6cf7a36 + 5b87e5ab0f97669d705271c435c4e070712bd16f2c5d2e68; + 0000000000000000040000000000000000000000 + 10d92270537442d4b847b42107047bc05239ef1ca981e89a + 931bc9341a445caea1a5088b2b4121e8f8ef085a86075715; + 0000000000000000080000000000000000000000 + cb5438433b829ea6a99da8216785cf60b99ceb0923b9571f + f239aad41f8d994e8019211e64520780dea454282a625568; + 0000000000000000100000000000000000000000 + 720dd5511ad848d9c25861488223d168fe72bcb22918fda2 + c39891cba3b1e61e71101f3dfb2e72b1bed9866050dcc11a; + 0000000000000000200000000000000000000000 + f0b450e144ae3ca96a39f8ec440bd9cd20bb77deda9307e6 + 0da749458faef5ceb6192c90857a7aa5bd010fdc57799dfb; + 0000000000000000400000000000000000000000 + 01e54bdceb03d02c43f7a24495c462287bdc2bd34ea16e0c + 89cba811c829d32dc1bd8e3302c13415dc9676975cb8ea60; + 0000000000000000800000000000000000000000 + 47207ea139f08fc11911585ac7b449116552db41f111c437 + 798c17318213280bdc778c2e761913983673079ef8d74230; + 0000000000000000000100000000000000000000 + bddc51901a7f6556334147d54051bb50ddfc42b4ea97d1d0 + 07c366e28a2cca1cf218b56e12277e18c7ddc698f2ac48ec; + 0000000000000000000200000000000000000000 + c2e65edfbb87317b24d411449ed48f323b12ccc1d5a5b7ff + fd99a7ce5d3e82b466e1b5396a0fac675678d17237b6d52b; + 0000000000000000000400000000000000000000 + 30a8d0ef4c28908b2f18b2bb9848eae86269ac525798ae76 + c36b40691fb3860ed243d7c4ca22dbe6300b84dfc91f541a; + 0000000000000000000800000000000000000000 + d2bfc99db253d16a9b3da4c77b4d8ae6ce5a82388ad113c2 + 5a005838a2a9713b8384cbb052ff742664f69a24260a03d4; + 0000000000000000001000000000000000000000 + 2a916a4edd73e4dca0a529a08b8f9d29e437edaa9ea50bb0 + bc202d61c79a55eed0cc2489c4ba4c7b5bdaccf3e6404dba; + 0000000000000000002000000000000000000000 + bf7879a48b750f7b9392746617c768581f3b21b231ce81e3 + 67560a5ac0f6d75e0b9e0c81e006d685923d80bdfc75c064; + 0000000000000000004000000000000000000000 + fd436ed32f95d1682008a0faff041f4793f67fadbef3645d + ad24e531f725780b4e2a33c01e1cab0c278bcb6f40edc186; + 0000000000000000008000000000000000000000 + 524a9d2ffc5a0261bb2db2158632b886966ac2935c05c0d8 + e9615c9cede6feaf6877611d633c2454d3acdde2ae2ceb4c; + 0000000000000000000001000000000000000000 + a6a9f7b07ba8db6b135bddcebf9f137b46c21366c742b3c8 + 2f54bbdf8a289de06c20837df3752765970d582f7cfbb5ed; + 0000000000000000000002000000000000000000 + af9c61ac592907f8526a96bb7b6fb146c5a069aee0775b07 + c79a6ccbc8d009fc3358646fee5236fe6b739f02f2bb5a86; + 0000000000000000000004000000000000000000 + 0ac8672af776f5e1ca0fe859501d3676b5358f9b22f856e8 + f113bbcafb23ccc325b906522b4058e6cb26fcf24abf6658; + 0000000000000000000008000000000000000000 + 498b0116b3767b651da3b7d4ec2d513305d1260826d3c166 + 862fd18cd2fa16ae249b66066db3cb871fb1571678bfc82b; + 0000000000000000000010000000000000000000 + bdc25d6e937f2e889fd774cab71fc86b2898652c44406193 + e48d25b9e80fe5bee1fa7e6480c9f4502fd0d5e1534f7748; + 0000000000000000000020000000000000000000 + 978a52ba33b411f1dd33ccb5f9fa7978014ff0877a8ae115 + 9710fffcc51af2e428f5a4da72ab1fd721be7ad3aaeef40a; + 0000000000000000000040000000000000000000 + a79c6dc139e5d91b27102f5fa0f1b8e6482fa96fecb021dd + 15605d2943c8c9d182208e4db05075e132e451086a9b609a; + 0000000000000000000080000000000000000000 + 321eac9f621e2ac12cbe8b5d5d1a75fc03f6c16371374934 + 548803f109cf611d2e7ec0e87098e27b2c149194ed832352; + 0000000000000000000000010000000000000000 + 50117692ce6e19e23d553a4266cc3458f8b05e02c7dec8c9 + 6c83e70eebb0018f4d6e229404e39688bd07666f6733b560; + 0000000000000000000000020000000000000000 + ff480a631e43dfdab88f31f20699a113d7a6ff04d8f33bab + a1485a58f6d8c01604dadfda7d03d7717a8dd2c2d20a074e; + 0000000000000000000000040000000000000000 + 23e5ca641b9b76fee53eb3f8783a24030dccfdacefc8ef29 + d4a1f481e845a6025b3bc9901a003e2a3b4a6ea49e8ebdbf; + 0000000000000000000000080000000000000000 + e06841bfb58278e02eef5c29cf5d05c00274e18bb34d967b + 70097b468635250585a96b9d81f1d54cab338095c33b954a; + 0000000000000000000000100000000000000000 + 853d124cdc7b138c9b17798a4f1aaa343bc179c7aebfbaa9 + 59b5ca04ffb3d7277c0e0505e8be581641f233e7824d5e11; + 0000000000000000000000200000000000000000 + 5998176bd90c122ed78911aa5948a5ad2a07df42cc41e967 + bf577dc495b1f12096a3c1503d1c3a1263895dfc9669a2dd; + 0000000000000000000000400000000000000000 + d11f16da1b85b6b7f91fd0c4e24122c9169b45fcc0f630f2 + 03d6401fd083a0700a06a243c8cee99c0966e61230c70901; + 0000000000000000000000800000000000000000 + 24d65de955a156e8253055f73589da884636a0c5058bf6b4 + e89aa9e074432b437f15b56f6d38a7fcb24cbb208337dd01; + 0000000000000000000000000100000000000000 + 4b93290373c2747ab475d7f4992477727b21391f0cb42739 + 959d181d009c0d0898a694b8d850647d76961f611682ea7c; + 0000000000000000000000000200000000000000 + 93fff47d6977a99536ab313546ba940048841fba7a5fd9eb + f8769c05212e6d6d4093fbd80ea4559513b3d18f62ed698c; + 0000000000000000000000000400000000000000 + c8070ba52cb08c0f814b025d10071efaa91babd0a3a8a1bd + fa1c2ca6ecc071ecb923ccadc0f69acb701daef5f56f1936; + 0000000000000000000000000800000000000000 + 0a3ce83ede05ef4dc7095fa9234e419fc31acf8696e9cb1a + b6fdefc344f34cfff5b2e2e4afa00f426607f4ec1f727eff; + 0000000000000000000000001000000000000000 + 4dc5c361823d632dcc5813096d9e0ec1e0f797d303d75e7a + f156ae67015b18cb6ecda9e03c6558a67b89834a175e5e77; + 0000000000000000000000002000000000000000 + ab85aa11008c58f59b58019794a2b480cf51aade35a2d269 + 9c2821ffb2e3dc84b9608d607133e4b34e35643de130442e; + 0000000000000000000000004000000000000000 + 87dc8d3de6852d06a9712bd570873c1620800ffd01e35b17 + 0fbe6f80f9306e00330a42a9d7e57cc68c0d992b70d9e982; + 0000000000000000000000008000000000000000 + 606855c5e2af7d73a759c740552e82ccb6cebe5509d6b8e7 + 78e8ab0a55e16027dacacf1de95a31f9cfe73bbb17aeacd9; + 0000000000000000000000000001000000000000 + a739b8e8bd92be110edb4378a58e0ccd15d564093f303750 + 124ef1013fa8a440375625eb3d056d78bbeab4f5e808783a; + 0000000000000000000000000002000000000000 + 58ec509a6c549d855602a8ebe8cd3e81be9125f7df70a84c + fd3f5db70bb2eba772ec550e30b2b3e5d51aea15ec0f2e3d; + 0000000000000000000000000004000000000000 + 447c79e0983fb296711c2fff964122ed7ed11292c018d2e2 + 83e12d4da49d463333fe370cd180c683ba65f9145a76aa18; + 0000000000000000000000000008000000000000 + be55d4ffe6d7cca90032c0808f58bb3b1713e19b1151ac0b + 9514f1e6c4e615dc11d0e4f9a25646f2d3361fd038bd8cad; + 0000000000000000000000000010000000000000 + b2288fec987471fff2d3625f55630630c6344b720e2f9d17 + f7eb7d549d9279701f73b30ac5747fb2caadf10af6967bc2; + 0000000000000000000000000020000000000000 + f4092ee2b5f070731b2d68a0acf2dfd5caff8b7302f00eea + 181be1b17f1bb5df53c76582bc5f460fd90eca3f273f004f; + 0000000000000000000000000040000000000000 + 7421b7fae0482f6cf39682fcf32a7c23377f46d15e5d2fab + bebc8fdcaae6d0891571abba31fd6b5525e3825689951ff4; + 0000000000000000000000000080000000000000 + 6a0271edebc4ee46a837798b8a11e11fc9dd37f5eac9cea5 + f88c774103bfd9656cad11ad4b2ff3246a79271f9bd319e3; + 0000000000000000000000000000010000000000 + 7e7790676f13b58bff48031105e4b0e0ddea47e227cab1b6 + 95e30e5b38892f17c26315287bb12011906932ef6888c307; + 0000000000000000000000000000020000000000 + e1f369e67be60abe334c75c254bd5f819d15397e52ce1991 + 5e08e9923dcac610c4f228b1feac23bc6e0ee8f2880625d3; + 0000000000000000000000000000040000000000 + 5da337bd8a553d4a311d9cd0d00cd8c1292a248704f08e67 + be4b68b824170d0a635b10c1dadb2a69146f5a9ff9c45d7a; + 0000000000000000000000000000080000000000 + f36268dc83dad1fb42ac11a70d2b04c3074caf05f0d28e4b + 93e3bdb8ae0c1283991383131f42785aa6c13efac96a4ac2; + 0000000000000000000000000000100000000000 + f509a4aaa4dd6d33c58f09517fd61b0a3e173981cee23328 + 0d3acc8d01a95faa7bae199eadb1b7f0a6799cc193a36b87; + 0000000000000000000000000000200000000000 + f06206eb3ca9d5b3a97ce33c86ab3ec88e025396414965f4 + 06c48b3173b95040a1b30b80892f28205bc3073c06af9690; + 0000000000000000000000000000400000000000 + d94cd93f0aa42e7aadc3fe5134a75e22901a277a9a8b8914 + d040857811c9e9ba2b1d13842e74a2aa3242e8b92106d648; + 0000000000000000000000000000800000000000 + de0fcacadfd215ef8ad575bdaa2fc3530d913a03801a7e93 + 142c97486e896f09f6694b3fb82fc7e6da00fe9882351ad4; + 0000000000000000000000000000000100000000 + 416e67c9024af80ce9084c854109b4d78fca84cffd481f3c + b9a534a054aa28ae408d293652388f7dc8782441dae29783; + 0000000000000000000000000000000200000000 + 1967362294f80c18835408ec52e69b4863a0e463f759a6f0 + 95e7f20d718ffc48412abc598fad1826697b7545c8e3e0af; + 0000000000000000000000000000000400000000 + 1ce4ad11f24cf2785769f676ecfd2cd5479766bb09236f8c + ae02eac15efa0b102722ec4b393323c3f9b4299ec8d62ed6; + 0000000000000000000000000000000800000000 + e3c9df7ae6d132da795747f26daf2a538776ed4694636419 + 9c6012e67ff701322397ad7a374116289b3b1e35277812ac; + 0000000000000000000000000000001000000000 + f4faf834e3aa92af4178e31d770e7ebf70bebcab1752c561 + f6fe6c69c4227663ce35b7abb77b78df395f2ebf8523cf28; + 0000000000000000000000000000002000000000 + d667bdd9f5967cc525310fefc616998b4705ed09714a55df + efb98baf6fe8946fe39778606ae2fa874502918c0885ff8e; + 0000000000000000000000000000004000000000 + 830e96038280527632cbc228474953ec407956662ecd1e7f + bc1b15c2f9951c77111f6aca5fc75222615e4a12287edc86; + 0000000000000000000000000000008000000000 + 6afe6de17fbd8260c7dce898f26d002a6359800bb5789c23 + f3c39e7caa6be7d346d62eccf9e1d20a4df2f2c52f0c4c2e; + 0000000000000000000000000000000001000000 + 6eb5d0fab61828d24ae3323d3018f65400c8c3c0ded66ded + 5a585a0bf790d36ca04f6e3db2a8240bde8674bf26d0bcc5; + 0000000000000000000000000000000002000000 + 279323d7c326dfe129bab246202e23158e24abf280e04a5e + 721cf1d8e73cad3c3ab65d34cd83fc131acb73161d33ee18; + 0000000000000000000000000000000004000000 + 6e74528189d18b5d8de86975b2272b708dc62f912bb1f90e + 8e2431350408e2394201afeed37957886df2ec97eb5a872e; + 0000000000000000000000000000000008000000 + 0e4780dbee0c09822f67da8b98aced5440e3641fc8c80d4b + 5049f512c2cb135fb8842351a8cb5502bfb9895914494497; + 0000000000000000000000000000000010000000 + b40751d42e542a27240b1c25d17d088fdf35357a8e606b65 + 0e9feaceb106eafffd46da59acfd588c91510fdb60f6c101; + 0000000000000000000000000000000020000000 + ccdf33f8a14357509960e96ffd707d34d6e125593c470b22 + da36d09446c89b49417909efc8ab9b8884a82676d0083b27; + 0000000000000000000000000000000040000000 + 7b51094cfa2d2972b921feb7bc4910af27329e6417eab51e + 4af16a9cd82694f045f72a419bac4b36c8f4d1ba7b6d7853; + 0000000000000000000000000000000080000000 + 8912b55eabcae2fd33cc24d48c77e9ea91ad17637fcc4e9a + ecdedb7cb770eb34f181e7f4e168d3cb97a62eda8a93a71d; + 0000000000000000000000000000000000010000 + 4da00b91551750c9e42920ca30cb60c6800614cdd94478f8 + a1fb6aac2ba91f1db16292fba881ec25ec5139a05bef8360; + 0000000000000000000000000000000000020000 + 1ac4f21d876b643c6a4e7dbde96f5b46871988c089075722 + 957f88bb33b20c12a264f47f483a7319275351c5beae257c; + 0000000000000000000000000000000000040000 + cf0e9847cf96d79d483634b86b9d946163fc7f75ad200380 + 090dcf1b1e3d1614b9a81368ae7494eaebafa78f7c8ee545; + 0000000000000000000000000000000000080000 + 8776c8edab400e4e107458c529119fb645ed0232c13ef316 + c190562aa4f0e4a8a0b142d3842e16a1e4145a865533f820; + 0000000000000000000000000000000000100000 + 5364915ad601a7b24e7fa93224e0f890c1b19976ef727604 + 8fb3df4ab244c50af5acdd8273bbdd5ee22433978a1eb577; + 0000000000000000000000000000000000200000 + ac3f6c09935979c1c7ed97fb57b6b4effc7ae93007905959 + 65d4b7f38a928a43be02d8c01e6de2709e2eafe4cbdf00d3; + 0000000000000000000000000000000000400000 + 6531fb35b522582fd8e344b4967d4fd96f3f028df9b8a0f0 + 433d474f5759f5a6268d21ff330185eefd7581fb417824ad; + 0000000000000000000000000000000000800000 + cddb346f0a62dab089d9d08e5728c390528341a65207762a + 15a50b1d5b86af3bbc2d769639d1863187e6abf155550d85; + 0000000000000000000000000000000000000100 + 76a743ed49c15a6ae22baed339d3b3de0538d9dd9a5fad03 + 2f81d127787c8b56417ec1b0eeed0bedf24dfaaa5fc101a9; + 0000000000000000000000000000000000000200 + 959c1be8dc4a8d23c065d0af24ac881204f64c6ac6f39649 + e5535e583d915bcc451d04d40f88d00d531eab1e74a85936; + 0000000000000000000000000000000000000400 + 60f09275f915ecd4753a88c14f310627a68c85b0059cc7cd + f2eb6f33261a6f1521acf10950689cf8300ea1f7dd02c455; + 0000000000000000000000000000000000000800 + a582a3a84d722b1888eef5459d744f4c9bf0f254393eade3 + 5171c29052d8aa3d3bed54ed6013e5bf27f0ca0c256e5df0; + 0000000000000000000000000000000000001000 + 5075b276fc0c1b44b34c2d7103a321119dfd5ca9858f5ebd + c3e543ed7b34b725a060380f5f351859b5cd34c3655c1bb8; + 0000000000000000000000000000000000002000 + 76ecbfce581f71b255f56aa7118900ca55482a1402d508ac + 16f238cab43a3e15aa8bdb6546bf4907171d6062faf6d51e; + 0000000000000000000000000000000000004000 + 48c37ef151bd87c3c8af4b33d2cce7007aeb511e4c9eea95 + b78ed418a8749a58fd1fa8eccd28ed1ce220682caae446b4; + 0000000000000000000000000000000000008000 + efbc6f0100835c8051fa95f338915f80004763efd684f982 + e88cad94409c47ee2fb48fea7996afd75780fdc66f55e145; + 0000000000000000000000000000000000000001 + 8f537350f5a94603ac84b105dad1ce2b27e775b251ffcaf1 + ccf28017b1b6d8e853094535b78c0c533ca88d3119f88130; + 0000000000000000000000000000000000000002 + 73bf403e90243af00ae3573bf26cbbfaf22bfc64c25042ba + 842c8b6edfd5470e1261b53cf3f495c03e7ffbf747917b03; + 0000000000000000000000000000000000000004 + b2e7d8fb0bb71f3543285e36b768726cdbad667cd415fedc + cae46b71316c769290340cdfc99c9751fcdf53a911e75700; + 0000000000000000000000000000000000000008 + 391c06d7329a903e22f310c602d86877dd921f82e15173be + e2b1e5114f1648ba3449d564fb1ee26d7c325630777a6ae5; + 0000000000000000000000000000000000000010 + b54aa87e67f0e182a88660fe8df6a34dc2fb021fc80e372a + 30d3fcde749a306eb9d5aad0527c7e187449beb5a0b4e2a1; + 0000000000000000000000000000000000000020 + 003bc47785839c9c0d915eddb61b2eefb3e474c86cccd321 + 388746b96cc6ccadf4f86e0a98baa5dcf6d2c777195a8b07; + 0000000000000000000000000000000000000040 + c737e23e4813ee5321ac10198e108ad3cb59dc35a46aa4e2 + 987655569a6d6c797b7c432b8711c1c4a29c95c8849fbb6f; + 0000000000000000000000000000000000000080 + 2ea5c63608597b7da53a2ceed973943951552fffd89c0101 + 1d6673cdb23e07fd73fb0f325b98a9d7640a118e170b20ae; + 010000000000000000000000000000000000000000000000 + 950227a0e0af4be87ad9923642ae064a989f7bd41783a808 + 9d1b35004e09dc8a26c67a60c358a299cfd493a5825d2bfc; + 020000000000000000000000000000000000000000000000 + e06478bdbb64dfc81293d20b3babe451119c00a57abc32d5 + 5cba681dc30a6350b640f6ff5d82b9a59ef4724cceacd6a8; + 040000000000000000000000000000000000000000000000 + 9e2a31deb5c28e271d69790d7dde1fc96b5e2f727ba863d7 + 383972aa8b8a05beacfd3cca26b84ea7e658f0a161c44307; + 080000000000000000000000000000000000000000000000 + e7248873cbe00a5eb07d18a36dd1551e1de656f175795b68 + 72c76c4142011ef65b3ee4d1d92845dec5d24c09b8e15ea6; + 100000000000000000000000000000000000000000000000 + bc6a56d706b865d0d0bb17f6f56a946b19b6463823b50705 + 5856456857fe3829df5ae6ce9c1559e2ec272e2023bed389; + 200000000000000000000000000000000000000000000000 + fc9f70464be8294b04c3092a09815ca7cbd9e4007e35a6e7 + 1873b51c4e65ef63ea2ad3ab7bbe2933c53607c2f4f822ad; + 400000000000000000000000000000000000000000000000 + 9252b21b6ee8ad2618bbbb0624fc077c593422d73c205172 + 3fa2ea516e55274a6eeffc125729b4f323395a9375fabe20; + 800000000000000000000000000000000000000000000000 + 23ff2420dc5bfa41b4c1e02c9724c8356973ee4c29900941 + eb5c441b2c65f801f3781c59bcfba202ccca06a5a0daace2; + 000100000000000000000000000000000000000000000000 + 21bb39d0e07a104683fcabcbf086ae38505f21119eb69eb5 + 317efbc320dc245436f65995b9555a70567061f15b882765; + 000200000000000000000000000000000000000000000000 + 5faa02f914a0d07a3ef66ad9b85dd7292cfca0e96b41b18f + ac6668e2d5bc13abf89ab4ef5ba02e4893c63453fe6cdfd1; + 000400000000000000000000000000000000000000000000 + fd2edab89c53584e62d29154ae3eb025eda061a2094d1c55 + 074cae6a1865c11c8a740c06500f972946ef3f7cfca6c784; + 000800000000000000000000000000000000000000000000 + 1200e02bfb0d2994eee80495fe6f8db63f480f23b06943ae + 665960dec953660aa472689e099663ea2e9281bc0ec42b70; + 001000000000000000000000000000000000000000000000 + d7680b371b3db05b0fd319e98c4fb48faa5147c24fb8dc98 + f0faf1fe00730c1795fbc5865cf67def50d494e9b0e40085; + 002000000000000000000000000000000000000000000000 + 0ba73097866cf7add6a87d76db9512a2965f43a59842dc9c + 867abf83d19cda8d1c980c008be09eb6d3fd4c2a3aefe157; + 004000000000000000000000000000000000000000000000 + 0efdd7ae03dd5d0586093ce70bb56933d277cf262a708e53 + 15828719856c5b9f77c12dace0afd8bf79de06c99b18ca32; + 008000000000000000000000000000000000000000000000 + f8aa22bf8e9b805311ea0cfeb6633a4d333c25df26a44086 + d24bebb6a79cf48786be0aa33e3f0d904f4c1c256ce5284e; + 000001000000000000000000000000000000000000000000 + bd4971c056be4d3e3a7a7f727700ab237838abe0cb8006c7 + ab9a06b02608dc9824147e4fae22347564145cc72acf6d63; + 000002000000000000000000000000000000000000000000 + 47dd63c99f11d04f002c78b4a9f7e87e6a95103f6b952088 + ad3844299f2996c7124618b420a5d20476f8724a1a2a554f; + 000004000000000000000000000000000000000000000000 + c23a8c3c1c99c1094e0e33ea48a795e457124f219a7ca076 + 1756e14debebb81278d38a6e1e030c41ab3ad10db3723956; + 000008000000000000000000000000000000000000000000 + 4e51df50080c1c5ead84794c7f8c0b6af24eb44940230a54 + 6ffad11649a0460c565e360be1d922b3882760bf6f6cdb0a; + 000010000000000000000000000000000000000000000000 + 94544aa77e6f2e88130f6d882ce6d41b92805e8a33bbf758 + afbfa3504fa60b0c174dc726c32e36cf044730b03de81da9; + 000020000000000000000000000000000000000000000000 + 4fcde9e30ebe03a1f724f6b00d806273582e1cdfc15ff147 + 80558bc2b6f44c7ba7d6640d99278f274b2290e3d574e93f; + 000040000000000000000000000000000000000000000000 + 2fc3569fa2e00eef7c411f2b469869e37982de1d4a6e6a6d + 6adb474171dac11f836848dc4753239335b91b1f5e1392fc; + 000080000000000000000000000000000000000000000000 + fc5b0abf6a26469cbc8b64bd73322994717393eef4fcfb9d + 3c2acabbf67983924899ccfc1d003cd931f4808fd2aba192; + 000000010000000000000000000000000000000000000000 + 4c72a0fc014cb5ca4e85b0871f3fce111bfeb1ee212bc3f3 + ef0ba0a4ccfef260c42884b03ca09c7bbd022b3c69d2efaf; + 000000020000000000000000000000000000000000000000 + 723a6062b95c8e17cd63441dc3542103ef5b62b2ee67f696 + 0a0c19d7009f4984767aac9284ee75784b632ff2b8b0165e; + 000000040000000000000000000000000000000000000000 + 00f433db06d51a81037b312e1687b90668b14b5c87019e79 + 2769bcb9e372babe64498035c9ca6d385e713f2c62da9830; + 000000080000000000000000000000000000000000000000 + c00a26a106c43e944d8012181e873d57658bd3efbef46926 + beb3b2eeb0e4cf7af92ab9eedab0afaceda36a4d158fc060; + 000000100000000000000000000000000000000000000000 + 2b6af19499046a72002bb08321899ea1196e43a3445dc66a + 53355ad208629b72a6b63955ea29d96f8625ef065d7bfbfb; + 000000200000000000000000000000000000000000000000 + b8bd2b3ca21a4e9c46f3a6ee8283c629e51ad868be5da5eb + 099fb4ee85dd16e2adb3a8392721eddef3284ebe72a629fc; + 000000400000000000000000000000000000000000000000 + e7a823381ecefd169648af7cdebe27bdd33575997b16c9ea + 2087cb8faf6e0f87bfd483bef04ae0aa84b7faf1d66c3067; + 000000800000000000000000000000000000000000000000 + 10bf2538f02d13d5d6df68708a1a875152c8253a189c44a6 + d7c45cd1b7df5ee240c9e19d9a875c99d06bffd5b58249e0; + 000000000100000000000000000000000000000000000000 + d60033a9a4020d3be5214edc136c993f05a04a3e8ea5c8a4 + 25b00716396a5cc3c54215e42da5c2642073d967fc26dbee; + 000000000200000000000000000000000000000000000000 + c69e4ed75ca48419d526e5997f9634d1cc230c49158907d5 + b8eedcc2227f3593df72a78ed1100394eb65f9098b5eb4f1; + 000000000400000000000000000000000000000000000000 + 9dd47ff28851b4da258c41aedadb4d407e39dcf8421fe2fe + 913ceb307bd491e5a5e7c6945c7b3ccf2b30571beeab889e; + 000000000800000000000000000000000000000000000000 + 245dadd57e5ea520d0319892ecb964fc7d7d75ac259196e5 + 06ed9325638f5f233cc3c6687e966d18d13a2376a7d0d2e3; + 000000001000000000000000000000000000000000000000 + 4b88b385ae2ce90610c3de9942359182b23cf96617b01a50 + 1789bd30c366f57f606c139d7dc7c00bd6999994bc225eba; + 000000002000000000000000000000000000000000000000 + ced8575125b759ba6fb81c4cf51b309f1199038471b1034f + 4d3bb5964432e95176d2438ae186c9ecd0aba9b71899b85b; + 000000004000000000000000000000000000000000000000 + 2d74c25a841900a8b9a663b0ef0dbb1e24a4950eb06445e3 + e766ee906e42ad9fbde3aeb74fdc464fc3eb72c87bef45cb; + 000000008000000000000000000000000000000000000000 + 20f7f88a12d40f3cb6b592008dec36ee508387a7870e8ba0 + 68f515a58c25941d27fc209666df7caac05c6ac143a883dd; + 000000000001000000000000000000000000000000000000 + 9c95399291b0d3202663fd9f6ee972975c862cedbf2461e3 + cd0987b7da9744e475b9a457e34330216858240559c3758c; + 000000000002000000000000000000000000000000000000 + 877cf0278449adf691b20d5b453d891951a1d1e8eb03c47c + 5b16a43b032ca092aaa101ce8d0daf61894d53075fe02768; + 000000000004000000000000000000000000000000000000 + bae2c00d2a033ad2acd8719acfb01332aaf91987a84b046d + b9f4306305a262b7a8341f8bd9a30722b18479e8a722c030; + 000000000008000000000000000000000000000000000000 + 3a8b7c986f313adf30c17005fc8f4e4783cc7efbabb45b0e + 80c005616ccd2e26d65e3b9d6b3284218a90448b59d6a4c1; + 000000000010000000000000000000000000000000000000 + fd95f34a972382c5c78e702b777c873040970ec04477a9b7 + 0f8ef6fab119411fcac25d7794514f6879ccadfbbdcf1737; + 000000000020000000000000000000000000000000000000 + 0e76cd58cca1993794ee6fd9537271c337844d69317a3064 + 0187210213980e21d629cf30ce5702e6c3a78fbec1847c30; + 000000000040000000000000000000000000000000000000 + 7cc71eda22e83901a5e7d5d0fc5a2dd1a9a74c25146406ed + 040739cf452779ac78d307c96dc0298e34f9ed95b4bddce2; + 000000000080000000000000000000000000000000000000 + 34a0f031a22247f0583237ab3084581ea0cd8df336723285 + 3a9ec82043173a791c04b9b8be7ffb35118bf09e3d2ee0ff; + 000000000000010000000000000000000000000000000000 + 0b6cf14a5abe2dd979c268d5145083b48889d69df0d37708 + 991b6be8eee496149a181200b1fd081e437a9b5fc0cac4e0; + 000000000000020000000000000000000000000000000000 + 08cc9b13e27d4cd3e3d7563eef1dbba235abec2a418f1852 + ae9edb5746fdacfa76de58675cbbd24a4a7e77d96fbe7b6c; + 000000000000040000000000000000000000000000000000 + 824c0dec5d6a4df429da24bb8e2fc8a4372bb92074a2727a + 8f0715b035222ee533b0981f01550e8e5a9e24412d9ddfb4; + 000000000000080000000000000000000000000000000000 + 68c15e06234437eeb45d5108e8259a70e13258dbab25b697 + 8d177379a2039c1a7843ad87fc6ee1393a4cee80a2751141; + 000000000000100000000000000000000000000000000000 + 1001198aada4c22c4dc1d84fa1e010cd54835e132f22dfeb + b8cd530fe6ca419cfd7bb8081845fcde53b2adedbd801018; + 000000000000200000000000000000000000000000000000 + 9ee54d6bc7e24d0c738ddfb263e5b63fa26811b76b578409 + 7f7446709375b8e32d8f0fc000eac04f0b1b82a3125cdf96; + 000000000000400000000000000000000000000000000000 + 85c19ef941156968fe05f7fb61bbec5122012fa0fd4bc828 + 7168634d5b191ffacd2f8e4928119d68627bd4b027db18c5; + 000000000000800000000000000000000000000000000000 + 2e644758b3e889cdaf5c845e4ed308be6a3eea514f893e6f + d077d2ee5cc8d36b632d4e983578d6bc894ed2006b57b466; + 000000000000000100000000000000000000000000000000 + d86c637f816b37de534d296fe76092971f47418fe1250959 + b15790c9ab783aac93d8944f77eb9d0d3ef9fecac04a2918; + 000000000000000200000000000000000000000000000000 + 864954a4c173fcf64b26cd5f046a1c7a05d1c947e054f155 + 4fb4609c1b2739d513358c7bcf38385f1d90431c60437b6f; + 000000000000000400000000000000000000000000000000 + 7429d917ca0f35eedf754a3dfc87fa86efb1c7d67297343b + 7c66f4fc42a427a5175cbb09feac1aea770471a8566ea04f; + 000000000000000800000000000000000000000000000000 + 3782aa7d7eb154ed5d96a1cba095ddab7d2446cfc02928bc + 1e6d44ca07547ad0916761154378d997b27c06f4162dcf9a; + 000000000000001000000000000000000000000000000000 + a668c27906252b42c57223bf1041b4474a265e456e2b2ecd + 3560a2b61ac784e7a96ef52262e6dc91e50518c9fac3b4b0; + 000000000000002000000000000000000000000000000000 + c84f1667f91ee7bdfc4354dc978f0d7cb7bdbf8851a26120 + c7e80fbe3e6f54d7b6e5d8b678c95da1836ee1f51d9433ae; + 000000000000004000000000000000000000000000000000 + 29292efb39b4bcf42c932f53d49b14c97594be6e0b3433f1 + 37073c3c11ddb32e01fdfd49f6eb19b2b651fa9243a77376; + 000000000000008000000000000000000000000000000000 + 55fada32dbb1f89e56aa524e1fd89d54b43c4df2bc223e4b + d6d58bfc7a97a059494c17ef3affdf7d3e1702e78ca36062; + 000000000000000001000000000000000000000000000000 + ccd662881392daf3ff1ed0021b38e19d8ab8d01a2bf58700 + 336934b6f95645d246b72d600bd366a77d312065ff9ecfe8; + 000000000000000002000000000000000000000000000000 + 922bf0e21bef2411ae54cd3cc6d5eb7a9ecfadb1db60fc5e + 88d77b89f6936f6249cd1128bbd9ca6625fcb1fc3a08a251; + 000000000000000004000000000000000000000000000000 + f687602ca24ca63d2a29a2767278dc6548520317451902e5 + 55d57692a413659d964e04914e6256bf92155c60c99bb55e; + 000000000000000008000000000000000000000000000000 + b5f8969d59419a804c80468b2a9de9c79516a0799abac18c + c1057e3f43e1ebaf15d380a7e0e6de243f7f2fa3950e4c99; + 000000000000000010000000000000000000000000000000 + e04bc9f8b61a4f9de92ae6244c7b2a4e08f6c3e3f1448f33 + 0f8fde70f9e667cf2e9ceaffbac28d2e209ea2abcbbb8a77; + 000000000000000020000000000000000000000000000000 + e971da1f557584cf07135aca681908701acdaf839e3712d4 + 09acbfeb972d8a06fbf34de6c82365c23d999cd74647abff; + 000000000000000040000000000000000000000000000000 + bda162e322c262b9d35b36e0e46a23676014fe48429f5cdc + aa5b0598386fb110a46a87c8fbcaeb516de28ea2ed7f8d20; + 000000000000000080000000000000000000000000000000 + fd9ed1383cec0c64be074a4d57ddf0afe49e5ad2c009fe66 + fa16f08eef73e9de97deb09eb19f332ea42193d110bd8404; + 000000000000000000010000000000000000000000000000 + 27f427404340f50680538b37b52c848743366495fc402563 + abaa5141060bf1bf3134136e0b0b141ab248d2ddb9ff063d; + 000000000000000000020000000000000000000000000000 + ae41da022c6449e1e8a428ec9b889ffdb8a437d6480a0c81 + 15abc9a52c7469e98ce02e534753cc84f76cae07acddc082; + 000000000000000000040000000000000000000000000000 + f0b9b3502228b1f620038dad3f8851b141a294c1248d68ab + b76b98012d904ebba304ae707227df9950522a6d5d4461a8; + 000000000000000000080000000000000000000000000000 + 60ffd6930e94706f169e7067ae595c5e8e0ddf0b77db2829 + 3e8e2ac1f42519bdf5bec90400c716fae98a1be517fd4792; + 000000000000000000100000000000000000000000000000 + de5aea72327f9a7b74a5f80fda52e2157b22ea92e14adca2 + 55d09602919f23cdab77f5c03bc381a6bb318b8468f21c8d; + 000000000000000000200000000000000000000000000000 + 0b5ab5730b4974b1eb97cf228b330248a095259668378c80 + 268cf5bc198bc91b6644663d29ba29f90916737b513b54a2; + 000000000000000000400000000000000000000000000000 + c7fda4b796b2152eee8141d57bad874253c307c6458ba9bd + 0211fccf6da981c4e1de0f8b8fe3e1dc12e57d0ba2c4bd45; + 000000000000000000800000000000000000000000000000 + 0ccf6e36230d2a3fcf1c3166362811bcebbf84ab4c6266dd + d185d6a587f704393c58c0808b9054aba16b27c46129afdd; + 000000000000000000000100000000000000000000000000 + d0eb3bac789ca548310b28febf4ebe3a8730edc80788e322 + 72d5147984e036a42b7b803b1ab7e8de83a5bfaaed63eb93; + 000000000000000000000200000000000000000000000000 + f1f9a72096a0d35a3bde4203b234d6fd8fe7cee52c73d3b2 + 45b9e1ac776727e325b3d07cdcb8c7950586be2ba64a7e20; + 000000000000000000000400000000000000000000000000 + a0f475abb02d86fca05f4ee38a4b96f1671edc37e4921789 + 92e568e95bb7da1bd9c413d3c506edd480ca5a2022145e18; + 000000000000000000000800000000000000000000000000 + c2cb82eb6202462faffbe17860caf958127837bb56679d26 + 84a77a9c5053d7b382937ae4058a0c2c8e0cae806750047b; + 000000000000000000001000000000000000000000000000 + f69a70aaa3145b6648b244b0cfe95e258de12960733fef39 + 8e1d6e60c18153a420586a9525a8a35a0e01c33d445d394c; + 000000000000000000002000000000000000000000000000 + ce821767e1c5200f6e949eac5d032365a021002376f286ba + 66c57c2559bff8bb523acf8308a6e87d48507287f78d5fb2; + 000000000000000000004000000000000000000000000000 + 25a78a2f37beea632aba391e99c8ee0cbd895861704b0508 + 7837958ca54303afcf6497fbfc3feab75fa8dacbb2da0271; + 000000000000000000008000000000000000000000000000 + 424443625ccf703366b5006c2a06a5844107afeaca134291 + 67d5149bf0ef07975a81fbb90367b0c388c71706a71b57de; + 000000000000000000000001000000000000000000000000 + 0c4b5edc7c9af09602270ecfcb227a08c3eb41e8e743c46f + 38451d3e127ced080e76deac3a2608e4ba9c6f64858986f9; + 000000000000000000000002000000000000000000000000 + 3806f72a054c5cae45b69837bf2ed1cf3d95f548ceb6ab8c + bf3a0b3586be379283cc846f0e2f7a726667f22b4bd8073d; + 000000000000000000000004000000000000000000000000 + 53acb46560bcc190fae42c7a64bf9dc3523d6e039a6a2362 + 1662cc1720996bb8a3af6255e767b3197904d036ffc66bf6; + 000000000000000000000008000000000000000000000000 + 02f3e87b459d0f8b9efc00443a035552f21f114b7b85f451 + a9b157c5bfa6119d89b2c205b7a1f9742865b4c1e7f64501; + 000000000000000000000010000000000000000000000000 + 8c5505d686afcdecb2260e057ac8f325657df05bf9b05966 + 5ec81b79d35ba3280ea12e5b043b3e31e268829e3d563eff; + 000000000000000000000020000000000000000000000000 + 55cb50e1caf5c71429c98f03714b692ea31b1c43cae13b34 + c889fdec89a6a1495614efaf5af9ba6defb5a56452ddf97a; + 000000000000000000000040000000000000000000000000 + a738befdbe5ca885c080949c0c6d20ae12673cc7d20f8f83 + b6a93ddc7d3c794fc40483401e90d67841b9f5354e14c5ee; + 000000000000000000000080000000000000000000000000 + ad437b56deab48e58dbac0415241c21f1e58f9697810c86e + 5f39077bf328fac90226b173cd437ef53ecb7a98e0cd4439; + 000000000000000000000000010000000000000000000000 + bea057a143e4fca512bc0a7905a92efde0403dfc766633d0 + e22ff885888f579985075b711375ab522d0f44def0571561; + 000000000000000000000000020000000000000000000000 + 52ae9040cda27f5ee7fe1414b48401560faa8141518dc3d8 + ca197b53ddce530fdd18c70d16cfb3ebcfabaf86f28a3593; + 000000000000000000000000040000000000000000000000 + 6bb619e1ad95c1cae465758158d3eb2f49eeb6fdf72f46b6 + 87c5624f8f1cd1ebef2de00f71c5747bd1b62abdba15326d; + 000000000000000000000000080000000000000000000000 + 6420252af652e672b66ba8b28241d159e9ba6359c5c9b917 + 090a8bc5603faff86b116c11c4934bf8f5c1aaa119fd4b04; + 000000000000000000000000100000000000000000000000 + 1761ffce62135461d02a5426b1c31ba1e693ab9a12aa68e6 + 82d92d00ab3f980a7b07e7fa4edd44dcda5b0f57cf6911ad; + 000000000000000000000000200000000000000000000000 + 8f05ebc8491092d047674a6c6b984e95076dbcbc476ee825 + 66a587a3f6a816a6fc8c5ae7945b26f5386a156fd886e8a3; + 000000000000000000000000400000000000000000000000 + b5b04bb84c64d7d82a9a6627b45e2d730e619261ccaf8612 + 0b258b61b0732a06f0b3b1e6128461525f14b93edcf6e65b; + 000000000000000000000000800000000000000000000000 + 94efc3bae8b030363dc12b9d98f462a53e669bab96a04bd6 + d19b3eee10c9305677102f713cc0e44dd94b38b586e66c85; + 000000000000000000000000000100000000000000000000 + 44f615f33c33876b0a7f5eaf4e5194228138486b7bb661d8 + 324dd74ce8e0b2353f6b0956d90db45d0ba174348fbe8009; + 000000000000000000000000000200000000000000000000 + ab1ee468f066b46ee35ff4cf3b061e0b032c11316e829294 + 0b9fe8ce0e6ec4775aba86a76e6f15b01139c55952356e45; + 000000000000000000000000000400000000000000000000 + ff5f9a1310f1972c3e2ff648f5c7a3c253910b6f4c9cec98 + ce4364ba24319ee0e1d7b47207ed8fd704d41284f857aafd; + 000000000000000000000000000800000000000000000000 + 67547ca22ec3022cd81a011d8a36f081e6e6665d53d59615 + 3eab5b8d3cb573b7cd71dfd69f8865da04e88bed2c22fcc4; + 000000000000000000000000001000000000000000000000 + 43a0b4632e7b5746206f24fcc0cc5c02abedccf93209a90c + 86f8af1e716badbcc467b179e06f84c4a0b7050b3d381646; + 000000000000000000000000002000000000000000000000 + 84e3a90828dc4d3a965e6a2ab5d0aa532aab68bd6dc61171 + 780e5dae9e9d1f276da173517a11d0b70daafbafef4ec191; + 000000000000000000000000004000000000000000000000 + a59916e1e69488af5c2315227ae07a1fd29c7e88316de33d + dd0a3a126707ea8a9b19b2bca7d6c6f91e4288707da624b3; + 000000000000000000000000008000000000000000000000 + 5bb210f3f571f79c7b6020cd4076feecebce67313fd4e92c + 5dd34c33bd75b5cc2712c284f06ebd0771f03bbe6a0933ef; + 000000000000000000000000000001000000000000000000 + 16377666962332f0d015c24a8a64c8fba0a6b0026448df2d + 4dc232f7602f414acd74682fc955cd7a39e965277ab13f73; + 000000000000000000000000000002000000000000000000 + 88a0800a751e61a4cf3556fc09a5e2267f012c48125f9b6f + 0fae8ad675be20c5cf2811f31e013754e20600d789d0d366; + 000000000000000000000000000004000000000000000000 + 536255493cd9b75e93b7b3d8a22b9a5250f5715da602c2a8 + eb03a459e1ecfcf80d8c869a0800d10d9bf0eb16deb0feb0; + 000000000000000000000000000008000000000000000000 + d23dab5d3651b9b3d90315939175223e6e3dd8f06c87b2f4 + bc59d143168febd05f77d5edc352db18040573e5e90c1b97; + 000000000000000000000000000010000000000000000000 + a991cf922b451c1eeb6052888c28b5c51371101c15ac05e6 + 10467d595653eca2298f0fb16b0260e79c2f6bfc1fe0b9bd; + 000000000000000000000000000020000000000000000000 + a54de96886108612191972a6c17cc10f2fe3b218433cb6e9 + 19ade54eb641c24ef2cf34831b80002993d1f584f5126112; + 000000000000000000000000000040000000000000000000 + 4df1ea44dc58b80b0d4ffb6440a023175f0de0ca13e5b20f + 3b73e209e5db273ea076697eb09a23d75a06763c95ddfa52; + 000000000000000000000000000080000000000000000000 + f8266b0377535bdeb855801f5815c1c51e6de75d9372c249 + 8f3b81b9b8daa6b9134c358fd69df65d682a2bb1e3897653; + 000000000000000000000000000000010000000000000000 + 96712bf387a2bd8915be3400cfe50c9edba2a03e24e9da7e + bdcee44e3c128f80ab846ceebd787775d7d12a8c0c4b1b7f; + 000000000000000000000000000000020000000000000000 + 86e7bd89620da09a32041eed8dc60f4df1708c674baf7d9f + 7ac5acbe1e3549204cd4940e4189424dc800a37e3bf49645; + 000000000000000000000000000000040000000000000000 + cb943d6a0c33f4d6fc0856026a2e0f8b8b15572789cc156b + 3e16f341f83c585e427dee9184d650a00206454148fe2c47; + 000000000000000000000000000000080000000000000000 + 15abf241bbb3e72ffc263366ccfe5c42b8afa0e615246fa2 + 1bbc37453d729fa3f560cdcefafa5bec04097b34f04e69e0; + 000000000000000000000000000000100000000000000000 + e3a2fbaf70c336c960076e25901b08ea70f00cfbdb678c99 + 6199c398d7970a32a506c58e7deaef154b08bd660cda65dd; + 000000000000000000000000000000200000000000000000 + 4ba54ce0040ef1780a0286d10ac5cf13f563d688c214080a + e2d23bc27ecd4508c2b934c201410ec11ccf581738f9deb6; + 000000000000000000000000000000400000000000000000 + 81953955d6a216c4be8a3dc461783a0af5edc5f4291f4edf + 858b1e9cd5c1b34c7df03a68aa618a046e9870f3edd2be08; + 000000000000000000000000000000800000000000000000 + 46be627870c3f043209d65725bf2a546aee9d2dc6d355f03 + 6d35d794d51108c1828114d73df644f5e537523567ba3866; + 000000000000000000000000000000000100000000000000 + 6081001224d8a1b4062908a261bab7dc4dcbadefb31c47fb + e62bd23c4597a7fa473c3fae0d3b499cdfbb81a3cf2ff46e; + 000000000000000000000000000000000200000000000000 + 9cd0184802fb4297083c8fe4289a50b0b54daf57ce7d3c7f + f08cf7cef963531dd323b2d85ee2e57956eefb463813e810; + 000000000000000000000000000000000400000000000000 + cd2a4132daaadd45eef34602ab287ab35da3216d7e0c2201 + 18bd53d544503fbbfe63fc730f9ea3f83a92a075b9c731b1; + 000000000000000000000000000000000800000000000000 + 7dd4dab1cceab233b8f440e7c798d926d6672fae111b97a6 + 0155e424ee93cbeb18f5de8353fac06917061248e64a1db0; + 000000000000000000000000000000001000000000000000 + 2bebc540b952ee15d29456eeb9754bbfd6d14dd4df9ee357 + 4a6e99f2277d6436c5f76ed6143a0a5e0871842134a67f9b; + 000000000000000000000000000000002000000000000000 + c599a8f74e66cc416087a2c232debb1b9ca96ef0eecf7692 + deb16181993fbe042307dea974ae92137f39a6107a6cd52c; + 000000000000000000000000000000004000000000000000 + 1ed3a61376f1e6730127787de72c37ba58d748acdad988b5 + 4b4d63ad13b6e936379710f9f1c9d5c01a3884713e2323c4; + 000000000000000000000000000000008000000000000000 + e976691853eee2c466e8d9ecac6f2be9dd4d119250e9687b + a9d8242d5171109459a60bf382bf5542278a0fafd6a31c33; + 000000000000000000000000000000000001000000000000 + 817d9313109eac3b60bc647e881f9fd77296b7fd5521a4fa + 083fe0e8e375636af03941ea797f9a5a7798cfab8b260e19; + 000000000000000000000000000000000002000000000000 + 3609713a1383562d139c62be8b46b22814c52d0498bd0743 + 31cac650c1affaeac478b5cc8145e5afff54f9c486803fb6; + 000000000000000000000000000000000004000000000000 + b6da3ad2f7b51786fb5a1e52cdeaccfbeddc948211e1fd6c + afb15f06a78e82084de6200f85b0f7ba6c9f80ee34fbff8b; + 000000000000000000000000000000000008000000000000 + 30e517ce758f7bfd6d50c44802880144b2f0b37052cc5efb + 3183baf097aa12da6830fb3781b803f32e8f89f01cd9d25e; + 000000000000000000000000000000000010000000000000 + c561eb0df785893728c7ab68541ee65b5de5f0def12f1570 + 92f0838b81ecc63bd92162455803a4865f3771af19d0cfd0; + 000000000000000000000000000000000020000000000000 + d5fd1003a7018381ade31fe9ce9a64126ee798d2a2ec8733 + 7336952580c0fd50af4df8939122ccb98963c88631f4e74e; + 000000000000000000000000000000000040000000000000 + 99d96e0cdccd1a71a29a6e15441a2d3a25a0718ea84c2726 + 04c80e68b0f9daeddbf4a243332a2a9c03684811420318dd; + 000000000000000000000000000000000080000000000000 + 5c123dbda2b026c444fc873e2884e7c733642451b8c58bea + e4a1520b9dbb0580eadd7e983e5f7ffca560a2aa69cb4acd; + 000000000000000000000000000000000000010000000000 + aa82a0f119dd67acec85d42d52866a18fc250f5b063bbc67 + e01b60199b085ecb412d68b2b4fc65b5ea827a6f5e2a7b85; + 000000000000000000000000000000000000020000000000 + e3d91efce207edf5a3f0c5412c517ca2caf860fb80c75a23 + 5b79bb6bd28b687eb07afe51566ea4b1a791aa9620734a22; + 000000000000000000000000000000000000040000000000 + 120d205dc675f1585fa3b9cf92627e7644be58785b0ab209 + 98f71325ccdd857d0eac2bcd8e6201ea042569d2b06dc82f; + 000000000000000000000000000000000000080000000000 + ecc047da556e6c5ea7c195ed3c5386f60dd3b95537e41aed + b21cb8440842e4bde27ee84bfcbf0ee0bc8b8b3ad88455e2; + 000000000000000000000000000000000000100000000000 + 9c595d82e523573893ef08454be25082e3e2dfdbe71f6634 + e040f8c529241507b3f450b48f1f05605c1566443dfae0e3; + 000000000000000000000000000000000000200000000000 + 35f4e989da7d064611287588d3566eb092c87405cbdc6873 + 913e8b1818b9f317ac16b02ff0226c0d7749d40612eb5a6b; + 000000000000000000000000000000000000400000000000 + 8efaff57d270546c21d4728e904409ebf9d19d86ba797a1b + 4423538d5d87cfb5c636b71801ed86751b722779545a73e0; + 000000000000000000000000000000000000800000000000 + 38f285b482c3d66af4e661a07a3e6069143cad4dc1e3e804 + 6f1184beb0f6f27e0e2389d84bc6df3d54a51bd1c6336b8b; + 000000000000000000000000000000000000000100000000 + 9ab7f76f277e7c5e9e437d44506feac61c20c40c50d4f4a6 + f5c357f4d66b8e96f8245c41324e8645cfa9953dcb2f4b70; + 000000000000000000000000000000000000000200000000 + 6077ee198eee87d2ab2bc968f4f594b7db9070b367409f9d + 8e3e4e0f06c954bf256d3ff91852e1b2b392665c4385d9e2; + 000000000000000000000000000000000000000400000000 + dd9d75908bbdc05e2cfb8df5d1db68ccce7bbe7f121eacc2 + 78082c854cd92adbc3c37daee124d4d9a7d97b9c6c7ff4d9; + 000000000000000000000000000000000000000800000000 + 41e7465edc8a9d8bc8f4eded1405c82d2fe9dd6232807b95 + 3a4701a2768128fdd2dbf43278039f36226d0f32401c2f46; + 000000000000000000000000000000000000001000000000 + c08c6119ee2a2197f963a599bd65b0590ef5a519e33c636e + 977467c483d31158e24a00e7057e9122d84b8c29df6a40bc; + 000000000000000000000000000000000000002000000000 + af0bc2d846a385793ff0719690346f88e8906d59d731b053 + 5961660b15037b718ca51d2162edbc423c42ff094c3a74c2; + 000000000000000000000000000000000000004000000000 + 00fb58016823ff21666d4834be7777977c39dc524831f78d + 16f43859a26050bab89f24747aa2f159f7f952a4f7d0b423; + 000000000000000000000000000000000000008000000000 + 8888994bacf06498d6c65514458e0dcd5c47a89096431c97 + 84d3b8542bce25195af4c2c2db5278afb5c090980e978d84; + 000000000000000000000000000000000000000001000000 + 5c09111b5f1d7071f9ff25551b298c3ce446aa3413097e62 + 583739a94482dd2d485b26f9eb11466298b1ad5c1acb1204; + 000000000000000000000000000000000000000002000000 + 04aec49c4fb80d6561c745f51784f4f3d31547bd4de5a94c + e7f83b28e61a9eb7929382f435c7113a3110a08c7cb69634; + 000000000000000000000000000000000000000004000000 + 8391493f0cff3eedcb9fe1bdd422793ee5e124d343b375f0 + 2d9e4938f6c4c337b943809490c1b6ff3c843bb0bff1dded; + 000000000000000000000000000000000000000008000000 + 6d1246c48d1683a7fd7329c85ba193d285192c8831176913 + 32f271fc06af76ab98807731b3a47eeac2a107c02cf30196; + 000000000000000000000000000000000000000010000000 + 3cd9d97a17d77d3f3e9edb8d72032b5f655f948b32f59e00 + 5d7c293fa62a9a1f91b0baef7efd96f8e35188f75cd8a331; + 000000000000000000000000000000000000000020000000 + cfcc2990da7be7df288d8be5f9be1deff14637612107ab29 + e381e161b0b8bf30d3b28575c72f5605a83d5ea4d23a34b5; + 000000000000000000000000000000000000000040000000 + ac740d1ff0eacc8d57f042f7835ad95a80edcd3fdf28371b + 7ccb5ead7d391d393d19ce552040dd00ee411901f82f53ed; + 000000000000000000000000000000000000000080000000 + 177a0fcbbe76481f473a27bf63aaf2ab9d127e399a3c73c2 + e21338988039b5aebe5cb3d5b632250b9801271a117440cc; + 000000000000000000000000000000000000000000010000 + 96ca2977c2f58083155573e55b681ac307b40e601652836b + 678a557c88b2e1df13ac012a7104d40d33349b981db71476; + 000000000000000000000000000000000000000000020000 + 0e7ba2f3476c82f01ab7fdc7203ad2cfca591ecc829d8409 + daab2f21fd15fdc90a7cb7a6a56a0d0c6942ae2b86113373; + 000000000000000000000000000000000000000000040000 + b309f8daf59f74bac80f710fe07350f899bb1492f24e1425 + aadd706e551425657e4e8d5138a8d13337d53346885b2ecc; + 000000000000000000000000000000000000000000080000 + 2d392f58a4b220211b884f4287ad76c9f9515ec47c284290 + 9aa9a624109b06d5722df543b3b0e105052ad578b54e47d1; + 000000000000000000000000000000000000000000100000 + cccb9eb8fc84365765163c40bd24b6bb51a45e7345bd7a14 + 6d9e8097f75b13cb808d2c44efaa556a56aa7c9ab8106563; + 000000000000000000000000000000000000000000200000 + 78a5d8d79b63dc0324761e93b76a7c79d6455539ffa6f088 + 8b6df918ec48a084ee472612bf14b3611a9a9c10660f31a7; + 000000000000000000000000000000000000000000400000 + c8240b82b4e438074aac4a34be3d0b01b3b7a5c1746f5dd0 + 5c4650702bfc551e85a269d7f97fd98d49db0f45f40ea608; + 000000000000000000000000000000000000000000800000 + e6880f3681fdc188ceab24c0c1cb3f90357fd05130687b07 + f53ef53b6216d61118877eee6f9406f076a9b8bf4b31ad9b; + 000000000000000000000000000000000000000000000100 + c734620cda2c3f3b71d8195949898c8740acb8444fa9e1e3 + 2083e8448b090301f991ac6687179d6773c128dee6aff608; + 000000000000000000000000000000000000000000000200 + 2f67eb665331c85869ce51b067c6e6e94cc8ab45fc71407c + b61d957135c33783e803e9e535702f2818c21ff62be94c51; + 000000000000000000000000000000000000000000000400 + d590b7a848006f402461a88874eb9b5d9add7ec80c81b154 + febf425ef71bc535730788b70bcc2833e08accaeae7e9ee6; + 000000000000000000000000000000000000000000000800 + b02090c689481635b33f992e13b59eea15aaf9f25b778979 + 417ed646b20cbab90952020eee8069dbe00f18d2572f8d72; + 000000000000000000000000000000000000000000001000 + ff1e358c8bd643176d87f75c2175c4b66ab1ffaf0079c012 + b06d3d892f6d85bf268276d7102d7471eaca99b16260a39c; + 000000000000000000000000000000000000000000002000 + 57d86ced26040b7dc14c2f47cbce1f5c70398ec902d6d484 + d8ea3cdcc2566d14f6d996971796161e493677cbad536027; + 000000000000000000000000000000000000000000004000 + 1cbd6500cb1061ae856e10557c84f085d340b5ac6394de48 + 0fdb3c9f37cd7b03b4ad10a5a090afaabc9eb6e623721af1; + 000000000000000000000000000000000000000000008000 + 18975b942cfdbe8391c4e2a96e03df6cc3d44d1be1fdb697 + 86f3a467cd9b71208dd75efb91fc77a1dcc25dd45a6002f6; + 000000000000000000000000000000000000000000000001 + 806011240d6c13fab000555504cc68fa756d5c0cd85d2933 + 7793edb94f67a425483b90cc7b869880143272ee85ca2ad3; + 000000000000000000000000000000000000000000000002 + 3d04d556fbf1d4dd76fa97215fe58c170d0198c19d5a0b8e + 850321dd6927deef53ce43fcdd07df6a3aa1fbe0d26026d6; + 000000000000000000000000000000000000000000000004 + b1a243ffdbccf642800db3cd11beb064a2674f49ae9c6550 + 850c7c28e1d1dd64373ddb8388755325671fd7cdf34fdd2d; + 000000000000000000000000000000000000000000000008 + 3705ff7df146cebda207c1fc2348252f28156b752e9cd167 + 418592dcaf9178228f66511810bfed87e7ac9d2a138d741e; + 000000000000000000000000000000000000000000000010 + a4597f7b0bc5b5cd53bbc04d644901b385d2c5d03aa0e363 + f1f007c32f306ef45e0f78c24bbdf7507a62e44861c1d579; + 000000000000000000000000000000000000000000000020 + 3f2e6b8d77db0bb0f4dc09f8b3f5ef841b65f389194865ae + d50dcc3d890fac6c458ffe6334a2ecfe329f9ccac8bcd609; + 000000000000000000000000000000000000000000000040 + db05a0aed5d55023dee7dd6671cbcf71cfbb29c10c4babd2 + 8925fce6cf19f3b2f34d61b894b213a8c59e69a3993cfdb4; + 000000000000000000000000000000000000000000000080 + 4c73cdb5851ef5a107ae0acc485cfe49f23051ada2cfba2b + dc81803c4aba313b5bf42236e208b8bf66d62810ec0a8fc8; + 01000000000000000000000000000000000000000000000000000000 + e466a171f30130c5886045ab035a744b80a63cf10ad50670 + 7d0a3d9a3ad5af4590a18eab995623914ab2377cfe35d3be; + 02000000000000000000000000000000000000000000000000000000 + 3979486436134c0b0d1cbf612b6745e7a43038c176e50759 + dc0c555a7b1425e8d83ae80934676ece2a2f8a654196dbe7; + 04000000000000000000000000000000000000000000000000000000 + 517b1b4b00e143a73e315298830e0fd8f0692549b4efa53f + b47ae72ce84e68257377022abb9cbb566e58c501e1ae8956; + 08000000000000000000000000000000000000000000000000000000 + 197c1cc090ee4f199c5573cfa65f6bc84ab8957fc8c2be23 + a56f67e2313fcd2fdf621da945eef4e31a8fd9d0445b1b66; + 10000000000000000000000000000000000000000000000000000000 + d59e9e6be1cefd6881df7772eeb46295e7c6ef787264ea73 + 9c9bbcab22f66a437538d795d041399093f694c669b2f559; + 20000000000000000000000000000000000000000000000000000000 + de47466a965a4d5d92eed3b856591fbb787ce6863da4d8f6 + 94a4c31a6e8418b46529e547d7a9aa0e1d2962a63eee5654; + 40000000000000000000000000000000000000000000000000000000 + 36dbd72833a532f365e6be111aafe17c2fd49f21f4eaad76 + 6327e174d21ea698cf34bffe36672e7ffa931abb615148aa; + 80000000000000000000000000000000000000000000000000000000 + c10d857d362ebe177aa6b240bb27340b0ad2b283cbaaa84f + 184d05e1651645e67d0d42eea84f4a8c56972014aeab4602; + 00010000000000000000000000000000000000000000000000000000 + b23943ae799651f7219dad8ead93d03c4eed373f6389b117 + ff33f2564db3a027b45f2652ac244eff9d5641212fe33a33; + 00020000000000000000000000000000000000000000000000000000 + 9126da9f43bbdbd9216f40c2414236438b5520304f21b2fd + f7c8bc04d48f4b18f44044f6a5175b67e5a0369475e38840; + 00040000000000000000000000000000000000000000000000000000 + d73e01f210826c0205aaad28db4cb341804a696f1b683a14 + 47632f2712f7d9a63c7fb8c1462279e3c5d824ecfe35d3d3; + 00080000000000000000000000000000000000000000000000000000 + 3a8a518775a687bcd6245cd6e8504765275b7c9df76817b7 + 884f7908451106aa852323dee7b353a4b1686cc7f74b738f; + 00100000000000000000000000000000000000000000000000000000 + c054a470e6d41003d3b20ba165d391cdc934138b55ad957d + 2ff8dd62427119acf5427b73db572167f953f778b5536a3b; + 00200000000000000000000000000000000000000000000000000000 + ac86f7a300e3f4b248c17113ab2a5ff0ec5aa11c26f7e9cf + f391deaba561f263728c3810c4246bb850a38c22c3d0ff22; + 00400000000000000000000000000000000000000000000000000000 + ed1cc342bb9b9f0463f8254343f79ef3ff75359bf78c6a06 + e657015d282084ec74214fb5926eacebe91b2b0818cd96c2; + 00800000000000000000000000000000000000000000000000000000 + 275083f0158e81bbdb5bddd8471d4346d2dc2dfdeda59d17 + 85405f2ff391329b38a6bcbaec9890fd5f6c27c43c4d42ae; + 00000100000000000000000000000000000000000000000000000000 + 5d875aebf5496ef91d1fb5fd6b7c10ca3472ac04190fb5a5 + 30f8d4f4e34ded31074ab7bdd98cdee6995f363361dfb67a; + 00000200000000000000000000000000000000000000000000000000 + ea05609c5f54d16590cbf9bee2fa008f60aac96ed40148ae + 0356240ac83e1f2874e37d5577009d79cea8ab677d05d35e; + 00000400000000000000000000000000000000000000000000000000 + 241a143eb59063bcf573483f0453cd3b7c20613e976e1677 + 584f0cef868af6aae2474278099ecf8d9af01d1b540c1853; + 00000800000000000000000000000000000000000000000000000000 + 8d642d6c2ddeb938e63fe0da1f84700ae21c35317652dcf8 + e692d249d7c24d32555f7a69d88980e56b33e95659ea5182; + 00001000000000000000000000000000000000000000000000000000 + abe335a44913c306c289a66bdc6551dfaf69febea41c73f1 + 669f21ff2d1979cf255d0f357d477f62a2c376e2f7e49ee4; + 00002000000000000000000000000000000000000000000000000000 + 88ace268351b45c9ad63579ad01f5631fc6ac91d5de6ef19 + 065b1d6414049be6fd09ae8f4cf9101e625ac3781f146a3e; + 00004000000000000000000000000000000000000000000000000000 + a6d8ec0b3de91563f75df992e97a5f8565333056dbeb5495 + c56801660652b4d8973edeec960f6c606f553af746e7fb36; + 00008000000000000000000000000000000000000000000000000000 + a159457dde64aa20ffb81591e52a684c4f01f224d77de994 + 2ce28f10c61918f29a4ced6d5969aad3e26397d68b273e3a; + 00000001000000000000000000000000000000000000000000000000 + 0658da014d05ae4231fb93096483492482ee0ce8495a482d + 945a27517e687cd2fd0d03c57dbdea162b4fe10d05081869; + 00000002000000000000000000000000000000000000000000000000 + 85ca27e90b91de2e400a59c00ed82116302cd2a1367c3411 + fb1858e39f2cf75d36fc308270510d9710fc6bab72fb3162; + 00000004000000000000000000000000000000000000000000000000 + fc60f7ea828f3813eba9d5136a34ce868510a6f5c9d61124 + 74fa96b782f8e68a9b93c82ff428feaaa66a75331df5e98d; + 00000008000000000000000000000000000000000000000000000000 + 49a4c0b759451a9047440e8ba0670a750a69f92aab520c26 + 4e1631c860ed0a4a9917983f15f889383860921298bf76f6; + 00000010000000000000000000000000000000000000000000000000 + 090c2326593b51e1dc6d59542c8ec15d2f60302371489e36 + 8f961912ca14f7208c5608eea98208eea9d45255e5f4c900; + 00000020000000000000000000000000000000000000000000000000 + 04f1eb6340739f6c37e3b0571b1d41553adfb376053ce64d + 242c48e139838ae26843e54dc149b154bf3e8c490fe0f1e8; + 00000040000000000000000000000000000000000000000000000000 + ad61378d9b886d236a585a35749caf40552a018246cd8203 + ea01b68642d2988df8d124f74dafa6abf853b017d4cb5496; + 00000080000000000000000000000000000000000000000000000000 + 5291f7145b376f42de91b492a803c3da552d1bf3cae38f74 + 1bbcbcd28382cb960e12663fa17ce99d8fd996480afdacc8; + 00000000010000000000000000000000000000000000000000000000 + 3283a8ad59723b954c26d32641e1aca7ecc37cad79757fb1 + 331cd49fd0def48a4c449efbcb35b3ee20552fc441300884; + 00000000020000000000000000000000000000000000000000000000 + 1e9b00edfb67ee5e7e72d5bde45c69dda0f0b9f145ba376a + b11264164e9e70271ea379123bba996844d8224b2c4a5792; + 00000000040000000000000000000000000000000000000000000000 + 891d65411edc72bfad04c2b32dc4f3daa46fdbcdf2295b7e + 7019b3daf1d8d054ced0c9b41903c328cef85eb8b30490ed; + 00000000080000000000000000000000000000000000000000000000 + a692a308739c497d2fbc905d2c1212d9ba02b5c896330480 + 87747a33be359d180b13c7c2da559adae20d7e3fa677d80a; + 00000000100000000000000000000000000000000000000000000000 + a646d48b3a7570c884b7d20b3ec1910062742ea29f9b87db + 6dba393a5c0c22f991052587f2d03cbd6fa1b97032ce8d70; + 00000000200000000000000000000000000000000000000000000000 + b9980daa0335682e0d5f943db1d63f76a5afba294b00c894 + 6dcff8118dbd4938d98327457b611b78bc6fc3858308d44e; + 00000000400000000000000000000000000000000000000000000000 + 5a6d143a6bbe108a8e865d262700c5e3d681a864c9bf2889 + bb00e78a312810a37d218fe1e898e34ba684df92d5df8a80; + 00000000800000000000000000000000000000000000000000000000 + 27b44c0f87ac23ff95a31e1b328d928a1c08104a3d67a9a2 + 2d2fc5dacb8cc5cb49812ff3fb4c4dc710b27126aca8af6d; + 00000000000100000000000000000000000000000000000000000000 + 52a8962f43e282225863b45fcbdca1c7970d05cdee3661ae + 0138f4025e6f693f784e26c368f3e99bfc912da83619df70; + 00000000000200000000000000000000000000000000000000000000 + 9d778e66c779bab53e8bd4cba07121af23a00a64f2d69033 + 74818f00faeb596041c9f60ecf7fd36ce6ca568bea39cc20; + 00000000000400000000000000000000000000000000000000000000 + 541065c87d92ba58c18ae8220da27a8d54ad7741989ad6c8 + 4c5ed522130b99c5d54d6c9d500e04646deafd63003904ef; + 00000000000800000000000000000000000000000000000000000000 + 2f20f79d4c2b14d94977d1079c3c94c781df42adf3d6901f + ff0efe5eeb85df42c23a1c7cb86b3ef67a423f7dfe4a8ebd; + 00000000001000000000000000000000000000000000000000000000 + 2e5c45b439d98cde7dd553cc7f6d55867792f2b97d4096fa + 432b23888d0e8efa3ca6e7770a9b70add2d31113d187cd15; + 00000000002000000000000000000000000000000000000000000000 + dc84f5bf78bed0ec4011a808b3ccba862ffe18c6bd0af093 + 8a7df628ccdb8d0d9527d0ac6a2a37cc3496ce920a6549af; + 00000000004000000000000000000000000000000000000000000000 + a8950cd163f3bcef61d2fd66c2c84a7069498f1a4480fa9b + a52e41655dcb9f4419b3aafdeb1b388fdea9ede2eb71d55e; + 00000000008000000000000000000000000000000000000000000000 + 48ec823bb0601d23644fecaf15522422ebfc773c6741921d + a9f9ecb94e7a4a0f6196d9f585f981529aadf5b1ee13c5aa; + 00000000000001000000000000000000000000000000000000000000 + 4a360f8b6fb99125be62dda9f47fc5568119ab2e76dcb2da + a2bb0963d479e76d1f32a7e724ca64982093d519649a2676; + 00000000000002000000000000000000000000000000000000000000 + 5628f1141e35d240bcf5ec4bfadb44376b82edc1c1821181 + 00fe7d461f3b521fe1d76fdfcfaee8b2f95be74121660550; + 00000000000004000000000000000000000000000000000000000000 + 6b7e5c402de45b783cbf0bc2a922f034d93d41dd69a02d98 + 4e64fb1db55e3b0c622002306567bd38068dff297b8caddf; + 00000000000008000000000000000000000000000000000000000000 + 2a0a0ac9f03ce1be0f6a913cca6f12dafb4ee79af1173aea + da2b5561384eedd083365dbfdbac266556f306779654a946; + 00000000000010000000000000000000000000000000000000000000 + 1c1b4df7b4f126620df92c52fbcc07d7b8a5aa44f3e5f1ab + 46626e5971070b4cd57d5b49f3b3e228e2dbd1b9798e79ed; + 00000000000020000000000000000000000000000000000000000000 + 5682d5056b30cd7b84911adaf1af2af99fb16fe82beed222 + a62abeb1341cb2cc15a3947ce8b571d2b48ebc7365072e2b; + 00000000000040000000000000000000000000000000000000000000 + f20e8c97b521ed21e72686e503b30412060626094e2569ae + caa011296fd4dc935074560a2608c9e1db2848ae25f4395d; + 00000000000080000000000000000000000000000000000000000000 + 461dcc25da2c567f2c330d1ba39172451f8b0c1e4575623b + e4a8929a202cd9cf07a3a914d900eda1a1aa79dfe332fef6; + 00000000000000010000000000000000000000000000000000000000 + 179913568dd00f3c3e6638fff80b19078f605d2989b40f4e + 98901d6c7f82903c81fb45e93a8d70b2126a40465cc82536; + 00000000000000020000000000000000000000000000000000000000 + 01d0dd28e61252d14ec58b782dc7c777f3e88a652014bb84 + 71802a1c775ec9574b443f5ff43868d8df47620e291aa4be; + 00000000000000040000000000000000000000000000000000000000 + 0f6ebfa8809b841679990649948d76b1d79ec12ece1f4751 + 69f01483dd242bf68434e66b66fb25ee6115664ce75850ba; + 00000000000000080000000000000000000000000000000000000000 + 089df5d6f5a4f9967693d8872da3808eccabe037cae99337 + 95ce5e283ee609b6d62bbeb996d3c99bc11e66250f2884d0; + 00000000000000100000000000000000000000000000000000000000 + da907941cc5d4349988756b71b3d625ffa68f36ddb5b76d1 + ab0b6cfc89a17453f0a7e76216d4c134d8385732e8b7ea9a; + 00000000000000200000000000000000000000000000000000000000 + 61ff06d4942fd9296587bdfba1e8e27d42d7701ac7efb31c + 69f0acaa8622c8d71497ed99f646d033d81b943cf2da78f4; + 00000000000000400000000000000000000000000000000000000000 + 6bd9b77d87473a6501421f565884cc9bca0ff6cdbd8608cf + c25e725bddaead2ac2c854d645565cff9d13a49325318470; + 00000000000000800000000000000000000000000000000000000000 + 779ee5f0fe88dc65da96ffda43e5bbd77fc34efa0eea92d3 + 1d32b8d6e4ca8735ff8489f3316e5dde7eae25346199436d; + 00000000000000000100000000000000000000000000000000000000 + dfe0750917dfced0bfdce54668950a91b3697636a7f622da + 785410a4bd7246c3f351ec3c17dd4fbea179d282bd3edd35; + 00000000000000000200000000000000000000000000000000000000 + d88b50720ac2b514d8e32766e4c10f52099b7c9dbdfa4639 + ee78f304793920cd1996322df67166ccce319c7b79aedbca; + 00000000000000000400000000000000000000000000000000000000 + 40297cfb793bc7411ac6a38c2f5e35f13e076c96e3ba8cd7 + 8b19a2d7268324413e76dbef51d544522afcfdb234a80b79; + 00000000000000000800000000000000000000000000000000000000 + bf474a47de1427ffc76f22f85fdcb322eceb654b82ae1476 + c1107b5c9aea17142905e7423c03ada55b4de08d68551412; + 00000000000000001000000000000000000000000000000000000000 + 5430fc20a9a834d033b1931d41c692682a389b6bd68abfb2 + d5007648b6b5c9b3ce44fe8c8261af3509f2854bf12bca03; + 00000000000000002000000000000000000000000000000000000000 + dc814d7cafd842955d624394a5885e9900fb48302c02079d + a8507e6a2969200463221a3d8baa430a65dff06e495d54f7; + 00000000000000004000000000000000000000000000000000000000 + eec73ecf6bda3f4dda70ddac567649e3acae53c79973d91a + 43eb2159dde1ef21d0fdfe7d0313f5d608b12ae157c0175c; + 00000000000000008000000000000000000000000000000000000000 + b31185b8c7a09b6c8431604c9d73a92cb0e368af1e109593 + 1621f258ac6562bf15900e46ee38ce54d17fa998a6718126; + 00000000000000000001000000000000000000000000000000000000 + 861599547a7005f367bcf4bb2d7e77d23ae864dc0a97f3a4 + e81d4a8675c7805ae2ddfc663db35f050decd5bfd14f89dd; + 00000000000000000002000000000000000000000000000000000000 + 4fa5147d9ec4057b649f7cff1202fc99cae58e1aefccdab9 + 064b3918cd10ce4f246d3f79ff52e3fb20f770f07e942b01; + 00000000000000000004000000000000000000000000000000000000 + 35eaeba3a19c8fcbe86181577734db4cc2ae23a0035fe2be + 6338c7f38226401f0a4c72c5c4a43a14ffcf0724f7cc579e; + 00000000000000000008000000000000000000000000000000000000 + 843eb5da5349484b83b951550554fbcffca7c80861860b84 + 1d127da43d43487a2221c36ee63ba71f75e6e7254307037d; + 00000000000000000010000000000000000000000000000000000000 + 39864279e3c8580727d48936a1620cf01667f76e3c300498 + 137a5254e5815de51641a5d15b2691b31e08512537427e3d; + 00000000000000000020000000000000000000000000000000000000 + c6d896c129ea56b02c159cade2a6cbbc974ec04ffb4f538b + e546edaf391396e7c5cfacf94cf37ff79ca56a0418872860; + 00000000000000000040000000000000000000000000000000000000 + f35dfbaa8f13910ba7f3a9de5a9fd6f36d8dd8a444fd3144 + b3882f070df1375e3e84e933de4e4372ccd8dd84923d228f; + 00000000000000000080000000000000000000000000000000000000 + ea26fbac4c2c5e46100785a99008d4ae890ad258918aa18b + 768ec538c5f61bad6e7b49ae664ccd4ad481c8c37f317b31; + 00000000000000000000010000000000000000000000000000000000 + 477c6bc073748fc4c0511b0d1e180315530037ef71cb4026 + 7d8bdebdcf35e2c38c6d9d19bf97f6fa76e75a3f9ae22e9a; + 00000000000000000000020000000000000000000000000000000000 + 655699d22c61a253572cd6d4df64d4fab06874c340e95783 + 7cd5f30366d96ce31338f5438263c887d4698a2d1f826509; + 00000000000000000000040000000000000000000000000000000000 + accdb0fada298f97c199b0b75ebec0f8eda6c819a322cc84 + 839916db991581426da7dad428a2ce1f1fdfe0e94551e45c; + 00000000000000000000080000000000000000000000000000000000 + 710b2db656a99904896580bc97453f7af6d40326f8ccfa0f + a02c312babab962db4503415f05d52b2f30bfcc35869f08b; + 00000000000000000000100000000000000000000000000000000000 + b09a7b21b66ea4e6409b36515c849ab0c89cd4793b86aad7 + 25d64c7e387e9f7fb9bcae80fcb95e60ee764b4b91f5a623; + 00000000000000000000200000000000000000000000000000000000 + 961df75dd24a7f370750a17c2025867442411790e604c7d5 + 762b027acee1b991b90b83f9d918f2f74e84383f425c64a9; + 00000000000000000000400000000000000000000000000000000000 + d9a3a55ac9d2517b149b2a6981a1123c0d9b4abe03982e03 + cd43bb557f2674593b8692472f225fb4c7f5f207ea1ebcf6; + 00000000000000000000800000000000000000000000000000000000 + 3d42aaf1230930786e7febf219ff6c90759295547a2c0e9f + 3a00b929fe7dd2f848d9078fe862bdc1abfb0b242f2709a7; + 00000000000000000000000100000000000000000000000000000000 + 4dc0cb0a3d1ab6fffab767a4ef3d47f029d9f035192d7dc8 + a10e7b96eda011b4b927bce0d98b6822540b9b7521a22b57; + 00000000000000000000000200000000000000000000000000000000 + 5b23eaf61681e3574a8a097d763a3cd828626b749851ce7c + fb624ad9a049613c27011972f01dc669560322040aa7c4af; + 00000000000000000000000400000000000000000000000000000000 + f6db6f3ddbab5d3228812a70fba910ed17ef493b8cec3ca9 + dc3c24735d9fa10c848f9b09a9fd8514ea4c1a576f8ef4d8; + 00000000000000000000000800000000000000000000000000000000 + 07f9b15343927460366de4a9ac3f819566e670f4b58a00d3 + bb6bfb31664ac99f9af977589ada9831b121ad90466375dc; + 00000000000000000000001000000000000000000000000000000000 + a305415baba5afdae40a6f9a1b6e8e3232e143a7f1138c6e + 5d4109fa28245a22bd6c812016617e1aaa21c9e5b5cdf87e; + 00000000000000000000002000000000000000000000000000000000 + 74cd6460d4ac168edb0e544890907cd954c24c468ed87848 + 0ce59ed2694fe93103eafe67f702b32dd5545e5fa53b261c; + 00000000000000000000004000000000000000000000000000000000 + 4cf6e84f95eda559ec34c93a2e4ad35325e0885642d4dab5 + 6e8d542ff0d468d44331de0482b9f483ef1e81afce8556c9; + 00000000000000000000008000000000000000000000000000000000 + 223fbd1515d17968e6365920d08afefc8dcc1b7aa1a48a94 + 846cd8e79252fddc2bd9dc79047d55c96158dd9834e79e43; + 00000000000000000000000001000000000000000000000000000000 + 3d42cf134f2ce3f69168b13b9104bf20e720aa1ca5db3abb + 076f0dc3b495de14b6626ef3986cf70fcc62c73101b3c00b; + 00000000000000000000000002000000000000000000000000000000 + 62964b3de5a5f29fb46af05e22e604adc0ddd469023572a3 + b53b2d9fddfd2e9ea18258fcc56afdefacb68000766cb625; + 00000000000000000000000004000000000000000000000000000000 + ce9999154c2cb7cac5bff38080d9cb5bf7e25e48469907a7 + 126fb43d45542ca289681f8a96f1eca1f78065dc3d563476; + 00000000000000000000000008000000000000000000000000000000 + c316c04b5351c4a9ab217b997403bdcd4b6b0cdbeeb61020 + 8359e9725a86108c9e9df165c8db8dfd97ef0c0d5ecf8700; + 00000000000000000000000010000000000000000000000000000000 + 037524620d481439f805bd9b97f564fc54fad6d68ebf6d37 + 1a3ce3addd3aa06fe3c0851bb36d6484d00b71e2f7f24f93; + 00000000000000000000000020000000000000000000000000000000 + 678374857cc068a2a29348279f2a9ec8edfecc0cd658defc + b22c3aaefa728e55ac29d4b624eae74248f3f983029b4b30; + 00000000000000000000000040000000000000000000000000000000 + dc8f9708feef6e43a07c93abff90668180ab88838767164f + d3afd33038af52da8546589a263cc81dad1d99d156b321a5; + 00000000000000000000000080000000000000000000000000000000 + 6eac02f84c3e0ac288f692dcbef8ae12cab31fbd53d97397 + 2ad2aaafe7a7ac392fad7a0287fa2f2d2681dab726bf44a6; + 00000000000000000000000000010000000000000000000000000000 + efe7d7c2bf9e3822761cdac372165820b9ab2ec899424e8a + cb3757944a16a71ec99813133ed5745459defd3bbce8bc73; + 00000000000000000000000000020000000000000000000000000000 + 48b83fc1b61f1f635033c366f9ada4d79966f82a68764c7b + 0844cda500c0ddeaeed7b63f2223877838f379aa7504661f; + 00000000000000000000000000040000000000000000000000000000 + 842e81ad0e1d515d7cab6f58288c30357dbc621387091fae + 9afa55ddff3b59ff3a6d3b52d011ea090cbd32b56f25ecd8; + 00000000000000000000000000080000000000000000000000000000 + de27653b243a814cfeeb90eef9d612ab98224704e328923f + 093aab7b15166c45d7381decbdb00d3fcc62e59d6d3fbc59; + 00000000000000000000000000100000000000000000000000000000 + 80199c47a849f02460357ba7c920b4f91007ccc3572f8a95 + 975554126ac6b55767e57be44de8141f83d2c6e88371c207; + 00000000000000000000000000200000000000000000000000000000 + 18214d1c20eb598db7ef9e19f66b41be9a3c6a28a2a06c09 + 36d76057e43f8033756217742d563bd811e1130b9273a3ab; + 00000000000000000000000000400000000000000000000000000000 + b02556b90f7846ed7ef080a17b6131cc6e34de764fedf66f + c5a1433480f37105516a2903fbf4a2cadf94061dad71dc47; + 00000000000000000000000000800000000000000000000000000000 + 67f22905a1db5aa9dbc49b92986a0e6a76f555b26fa844cb + 9197f321a515351baf650e1375ccf1d0964653e35e4f2f3c; + 00000000000000000000000000000100000000000000000000000000 + e684a0b52b370cb0d1a56313d388a136108c642d3b39bc9d + 62943cc6636002312b13fa373109f4291ccfaa872da2ee77; + 00000000000000000000000000000200000000000000000000000000 + 5a4dda4fc12d0c760398b47169e470f74446acb791559bc6 + 0bcd3206810ee183fee9b0bb838efa857d695ca3e7ed1253; + 00000000000000000000000000000400000000000000000000000000 + 9fc13edf3cd388716e9f4e1494d8a0a96281dc961d4548a3 + a26ac7726848e147e7ced7cca7e4503ee20f42705fcfc755; + 00000000000000000000000000000800000000000000000000000000 + 86f93d79f1f26b011541ae929aa31b9a4c84e8c4d880d5f9 + c967183176facd949e28f687f2086f29a6b6c955d64b6178; + 00000000000000000000000000001000000000000000000000000000 + 2dda65d35ba60b691738ab14de4aa36c4ab68618547f1b4f + 0db07d9558e660576689ff6572d2af9edd01452072c50fb6; + 00000000000000000000000000002000000000000000000000000000 + 90a296d7040d9ee0fd061caddf8e617c536560e397e9725c + 69a73a1e466811b91368ca4791ac75045174f24c389aca14; + 00000000000000000000000000004000000000000000000000000000 + 466cf4d9755f99cfe79a8d73f0e9274e266e6acae13155f7 + 83b4f7458050bfe285c60e56424314fd6b01a6194fba4960; + 00000000000000000000000000008000000000000000000000000000 + 93d678400420bd1d482812485d96fdb170b4f055e1bf98a4 + 400aefb2a3dcdda2e48195eca5b600eed2a4c6c70db3a20f; + 00000000000000000000000000000001000000000000000000000000 + 61a2973e5424ba1c6d3e276569114d4ebdfadf198bdeb004 + 12957492fc5e51fb9f87b5f263486bd6e9030ca493e40b1a; + 00000000000000000000000000000002000000000000000000000000 + 38e6ce3158f5b500a01c1920345e2680695993ac084b84a9 + 1e11bdc8bc76b33ce64300760fc35e8bca2b8f7f8f708287; + 00000000000000000000000000000004000000000000000000000000 + b8d2cf2220f5ab4797feab4ac9bd35cbd2564dcfb099b5e6 + 3f66306393714717cc65e6a61242cc809c1a7c56f03ca87b; + 00000000000000000000000000000008000000000000000000000000 + 2b402e5af6ef5af420416bf1f5a2ac86576443db7e33974d + 61313e285d7928b69426ac7310ee16c80138c71adb9acf2e; + 00000000000000000000000000000010000000000000000000000000 + 002baae76bcd86eda5bc78d008ba23b0d2e772ff31004297 + ac9e2599d3b76610df2a492191e54ae52f2d1fd0583eb4b5; + 00000000000000000000000000000020000000000000000000000000 + bc03714729c9d4d276860ca7654dc3ff0956f84e1bbb9efe + 90ea6fccf1b49e1dcde379e04fdc02ffe00e30e07d5fed1b; + 00000000000000000000000000000040000000000000000000000000 + aa901e454ded6dd58dfeb8204b59bad80b570ccf24cbb23d + 22b08dc3430cb5ceca63a8a9b39ae41d6fd3dfcf95a1c88c; + 00000000000000000000000000000080000000000000000000000000 + b5e0906965a567b3784924265066b5a1756bf0cebd39518c + bb18608dc7c7fe6f59d011573234a4208a227f341bdd786f; + 00000000000000000000000000000000010000000000000000000000 + ae8b977065e3abf413f592cdefa3d2da660649f0e2f5a94c + 82899bc15e3efebe9338ac27ee29ea69dccfecd7e649af51; + 00000000000000000000000000000000020000000000000000000000 + a0b0a11f8461d83fa6fa785cba312b64367555de2759d4e5 + 0daffded48564ebbe98f69964b4959ea0aebe5a28a3d5a58; + 00000000000000000000000000000000040000000000000000000000 + fa55efcb4c907fcef36a43f6c2608639b56ce2effad4f6d2 + fb02f2826bf087101311832eb00d57a1d771d705ef70e337; + 00000000000000000000000000000000080000000000000000000000 + 1cc3544ae7b7c2737b6bd7e2ac832d681434326a556df8fc + 083d876d584412e85543eeee4512f059636c21f7bde4d3f9; + 00000000000000000000000000000000100000000000000000000000 + 1d4fa6dc25e6fd24a5ff13a30f63e783860c6c671ef428c4 + 90863553710ecfbec99e8b2b415b4e4f71dd88f6ebce7e38; + 00000000000000000000000000000000200000000000000000000000 + 45beef6f77bfaa83e25df7fd33806a7dc63175fc25c8a29e + 39fe2f8bfcc92b89431b08d5d9e3788f92fd10b9d5e18e70; + 00000000000000000000000000000000400000000000000000000000 + 28043c18a7e18389d6d73860977e2cb0c9cd282a267c5b72 + 17cb6c2df1e9b9fa149d0f0785f8f2f263da16ecf1935d89; + 00000000000000000000000000000000800000000000000000000000 + 4765dfba04c731becb1085f02d4f5eda72689f4bae916ea3 + 5d3068aebac8cb3cf5516b77384dc3416e2b5e8c982bbdd6; + 00000000000000000000000000000000000100000000000000000000 + 46f68d6acada331052225f714a5729c8116d19076f00ce44 + e7d20a3ca6208e5f407aa0f94f79bdcf82ad79592a079ff6; + 00000000000000000000000000000000000200000000000000000000 + 82b3c9ade76a91b3672754877beb7f1a2c87daec16b8667b + 13edc9289453530b65339df5c6c82c0a31d9e0b90e3ac873; + 00000000000000000000000000000000000400000000000000000000 + f36b6f67f121d8bb7f5de602902a9110abc7ff403913f3e6 + 4407a45e633e76537036fece0a3c71c0f15b88027b3303e1; + 00000000000000000000000000000000000800000000000000000000 + 03deea8338479826f1687012b30423234a36163e4aad49e6 + 9f7f6b5f8dd376aa0716651283ae9f0908f0cb4b34b771bb; + 00000000000000000000000000000000001000000000000000000000 + e853a06b951d48565445889b4e320bfe1c6b9084720cd142 + aae2e8c15f771e0ed58f8a92ef4da29759c38de9565ea06e; + 00000000000000000000000000000000002000000000000000000000 + 9d1546729f32d2188be60529b218bd703736f74e9f432d35 + 201f67b0162aced8172d99e73ab0a182154f3615f2e28f4f; + 00000000000000000000000000000000004000000000000000000000 + 07e669da1d9c8e593fda3ced0eb617708f2ac422d43c45ac + 1cd97e6d08da27f0daa041282df010e0f43908d8dd36b9c0; + 00000000000000000000000000000000008000000000000000000000 + 6bf530e97b29ece372e7ba9a7831dfbf56d66936e773ff19 + fa8388bd4a8c495383efebcc1416fd38a139db06a1729f4b; + 00000000000000000000000000000000000001000000000000000000 + 5d83bb98570d03ed7b6e5288911100680abe75d88c9ec453 + 51b426c7cfa0c0b178ed9def654b7e777164c7c1d945d394; + 00000000000000000000000000000000000002000000000000000000 + 4747797b044c2fc06cc39bdc2ed894585aad485e039b4988 + 79a1b62a586d5a72bbb16ed12d7b6692fd5526872388ce8e; + 00000000000000000000000000000000000004000000000000000000 + 9f79507a0960c45fa87e8f83cc6699a4932ba4c15791bcdb + 4a055efe90785b26b43cba08efbffd9de944028147f471f9; + 00000000000000000000000000000000000008000000000000000000 + cb56d08085757939b6542b8a6b80caac7508683cae4752e4 + 73a4795fa9184b465d6a6c3fbb3afee1d77daf4a9b4617af; + 00000000000000000000000000000000000010000000000000000000 + 765cbda6115109ee35dd5132d1467963c8d01c98c45c3453 + 02c719a0f74edba7975927b1854d3508b8f3ac1208c197ba; + 00000000000000000000000000000000000020000000000000000000 + 0209e8466c40204db5fdd3359b27e40920c79c1c63c6f030 + 9ffb260428629704470a539de1daa6f7afd55bd0aa2ba9ed; + 00000000000000000000000000000000000040000000000000000000 + 5738c3f833379616dc030b4000f32d672d30fe2246aac454 + 5b92b0ac5fd6fc2fa16f09c3b561300423f6d85e30e3cb26; + 00000000000000000000000000000000000080000000000000000000 + f7675f3bba2be50634a853bba205f33616eba5716513e28c + 5da69b1cb28398302f5896aefe2013ca82d0435550770288; + 00000000000000000000000000000000000000010000000000000000 + d3589f775c28ad54dbc5b3f5fac58c7f714b02a76c724212 + 570c32b8036aea0148294b6e3a7f7645716f4a34a7d391b9; + 00000000000000000000000000000000000000020000000000000000 + b3cbc1dcf7bafd4831b3008d60d90bb94ce50ad0cd633bf4 + d12cfaf58ebb31eb52c15279b6dc2288d403c5095801bf96; + 00000000000000000000000000000000000000040000000000000000 + a4fbc80a9d9e447197727034ebe3b15160cbc7cd9f269fc2 + 199b46bf2f636e5cf1ec0f1941a82d8b6d64e1b663894942; + 00000000000000000000000000000000000000080000000000000000 + 0c6ebfc561c10d994fd1475a2a3675341f7593f9f66cad31 + 6a8e9c8aa02e39174dbbde841585d9e874730a52d61649ba; + 00000000000000000000000000000000000000100000000000000000 + 25bdd9705ce78a156f3776455ddc4581aa1aec50684936c9 + ccbe10b3b46d201f199b58c3d19d1f9638d2886e7ce0478c; + 00000000000000000000000000000000000000200000000000000000 + 613f897e927225132429762e4dda85c607abba9a858c8996 + f76e01e51cea715d0dff5d54736c93bdfbf019c78a0bdd1b; + 00000000000000000000000000000000000000400000000000000000 + 65e343dc8bb79912567a55f71e99b3feaf3ee50c427c6143 + f0d0a8cb38b9d35d3b6aa98d14c323458dcd13e1ce4a7772; + 00000000000000000000000000000000000000800000000000000000 + be901e27296d7b03a1a7b96f1cd04fe3082ceae9efc53a5e + 359b7c239f049c9643aae5cf2d928dbcd5b05a4cee9ac27c; + 00000000000000000000000000000000000000000100000000000000 + c4707ac4f4b93bcf32243d79dd30ec29ab7f36fabc2febce + c70cff93a2465945e80ff266fa22d2680caa09f4d3679f65; + 00000000000000000000000000000000000000000200000000000000 + d30d652d01d6935233b1c345293f0936146cfd487a2601a6 + 0b752affdb6fb51a9e4811e71bcd057d0c586feb5f992e9d; + 00000000000000000000000000000000000000000400000000000000 + c5ecb03f48abf44cfa91c989948e4a211a0a8843a74154f5 + 3fc154fc54f79ecdbdfeea0e394341f4f0b9947eacf35ef1; + 00000000000000000000000000000000000000000800000000000000 + eac3e4e82fd8888c86cd00b70624420bc40a329308291941 + 643b0abd39245647ecd9b49028267e84a3fa5f4c1528e9a0; + 00000000000000000000000000000000000000001000000000000000 + ba153e4e10b7e393efcac79f73f7a6a78717e866110a6c18 + 98e9a632cb6e6ce3b28f461d51d2f95fcb476f25259338a7; + 00000000000000000000000000000000000000002000000000000000 + 2f5e5111f2c6689c1b7922f13b77bc21d1dcfa0548a365e3 + 7381da06831dad907c647f476b6b7acaa1c4f8bf39f906b2; + 00000000000000000000000000000000000000004000000000000000 + 29289bc290af03cb098c53e68749b16d5622d3db2f3011eb + 8844a8e6f3c043c0a6e1ad0c7f2aeea959e314cc794d7481; + 00000000000000000000000000000000000000008000000000000000 + 2a2993ed185b84670e2bb7aba5ccb4144bff86ca3c3e37ef + 76d2ab7bf99472ca115b666c932e90d21df5cb555e2d7985; + 00000000000000000000000000000000000000000001000000000000 + 44a7149685be83061a8141f9f86fb598a2d2489af958237c + 12d9cd9df6be396ecf0dcb2eea70261db337379379a56b41; + 00000000000000000000000000000000000000000002000000000000 + 2a54c1eb6658e329179fa565fe8e70dcd325148c764f3278 + 6da20c81af891dc85b8b42aaa370c490e2342d401ed8b36b; + 00000000000000000000000000000000000000000004000000000000 + d002d417bb650e197d87823051824f0060127a5d9a80cde2 + b6858026aee1cefb44780100c66666a157ef41771be03d5f; + 00000000000000000000000000000000000000000008000000000000 + c87daae7c988751a47c8b2defef5662711bffcda2b04c68d + b9f0df2039ed2a5645162dda2143829d5c4d6e6a3ce2bd66; + 00000000000000000000000000000000000000000010000000000000 + 82c21873ca16ff6e831d9a630dc8edeef5c0e45233d9e653 + 10115819eb20be42ca003cf7b313446ffb522e1fd1e3878c; + 00000000000000000000000000000000000000000020000000000000 + d9209dc4bc41a359f42281e85ae7a815a372ee810992f297 + 38a198719939dd10ff3f978a6ccd182f8a2a7ce6c79f6d45; + 00000000000000000000000000000000000000000040000000000000 + 7772821616ba97f2cd390075d0d207742eed03e4ef9ae8fa + 4ba5d91e1ce3f521d1365157de2adc666222c222ec2d3227; + 00000000000000000000000000000000000000000080000000000000 + 4c49fbe58fa73f8f6984924ee2feb30c11af06b6127c23e8 + 4a5c4b2cf401cdc8a8d42fa2c04065aa52f351b20b60df20; + 00000000000000000000000000000000000000000000010000000000 + af551b0b91cc045e718974bdb030e0f2c70c512aa2ea1032 + a1649d4e580003a845693e8b25388a7b9789126e672548c8; + 00000000000000000000000000000000000000000000020000000000 + 877e0d6ba70f8642e068805a01abc9f66f6ca53371ee07e0 + 9bad4b2043b8ca9d9045dcad8d3b85c1e7c312f54c93d465; + 00000000000000000000000000000000000000000000040000000000 + 737a994ba01e24ff5a87cfc942c7e398b9fe8f5c36480f7f + 206781c03a35312079afa8630dfef2597c886e9a8d6668d7; + 00000000000000000000000000000000000000000000080000000000 + f3699997c4c0df71ca34541d9326d4439ea2b6dd194ede4a + c9b558da91f88f4fb0f1ae1c462102cef0a0f03b5e001cfc; + 00000000000000000000000000000000000000000000100000000000 + 258e1e16d13ce49d113eed5aa036400fa1967e8f9e3f2a52 + 8b3e40554cc38790919fbac7dc1ad86334e4df9c2a50078a; + 00000000000000000000000000000000000000000000200000000000 + edec557cf03cf9bfa8694c02a366ec44d552bd9034eba4fa + 905b8240be31313ead25d8380c55f6d1a0df89179884b494; + 00000000000000000000000000000000000000000000400000000000 + a655d39d3d8b773c9fdde7c9ad2fe5f8967800a621b91aa7 + 23f9a1388e522b6b7eec35c9f1c027385f2f74aa8d9feaf1; + 00000000000000000000000000000000000000000000800000000000 + 11ba6f9a3cdb2a23aa1b923c797b5ec61b8f67aecc8218bd + f2994709f5fdf5edca503eb14a1b237c272cd7a16c4bb072; + 00000000000000000000000000000000000000000000000100000000 + 9f6c02ee484726800d87ee458e3c69fd4b44f3a93714a791 + e489a54780e1d8facf73b69d02dbe550ba970997f292993f; + 00000000000000000000000000000000000000000000000200000000 + d11f7985dc2c25d01e3a830c612875b27459321fee2de1e2 + cb5311c276aa3b8092c9a63b569d6b2c6f5738ed264029fa; + 00000000000000000000000000000000000000000000000400000000 + f3fa791265d231b06bf42f5d120edc44c080ae541f58043e + 0dd8b041c1a3dcd2e9f79fa6b027ebf3aedfed442c4139e4; + 00000000000000000000000000000000000000000000000800000000 + 21ac1c566d8473defc012313319fc2d8da50af71121186be + b39f67818cf2269e439ccf386aa13dd404ff5233b9345e61; + 00000000000000000000000000000000000000000000001000000000 + 316273fc4a0b6ddd90574335fb8a0a20ed0a0104e70e9a1f + 832163f88a2b62a4aaf619fea36cfa56d8979011bbb8fda6; + 00000000000000000000000000000000000000000000002000000000 + 00b5c352659ab100326d110075c041f8217976ed3821547f + fb48516c09d9593945e71a141fccaa663e8df96a44eb9327; + 00000000000000000000000000000000000000000000004000000000 + 6bc65cafae23e4394e970f4679861a2aafeaefe19633bb51 + 875173998a5e5ea76517c0b0a229219e0a5f3700d1fb75ac; + 00000000000000000000000000000000000000000000008000000000 + 71d385beb370fc18c1d7173cb75b3b1f15d30d8e3ccc7cbf + 1902091418ff8923ae4d4ea42fe9ce406a2cc5a394def524; + 00000000000000000000000000000000000000000000000001000000 + 960d8a3ececaae6e42d47d39fea65aa3ecf2d5ab7140944a + a981274234e998b241ef58d3424055faa7f701c312b7f958; + 00000000000000000000000000000000000000000000000002000000 + 5cefd34143969f72981162d8d10bf719973e9fbe7e9492f2 + 0ddeebd6797292c2f539f8f0a82dc646f42cedbe163f89e9; + 00000000000000000000000000000000000000000000000004000000 + f70b2d5be4989f4e7711d02c0bc03a7e1a8f8cc605e3a853 + f7778358e0e77f7f7ef7ed5c41005f49ec91e4d45c3d8495; + 00000000000000000000000000000000000000000000000008000000 + 89957ec9016662bfedfcb4872c182e648edf00dc59012050 + b425631c3d6d683c8183590c99058c18c9c3d4cf56d10500; + 00000000000000000000000000000000000000000000000010000000 + 01edcc0af8796870f0cbc9ca12d1beeae0a693fcec632a3c + f848bbcb8b7710c805d884ce13c231f7d83ff63444065406; + 00000000000000000000000000000000000000000000000020000000 + 960fe2a9d448e5b2ab8dd99ec58a6c07c40b5af464631c34 + 55ae3aa987bdd74c63fd3b0cb5818557dc4f2b886a73d880; + 00000000000000000000000000000000000000000000000040000000 + ab20af3c5b1df2a2d9eea9a2c524bbc83fd1195103f76856 + 1826890675b9f2cd2b2af4b1fa67fea727f2b036bbd82d66; + 00000000000000000000000000000000000000000000000080000000 + c2261c4fa3ab84dd38c7ec512ac972a05e29b6ed65852e29 + f941c28063eba8408762134ca5c6132a2854c545d7a64377; + 00000000000000000000000000000000000000000000000000010000 + 3d9da2d2eaeb97d162cd86f1bb343deda244a304ed9232c0 + 77aaa14ed3e383a2e6c4455797ce6d683a20e280d5ec9ab8; + 00000000000000000000000000000000000000000000000000020000 + 9a121137759cfcfe9167b57727df46bf5b8d35e54e813ab7 + 2536cd77c22795c50384c0ffb3c667b13ec99de25b8cc659; + 00000000000000000000000000000000000000000000000000040000 + 8c308d1e799e8e4e483c0ed00a4468d06932c66c7fa66b4e + db1b00bb64b9011494de6a0605dd496d5ff97a89f7928490; + 00000000000000000000000000000000000000000000000000080000 + ef3da9e874c3c3abe1b6ce46bc78107e5bd6e5d4223c07d8 + 6c942783ad9307f21b698970e99be812ce10bec7282a809f; + 00000000000000000000000000000000000000000000000000100000 + e3465e5da4ac75dd663bbe7f59cea84db1d4cd987b659a1d + ebd3d5e7fd0495a999cce1d056b0e694cfd1167d277e41f3; + 00000000000000000000000000000000000000000000000000200000 + 9e115d1a939d05b6a970dcbb27a1d29182117ae6f90a6b8f + 7a0a4b5b59c7594fac6801ddc6b20ff56e6842ca0ff395d0; + 00000000000000000000000000000000000000000000000000400000 + eae903ee25f7c95a7384f4516e88d89ec8423789b8abeffd + 1442520d0cd4a9342da833f247446e08e200369637db11fc; + 00000000000000000000000000000000000000000000000000800000 + 134cb0fcb97808665bb77439cc40fcc189067eb89f8965dd + b101aa60872909d82906bc746f64d174b8eb2ad70ecf1abc; + 00000000000000000000000000000000000000000000000000000100 + 2fdf734b5a69c30be8214ad46a0327487d97fa2f694b6f6b + 87340c26b15fecebe01b98b3b86d3b0d434855c0d747c85a; + 00000000000000000000000000000000000000000000000000000200 + 17c9d9be32dfb06cfbd47e8467d7464d85366a42fa7b1121 + 71065364320dc8ebf10abc71915b9a37fe13fbe8012be9cf; + 00000000000000000000000000000000000000000000000000000400 + b242f3fc2bbfbe89a3f0ca2605244b692ee7d96fca5ec3e5 + ba5c15f7e1dea1c4c02d81b446b6b97e91d3f27acc3ece9c; + 00000000000000000000000000000000000000000000000000000800 + 1389f6dbb847264179557e2a635c3f0cd843f5b82a457cf6 + 064d9fb5d2409e24bbeba7e45c4c57156c4fb11f373e76ca; + 00000000000000000000000000000000000000000000000000001000 + 42f828955b36c547dfbad0c56d6b4d2f623ef52ef7fa2738 + 3e80ab94606fef79fec3d3bfcb8707d9726cbe27233cb419; + 00000000000000000000000000000000000000000000000000002000 + e23e23434169161071da977b4620dbe5beb6fa04b47b432d + 9c1963564bf7a6473027442cb42cef4ef2e248090be98c2b; + 00000000000000000000000000000000000000000000000000004000 + e30e30336add2c54af49b3f2d172c5c151eb7dccd049f423 + b8d3c3935a0470147bff00344d0a9ca5ebd06ea22bfd2d6c; + 00000000000000000000000000000000000000000000000000008000 + 299e23a4828145c8c2bb7db4819b175ffd57ed50af2db5ae + 791ff2f9a6f0dc8bee326d9eadd920da1edc5d2a17d327d8; + 00000000000000000000000000000000000000000000000000000001 + 37de5c10c2e92a137264787163cb8ae954d81933dcf9cecc + 29ecfaa7a976d0b3dc7edd2066cefe484ad12f9aead252f7; + 00000000000000000000000000000000000000000000000000000002 + 0442bd68ddf0523120c45e5b858520cc025719fd408d757c + 373a1aa3eac3bb1b5a96a20e8e65bc41c5894deb725e27c5; + 00000000000000000000000000000000000000000000000000000004 + 4a6cd629968c0b125350dc0ff1ab3a603c0b93e9a3e56c1d + 03779efb521048c170b78c8502b166d9fa5813527e504e13; + 00000000000000000000000000000000000000000000000000000008 + f4d8d2f1b211988847b5313b5fefb87ad44d824767c22cad + 647f58392ce955573d3f741ffb51ec3cffb6fdb662996ab6; + 00000000000000000000000000000000000000000000000000000010 + 980a235b4a173431de984f8210de069493a85242bf14f269 + 1b4e10e4fbba7103e91b9977a6e4f492f04318e3aaba2419; + 00000000000000000000000000000000000000000000000000000020 + 647f56d74ca28c355462bedce39dc1dd85dad8aa5b1307a1 + 534a6e7b84c5303539ad359bf6c0603f29106f6333df6bf7; + 00000000000000000000000000000000000000000000000000000040 + da74d3bc915e164c185021b9085367232a1e10b8d063186b + 86caf736c5ddc7b3e4c15644a19334fb805ac1d869a88866; + 00000000000000000000000000000000000000000000000000000080 + 7343f4e043fd65520bd2d84e8c3edb26e617a654f05bf05c + e31bf2ac0a70d475260de31778ed39005cec782018514932; + 0100000000000000000000000000000000000000000000000000000000000000 + 9f5070b134d17734e035f8382ad4c1f61f83a6a9a0667e1e + 6c64f62e4376d0e962ece7e1aae286ddb0deca287e90b156; + 0200000000000000000000000000000000000000000000000000000000000000 + 3749a578adb8406d74022aa37e419f6a1fc561da5d11f163 + c59fb6c711df8e2ab61e9acaf513da8f1c76b91c272a6726; + 0400000000000000000000000000000000000000000000000000000000000000 + c8c990a321ea2a6a87066981b4982e89accabb0cbae03efb + b7502857ce96c6e469bfedcd3dc8eeb3f0326358bc076618; + 0800000000000000000000000000000000000000000000000000000000000000 + 73e3d8ac9ed3560c15322b54e30ab8d2c2162f029663c79f + 260b56cace6aef56377acf544c6899c81eff1a27c5d36f82; + 1000000000000000000000000000000000000000000000000000000000000000 + 738f42325ef664ec8928bc526abec512b8ea953e33ed0006 + 2090089fd9fcc5aed2612744712dae81c09ff05e5e4d615e; + 2000000000000000000000000000000000000000000000000000000000000000 + e8f4aac282194e7e31743aa524f7d9b004d2e63e0a30511b + 3b6c4ff45cf657d73bfe0ff0725b594a97d75a4cd02eebc9; + 4000000000000000000000000000000000000000000000000000000000000000 + 6ca217b943cef2c7e222e163bfec73c9f2a5b5674a39955c + 359b596401604ba4f686b1f81dfbc33e6333a6ab054d9b5d; + 8000000000000000000000000000000000000000000000000000000000000000 + ac011f99d6766074346e8155ac4a132558775649391ef793 + 21a191c34b73b95fdec1b26477ba3711c668e7e03b9e72fd; + 0001000000000000000000000000000000000000000000000000000000000000 + 1bf0e285f67aff5b9e50c33f72819e4954345c81d4bf4d70 + 82e9cf04f361e790544077fded5dc925866c0f6598016e62; + 0002000000000000000000000000000000000000000000000000000000000000 + 7af6bdf52d8cb70ad56ba7ca466315e9431c9be251059915 + ab68dab956704aa49dc6938771e720d53afb6c001a9c45dc; + 0004000000000000000000000000000000000000000000000000000000000000 + 6b64c2b68c3a70c98a3a27d73fde094efc351355708bb8e5 + b3e7e648edbdce4024fe88afd65bcf79756146f37ba2b523; + 0008000000000000000000000000000000000000000000000000000000000000 + bafc3238aebf8a428a560cf351d235dbde917cc1743c94c4 + 2bd0b7ab6759ca6461974b402f77287d4047b6c580ed057e; + 0010000000000000000000000000000000000000000000000000000000000000 + e3c12e9c2d584133495b3ad8a93a18303809cae7ac8a5c35 + 01f1f0781ab946f016082703b7a5f0a8e2538e6399fb2a27; + 0020000000000000000000000000000000000000000000000000000000000000 + 15b55c96181a311f3f7f74f1eb85acd21405e577c99ce7e6 + 7be214ae039f75aff28c25e1693d9509b95e7702100136bd; + 0040000000000000000000000000000000000000000000000000000000000000 + ef286b5b57c90b082099f1ba63d66b831c2636dbf89284de + 405ff3ab609cad17a727f3a32a728176f60738ee93ea4ce3; + 0080000000000000000000000000000000000000000000000000000000000000 + 6a9f9a517d801e276faed59b37815a0543470f62ddcb36d0 + 6cfd80ee554662542fa45f8619fa8596a5b0fa90207c6e3a; + 0000010000000000000000000000000000000000000000000000000000000000 + 2c65e60021dce4ab35356c77e3a8d9d489b229961214d45c + 84fb478f9555f964aa1c963c796afc08249dfa483cea11a5; + 0000020000000000000000000000000000000000000000000000000000000000 + 6290778c236da149367eff1a881fb693e5fc1577b911bd50 + fed8ace2fa769e2e59191c11af5981610c7f1d1cd16a63c0; + 0000040000000000000000000000000000000000000000000000000000000000 + f3a53dab4a1b2ee51c925c64b80509168fe2c4a39f89eb9b + fb14272d3dd9a4a43c3c77edcb2ee13d1c0cf5736c100e3f; + 0000080000000000000000000000000000000000000000000000000000000000 + 37853db27afa67b912d92274f952fe6cffcea6749c9cf346 + 5c3738ff494ec6280aa714196e4285d78ad3efe97dcbd993; + 0000100000000000000000000000000000000000000000000000000000000000 + de4ee75f7a008440578d541a9e9beae7ae6f2ce540682a51 + aa01dc968b1c9c699098297c7a6230ed03e9d1f8930fba2e; + 0000200000000000000000000000000000000000000000000000000000000000 + ec682371507c5eacf5b1c6510338f9979c93480dfeb327a4 + 00a05844fa3d11d1ecfab19b2fed0d6eaebe4265a89c2214; + 0000400000000000000000000000000000000000000000000000000000000000 + e1e5590bbbd38ba2e79d7f674c1446517c0fb92ea29d4b08 + d3e5d1af3b1798d750976f6744baa274a9ecf75c44efe46e; + 0000800000000000000000000000000000000000000000000000000000000000 + 121dadba2540831650bab205a38ede0f515ffaee7788932b + 2ae7182cd02fda62b2fca3aa1459f88ba131f5037734d486; + 0000000100000000000000000000000000000000000000000000000000000000 + bfcf69c073a8f4110b4f2506e422d57ac27336ca35fc55b7 + 9b92c327f8d3a10f0294570ce6dbad15e63828cce97ff2e2; + 0000000200000000000000000000000000000000000000000000000000000000 + f9e64438a44d994229bfc83934b5900cd3742508d8c1e3f4 + a91cde6622ae50df47b3efb44188211a9cb855dd13f196e0; + 0000000400000000000000000000000000000000000000000000000000000000 + 02bc24f93a54d95614eb323e668dbb078db65376f8222669 + 12e0a8abaf64c61b674b1e7e80245c8486d0b8b958d23d63; + 0000000800000000000000000000000000000000000000000000000000000000 + 38fd0dd2508ccaaf72e404c3aa6197ecdebc6bccc2906e35 + e7178e54aba498545f12beab6f4566d0af8ddd737e1094f9; + 0000001000000000000000000000000000000000000000000000000000000000 + 6c2bdfe67c48ab3cb5e107ef3bad9aaaf4b7815775e31441 + 51dfedda78ac4f3bd74de1129075f40b6489e7dcef913c8f; + 0000002000000000000000000000000000000000000000000000000000000000 + 9996e38570d89d1e4c716d17d2d18cace32196b32b13dd4f + 4d69155a61196d98ba7d4c3760cb5b42ca7826433f767477; + 0000004000000000000000000000000000000000000000000000000000000000 + 2e5f7b788f621e6e00e568a5d6f6366a204be180a4150c1c + ef2f1ced4c859dc6abe9a7797f94474a8c5cc738524cb51c; + 0000008000000000000000000000000000000000000000000000000000000000 + 225d5651c62b76b58162ee3565c87920e73f8b26874b5834 + 51d5591d45055db3213c2037ea19d19e3f30c57930cb408c; + 0000000001000000000000000000000000000000000000000000000000000000 + 778f01b3f568dc1cc0190d8a9d45f046ad0d7bd0a2e83bd5 + a659640486d774d149cfa752fe07f16839ad0a4e0965023e; + 0000000002000000000000000000000000000000000000000000000000000000 + 07469341cf3d3fa4f1e4503d51b2147eecece66e55a4aacf + 0f4db2767bcdce2479987e1dee35bce57d3f0c1f064e8388; + 0000000004000000000000000000000000000000000000000000000000000000 + fbb5a12272515cb6cef56c3394497f17c295a8168ab7cf52 + 79e3d684921c85b2aee19fd542fd0e326d06db185ed4b2eb; + 0000000008000000000000000000000000000000000000000000000000000000 + 23b46f278eab2f8cdad836b7a0805cdb5705959dfad8a8f6 + 47e50febaeb4948f0f08b02d8f00ff84b1a4e28741b84be1; + 0000000010000000000000000000000000000000000000000000000000000000 + 755fc8fb5a4247070161365d075fdca9c315f7ecb9638c5b + c0a7a431c614f79e0efa949a89b0a1d3a44b726f75cca6df; + 0000000020000000000000000000000000000000000000000000000000000000 + d1777c337f61776201449d5dda39dd3acf48b521ea993028 + 10e87a928e0ef507398afe7f1d3de0cfe3be585831d6b8fa; + 0000000040000000000000000000000000000000000000000000000000000000 + ed33aa1685adb27dbc81bff9211d9199feb400b8084362b2 + c75e37d353c1cf37451eeb3739c92d3111e5e6a95c3f6a1f; + 0000000080000000000000000000000000000000000000000000000000000000 + bc37576aeb1bf24f50806c7b96cc3ebedf64f5d444238cfe + ee28dd6263ba7f0cdc8588aeb27563e83dd26a66c519a3ff; + 0000000000010000000000000000000000000000000000000000000000000000 + 18a038c2820a8f3e7df91219c8937a403fc5b04476b5b00d + 9e3908a1ed2c0d5b7d8ca231a0e9d965c5bedd70c2e91782; + 0000000000020000000000000000000000000000000000000000000000000000 + 266d38db2332f7b5aac71f5e9c4f201abb66e07d3e0f33c6 + aa256588a4aa4bee6595a18b9083ebd7b4e33adb2f7f3112; + 0000000000040000000000000000000000000000000000000000000000000000 + 4e456d28fdb91a55600a0f0a940ff6a23e99a7ace2302257 + 7faaa8ceac5fdb90aa67d0cbfc3ba885c19236ccede0267c; + 0000000000080000000000000000000000000000000000000000000000000000 + b7e154b0cef10b51c0c37d92d1ee18f87e9c034bef605109 + b953b77fc877b9877c566c04077eba7de5ce3712302f5bec; + 0000000000100000000000000000000000000000000000000000000000000000 + 23076ca9ba4b66fd5dad468e32b6aabd89157dd9484de084 + afe987cc7c00e457432b4343130c0efab5ab5bde088a8b09; + 0000000000200000000000000000000000000000000000000000000000000000 + ba9528c919d59237d542419e822ea53d44d7709ed8831393 + a46e0010238e90da8a824c99e48ddd516b53d1b58babfb67; + 0000000000400000000000000000000000000000000000000000000000000000 + a45c47b8b5d93ac468ce2698c4bb818d18cddd27d3c90ef1 + 05d4636e0dc06295cf47fbe08564a1a890d42be50da9a712; + 0000000000800000000000000000000000000000000000000000000000000000 + 009e53d4f953ad0a4e3a6f424958319f9b0ebcd4eb32e6b7 + b26f95360e1f006e78c56c7bdb60aa517c08b6b353ef3954; + 0000000000000100000000000000000000000000000000000000000000000000 + 60beab9429813d3bbc70a65f440af15b1bcec02ab53e3b17 + 25eb48a26dc3ec9d67440f4adfaeebf3c851cfb774f5d9fd; + 0000000000000200000000000000000000000000000000000000000000000000 + 8446b9d837207ac194d094bfa5768dad1bc7ac62b507d6f6 + b93872a3955bfcb3a085def48e48ad7468172a3ef1381296; + 0000000000000400000000000000000000000000000000000000000000000000 + b18d63b9b8f957da2cb1d8315958058f607ee9aa10803040 + f8fa5297afba5460f910507495a4aa3c03c08ccbe658173a; + 0000000000000800000000000000000000000000000000000000000000000000 + 8569811b5e86046299507b8f1ca054bbd291997c92120b1e + 56b1179f4e1abf339b12b0c9a05b428171dd207e2f90e9ee; + 0000000000001000000000000000000000000000000000000000000000000000 + b2641a18af6dd774a608b6b7a498b5962ea67f5b52807803 + 7a7e0f1cf78a9fa1421196d03455525341514b24dcbbccb8; + 0000000000002000000000000000000000000000000000000000000000000000 + 5ee40a1926ada020139789a195f1d7fcfd8339a5905d8c91 + bcf4d04a361be5738498700a057b6a767af995b1ae9cc990; + 0000000000004000000000000000000000000000000000000000000000000000 + 97fc38aa8fb864828a1f8ae469219da97ecc1d352fd8478b + fbb3e38a2e3ae33ce7cbd0d9ef4278ecbbca11e5571a21b3; + 0000000000008000000000000000000000000000000000000000000000000000 + ba1314e36083bcbb1f01a1b0dcee1c5167d95058d03cb298 + 9c1f480bafe7df16d6ee5d5e44296998acbed57fa981cc8d; + 0000000000000001000000000000000000000000000000000000000000000000 + d1c445fbbb6c11b248816ee124502e8d9a44750df0288c84 + bde77bc4f65398b2e4385be1e459925ab0b29fad2e2ec1c0; + 0000000000000002000000000000000000000000000000000000000000000000 + 91e1b29bac8b3004b7e0a3c4df1f49131b73cf7ee9daf237 + e6838a7e1686dedfb4f590be43684645a9b1b4d41178368c; + 0000000000000004000000000000000000000000000000000000000000000000 + a618c81acb2f8ffa633fae6f430d849213633f506ecfb4a9 + 4fb027cf52b913a04d493a225be16d06e8bdd2e335a59f11; + 0000000000000008000000000000000000000000000000000000000000000000 + 425ac642bdb172b0d8af9b5e8733b4138f9a8b73c53e78df + fafc2c7ef14412e28b3091420e524b7a617fcb79fd7a2333; + 0000000000000010000000000000000000000000000000000000000000000000 + bb83697c816b291cbeacef56116984f1bcac5d1185a96046 + 94ef1fed71ae8838ea5dcd1fd87df10aa5dfdaf7247b20f5; + 0000000000000020000000000000000000000000000000000000000000000000 + b9a35b83d2fc63f3a59889ed2464ad35fe2304bc8b243620 + c072779c8f7c58b5e54f87de26ff3e8c9bcbddcd843d0ec3; + 0000000000000040000000000000000000000000000000000000000000000000 + d5ea0b3466ac121ad1117536c22443eb6206c8f0cb129db8 + 2d3e46147b3d926b59e2d3d848a519ae9d0dab3002c7a447; + 0000000000000080000000000000000000000000000000000000000000000000 + efa22fd1dbb1fd3fe8b4713b358382a3ebfb7971d71c619b + db33941cff2f3ba57574a6babe30d3a2482fa5fabe541248; + 0000000000000000010000000000000000000000000000000000000000000000 + ec54918b940cca8540c84dfb4951115e41eea879f69226e7 + c3f4bbd94a5f8ab825e14d399d1d63b419b920a985eb537c; + 0000000000000000020000000000000000000000000000000000000000000000 + 882f20f80febf9a64f8513d9da4a84ed12230066759e0baf + 171124ee711829702478c993e0a69614a5fa6abe5693c757; + 0000000000000000040000000000000000000000000000000000000000000000 + 999b241ea0f1f9d8291458bc1706019f2a62597d2e08e808 + afaa8b4bed7aec429f62ef6bd157ea1b0cca67b539d35f8c; + 0000000000000000080000000000000000000000000000000000000000000000 + 9d1c95595d1c8b43b32dcbd7d157ed0cc500beceb9ad7dfb + cfbc5738f8c2d1fe1489aeb853e7afe75d3228e820e5d1f8; + 0000000000000000100000000000000000000000000000000000000000000000 + 939c98efb6a332bd0d106b0ad73c7bea3b27509089a9b3ed + f8ddedef92e523ba101a8cbc3f5910457b4c10f632ea8c1b; + 0000000000000000200000000000000000000000000000000000000000000000 + 62260cb25a9c5f13da85ba16c781315e00fcf91a14ecfe7d + 4a81f4764d73cff0c6c598bb14d03dbe7456d84480b3d97b; + 0000000000000000400000000000000000000000000000000000000000000000 + d13026196c4648cf6eb48ab504801dceb09c184da5d02206 + ffdd66bf5a8ef884b365ff79cb468a07483ce1af9c781ad6; + 0000000000000000800000000000000000000000000000000000000000000000 + 1950354058a14fa13adea19ad18be46eaeae9d314400ecc7 + 3911826bb13fb45bcee0680c2e2988d22c404120b67174a4; + 0000000000000000000100000000000000000000000000000000000000000000 + cab6747886cacbd533a4a28581622772ca4026b7735cfd62 + 1e03b32dbe480ae229b614d23e1d0ca3b4089d622b525960; + 0000000000000000000200000000000000000000000000000000000000000000 + c258d3ab881322905a693d6eb560b14c93c6e1f1ace6cba3 + ca58904c0affa64dc2fc1fd744de880eb86876a93c30c04e; + 0000000000000000000400000000000000000000000000000000000000000000 + d059b736116667cfd8f94e294252ccc57adfb59c7f2a5f39 + 2f3e359bb0ae9d420049351b1b256049f61ba52996f08036; + 0000000000000000000800000000000000000000000000000000000000000000 + 8b8c9610ae81e48055eec551f0d52cc552b12753c6bb7924 + fc2c7edfce13b888076c6b8932a76c00aed86dc34bcb04a9; + 0000000000000000001000000000000000000000000000000000000000000000 + 95f736d9848960fe82200410199208bc50bff3776e7d800a + 01da25ce699dad03299a6b2f02422deb0296463df7976a1a; + 0000000000000000002000000000000000000000000000000000000000000000 + 348e25a9a47f7371785c033e858054e8b84b4aca450330bf + 46e40e1b342b0197a6c9823810b563ab162a4afff3ef8d3c; + 0000000000000000004000000000000000000000000000000000000000000000 + 398d57d71fbbc564ba40316a04a78661be30188d8a00a9c2 + 1dc6b4d53c6cb47c518a07e6caf6aebb60879202c2902404; + 0000000000000000008000000000000000000000000000000000000000000000 + 8c2ce222b3845769ac1b5c6087a4a78767bb7b5b6db0b844 + 386089aa0f982dab5aec5ce3c0d6c22e57850ef5dad854d5; + 0000000000000000000001000000000000000000000000000000000000000000 + 367067c67a278f8da0b6d95e01e1300c4ce4dc4564643a1a + d9f7b526134055e0863b763367ef09c4999b3d3f7478f2fc; + 0000000000000000000002000000000000000000000000000000000000000000 + c4531ccef569e7ac3fe27aee4f9413a5ea932d077eafe749 + f8617cd036e260fcf3cfcfd7227ae8ec3823dc1806a5186c; + 0000000000000000000004000000000000000000000000000000000000000000 + b23ab66b0a48a91976906f145c49acf72cfa24a718e29d43 + db0602809ba65f935b2b761ac68698f44ab52e3073318480; + 0000000000000000000008000000000000000000000000000000000000000000 + 84e2f169348f9c12292bae0e4a411c04bbae0dae1010c6fe + abb60974909b46172f0ff9f8d3e0c1ac90e354ef5d8d4b96; + 0000000000000000000010000000000000000000000000000000000000000000 + 178f1df13876d9aabf1d7567a9ac8548033ab879cea6c62d + e8275ded5d48c972e53d5542d039c3c0643bc221ec7ba6af; + 0000000000000000000020000000000000000000000000000000000000000000 + df2371204f0d5fb0d345feacc299424b1f09c4fdfe740b29 + 1d7867481c4958a1e96b74d7564fab9081826baaef1c0bc1; + 0000000000000000000040000000000000000000000000000000000000000000 + 85f193b35e480c86febd733e3d73c5e533f5af5fa670464c + aa297d5e92606023fcd76ff39b447bd6f8b528d2eb8aa389; + 0000000000000000000080000000000000000000000000000000000000000000 + 3c7e3ef5b75bdd8c4ebf0ab567fa9dfab7b14f65465d5202 + 2d1d772ca4e8c4627d10252c17f8de9fe4eb5f2410036f8f; + 0000000000000000000000010000000000000000000000000000000000000000 + 7946c21f3ec9019663b088701ec2fe303a91473d66166c07 + e0781ca73a7ba4da909faabd4ac41a9d2a04aee40741a362; + 0000000000000000000000020000000000000000000000000000000000000000 + bdc80943ef24005d2b2b9cf4a622cdeee6052c94028be903 + c1a5cf266e621e1dc67f7d95e8d4a0352abbe6906e2509a3; + 0000000000000000000000040000000000000000000000000000000000000000 + a363dfe9c29405923502bb20f0ca9433d2bd2e935bd158c6 + 73ecbaa847e33990a348518355d24250d78ba4bfe0cc6ec5; + 0000000000000000000000080000000000000000000000000000000000000000 + 91a79788d280aa0f726e81b5e120fd0d175e9f835196013f + 417a49bc83ff1cae0de19f5469644fdcff16a19b0c48e2ca; + 0000000000000000000000100000000000000000000000000000000000000000 + 4899462607deead1c0bd532d7aca9b707ab2e7fe0e29b590 + a81d309f9faf421664ba046616b4dc07c918d857d3d84905; + 0000000000000000000000200000000000000000000000000000000000000000 + 0aaae126611efd36cfaabc703328ce88567f1e1ae8d98ab9 + 642e95674700002ad5aa27d465b538e764fe7bd9c14c73aa; + 0000000000000000000000400000000000000000000000000000000000000000 + 89518487c389f394664d1db1e9110d4f31ee5a30ab504538 + 9096525261c9c51132a575c2fa95ec45b126d1978b3c8f0f; + 0000000000000000000000800000000000000000000000000000000000000000 + 48a115999ac4106147c25c8af6490e3f864fe07a4aa0814b + 6034cf7c5049884a7251bfe1e908db7ae5a242bd7528cb80; + 0000000000000000000000000100000000000000000000000000000000000000 + f4a37d22f6ccc6807c77a2b00892c34f751e6af9d507b7f2 + f05a07fe2964989df5de5c5568f0cc2a4cc385a0046653a8; + 0000000000000000000000000200000000000000000000000000000000000000 + 504eb8d6d794ad17fb17701daa68a27909c10b07db35d59c + 04d1a5d0a25f37c358ad1544a61c35e3b27bb8e872a66657; + 0000000000000000000000000400000000000000000000000000000000000000 + df0ad9ae9ea8203f839254c51201e4badf59280ec5791f21 + 60d514f1dc0ae5f0041b7dc951c2b7878620178f6cdf40b5; + 0000000000000000000000000800000000000000000000000000000000000000 + f134b86ddc24cedefa5919802e2ee4a1b8b3dfdbd6d4707f + a2a6684093c8fc7fda6d78137007ed72ae90c2bdd5457351; + 0000000000000000000000001000000000000000000000000000000000000000 + c1227e56f680ff943c4a6eae53aa8c47603dc225a0770151 + 20a18398e209070d630fd66253f8198d838c133fb8b2877d; + 0000000000000000000000002000000000000000000000000000000000000000 + 618aed56a6e67024f44a5182f8b3a0429f1f816e40d36940 + f4a5ef442826ecf4f7b51af42c67ca6efa9eeb05c950d0e1; + 0000000000000000000000004000000000000000000000000000000000000000 + 993f917a093d0593ffef2ee61717769d0310a338971ad5c3 + 633c510c65b17337fa6600f7b8c587f06cdbce7eed021dcf; + 0000000000000000000000008000000000000000000000000000000000000000 + d08c7506bc96104784ffd62989f3e7f14b7941408aff19a9 + 4ef7c78afbe041881669a436f0b3a2c175bd1872d417f427; + 0000000000000000000000000001000000000000000000000000000000000000 + e4c926c1c6af627ff4aea8915cbddf2d51fea4f8efbc84f7 + 297dc1f8f2f34488496c0a7315c434545c2c356da2f2b8a8; + 0000000000000000000000000002000000000000000000000000000000000000 + a1d9f20b38fc8ff10284673b5401b340d3606374c0705387 + 538fac79ea64656d7b752ea715238b7168b7fc3e3c307e79; + 0000000000000000000000000004000000000000000000000000000000000000 + 48a83c0d5aaa75c08186e0c3b43c12359d64ef6c5b51178f + ae4c16dbfd40480fec24032f13ce1ce1ee236785754befa4; + 0000000000000000000000000008000000000000000000000000000000000000 + 98c9f42280dbba13cc6058bcb1fc101f535c17ceadb39384 + 97c2fcd700e5ba4010191d1a2bf39b94ef26c1f10eb5dea4; + 0000000000000000000000000010000000000000000000000000000000000000 + 6e5185272ea765f9c63e084aceb39635fc7064c5500933a4 + 789c9eef18191c6eb37ff8bc61737be04cdb38074cf16342; + 0000000000000000000000000020000000000000000000000000000000000000 + f1a2076d13ea103ec3bc2a7981628b6c46b7e05ea2b8cff0 + 1c960f47235aa3c2f7db928c79eef79c1abb58df32be0519; + 0000000000000000000000000040000000000000000000000000000000000000 + 2a25e1c3d40e114369c652f39101b149ad121e1e297568f0 + 39a862fc9c7501571eebb68fda325a20bfbc18b8d1dc06a2; + 0000000000000000000000000080000000000000000000000000000000000000 + 4c368f98b55ba57c8a9f50143c85ba209f46b19a287fe96d + 805862de2dbfb0b5fc8522fe1775db56cae5d782c5ed78fb; + 0000000000000000000000000000010000000000000000000000000000000000 + a0c97c9e66701e6478fb012dc563dcbb1f5c6da5ab22e1c7 + 7deb07741bae22c3a4e245df6f6f0ea157e8c2fe11277248; + 0000000000000000000000000000020000000000000000000000000000000000 + c1aff5f111b93662f2101a991dc73b3c6ae24a7305ffe5dc + 0c4cda55e6b291dff5fd90fa1b5fec0d74e2658a9fb8be12; + 0000000000000000000000000000040000000000000000000000000000000000 + 2f7e8a0ccc58df1c6241c31911d531e9990eb7849c9dd986 + 57a80345e95f8e8f0c235e56e34b0b92bb6c3f7d1da32f1d; + 0000000000000000000000000000080000000000000000000000000000000000 + 22bea653be4b485e68b8579537213762f44e42f6d810a498 + 7c4fb10db02107f924884cc1813fafc08800fd616c7463f3; + 0000000000000000000000000000100000000000000000000000000000000000 + d7542072c23ba5a53a81ef80fd2e18a4fa4e797ff6600040 + 2a7bf2b00a0e7248f754fa91239b22954286887269c33386; + 0000000000000000000000000000200000000000000000000000000000000000 + 67cdb364f19b764b08f2fbe24e0d8f5045cd24643068dbb5 + bdcb57ef947437c8607c456b12a0e35dee06a72ddc6b39bc; + 0000000000000000000000000000400000000000000000000000000000000000 + 4b69f9d96da82a8e111ba914616b8181351b6c7378c398ab + c3c93b51b1523b3d5cff783005bc32aebb490df5dffbf54e; + 0000000000000000000000000000800000000000000000000000000000000000 + 9cd63826b5c968a2b91637f08960fff1db80be3e5f4e1b10 + 37e40726553084bf60ccfa589cd5a7ad328a9d2731b07c22; + 0000000000000000000000000000000100000000000000000000000000000000 + 9e35e64ebdb49e1eee17085264da59b066e3bbe33369e668 + e700e349d9ba81dc389c9ea47ae3397d2021cbb0a1dc3f50; + 0000000000000000000000000000000200000000000000000000000000000000 + d01966c6c3c1743b53cd852ed40141a122f10191b1c31a86 + cbb249292e1f8720ed8bd068e08d00e58b5b6ded6db35967; + 0000000000000000000000000000000400000000000000000000000000000000 + 5d22197b1f31e555244767a519cf1612dcb1e0c389dc5e85 + 6c356e034f76f45d77eac2372b1b8d13fe37a9793267579f; + 0000000000000000000000000000000800000000000000000000000000000000 + 7a6346dd4b48c8e2578dc9e44cef59b355e745603ad70e56 + e0ad6bfb7dd04c50408813e9ffc253a786a79f322270e3c7; + 0000000000000000000000000000001000000000000000000000000000000000 + cd6744a38f58ff1565c63b618f6d4602f48424ef96cba9fe + 223ebbfcee0d2261dcac64d4457563e8662cead4f842f885; + 0000000000000000000000000000002000000000000000000000000000000000 + e7181dde8f2bb5257724386d775d816db6ba1788840b2ef3 + ce12f93c38f34c761b6290ab661bea7a94d7bedcce619c42; + 0000000000000000000000000000004000000000000000000000000000000000 + 35144d4cd483e6ff784cdaba5d8fe43457400002e50652b5 + c9d58b472c45d4a0bc60c5f068babd4761119b8411392863; + 0000000000000000000000000000008000000000000000000000000000000000 + 49e3852d9ebf4a20761f9e3cc5af7079f92434f3cc0498bc + b5111d55ae21a4dd1d94208eb1e2bddc2121792c0865ea1c; + 0000000000000000000000000000000001000000000000000000000000000000 + b5be1b964131cf4bcc472ff83c7175747c0a8142a1b592cf + 82bd1f73170e94ea2dd2533fcb2e10b86d223ab573b7acb5; + 0000000000000000000000000000000002000000000000000000000000000000 + 436643b8310b2f8012fff1718d811445febcb62174eeaf89 + 4d73981253903319bbf05beaf81b161b5eda9da17a6c465f; + 0000000000000000000000000000000004000000000000000000000000000000 + 26fe5bba90ad70222b6e0dfb3f910225dfd1d94e8a6eeeb1 + e50c6fed998ff52d18c1cfaef6486c7dda0353d609893ed2; + 0000000000000000000000000000000008000000000000000000000000000000 + 167ca811688841bbc017aef57f046c72c89cfb105675abd6 + 474b913d96b3065573859d90259e7170ed086c7e85e6f833; + 0000000000000000000000000000000010000000000000000000000000000000 + 2241fe3b5601c4f8691132f7fef47b2a705ee925419fb2b8 + e4f6a1a195420d5be230460d72cb10e0d5fa98e3473dcddb; + 0000000000000000000000000000000020000000000000000000000000000000 + f73edb64726d1038febe1182d24c9df9ac4c2e44d27350a1 + d023f50e6c5815af9f68c18fa011c72a0ac1de37ba50052d; + 0000000000000000000000000000000040000000000000000000000000000000 + 414f12c0bd23b6541fe25e485c99ce83c5d29d5284c6d635 + b9be932cebc3b0451aca78b190970be486bff89022dbdef8; + 0000000000000000000000000000000080000000000000000000000000000000 + 9cb48ce5c9bbf7cdf172e72b8ef47ee0b9954d4d83f64e85 + ddbad8bb1b68dbe0d1c2377a9f851cdd40941f1e8b17a72e; + 0000000000000000000000000000000000010000000000000000000000000000 + 9ad04eb679eb45041adb6e18229ab8ef134f96b9ec4efa8e + af91847fd9a9b0853b5adc3952ec93b729931bafac0960c5; + 0000000000000000000000000000000000020000000000000000000000000000 + 7fdf8d84ca1f1ef75921d13340a8613a4abce59f8e6719a0 + 048a8092055d9bc71038c2adc3fc74a9941b1bad6bb0d748; + 0000000000000000000000000000000000040000000000000000000000000000 + 3bb8a2eede247347d3293a7827b935696db66633154f6eb8 + 6da269df5b0af347a91ef471261dc6aae07939d7562dd17e; + 0000000000000000000000000000000000080000000000000000000000000000 + 76cdee34adbfe476b19f218ad192ff91cc764594ea84e9e9 + b89d091dbfdd454d3de741971939aa47c84b65e5601ed69e; + 0000000000000000000000000000000000100000000000000000000000000000 + a5be84ab2131cc15fe88214e692c2a1c93649c302935f68e + 74a065159a3a25b7beab96afda6cb4a15f0f0974650825d2; + 0000000000000000000000000000000000200000000000000000000000000000 + a1c10a2b8f9117b9c7d2bb4a4b8fb19ad5862a070afb8f34 + 11b10a5b03c2e735c20aa91c796a30e1e5012eea5d17a2fb; + 0000000000000000000000000000000000400000000000000000000000000000 + f30f479b09b7078984a91a14766ca5331ca54f237e832e00 + 2754d3cdeb587cacac85e5b9bc2a8df745b72ae84c83e30b; + 0000000000000000000000000000000000800000000000000000000000000000 + f15256ae559de534a46259c458ed699763917bb67c42caa5 + 998dda9353cad5811b4d26b418d2c36ac8241cf9162afcb2; + 0000000000000000000000000000000000000100000000000000000000000000 + e9dd34edf9072580a9e6bf92f517160410c41b28056a8acd + 0dbf466153aff0de4e09a06fac89bde833afca483a514c02; + 0000000000000000000000000000000000000200000000000000000000000000 + a3af6ddf33c781ddce6b0033eb3afe64149b1e22c3298b6d + 8d18a7ab3755354db7ce3336d2ad1870d83f84efbabf3f1e; + 0000000000000000000000000000000000000400000000000000000000000000 + 943acab0e9cf4ec9267798ec18e96ea9c4953d194d06572e + 2ce3b4bf975ef64655d8bf4e56016cb2889016c1884d649d; + 0000000000000000000000000000000000000800000000000000000000000000 + b150a772fa4e01a865d822ad9f08e192a2f09e10ba815686 + d4e5f4ca1ab70dd9ba5b5af2efaa89b3a273cc13dd63bc5b; + 0000000000000000000000000000000000001000000000000000000000000000 + 685d0a283480caadd55b2866fb4a0a41b6c7cd10a178c267 + 4e8943a076e33ac2517b897f25f5e1b946a421676d59866f; + 0000000000000000000000000000000000002000000000000000000000000000 + 6adb8fb9971688de77028f21a600d2ec2e7ea7469aa68f49 + d25f5e79e204a87897d24530d30e7fd55f852298fe41b993; + 0000000000000000000000000000000000004000000000000000000000000000 + 34e213c058fa256f43ce41f0a636f04d6de70d66fe58fd7b + b5a6056e1a9fe00af39fc4f6dcc737bfaaf953b94c3d7d62; + 0000000000000000000000000000000000008000000000000000000000000000 + acfa06bba285a64d49b3e40fa21a87807bab2e1b8be93dc5 + 9c607c350a79fcb9c3c08482a9899662911dd9d78241e5af; + 0000000000000000000000000000000000000001000000000000000000000000 + af8fe6e769d9a9de9103857c73cfc48caf07a0a162a9c84e + badb8bf3e3901514c364d5ab4fd71dbb4adafc33a57e0dbb; + 0000000000000000000000000000000000000002000000000000000000000000 + 03e0acc3efbcef91c181e6b725efe6d5988aa3fcf2d97918 + 3562afdb394cb6c829361868d3fe9e2a795dc73d6650c385; + 0000000000000000000000000000000000000004000000000000000000000000 + deefc043580767155330551bbb6aefbfeb83f2a53645534a + c8162770dbda0fc2e009cbc088d52b75e0c5b3d8c3aa935d; + 0000000000000000000000000000000000000008000000000000000000000000 + ee46ee36468537d3eb9a8712e6ac1658c502a2ee5f3b9dab + 9f7aa36fec8e73e4e31f29bae48a0484eae73f9b1afa9eb1; + 0000000000000000000000000000000000000010000000000000000000000000 + f724e6422f7b27fcb8f589d2c1303a57c1a029486a5049a9 + 04ba1444c6b13adef4ca56bfd9723f32813dd2e96f7fd03f; + 0000000000000000000000000000000000000020000000000000000000000000 + 3fa0e90f02790b3a69e7c89a13d6237f2673e06ee8350c6c + 68709de5c53ea86e2ddf950a5f9accf42013439e1528ffc2; + 0000000000000000000000000000000000000040000000000000000000000000 + dd0a534025a9e27706db2a670c60f0b02dfc511b1b96bfd3 + 195469451086eeeec709c9906f70dbb4b1f69bafbf3764b0; + 0000000000000000000000000000000000000080000000000000000000000000 + a4da0b9a38fef97bc79f467b2f3377e146dc3b15803892d8 + 1a60ea09b20c6f489204d8118b122c5867833c7ef3bfae13; + 0000000000000000000000000000000000000000010000000000000000000000 + 4ce7a4c772c8f9ef1e4fd4702305e22a16658796d594c785 + 2bc89b262839d2e7c5a4d6c6d54d2c12c3b6f393f74911c5; + 0000000000000000000000000000000000000000020000000000000000000000 + f8bbca32a6f4757c7f11f4135ab07d44abcf888c01104279 + 92f67af3b9e25a74c087616ff87b74940ef2e13bdee48a8f; + 0000000000000000000000000000000000000000040000000000000000000000 + d7a63b5010a345f136e5410666d62c0d0db6c72a14cb0e40 + 480a96adbe7e4e18fb726976e153421b959e118d53db9782; + 0000000000000000000000000000000000000000080000000000000000000000 + 1e73ce2be743ce28821a6f9fa91746ec106e6027ee10813d + 4c295b3a21cc9e8fcc591dde212cfd4813bc12add97b6c5d; + 0000000000000000000000000000000000000000100000000000000000000000 + 3eaf2b1202ae5b92708c0ebac3f190c3716ef8c42f7e3eb1 + 5cd7adf3e81c0d0362b0b2d6ff1ba5a8c2bd1adae8e3750d; + 0000000000000000000000000000000000000000200000000000000000000000 + 5fe4c2d04550aed6b268726c60e2a3bdaee377ce8dded8f0 + 3c1c3483e260bec348c8e0efde742b41d16f75054171b1ca; + 0000000000000000000000000000000000000000400000000000000000000000 + 4571854265e30e3b8f55932f432def3e8c817608c600871f + 290bbe7940b15a6f592caf95508152e4016adb9a5ad04a90; + 0000000000000000000000000000000000000000800000000000000000000000 + a1955f1a9e1c293f46422688b749ddaedac0de5392039212 + 2eadf68986a238b85ab9576d1fe2fb8dc0c166f574ba2019; + 0000000000000000000000000000000000000000000100000000000000000000 + c0382ec488cb6cd0ab2ed8079e57229ca27219138da9ca68 + ed3ebf43bc1b7b5f4ee91e71d07b2cb4eb3f661cfc31b8ab; + 0000000000000000000000000000000000000000000200000000000000000000 + 22eeabdba671f4cfe635b615c4cb4f759263bd01ee087152 + 8d38f4ef0fd7b17469f70779e40c45a58b862d81bcfbe619; + 0000000000000000000000000000000000000000000400000000000000000000 + 10da653a6533ea959ac42304fee9983a673ff5fa6e5fe9c3 + 9f253744a1337662c662f359128b5446ea5d9f24c0bd9ec1; + 0000000000000000000000000000000000000000000800000000000000000000 + ab7f47fcb791cfe0d6fe82904f63653e747b8930bed679d4 + 862e7a3bd1cad80aeeec6510428e173529e4fd5b1385b8f7; + 0000000000000000000000000000000000000000001000000000000000000000 + 2fcd824a19c499683a7c43edd5f5e930d5ada53282ab92b5 + ba1f9df708477b5e0ffafa8e17af2c78b45ea8dc9f960ce0; + 0000000000000000000000000000000000000000002000000000000000000000 + 8ac9cec56baa8ac099a09910199e1bd22b8a12b35b9825ad + 1ab5db73d52b33050688969f6048d74c1f39e1a019481850; + 0000000000000000000000000000000000000000004000000000000000000000 + a2970217cd733f9e3a2fba569b5c69549b1d85fa0762065e + ae252ce23450578857e504ec52b91a452a44ee6e284e2fd2; + 0000000000000000000000000000000000000000008000000000000000000000 + f13b417168c5175dc741d3abff665b90323806d25a7ffd1c + c95a2a90eec8869f2d9c3274fc5c23ada2d19576ff61ee70; + 0000000000000000000000000000000000000000000001000000000000000000 + 5fe138aee8e0a7ae229395928700fa9a37f51ae1ce8a7d9e + 16bc8db3599524e304c3b1315c953e244bf106019952f465; + 0000000000000000000000000000000000000000000002000000000000000000 + 072a6b141853fcd7c03087fb051ca86c2999e287a19acc06 + 6e39c731cafc7ab8cc4302937a6eb2f48d5b69f59a8ab6c9; + 0000000000000000000000000000000000000000000004000000000000000000 + 6e61abf961c86ab5d8ff5fdc86fd254077c50b20831af694 + db7d8555b0499464c07e8046d2424702977304ea2ed3dfdf; + 0000000000000000000000000000000000000000000008000000000000000000 + c554b1f1bb02a20c71ccc3a5844cbdaab6ac6065f1981773 + 3ab9f2337b4b69e8cc3074bed8ec371642f191e4a504238e; + 0000000000000000000000000000000000000000000010000000000000000000 + 51b3412d7e6cdfa87026451d611b398963ed0f7914be657e + 8b4c78acb1464f76d7217ec4420c84ed8914426b96e995f5; + 0000000000000000000000000000000000000000000020000000000000000000 + 4e2b6793fbcb06050191865e6cd61abdd7f3cb3cfa0a198a + 40587eccc2c8c15bd735fc22c776f16c18c019fb7b4b04d9; + 0000000000000000000000000000000000000000000040000000000000000000 + 9e32130b3039abe1c5e5b26c41e633218e7e17be20463769 + 52e3af3dd33eb613e5022c26a0e97b3a43d983db2dd3d8ed; + 0000000000000000000000000000000000000000000080000000000000000000 + c18d4991afb0f844fe4430eb4ceef9600f0707f526d50cb1 + 60f22bca3934262d0d4d8f8118df4325b2440a2cefec2c8a; + 0000000000000000000000000000000000000000000000010000000000000000 + ba1c2f2d4855d9bffc68849e061cb23af605aad9e1ca459d + 3f9c6666ca2497aba5f22dc6d49efdb97e63b7e05de5f3e6; + 0000000000000000000000000000000000000000000000020000000000000000 + a58dadf4b734ba815d34bb5fc543b46db3b427f2f4d89c3b + b0c10ef8e3a3ff48c57b8f1b60d0b10b5b4f2121167e8d1e; + 0000000000000000000000000000000000000000000000040000000000000000 + 34b7ba1db271bde528765d75773f5956464b714d9c994878 + a0e25defbe4b845460e20fdb066c63a1e4593c63e88b6b8c; + 0000000000000000000000000000000000000000000000080000000000000000 + cf5cc81f0e5924e5c7503f919f137c50a7f59c664a36f278 + 0e3b9fcea7afbbb9c756a53d04c8dc3930bdbbc219b92e0b; + 0000000000000000000000000000000000000000000000100000000000000000 + 809712627c15317a1ff6a5a53a9af3726209d3dc74f281af + 9e4ede48a23fa258a1c7550087bcbf7cbc1a0239b35900cf; + 0000000000000000000000000000000000000000000000200000000000000000 + 6dda715bb1227452f50923799bf245029bee7eb6a6203b41 + 4987a0919df53153f00e23d8eb5cc95b873c0ad9b40f3c46; + 0000000000000000000000000000000000000000000000400000000000000000 + baa6dffbedd6c9bd75b929d444800382a3fd330d43eefb50 + 06f07bfa7811fed5de8eb93a5c2b28ca90558c62e4821ebb; + 0000000000000000000000000000000000000000000000800000000000000000 + 9327fe772c60b53dfc5e11c56bad70b6321acdcd88beec99 + 86f5bbbd94e1ceb8cf9b07fecd13bcba73ae64951c37e637; + 0000000000000000000000000000000000000000000000000100000000000000 + 3395521584ec93e8579797d3a966bd1c2380a66f95982be7 + 4383715ed3d034f970662395f3d1f0c5d14a9cc926c5cd02; + 0000000000000000000000000000000000000000000000000200000000000000 + f9d37ca7294d832210c1e653e441007b56381b1af68ab0fa + e1cd78182664abe5ad64c6188a901ac00e8006ac7176d0fb; + 0000000000000000000000000000000000000000000000000400000000000000 + 25adde24141811ca576c77e10c61b07e9ba9fb023cd8bd9c + e04f17ea502b9ab5b0f1c7ac16affb150df42cccd56152e5; + 0000000000000000000000000000000000000000000000000800000000000000 + 8903e96a3fcb869b6ed8ebd05b41d15eeea0b1b8c175fd1a + aa89b098ff1dad397e3ac31c21cfdcaf1889a704e9ea946a; + 0000000000000000000000000000000000000000000000001000000000000000 + fcbd400b1a05a47c9ea7f1c4e52403a6bdaeae6c2a6048cc + 761b1b18c0637dfd6d55d87a4f113b68af688f81f8d4f5fe; + 0000000000000000000000000000000000000000000000002000000000000000 + 88c39912dd77f2510290e9b32fdff085e167a338862d6766 + 7bcd793c08afc09b27b95aceb0d9616d7fd66335020e55ef; + 0000000000000000000000000000000000000000000000004000000000000000 + 51208b60bc0f91bfe1054342a73ade654872554eed23c450 + 426a4e6f17ae2f29a35133cc6300736b32b5679c8780165e; + 0000000000000000000000000000000000000000000000008000000000000000 + 003625a0bb5f162b18bab7b498553bd1ee67b969a504f533 + ff852ceabb97d9928cbc671b3987a21d0622bf480f9857c9; + 0000000000000000000000000000000000000000000000000001000000000000 + 9a776d5d249c627fd74d868ca2e5f30f9578e7dc3c1b4e49 + 713cf88deca40e521d15324aca994976f1d970ed4f118906; + 0000000000000000000000000000000000000000000000000002000000000000 + 47b7a8e4643e9ba7917144b787496f6e08a7c03e17ae9c6b + 17f02b23ced0669a67d6fd22870f8f60937c956c7aed718b; + 0000000000000000000000000000000000000000000000000004000000000000 + 09702bdb907f135f8ac4564319bb91e0272c5f49f63d6c2c + 04cedb6f979d648ec677348f46b3b6d2e491b3c735791ec2; + 0000000000000000000000000000000000000000000000000008000000000000 + 859421e35f2789869f2bc401e802a7a2e5a3dd671d0dd761 + d4430b200d778d764b57e4abbd9b6f2a0bebd6d4ca76dfcc; + 0000000000000000000000000000000000000000000000000010000000000000 + ce6f45b33b4517f6de34eec218103ab52e2f7c9ee5c3d5a7 + 5aa67eb1b6382cc16467d12322af504d4a7c5c6883fe7551; + 0000000000000000000000000000000000000000000000000020000000000000 + 55e3dca7d6904f0bd898779f77eb57cb670777f8e5840821 + dc0b2bd616b31cc061911a30121130880221b4c3b49942dc; + 0000000000000000000000000000000000000000000000000040000000000000 + 29bcce433a0f89958c85cfe3d4acfcf9d2392c25c75e638d + 5cd8ef967295257dc0fc379f496f484961ee297633e64cec; + 0000000000000000000000000000000000000000000000000080000000000000 + 735d4826ff04c760e49504fae1a49ff1070648d3c7d0170c + 28961576dbd22448001631547726e7cb517df4fa6d9e486d; + 0000000000000000000000000000000000000000000000000000010000000000 + a4522ada107ea62be6bf5b5bf160b4c75e15f6ef0d16595e + b45177640fd710089c014d55a72101fc7f973bf462f6e0e2; + 0000000000000000000000000000000000000000000000000000020000000000 + 42298f9e5660dde82a88fd096bfadb44aa0ce8615f5e2ea1 + c24ccf0957f55d4b9390672e525622b9453092176e5feb6a; + 0000000000000000000000000000000000000000000000000000040000000000 + 371b0a87d047cad422619a1ab8bbf8d2421625c36eb54734 + 154be268071b1b7d6548bf3933ce23e892dd4ef599e3cd7c; + 0000000000000000000000000000000000000000000000000000080000000000 + 1b3a0995a3ea458e99eca6ce81d8d2943d3ce4036f280185 + 5e1eaae31384cca72fe15cb928e7247a289569759c92f347; + 0000000000000000000000000000000000000000000000000000100000000000 + 75bf29ac66c69352ae6cc00493f8e448e3d568327b9cf474 + 543795ab540b32b3248a0d6518e6c3b865eeaebb36e5802b; + 0000000000000000000000000000000000000000000000000000200000000000 + 5a0399a8cb30b225742bc5cdb7b19c2e090bb1e195a66791 + c76ef9568728d4ddd5520ee9876a73ca72123eaf9ed79751; + 0000000000000000000000000000000000000000000000000000400000000000 + d18c12e6527e6e0f607a6babc9848f54082c3bc3bae5828a + dc5d12790a1da64c1976d0b8d6d66d9874f0b887444ec537; + 0000000000000000000000000000000000000000000000000000800000000000 + 870a20d71492d99531323a86994e43af13c7519bd2527e6c + 02d19d7b5cc70a320bdcfdd41f9921ffe0d6742644399c52; + 0000000000000000000000000000000000000000000000000000000100000000 + 54b0a108605642493ce135710d562de7c32889b831abf8f2 + 654df69490c47dd5fff15effb5cb315585ae64cf6d8a69d2; + 0000000000000000000000000000000000000000000000000000000200000000 + a59695a3fa53bc16c5ca7fa67f939076ae5c60fe454556ec + 528c3c4bd121d39056898a0034b596a433c8e70a509274f8; + 0000000000000000000000000000000000000000000000000000000400000000 + b2035a4f13eed6a75ff080223dc8e342de3d213c294c9b2b + 823cf02821214fd46d9a8a8def8920b8fd02043a90915754; + 0000000000000000000000000000000000000000000000000000000800000000 + 7e6009fc5a9a4bcb932fba990f5b27279ddf357a71f4f8fb + a18b1ee4c68c9b9db4b9351c147bdbc901af12d956eef5c5; + 0000000000000000000000000000000000000000000000000000001000000000 + 2ea14149be04b3f717bd70eecd2c263da8bb87513c7a3a35 + 65f1bef465ed26b40bf1ffb916cbf111ce5d5549eb19a401; + 0000000000000000000000000000000000000000000000000000002000000000 + 82560beaf44f02d49699d4288779c46b26e1449b3d347e1f + ad005df53b419cd35042f844834157cad6ff20b9820c58ec; + 0000000000000000000000000000000000000000000000000000004000000000 + 4f16682c365b3b245e2ac0851460e935d293ee25ed63b926 + f155888b05d06adb3b212c988978b509c819ccffce05a3cb; + 0000000000000000000000000000000000000000000000000000008000000000 + 65130d454a144c68a45274fb5a34000e47bda215d7ef794e + 7dc0c4ad2951417bceb94b84224e2392ea24e878db411d70; + 0000000000000000000000000000000000000000000000000000000001000000 + b229d4e287009b3bfaadc07ef82c7dcb23aa3efd3ccad210 + 0d391fe98acba6abb8fed9caadddc59cc933b07eecf98879; + 0000000000000000000000000000000000000000000000000000000002000000 + e997bd8285b6ac3f3f14fbc98e8a6f2d7f310eb250a1d3ea + 374efdbadf8a357324705281c621abd460fa3bd5818898a7; + 0000000000000000000000000000000000000000000000000000000004000000 + e88323084406260258f70be1a98be9f175bd33dba86dc309 + f689401325a73fe8d162b13d808a4027360d85594700776e; + 0000000000000000000000000000000000000000000000000000000008000000 + 5c877129c311d257a8b929cdce288c8c41d29f48c7f09645 + 766bc49677fa50b1a9089308c82f973b16250d8ce85fb972; + 0000000000000000000000000000000000000000000000000000000010000000 + 3847656ab3097dbdb9f850b3eaede060015145dfebe081b0 + c824634dbe6bcc4e3c0e4814267577d0a8e88e6484956e47; + 0000000000000000000000000000000000000000000000000000000020000000 + d6722ced938f45256e6bfac3209d8afc3332bfc4b9728f6e + 510d68ab75eb49f7aa970e4c8d4458f26c76da52b97d9c2f; + 0000000000000000000000000000000000000000000000000000000040000000 + e46d2ddbc9e9cd7668f0345ecb38f4b9d033e6277c770339 + 754eaf9252e18b20b04528133b5513d0b45eb610332bbbee; + 0000000000000000000000000000000000000000000000000000000080000000 + 6b179b4be801c3c22c67820b4a0602da09b36a0b4003e19b + 594fbe016179a0c60e814192aa5acf26b8c7263288e5e6ef; + 0000000000000000000000000000000000000000000000000000000000010000 + d3b5ae53b5bbed9e11806475fb8e892abad4d0df57d37432 + 925c57438355e2ed191f44a62ef5d233e736d533c384b23b; + 0000000000000000000000000000000000000000000000000000000000020000 + 3c69bd1198742f571ba466d75f33e2f8875bca181e7c5060 + 2cbce555cb50bfbc7f03b5cae522dcc9e3a6f652d7f95ee7; + 0000000000000000000000000000000000000000000000000000000000040000 + faf5577aa967ce1b528cb3183d311a4a01fe0bcb8eff52eb + 359c1f635ba4aeea1496961d0acea82f8b287e6c333c631f; + 0000000000000000000000000000000000000000000000000000000000080000 + 17a59ff4260e682c5fd265c4c8cbb1f2394df520878d54e7 + bd62dc2010bb988cd034dc3471b8771c1e83cada3160a162; + 0000000000000000000000000000000000000000000000000000000000100000 + cb77f4cacf18f51a20b2b2a9424df516ca09da86df7e060c + 8f21087d1f761b40dc9fdc48591725f6c3ab8c996da2e69f; + 0000000000000000000000000000000000000000000000000000000000200000 + efbb6a40a6bb6a73f2b00fe2672d9d9c418be6077d05d6d0 + 11556df337561494f1a88048287e274b091fdc8c3248fdaf; + 0000000000000000000000000000000000000000000000000000000000400000 + 482e51026536799a4adde4ed551b5b37bd946806f72a1e84 + 5c83416d574c4d4fa9f844a8bbf2502a2e423e9333ba5c09; + 0000000000000000000000000000000000000000000000000000000000800000 + 3f2aba49c1d122f4fcb3fcaca344b48526426a3a11792420 + bc2446d092a3cb6c47d34d6b8dc6504e71faf9cab27d5af5; + 0000000000000000000000000000000000000000000000000000000000000100 + d64b82bf6776e07d16dad6b610bc5ccd1566a340d5439920 + 9f0ec7057d88a8b9a1d7f37e8ae54ddc286143aded0b727d; + 0000000000000000000000000000000000000000000000000000000000000200 + 10ac120667f6cc8fb3eb5e4fca09393e4d752378c1ff3aff + 84fffb34309cd0f900753a880af05503913925a676ccf8bb; + 0000000000000000000000000000000000000000000000000000000000000400 + 913aba9a2ee4d9cdbfd723b02acd5fdbcecdba6e5ee9fba5 + a6935a6a0f5be5e36a5ddd2489a849723bbf32193b352276; + 0000000000000000000000000000000000000000000000000000000000000800 + 2096ad29e264550d7f50f5225b174de08c4e33407e229ef8 + 322b672ed96a11c24452ab02e5bbfcbd8d2c055dd4ff1502; + 0000000000000000000000000000000000000000000000000000000000001000 + e2fa3c20c1c3697f0fbef257014f4a0851c7a424287f58b6 + 3dcf94cfeeec73127384a8dc89d1de1791c2bffa516848e3; + 0000000000000000000000000000000000000000000000000000000000002000 + 25d94a019001c3a4fd30bd51206497e094942ae9691215ec + c52be65c97df81a1cdf06760d79bdfa04a8a11024535c51a; + 0000000000000000000000000000000000000000000000000000000000004000 + 20acbb4cb8509b255bf293e116b32d01a284c10402387352 + f98ab11ac1e9fd49d644292f7e70d78bc8528c5c85afb7a9; + 0000000000000000000000000000000000000000000000000000000000008000 + b61f153afbed502f9e64d13a25107529e614e39b992d3d22 + f720e227475a727d1e3f9ee9bc7d3ba079ce32d076a2cbd9; + 0000000000000000000000000000000000000000000000000000000000000001 + 1621dca63b7555e070a05b5a265a0ab530a79e71542ed333 + 220384f259384d523e7b0328739f608d976b2498cf77c7cf; + 0000000000000000000000000000000000000000000000000000000000000002 + 35ed02357b26181864f5de07718913a33ed9fab93d845302 + c7f8b065f6bd6d800c8881040c68828189979be2c86abe64; + 0000000000000000000000000000000000000000000000000000000000000004 + e0cbbdcc0724419ab098dc25606c6277160215eb3a166b5b + 106d2fc9c5e5d2f8a7e6ba7db2a4e1927adc2ab6a26d20aa; + 0000000000000000000000000000000000000000000000000000000000000008 + 2879e25e570e536c936c8bcd66bd780047b73d53922933ea + c3cf14d55169ad5281175057db3a614351dd78ca57c9ada1; + 0000000000000000000000000000000000000000000000000000000000000010 + 45ed18e18449285fdf874b675784b18d412e504075c61fcd + bfb1f7d80745dd69a5fd479fe14c449ebd1ff19501c42ccf; + 0000000000000000000000000000000000000000000000000000000000000020 + 3ccc94e3f12a3e2e4321e397300aa6444ec21526098b0eaa + 0ac9c1ae854812f92615b3fc45e65c945f3e1ceb8efd4a9a; + 0000000000000000000000000000000000000000000000000000000000000040 + f300d3a47eb7d9bf3215140c894b4e8888040541424e4c11 + 74587eb6e7f9b2ecf7bcd8f63948ad0417f439f8596ad52e; + 0000000000000000000000000000000000000000000000000000000000000080 + df6e46c2dbf69f357bbe22bf604efca58a7352a18f41a7ad + 1d5fa8d85dc2428dabb69eb4c9cea7180f2fa554eadb9dc4; +} diff --git a/symm/t/rijndael256 b/symm/t/rijndael256 new file mode 100644 index 0000000..9a4b866 --- /dev/null +++ b/symm/t/rijndael256 @@ -0,0 +1,2884 @@ +# Test vectors for Rijndael + +rijndael256 { + 01000000000000000000000000000000 + 0d166d15e764fb6bc005df25b169d93f1cc03580e9dd4a19c4bd7cd32e6ca03b + a8dcbf6ab9a5d693428c82d2de78a4fecd75573d00d25a1cd7723a3897521c4c; + 02000000000000000000000000000000 + ba36af55f2b81650aabe5f1496e0675bf42979ccbe66ce7e9dc42269c8a40378 + 710168005b92abf4e5fc36d9ae0aab11a872720aef853e37d7a929bf4ae023e1; + 04000000000000000000000000000000 + 79c77f01ae4a137b07fcc8be95693b7157b55aa02bfab77bc0ebbf7b383dfd9f + 1b82ae9934d5fd2ee151529c7cf17ee653ad859b80d1ab1a02b31f23e17c1526; + 08000000000000000000000000000000 + ce6c53e5ceb51d313d95c7831966807d25eac9fbadd3802f7bfbff4f9cf2dd51 + 1263853b8b7f61e02cc9568c6e925b79375a1d7212277bbb44e15aa5874842f3; + 10000000000000000000000000000000 + be529de8125596ed7ef7621e6fa1ea17343eb9b3c34181484e09af18dcc8343b + f91c5fd5f8fe1692a9cd403531ee7643ffd91de0a8238e3263f361c22b31bac2; + 20000000000000000000000000000000 + 62bcd58193cc12ed08ce4a5b51d3a679678a1561be6a805e69e1f1b2da45e7c8 + 9d1ee83ac951bece4f9535b1f4d461b99960b0021be3b8d4c8d20521ed3978c6; + 40000000000000000000000000000000 + ababd0ea311aea38cb364d367c27462d7c7c874cd8138dab3d8331d90c483e2a + e360e0bfc704c664550069c9c675304dd24121be987dd76b7e718f8a1aa2277b; + 80000000000000000000000000000000 + 93b811f0e3bf6c0b00d4f8002783ce01c24ac3671dc198805aba8846dfebb288 + 1726d2a0c6d4d7078322b48824071fc4c6226b8a10bdd8d09bd6b90d5cff9812; + 00010000000000000000000000000000 + 8b9328500908af71236b5ed841a9e177fac26c81034dffb99e89753de0aeb4d0 + 1ae78759e134dbeebbea45fe9a0a66174264a1efe55a87569fe1a1568a28544d; + 00020000000000000000000000000000 + c5c7c19175d9ab800bf358d066f0da2e86fd20ee6ba4e5cfec1e8b1932b42466 + 7b0069d82b61439e71a7cc911d3253f71efc8da14244dddaf323283c9c99c123; + 00040000000000000000000000000000 + a5a088b14f876b6291f5a92993540f972012b6e8a0eaf2ab0adaca3b3410c888 + ca33da2e73e8a8f62fb2b6c23f59a54363fff8bb3c806c6c71e1c22b6f90c81e; + 00080000000000000000000000000000 + 9c482dd8e9e514270d153a310d4179166391ccc10ff594133d2b023c307fc951 + 3e0d22a6e0dc4c5952b417ca6edcab1edf6438fece9e4d05a409d0adde7331b3; + 00100000000000000000000000000000 + cbb011e00200dc67a685963f6dd64373b87eee0e1db3c2c3b9f31a290682c7e4 + 4a71ca431d8e66467b67a5dda1c759f4e5a70eb6fa990d8621fc8c107ecc31ed; + 00200000000000000000000000000000 + c134cbc298d7fc2a3df295534c5b51a810999bc66c64ce5810086ac896af12aa + e21d816bd83eb2ccee4c12c0060a07b5a9b1f52639e957db1ba3c94b0d1ef5d9; + 00400000000000000000000000000000 + 00d96bf86467d8eecc800930d9ab0511252f62ddf77a2c6fcf560ec64a99992e + 8f8cb84f6ec8a751a2c52140d1aaccffd75be6f0750c0f4300d8a95be1497d13; + 00800000000000000000000000000000 + dfbc41532baf8d1ee9c00f40cb9dd9c9970949d182a651af9809ef097d9f95b5 + adeaba98648d76d63be914a169821e4b6b816965082a56c64a2600cd0b0ab1b3; + 00000100000000000000000000000000 + 3ec45f406e61c9c862add48b59e2193a9e044d8450dcf06ec9781ea54b25770d + 0cb3cb766c1b3af62594b5beb5f794c537fca3ef3a7aa34c19965d194d616590; + 00000200000000000000000000000000 + 5f63e9e91b5cf923dffa47b0430c9c5741e36bbbf2f7561e5e4522a9dd086f59 + c8d48dfaddd6db42fb88d5e5a774d796ca0ccbd2aea63ed8af958be542577c60; + 00000400000000000000000000000000 + aaa49691c18a878cae6d8ef28cea273d39a85d65ac6656efadba875d4de8dd7e + ab5274393cec473dda0b9b0d150c3119a6c7c7c5f546bbfd48be3fec8e0b5ceb; + 00000800000000000000000000000000 + a7a1884e2e0ff36211f92ececf5d10a026f0d7fca3ec36bb4fdb3dc39c8b0286 + ffdddaf16fce3a8ee9ffaefec4f86d0a12b153b1642147201fa93f0165d95786; + 00001000000000000000000000000000 + ca7d8e1fbc8de0b208ef96a731cde9e71447c7976a7b4b70f6c6670c3683825d + 373578f19f83d5af1ba61e156754fe0b8210d75b3b94e4ea7c94d51f2c6db580; + 00002000000000000000000000000000 + 82e91aea18e826867c8df83eb68d783f70792019c350859c4c6eddc40017aeb9 + 01ebc069581ee246b6f49707ea3d5e0f7b22665c40f111963d2e42f45c937f95; + 00004000000000000000000000000000 + 46acbcffb692d63566c52fd7f0ec13199b07b747c75d5edbf1a3f684b51f634c + 3c1563b0cc61be41ff454b2b1b4f7dd9b102efd860a6e60a245391629963440e; + 00008000000000000000000000000000 + 0ed05e750de5f56965775ce44dec375ab74d16c9537df755ec21402b3a10d0ce + 662e2d66cbc1a9018e142430e5fa0093dc5aa33d99e225944fc651d0234424de; + 00000001000000000000000000000000 + bba5a7e1d984cb9c1c37f664632649363524e1e2206ece1d998fcc2706545d7b + 889def781d00c866e878bec6965ff82def729be52611d0b805ebdc97541a63a9; + 00000002000000000000000000000000 + 99da531198516629a6c5625c483bd08ad864b54914efd29982737f6572076b55 + 40ea49fa08ecaf017df5e73f9ecca8c24bfddd40327add7407badeb51d551f21; + 00000004000000000000000000000000 + 9c7e2c74e8a14ef12e6a8106608bc3e70206ebd402457cca671e6804ad55648f + 5eef85026cd49329caa947624c88c91e27f817f8d01768b98d121a69d9cade76; + 00000008000000000000000000000000 + 53e1750bc3bf2cfd3ee05caff29cd98c56cb32ffb75548c8b3482a266b4a1067 + 6236cf6d9974e50472854642a529c86ef62599e4172e3bf5d12909721a6e606d; + 00000010000000000000000000000000 + 2cf3f5109eab2d3c501f70b3ae1fd8c744f1c1dfa41f34921f55a3547c76110f + 6b9f52bd5d1ab2d483a614f590f571b1f086aa63bfd0c197c02d514d03a7f695; + 00000020000000000000000000000000 + 81e041228896707809dec23dc43f023ad3a8b741fb097158de5abdd9e8e63e2a + bd80f493cba17cbfd79870c1fd0f7052ebcb07d19f3b7101e6ee9a64691b0e33; + 00000040000000000000000000000000 + df020d98627cda7f93bdda5f2544b46530b645ab1c619583a8d34ece8f0402e2 + d56f8c7d45ced4bd015c413b5076cd494ebf0ee3c6564b1c8980b6db9f8ef18d; + 00000080000000000000000000000000 + 3f2a2e2d05337597567e45ffff3644d1b78d446e54113961a282c63693137ddf + ed749629bc2a4d3a97a678bc810913458dc7f06d181e6c2ce232b01da705cc59; + 00000000010000000000000000000000 + 7276b5b02da780407cbe4a9feb17230e308d01d37c2d50b2f357d2c25342736e + da1d5b5238aa6516f1bc3982e6a22d18a404645edd961251d8242fbc639ef442; + 00000000020000000000000000000000 + 94df6723a4b7e8a3c548a794ae9dd2d44c2596e6a2b313f4caee48b2dab60d0c + 9b760a577ba48b855d2787253507b5405745ada1060c99ce476c3cd5863015b6; + 00000000040000000000000000000000 + b0942965db151da90df6354e57d78c3b0e6c31e624c610dc018d3e1411c13239 + 5c37701aa5d1d0b1681ec86eafbb59f8acca725816ec73edc7ff34a68b1414a1; + 00000000080000000000000000000000 + 4193eb057627735cfa1e3a6b1ff107898c1df42499bdbdb50999808a4443c616 + 2048e754d9481745d95a3e6b4d54cd7b3ca5c09fcc27f22a6bb3b411e4213ac9; + 00000000100000000000000000000000 + 6496cb3d2a6d1927a86aeb9a81838b7782554d67dd17da1eb55d86e680f18a67 + bf66014d7eb0b274ca931b913b1a792f9b303b6cb1581914f7d12ad92cfdfdb9; + 00000000200000000000000000000000 + 5f2e0aad9d2b66428bd14e92e04ba45c1b2c4d8a3626af7e14ba88ed30a939b0 + 53359f5e143fc6c5ed119106f09ed6020c07a840f37c881a19fbb664a2932912; + 00000000400000000000000000000000 + b7ac23c7ea16038b23ff99fd8471a66173c72992009d67c136ce635b6c9d9a0f + 9c1a45cf93c6c3eaa67f56c6fb0004ff9182d4c76cebb113a297a6786bc3a7e8; + 00000000800000000000000000000000 + 6af8fbcd1498dbaf169b3c6cbf99c0d954f0a6074a391b50ceb179a25b76a4d8 + 4f6042a77083581ff33c731111d3040fb551a9139bedf5266b83e0bdf5f4e9f8; + 00000000000100000000000000000000 + 66af8d706d38d51808409619ee4672ad39c45025094bff004dcab2d29057ae9f + 5866f66669833af9565097ab80f6b7ab00acc862e71767cf94e7c59dc0645ec4; + 00000000000200000000000000000000 + 6839cd0cbbd72732d67074d3573594cc7db1285aff8e8c2fbb8eac3d0e22b3f7 + d5df2fc8ccd2699e5af63b16538339487a94145dc1ed775fbb852b368106dc15; + 00000000000400000000000000000000 + 4a2afabea926caf55464e6508976960589b0681c0f0c42f6dabde37b3f2c2d7b + 8b17b2bdb951c39d359b5ffbfe5fd62fc5cf948652429c43b3a580a044fc2202; + 00000000000800000000000000000000 + 75ae68f8e02256da8395c00d1a79a398914aab74c1aeb6a1fd49ffa1e25115b5 + 182317ac645d381058cfb6582eed55afd1c41a01c1ae6984f475c1c9829b51fc; + 00000000001000000000000000000000 + 371cda9a5c73b8faf952ce65d226947fb69d22412669709a3759279e3b652b30 + 3d4b5768c554b31a48a8f2493aba5267e7ae2825a224e7fe296dfb2cd18826f4; + 00000000002000000000000000000000 + ee23c425adef80ebdde63fe7a6191d8065d719c3d24fc8939956225a3e4d9e57 + 67aa7cca219754c484451c80e76329984eacb8a664bd122ee7c81133f0448bb5; + 00000000004000000000000000000000 + 781a2bfdcf0f59ff6feb06131eaadec6b3f86febd94e875be5b88262d9a61e61 + 90e87594d441c52f3b940079b3144b16efbb7da652f85ded012e72df45c5f947; + 00000000008000000000000000000000 + 619835ea64b097c90af092514b6fdd58a5773f4492148463c98a2422e6d29ed8 + 94cff55bfec62839a98e2099bf70024bfa3f36ee382d79273da4cffd2af262c3; + 00000000000001000000000000000000 + 089af763aad8339e9a9019899dac708f9edd78d984d42105b218191e4547ef1b + 8f5400c80a1a6944e1494e72823013571bc53a7a0da4ca876a34aa3fc923e431; + 00000000000002000000000000000000 + e8da39299778df8feabfc548421775fc8ec1d473bc24397281c1b494fe35bd97 + ba3a2f4ad75c1a36d8ce2488d80d9a7c37886f0f25cefa6f906c1d3c97028c9c; + 00000000000004000000000000000000 + 1b6dea579c09a10ff8296c9d2fb29ffaef89169a901f48a1de8d1867e71bed1d + 306fc026f4f82433051bc469f6b4dbab3840332f6069a91df2cd5f8fa71779d5; + 00000000000008000000000000000000 + 84ccdeb939ed5ac41671c7c60404991c4411b5ece49d01401a10a3b906381777 + 5ac3702f5a3b7d54d5cd6f60fb5ba7f4eef23aac98c068f706042c91f7b9c8dc; + 00000000000010000000000000000000 + f05402b141f7578d2e7190d607ed24c60d169c798c36dbf510f57c106b4796a3 + d7853ee992f541e06ec1bfae4e0ce59cd02ec65130dd2c5b25164325ff72a89f; + 00000000000020000000000000000000 + c225cd7a41b66da52a753fd620c04655e1f5028857f5004617228d0a79677ccc + 44534e3a429b02d1280c784bc3d43d3f3f7d68a5c1e4bec773bba7fede5b539e; + 00000000000040000000000000000000 + 5b02c15dfeacdac4a847dbde35f251aaffc17704bf8727a5ad53f84d0315a405 + b9520766f0f67abb9e3a879239650cc41d90716560d83f6c2115e62c67ff9bd4; + 00000000000080000000000000000000 + 397b5b0ad0d8540d90b96a293e9e3ebffbb2ab2272c93f5c854a1316cc45fa00 + effc84efef486e591669f535d5cef87b0cbb224b7e33e0068b4d058a8a81b4d0; + 00000000000000010000000000000000 + 1e8942d564866774f20a8abe42694994b281278037f373b5c867115bfc8500ad + 052566319e8cfe1627f10d5ec55ec4eb50cd1b8e82c7bc9859f7b1ede1d2822f; + 00000000000000020000000000000000 + b71ca147cb496c3c65099a87e63026aa51d044ce55145adb861f1d473c1d856b + d08a2b0bc7ad08d1ff0a4b7f5c285ea9df8b7583536dd58f8d184f9c7a657909; + 00000000000000040000000000000000 + c048a83a291148835727a9792e7864550e71812eed389d97c8bace4246ea75dd + 0af26c6f1f02650ab2532756ae34d59d8580310cc4c3c26f147ff1197a6e09eb; + 00000000000000080000000000000000 + 4d425145fd1166ade64ccfd5e52734ebbdc31ad4512f74e4a7e5e3e0d24dc18d + 35855dfc6ae18052f682b171895f775aa94c293dee1512635f1ed5216fb96558; + 00000000000000100000000000000000 + 9ea4fddb10565fbcd92c352fc81fea49a755a3b64e98ace666f81f42678c33ee + e8e17030571a18fb74a91d93c8d2907a5befb7f0695770d203965b25984c9238; + 00000000000000200000000000000000 + 48059d5828c995e546f8bc6579a167c9ce53d6fde10cf3b7d923be137093aba3 + 4bb16948d4126f77882f10aa89876c55b80b390fd516eef2fb1db6c1527b28c8; + 00000000000000400000000000000000 + d3a5ff5dc944cd7944103104173b40aab097ffd6973f7cde14a001c522818872 + 247d0b74d7149225a6c05f832fd51e221730ee857b34671a4b9509cb2e2bd4da; + 00000000000000800000000000000000 + 2883cdec39ade0aefa06f3d046ceefb87df0dbaa79e978af5828c429d4fcdcfe + 7ad775fd0742338854dd747b5381637ca5260c90e3954774cb4a2ae8c5a0b92d; + 00000000000000000100000000000000 + 8d09a89b9bd6428d8461d17682b84cec190cd76a230fbaad63179ae678106aa1 + 11762fa2295143bccbb767f201dc866258bc600c7ba012fbe8caa8fcbf493790; + 00000000000000000200000000000000 + e57182f9cfe9d9d189e3d679c02e5102fbc6b7fa449357739bc7ad2c7b479214 + 2203765631ddd429485e18f78dfde1b869195f81d8366f352faf8d48dac3a7ad; + 00000000000000000400000000000000 + 29e7e527c65204a7a21ca5db7b9a4d9e3341a1af894ec0773de2f3dae3d3143e + b87c10b138e84a56de01841ed2f73b15d192500e89337e964025ebf6f6387297; + 00000000000000000800000000000000 + b6a6752bc5bee6d41ccc022092cc46b27145fe2902091c054363cfb472d48b81 + 43352f812f48951dc628216466304c09d1f03b19d807eef29a3f720378777241; + 00000000000000001000000000000000 + 278b6c69b23d755bda9eb003a50fe7a928a38d7c9b85eb71692c79d7e0f0800b + dcf964dfdd2ced07b2aa36622f1fd8b7d222d02f9acdf1c1acfbdff9a0199b59; + 00000000000000002000000000000000 + cc50d65a6a9184a5f14102010cb4600393da166d264a605150b1c0718f1e04a8 + c22ee130cb19ece6ba705757d6a416abb709c691898293d31eb66a72ebf81549; + 00000000000000004000000000000000 + c0ce6ea99eeb4674828fcd37fb65e7c2af9ea924a19d121a7f940a026fd2dc40 + 315be95dd9b189d192c5c9333a145d8897af5ad256ff8026fdde53f841b99756; + 00000000000000008000000000000000 + f5fc52f270dc27f07ad2780891d9995c914f8931dc45f6a1fe423fa5fcfd4a1a + f3d2d39afaae2eb6bb9cfc255ca09ed8c46152e75d13f6e2e9f818a94b9a729d; + 00000000000000000001000000000000 + c5e467ab0c5dadbacba076637d3ef4a54d1f086612b970b78f562980324e2d31 + 9f1e48b2dbd80ab69f76fc5e827653dbaef521afb5d6949351ebbc31f82c0a65; + 00000000000000000002000000000000 + 34abac049584a4d1e29bdb7c08ff7ca43dea973e6bbf196ff470d43712610a9d + 676e22e0c042aab946ee5d009cac02b91c104bf324526c39e6b3a8ce57734ff6; + 00000000000000000004000000000000 + 701c6d175096e7e8ad4187c1b592cf81db897a54fddbb542152c7d50b3f1b81a + 77119d05608366998aa3b08e473f4bfaf9e694bc15c15f73e8f33b3fadffbea9; + 00000000000000000008000000000000 + 4e98b3ace7c111c1e81f6f2b407a934877a1c08fd0dfa9eb80698d985d68fe23 + 83c58c3066f0c4feff1d4d5a098afd3521e30fd8a0ee221a80671ab1c17f40b5; + 00000000000000000010000000000000 + e1b4125ee35b0e69f1aac9556596147bc526647375781e1926732976a77f7550 + a341567706ab2a2cb79adcbccd39c81eea1e36e1e0eb8f118a9fbc502eeaf105; + 00000000000000000020000000000000 + e479c9546ebfad858cb2353808aaf1a51b1473f229f81e13e1b5dc7cc7fef349 + 572915a2eeb3dba77a3596075313d43709e01baff1e591bcbaa209703d3a0bff; + 00000000000000000040000000000000 + 6ca46d724403120fa8517f40a36eaa1759653b2d91cc9107c2328602d04ace40 + 4785180fd5f43b9941ba27ef0ef72eefddc77c9dd6ad7ea0f11211b8b55e3025; + 00000000000000000080000000000000 + 32b9348cbb3eebcafdb4716b69b73b0677e1e5e3e6e68758615809fd06a15368 + 22d90cef816242b9dcc7fb7fa644eaf9643da10bb1136cf6788178aac1e532a9; + 00000000000000000000010000000000 + c3ed54670a25cba194830476ffb2f5d765d5dcf476235a0e7df9f405a8679771 + caaf44da13d9a6a68c162810196a8de1facb747efee5d73d0916da3c4828382e; + 00000000000000000000020000000000 + 7e20b32d7ff48cd1be4108dcee7c9e61c99d3d23a79c770a3aa10853e04b0dd2 + 75779c17a8ef0d15cb1eb48decdf3d8c3823eea7c8e75b8b2393b898c4c0ca6e; + 00000000000000000000040000000000 + 43adf9131d705d4a66e300af90ce15d82574e71ca62988ccf4cd03a460518889 + fdbc8f6097b19e5ce90411f88acd3002d27270de234d79d8808b950f65e3921c; + 00000000000000000000080000000000 + 93f2c1b9a55a325d39e769b23da246865f66e15f25dd6f84f44e58ecdadd2091 + 06db50bf315c02892d1bbb304b63ad876b8123cb87a9d1c4b1681abac4a6230d; + 00000000000000000000100000000000 + 39bcb5eb623be3e37858c37e7ee77a56f7983b4ae246658264b760e77242437e + ce60286ff551c33f6a96510bbd33632721db632291c54543b641b0de5d0045a6; + 00000000000000000000200000000000 + b1e70576e01c1f029dd9b309670bc41161bb13888b1c93c6f8a0fd2f5a6e7fc3 + 45e345d2b2610909dc837aaaf07d58117189369c8e3bfc5b718457083a61346a; + 00000000000000000000400000000000 + dc8af5dde236c0d2a18ad310a21abab9549a54c4b3f16d6e3433578f35f04322 + 94580e73b2ecb615c73fced8aa1b14180068b8a1aebd3b677e1d37c21df4abc0; + 00000000000000000000800000000000 + 53823c917b2dade044551689d7f703fa83f31237af4f4687016c4ec13f435993 + 1bef0d32e4ee66c805f793553852ec7b803b300c5434215cceabd276fedea323; + 00000000000000000000000100000000 + 2c5d0e5a610cc3dafc0ea2340d8340667a7870ffeaa2b88056ce23c93131f9cc + 5e73c45a4318ac800e3459af74eb3fa7a2010b3bbd53c9bcd51613fc63cc79b2; + 00000000000000000000000200000000 + 118d26d3c0856588f39d2f654eff64ded5e93fd1900e85abbec0a2c25cfce7d0 + 20d1d578de49459eb928acf39f46dc28089dd3972e57818e0a49f46c6d0576d2; + 00000000000000000000000400000000 + c1253993f9b3f51578f16f5766161b3ff425cf569432121dad3eb9623b9ebcf7 + 9acbaa6aa62d50751f95583545dc3b83c235e18a2b868f4d866e86417c75a22a; + 00000000000000000000000800000000 + 538012f59baf81597c561b999827d7e177542fda70c9b8a20180042cf49f0511 + 088a9449af39cc0b2a88863fa939f31c8730e696ae260a286e8e5f725167e725; + 00000000000000000000001000000000 + 8e058aa747ad629433aef87fa710053792c9ecfd6f04f749aaf97bfe280707ae + 70add57b59bd76f07688c0d9753dc6576301471052885ca8bfce36a8ae17a7dc; + 00000000000000000000002000000000 + 54eea8fd10d61d8b8edd62f26c4bfc47a1b444210c1550c7860cf558de3f3e02 + d22c759d1cf0da43c9ad0cc3ab34fd4c0d24dd4f0a12050af976705422abae39; + 00000000000000000000004000000000 + b117f239922fa9d89f9a0d77d212f54a82c20b14d2031892a1215ab70dac40b6 + e9f9ec1886337f55d43ed990227687c796aaf978af708ca6ed2308e4b706a2a5; + 00000000000000000000008000000000 + bd17e0f86d1043e1f48b5e3bd2267bb9d1834d4c710207deb618b9786610c0e2 + e251c120f7141aa0942b275c26e487212849330a798f392229a2b4909b97e9de; + 00000000000000000000000001000000 + 62a328c617554b9382aac406ecaa84370fc28c0b600711ea2ec5d132231913d6 + 568c846b732c9ec98cf437fe67a223a7e7b63d42b20e57fe95572a2fc6cbda10; + 00000000000000000000000002000000 + 41242d5ab9cdf29b78ad952fe5a967918df393d64613df7145adc5f540ac163c + 87b5af373d78b9edc963cfa1f2b88a55143fe2996403cf6b12ba4d2a4de0dd95; + 00000000000000000000000004000000 + 8d075e35e0cb14e23310bb213e59c416d35bcdfa548b7e4a45ef159c10635532 + 57392072b104f59f65043656c14ddaf32ac366f0cdbedffa7c5482be297da5b3; + 00000000000000000000000008000000 + 01a45d81b5100e5d8971525bf21993c8d18d637b17d91b5d704c54cf081ddc60 + 73790c7237a1eecf35349452f60d4c934dec2a3f42f4bcc4939e63245bb97882; + 00000000000000000000000010000000 + 09843cdeef62a0420a74674575790d67934f88dcb8492a6f15aff243c8e15e4f + dc36416b1f0a13a0270816309d20507c6479f735acb3b35c0e5700c5349d07f0; + 00000000000000000000000020000000 + 31612d05a352c54e516e379767c096a79a1c4234bd17d4f46c73205980561b8f + 9370ac5d3c467aa1f55b94fdf7b396c2f2c425d65e49a225d4a12354d586e2d9; + 00000000000000000000000040000000 + ca61064d6edd95e3aebb9ad2ebf54d515272ecf033e146c7501a240aefb1f026 + 68c498a69f4546f60242658595a81dbb0eff031e29bffb9263411f8d346e6836; + 00000000000000000000000080000000 + f126d3c9eadd62db15cd371ba858acad93d9c0905c3e956566dbd1e5fbe4e43b + 0dc0eb6ca4d30b01f19db8d9484cbc92af194cb9cc5e698af8f9bee1a08a2f19; + 00000000000000000000000000010000 + 1f4b3e99d260d36d735f79f453108bd7ebf8746af1f39348adc65d59af6a29a1 + 8a50046878a62f10557d8e94bfeeb1a26ba39a9a5a76881ca056deb54082db16; + 00000000000000000000000000020000 + b4f573c9327db5e44aa95583f188849edd8454c6f31eb18765de7142ff91420a + 74890b23d53da33244da9f908d4812d27677a294c61e3d29d7dd495f394201a4; + 00000000000000000000000000040000 + e52d19603539f17a03ea93ca700b9eeb5a9d23de423d4631787c1572dec40780 + b97b5d286cdefb8d83cf18e6c1912adc34522bb6488e7abce2cbf743851743de; + 00000000000000000000000000080000 + 3abdcaa1600a946271ca2ba7fe9c7290b5f90adc1978e0cd5348747b118cbecb + f740e693758e1e5626bbd773a0a42a967a540498f250312d862579f7da3b534c; + 00000000000000000000000000100000 + 77411d75f740551a003ecd086d4563c881714a79d053f1d99120dd742d002fe3 + 8cb92110e3a28d7c42852b6e1e16f31c08693879ee68c8eee020ed9466904b82; + 00000000000000000000000000200000 + 09338341baf259f56644c919461974c3b7c81e3347d983545a993239bf051f62 + 1697fb4786570b99034fa0bbec3111b1d2765ad4f21492721b797ac485844630; + 00000000000000000000000000400000 + 728b0b2d9086928d19bbd761bbd18ce018114f9a357fc719416629be99d569ee + bfb243eb7dba6ceb8fcbfa948b91d438a9ac80c960adaea75af7de45fc3cd519; + 00000000000000000000000000800000 + 213be2a825b5694f131d20465a490f8805cce1b471ade0fef8ae05d473d888c3 + fe381bc82b11191ae1ba5e0e526bc64eef8a69052805c532ddfdf7a68f26c6cc; + 00000000000000000000000000000100 + 0918a9151b01813bbb43772707ed48e88464966f41581a23d1422e936b6e5dae + 65b87265aeefe0e04cdf2917a51f7c46b96b95645d4b4f8ddc40fe9de229e1e0; + 00000000000000000000000000000200 + d684c064f8ff906797e3c1046bd1dd19f1defa5a33292947081c35cb8c2dc0fe + 0e4fc41d8e7761c4e75c62da50b762820e396c794ec02386f96ab6ae4f1bdee5; + 00000000000000000000000000000400 + 568310b144f484cb6468d0140ed4d3ad6da518960f79660c7ac827f065f8f9bc + ac82171949984f7dd3d23417b98cee5ba45cf9e67bc2682c134ed58828f29ef3; + 00000000000000000000000000000800 + 3478b762b87196cf1f12e19dbbfa8b9f7ae89c5ba32ade4b9e292f40bed5daac + f455d1be4bd6c9d8f2ba12ee2506ec58774f51c61c434fd29bd307703909f9fc; + 00000000000000000000000000001000 + 61b4393bc414920b4cd28f1b62bd7d14ce09750ad2d5fa055d7264808bb49021 + 3c6b3f7410e47215bcf5649ec69aa2aea42593d18ef388f60ad8c1a74a159aae; + 00000000000000000000000000002000 + 76ce612f9d8530ea654509986ba4a0645df0d0b80e10e2b12e6a4cb702f95c2a + c0d96527fe806580b6be5d69156b82dc48bbd4b12d4990993d40cafac328f24f; + 00000000000000000000000000004000 + 72d9661f54335be3bf33f58b0691ec93c9a609c17f0fa2dfbec2447eb34e767b + e93447fc36f2f9d37e2cb768c89db3516d2101efe05d0c3b22223a1ccda827e3; + 00000000000000000000000000008000 + 8e021165e98627b217339085ae839f83eac9175aff22755ad7f74ebaa20fc5b6 + 5d2972b74ff22287c8d6e4e970bba73ef9fee1e4fef6ab2b99d89266369d5069; + 00000000000000000000000000000001 + dc73ffab02254f4b2284ffd856e2919e87fc0b9527d57b9e3bf61a31d03b81dd + 635008b2f0fa61c84f18d7a35a7a7348a962f913d1c9b2b4a5254d571da005a7; + 00000000000000000000000000000002 + 4afecb963e1c36d3136cc4f4daf50e6bff15f54267917b3351678e4600523aa6 + 7fa9d1013537692d705c5182b9091c05966dca86d0028e14189116c19f000260; + 00000000000000000000000000000004 + 9f4b44c46e94743c924e4d8cc858d6283e60143cc0874a1937306a75052fe73b + b6024707af59bbbb0615bac2ca2a33da7b06f1073959f2c40c3959bfe97393b5; + 00000000000000000000000000000008 + 63876e05b127c60c29841b6ca86ebd18fef4dda37a6a3406e043b26bef1c3e22 + a14ec552b38c9dc86fcd937f6e9693728fb6a2fb7d3d58171cc0ea566917ff0a; + 00000000000000000000000000000010 + 9edb39dd3c860b44b0b9c8c3ad0409c4d5d46ab9da835790caa0dee5fc52f638 + 500c304547307d1fe152c11064fec74c57ce41f6aab2b169c2f16f6d08fe64c7; + 00000000000000000000000000000020 + d8a17909a21e577f2e328d71016f71de512b713fea91321410a115be5acdf642 + 41f6f55e0f5f58366cf9545cd5468e2d4959ea3e68dfe86ab05bffff37e9b7c5; + 00000000000000000000000000000040 + e6b771c2479f884e6b02273538b9c801699b85cf9becab29c5fd6a0cadabe4cd + 73ab7c6f4490bdc9db345fd394569b6ecb8a645e0d3d96f6b04ed878f24c399e; + 00000000000000000000000000000080 + 0f2643a424943fb1911fd77fbda4bddec8e2c7e0fef23aeed6229717f6fe08cb + cc23471cfdb0baa7a388ad9117c1f18762ef40c169b31ea08d045cb79499f78c; + 0100000000000000000000000000000000000000 + 8070a4f0b3cb8b5c98a481a434bcd1f9fbe57a6bd2234f65d3b13837669d0123 + ff5afd2824da440e1db01ece9ffffdf0f385dde8d53e1d2bcc105cc6ef9da6e7; + 0200000000000000000000000000000000000000 + d6eb96497103e048ac9c11cb94a715d02eeadf278cbeab8fad0cb6a0ec5b0cbc + bbe61f08d13b874806e69dd218276e5063e7f1f751f5925db4589e4c3da1e297; + 0400000000000000000000000000000000000000 + 59d339d55b08d800ac4ca97c8d86a5e7c1aaee0c7e65ffa266927b3405d60e98 + 96f4751d5ef02128272f745f849b156b1ae4e9b0644a5067fce133d27c60d732; + 0800000000000000000000000000000000000000 + de5325a11316c25fe1b91e65f79d3c6a22b828c4964f23fc45e633f15a87d595 + 079c540a230618dfe713e1829b8c7e93b0e158daecbc960bebadb82320efa77b; + 1000000000000000000000000000000000000000 + 596f017382966b3627b1f25542af544e84ba96d8fd3a8aeb70144ebf31542388 + 59c9bcd67749151c8298766fb67942b6f7eae3cf18a4360fdb712cd5e75bdd7e; + 2000000000000000000000000000000000000000 + b7949a04ac3f445ce916cb9e09a05f9806ca7f0566c08f8f0dcceb97c46d1b95 + f7f160bb58a6190f3c070f2cac35b8ee30849382870b34b705e4f7dd308fa403; + 4000000000000000000000000000000000000000 + 3c881dd73e0144100351026376ce0a6a1941f10c03fa89ff2428d8826cbf1903 + 7aefa4b489a42ac86c105d410f5979fcae26792159419768cfd6aa1fc80a6f34; + 8000000000000000000000000000000000000000 + b32024da4d4bf274e91d9bc3fe46dc22e69c8b4a63d64c7b25e670f7c03c8bfa + 8e14c8584620b3d9782e828cacf93af391de629ef9c5befe7da320ad6f9f8b36; + 0001000000000000000000000000000000000000 + 0f4214c4d1bee959bc8c28d62cce6dad19939f6f860d23c635bbe5f384f12cff + 6008e0537b75cd2014da4133cd7712759fa1643be44533e1b2a03dc54e2290b2; + 0002000000000000000000000000000000000000 + 3ec7603e6690a95b44d45c6fde7fc3a78aa7b6eed2bfb895edb615a46867a7d1 + f8fa68c2908dd06a866a2c4fa3badee7c599a096346716ab31a7561db7788e25; + 0004000000000000000000000000000000000000 + 52dfd065752448ecb5ec6b0d6cf8fb9f8e8a49e2102e8ff7c37d5b3dde9c0a28 + b1f3f4bf235dff66f32faa679ebfd5b325611ba7d3f8fc51d9913e12f14de3f5; + 0008000000000000000000000000000000000000 + 3687e56d4ddb4747cc5bd9d87d788741762c70d9788726b5cf55212994138b9c + 81515cb2c8263971f764fb31fea9bf985b8407f30fe10c58ba520806832e6e73; + 0010000000000000000000000000000000000000 + d3b22949ce07d1f3d987af325246b02d4ee0e7a25ac7ba10d9fc3b92733fb076 + 448dccbba85ba4427e57bf048c2edccb826188767fa6223cce97709c3f3bf0bd; + 0020000000000000000000000000000000000000 + d6d1af9d789c6e91d1843d9ca3a45a0b7acbe96a94653bed6745d3c664d372ac + c32c33ab9df34036b5d18dff8fe15e57b3b290b0b734417035e68bb6661f2d17; + 0040000000000000000000000000000000000000 + bd8dc5a89393dfe78f81b85ba045b2d7a2035e38bb21f44b3ce1b15c617da6f2 + d0a5f64dfa590de17e3fd7b9fde24de1418221879c0465ff2e9b8528d3cd4c1c; + 0080000000000000000000000000000000000000 + 6e53761d95b891678bfa2f193b92d41b83e8c20532f35558be5038e0e85a0e8b + ca8bf1a499c9993cd56e17e5db838f99ee6e29d0f4ba6b0d684f543b71d7a489; + 0000010000000000000000000000000000000000 + 43ed0aca7101f8fb1495a03ced519942c69f4504f2be3509ab35c0be0de4cc2f + b4536eea97929db21b08fe4ea78d3069f286234e2e287a3097480538bac74b62; + 0000020000000000000000000000000000000000 + da9389cf54ee87ca918aa30b99a37f50f67e2ee8d27f15cacb4f74fbb1455844 + 28dca73c0a5b6500370aa766fd03b596ef1ad7cc27843ea83c846a258c595024; + 0000040000000000000000000000000000000000 + 61a6288bad6f3a91a68752814a0c8acefc56b94b4c45b282d3ae3ef6029e0490 + 8b8433d94c9e6b4df405d6d3214889231efb191e1d3aec05081f982f32054841; + 0000080000000000000000000000000000000000 + d7141bfb37d834afa650bb1d7839b34d1ae0ddd517864ca48b310b53dba1a47c + f68a00c3126b04a87d6a9ff061fc5c8a2d0e66ac263094fd3f081c14412c4a73; + 0000100000000000000000000000000000000000 + 8ed10898964b362405b3996a4a6ba087330190e6bca03990e3218a33411783f5 + baab2232f4ca0ed0f54fdb2b0f73f8433c9af741034117f9f5d2cd10615941c4; + 0000200000000000000000000000000000000000 + 89d7ef42eab86d3209b67353e76da8d8063c91447f916f91378a627a49a0e459 + 2a517f1fdd3019a3d026d9f3a47545ee96634ac8e13b1064a57f82218628039d; + 0000400000000000000000000000000000000000 + 009ac31bd1a5117e0368fdc254230a92cfbadd5984fedfe684b3ad18d0489f41 + a5d26e2813bc41a4e9c40af519b72ac6b2a2188c8b89c77a410b6fc732c41581; + 0000800000000000000000000000000000000000 + 1270970a59191c419b2de4003db3467cf453ad79ee93ccd5ec06da794a0174a3 + 99e4e43c3199b6f493fa633303ec08942b6991188b987900ff3b39699f7b6485; + 0000000100000000000000000000000000000000 + ef02c43eac97a89b7f0ffd491a031dead11231530abaf2ac6b2ade53e2f742be + 8a74dc87527389474c1399ac4b7f4c47522d8b93df856c96c129456e5bcfa0d8; + 0000000200000000000000000000000000000000 + 66efd72c1ad170588847c1ac5f1e957e38e4e40eb891bb75093ee03d19339141 + 8a822f512118c172bf832680ccb9e0e867e04ee2022db6a27d98ed56ea9069a0; + 0000000400000000000000000000000000000000 + cdd36ee6c5cf010b1b093b8f5e0d91d742af7a32b6e98f9ba412c1d523687e5b + 92f8d1fa8d6eda70f7c404088b519cbcd3f31a755b74a7c4474ae4eca952c7ce; + 0000000800000000000000000000000000000000 + 99576731bb509c8f2789eca8269cb7d200e7e7c487a59586e7ca065c6947c844 + c4041960f5ffca9c75a7d27f5865fab9f2c8c536ad6408d191470f2e0d6ce33d; + 0000001000000000000000000000000000000000 + a49eced3ac57b8733ac330b477469b8d0d127edbb76c8b928ef8f3f6e7a844ad + c048e5899e9eaac8ef454098a4bb1a48e0cf58a06d4f1f19f490452e43c23888; + 0000002000000000000000000000000000000000 + 6372e04bdbf3f8d4998cf16dcb310a17d4257042c2ab5f31ce7d75a7c4477ce5 + e6eb8f3eb48465f368a434ea0e66a5d1bd4a8bcb3cc665a48f9e20d6c15e2d8d; + 0000004000000000000000000000000000000000 + aa3bf81795afc567b3860441ba542fadbe778b837d89972e419d9dea5f886cbf + 2fe69f415c844ef3ead9e86620844dfdc9af44c0133e5655130fd53e59b9052a; + 0000008000000000000000000000000000000000 + 8a5c212066e91da99ccd0a8ae0fa1c7f232ff503fdf33d84a6311d421c8a6e32 + a2d43b8ed9c582f1ec1b7867b74c81c17450698fb8c2e2333e4a7fb9986180aa; + 0000000001000000000000000000000000000000 + e65a5b5f8bf7395960e4150e682c586156617280b5dfa259310491ebbe5bffa5 + 473a1e953ea38940e3d84df3ba7b6fefbb7bdf7302a9a9d959d088aa56fc439f; + 0000000002000000000000000000000000000000 + 215237bc89cf72610eb50cc2f788fb66f5dcf5a36b11148d25f87d3fda60432e + e1e465d5d23f00aac475c9021a5dabd753c292e6e0670d8db8e5e2519476c3df; + 0000000004000000000000000000000000000000 + 521741c91ad5fde0abe8ddca960ca3535041fdb1e6446194e63d1930e7c96be3 + 32611c8c38cc3a0df330bdfc4ad7366287ab2c22dedd6a852e63eea38e84192f; + 0000000008000000000000000000000000000000 + dd7eb22684ae6346df02da61fabe51ff32fe48e5c2f276976054c7fb400ca640 + 8702b65a7d1b61b5843dfe394cead041a481f9ddb368187b60291730d7132b7f; + 0000000010000000000000000000000000000000 + 5fd0b1e839354deea2b44c7811c94c81a8153e6bbfed98d4e744b02fc965bb5f + 3c6bec05f5cdb092483cecb0f7996d3aecbdb8f7d738bbfcae9d25a210d3b94e; + 0000000020000000000000000000000000000000 + 39c6626868026b6a15c5ccfa2f83dda7018b6f2f576de8cdf009d84008fc726e + b7e8ff789bee4bdab1fc6c75c73d83dc3cbc1d60c232f54c4dd946470b7f0b8b; + 0000000040000000000000000000000000000000 + c945f53f19eed324dd2035a90014bfeee3c46216f26e7b74978dbeca03765dc7 + 38b825729109c791dc588f392f448085ae8da62feae27adb5d667b7006fb1edd; + 0000000080000000000000000000000000000000 + ce0d4ce7c9a8c7ccd6ea6e5d433c4d7db4663542a7d1c90dd431e552045f5155 + c50ca8e102497116dbb78c0bfeb0e39939b5aa59bb7cac8f127ff9f693f7b124; + 0000000000010000000000000000000000000000 + dd675ec3415137b62955dc917d348109c45c85de9c60095f94539dc9cbfde9e6 + f26014ef5bebf40dab8052592070a3a2f0eb6fac1b0627a8cad7c8fd19511e41; + 0000000000020000000000000000000000000000 + cc5398fb1486ee124e32221736c765e88006f8e0f31f65e337f0703241497896 + e8527d10755dc5ed2512898102fa37a952e12d5a9cf99ca663c4f8aa556107ae; + 0000000000040000000000000000000000000000 + ba7a51cbdfcb2b3b9bf200cd0a5c7998c5753f861ca0d2591c7df18319b0780a + 6a5aa39bd5e4856eff8ce57422623aeb5c5fc7099c6d59e0b8d1f47040f833bc; + 0000000000080000000000000000000000000000 + f8b7f1b3006cfe461b183397ff4ca13eaaf8c34528f48eac5514614eef979d2b + c276a602c32cb0a9f15d45a70f606272179ff0b13e804fc3290d14cea182d555; + 0000000000100000000000000000000000000000 + 8ba47e063938c6cadd65fc3db823e83edde887175d6103417f2648a86ecfa38f + f2b45766823ad20d89b12b1eb65ea10ac1f4ca042408f775e82c3a86c7d870ca; + 0000000000200000000000000000000000000000 + 82f0a8825caedbaef6991dd7cc33d8a22757b4b65186bbb70dd274486bfdc6e9 + e98621489d27a3f8ffafa5f60c454f5b43073fa13b7b1e44cf5b42c1f410b757; + 0000000000400000000000000000000000000000 + c748b58d58bd39b77224713354f8abe888a55813cedbd581c811edb61f6ea33e + 0341ef9ecee1633e77d1d8152dbc4b536cf1d5106e279f99bdefc7f65b002dd1; + 0000000000800000000000000000000000000000 + cb1703a29bfa0d5f8e074f8c8efad1c3f99c3c9d56270a3b0b223d792414a6a5 + 153618a5aa9ce0a5640c395dbd5c65fc78ec091d9268083bf1a8ea6309572237; + 0000000000000100000000000000000000000000 + da0eb94b57b73ce632f0e096e8b9657a8df2a7602ff80f33bd23621b3a9011bc + 84946c36ac9e6ee65c9f39aeada388f91304420de373b45eb9899941e2059bd9; + 0000000000000200000000000000000000000000 + 28593a296d86d90b64ccf70ad60d0806c194a49477369151d8d1b1f534a73ccc + f4a5b4c8f1d7a01e23b7695421e91f864044ca51b3d6e946eda4dccc66bbde88; + 0000000000000400000000000000000000000000 + 5432743ae99f48de5c2c943b81b4c994e7af4a9df102302bce61e51da7b7b1f0 + cabeb087d68155a0ebfd81f81ea7a0451347e8bf2b409e4d3db752de191edaa6; + 0000000000000800000000000000000000000000 + c68b1f8b2e568b015ae4684c81d28e1dc4f2bf15ea8637043589555e59fea56c + 3c7c59a6b7446857459e8c2812f318c99d6f2eb8afdc8f7cf3fe79b9e43ebe6f; + 0000000000001000000000000000000000000000 + 1e2ce4d6fd55f7b624b05e5ceea3915ec6f061229fc5897fb5ccbd2041477968 + eb6ff717f26c66672b5c99bb95c0604d812a70360e361cfc1ed6f67226f2f738; + 0000000000002000000000000000000000000000 + 882b04a32f0ae1ee1c03856d4997bf168482eb9e3c66db15caa3a5ff61f92663 + a28f92837893ca7cdaeb5afb82ec7808d6c0aa734a81c4f9e8c207211fc00dd3; + 0000000000004000000000000000000000000000 + 0e6d2c813dbcf23cd711ecda6066bb9d03a9babe2f6471d683494b58c0788d44 + 4c601b1e752c45492e42f54e5eb528bd884a242a96bb8a638d9b92201ebb3707; + 0000000000008000000000000000000000000000 + 6e697fe8636b48bea38357c377f999c717fa7ab055a124b20868098aec8def00 + cabcf9f62a30e5a27df4064af20a3d6f0db35f915f556fc9c349f41575f97247; + 0000000000000001000000000000000000000000 + 9bb65307fb501877e3ada81442cde498d1e05d7cb5deaf88ff1f0b6db92da4a1 + c7972bfb8c66bee89a3cae24999a2671a661bb5e3591f811749725c31e95daeb; + 0000000000000002000000000000000000000000 + 4b1c3460a94891e4f8708feda342f8c13de4f500ecf890c23b54614f759c351f + 3dccf6aafd9acc0a52003729bc92cf541c72f1175408aef6754c07308f3186f9; + 0000000000000004000000000000000000000000 + 237f3b1b70bebf261fadf4fbc61f4aed6b2f7d41fd0bc3b8701ec87f0ace3b73 + 9b575ace6a7d3614985498611990b61cc6fede975d36c08b48f083a2eda498b2; + 0000000000000008000000000000000000000000 + 55819dc855dc272f8e813f473d0be9f7b0ee777581c68236fd55ba7cfd7fad54 + 01e96efb1cf82aef7bb041c59e16696a196fd263376d478d12d5c21f8b76bf38; + 0000000000000010000000000000000000000000 + 46a9e2ece5c6a61677e9fa44e91c15ce095e6c2af0e66e3daaca8be8f55bc072 + 9d1d1717693d05487a24e6c0824c07ad87c0490e6a29de6332e5aa0130311fa8; + 0000000000000020000000000000000000000000 + 9163353b13ab53a5f0cb758072b96891fb46d429da59ef58cda3ba1a9a2162e0 + 2a939e32e660b6cbd4ec22903b3eb454acabe834e59ce753bbb566bda8e5745d; + 0000000000000040000000000000000000000000 + 53653c0563d023d51c758273c7ffff07897ed19015f2b352543711805f25d2a2 + 638a9f6d0768463b2716ca71fa1c3ef0a758cc2f47e0d3c3afcb50202f251ee3; + 0000000000000080000000000000000000000000 + 7b1d6650b48a58d529d174d40c34ece0c4725893508723c9e110306f12d2769a + 09a5fc3739cd6e79e94e250eceef8a31bdb30ecb4f4f47e18f9a3645e82e2642; + 0000000000000000010000000000000000000000 + 92fcbceb6fba200a50f039637b8afda2c5d4a06efdc98e6094a986d0eeee92ef + 08250f4cc12c732a3b1a82411ec4a8604bf119f69b07072961758780c7db87e4; + 0000000000000000020000000000000000000000 + 82af5330a7aa9696a6be8129342b9b1bbace0b879ca107b5184c0902793efa49 + c286bf6ab754af7f16244b9de2566e9442e13919b2d699d62f52d384362f6331; + 0000000000000000040000000000000000000000 + 93e0bf62136720977660e0eabd4694514371b3b54a27027dccdfbff5aac51f34 + 29955264c6c52f5fc3c5475f4f6d478f1b17618585097b9fdeae091bdb9e8446; + 0000000000000000080000000000000000000000 + 69563766cc3b858a015e0655cc056ac5356ac37f3561495fab6a012ea62276b1 + 41bda0a8164a083e3caac42fb15d94247181034d2ade38a1b4399eaaac07cbd5; + 0000000000000000100000000000000000000000 + ef0523a9b2ca36ad2b3b9bd9c2209a1ab8c8dd205e48140d577de7ac0fae02f6 + 5f3f8b6b15d822ff9d852c701294d5c1bc2e5e20c4da9e56dc2ae6f1ab33c084; + 0000000000000000200000000000000000000000 + 0df666c1b2d781312887e6d30f21f12e6e2d4dfc2bdc0b5484f85d35c091a453 + 87a7fe3652e203d98ec75f3c61afbd47f8fe2f50505860a093a7aee292366d10; + 0000000000000000400000000000000000000000 + 99d1b163bd4fdd4bed820ddd6f4b5b8fa0f1590a97117956570a1a0fa075c473 + 24e6a698f9880e19447971c1de0d598472d66df54ccb88624369af5339e4627d; + 0000000000000000800000000000000000000000 + 8a76142c207334f1482a7b748f48fd583e34ecc52c33ca6938a10afe9fdabc43 + 8311c7ba99465892df7554b6c06740333d4f4e79496b6bff747d87bb3f88f780; + 0000000000000000000100000000000000000000 + 1db97ea24610af47d6b4a43c2ef0b031a81547d98723e46aaec6d8b4e29c2d8e + ead758aa4b4ce689d61f7705ebdaff4334bb882e8286fd6655398a8f5013449f; + 0000000000000000000200000000000000000000 + 38f0302fc696e3e644a4c58400b050275c75dd77880b7c81b48bc49f5eec4566 + fbf97ae99430d0582c8818945aafaa9d08516a56150d96842c67a69aeb6f79db; + 0000000000000000000400000000000000000000 + e10afdea821dcc504167b562bb1abacebf03a183a29a85593f51aa83463ccf42 + 1a60ae0e1289cb5477717f4bc7fb936b91d2018a7121f29db751b5ab9c739657; + 0000000000000000000800000000000000000000 + f8178e6e47dd9e38fa46d139e9da92320ccc56580ca6790e6739d98a16cbff2b + 4d5274c530a947a0475c0581f946897e2b4f9e01cfd5e9edd5f00109724d63ef; + 0000000000000000001000000000000000000000 + 057dad112fab7e5e2f13bfe3692d29cf7231169ba5456837384e1d3178d44399 + 493491ac15958b53294afddbcbdeeacb34f1862c38f0f8514b3190d494611dea; + 0000000000000000002000000000000000000000 + 32783556b2a205849744b683e3c1cb67a4546671d51adb868f2abc741d277ddf + 8b7ed6253816d59663a99df68a9c4437ac9ad45c2d400097e69c1492f5a26ef1; + 0000000000000000004000000000000000000000 + 192b1eceb03afbee8bce727185baf599c1e281b6819b219f7c604646362ef507 + 21c826646e076e934f521cdb6933b547e1f58a1005eb492d768a8abf545f99eb; + 0000000000000000008000000000000000000000 + 151ac1d0c9497bf7905ac32c3bee78042c1cf57d144b33563c0d524197e1684f + 532ae17f1858e56b4fc1c3442a3eb5aceb9c38dbf6c8373740d2c70ace135610; + 0000000000000000000001000000000000000000 + 43d263d71480616fc8d3ee5f26a7b4322f64c52e2eb08bf45da98a501379d42f + 10915428d4d72172524b0af0a985b857b11fb208305fc96bcb0bc5da329e5a4e; + 0000000000000000000002000000000000000000 + b93915219589225d93000fcb969ae487a545f909fc74b6eefae8ead8697f4a94 + 2071b90c399dacf0251cd331d008b40d75c5fef91e76c2319ab297226cfbb751; + 0000000000000000000004000000000000000000 + 63304c37894c70bb5d871c7cebd6a03e5e63f4e1d0ce0149c287f148d2b43bce + 5d7fcfed1eb5cc9052d66c073e9817db944323b90f2e60871781078aeb23cc33; + 0000000000000000000008000000000000000000 + 56f9602f84bb4c0c7d7cbcf427a401fa8c063edead092d93a27ecedbbc080238 + 683821a05f317992c6ed3dcc523d147872ee872552fd4d9935e72cb6880c8ffd; + 0000000000000000000010000000000000000000 + a36adff7f8c3aafad248f0c875e959212b533e09747a95c89b6443487b426be8 + 2028682f6b9482f668e55b06144ce444d4bfffdbdb119b2552bb2ceccfdbad5c; + 0000000000000000000020000000000000000000 + 76131f29b957f35e6b776ea6a737199b00f945ecfd146443de23d1c68434209d + 1f40950024d089bc682ee4b0fb5fbe079f988058993f3d3ff928cf087cb99dbc; + 0000000000000000000040000000000000000000 + 6589aac4967d58ae26372b64a7fe4741ed93ad4bf7fbe61f147c0bb21056d95b + 5bcc6be06b77e64e4f04ab552a0035c664be7c6ebb2a781e7156cce573e2856e; + 0000000000000000000080000000000000000000 + c6ad32c723a34b02cfab4f5f9d5b6f14d2a27655620fff9650c5f496271594e2 + 64dcacef6699660227dad31c50c1752711dfd4df95efd2918391371cbdb19f6b; + 0000000000000000000000010000000000000000 + 637460f7bd663081a501baf9fbd8f910d32b74f95532c73d2931cc1c70b6f61c + 6611acee8bd7dc914cb5b2310aa37c44041d2d16d2c6f66493d7d0364ea0d137; + 0000000000000000000000020000000000000000 + 2498e35499439986614f26286ced257b12145afa582093f2df311a6eb768a3ad + 552f96f75bc0d3c7995970c9785cec08d1e6a848906604d7ca1410caa09110b8; + 0000000000000000000000040000000000000000 + 08d3d5cfaacdfd78f5890e84ebffa55f6a30b332d09aa99f9a39c57b1a6e64c5 + bdb53e5e22c6dfa1a7ee078c6dde02f999d36a8d2bbb4bd6d8d63344b50d7f19; + 0000000000000000000000080000000000000000 + 6cfe9b516cf7e08a58d825e13c4602c1c878297b993fcfe48398e8d6db759940 + 38f793f71c6896b2ae6bd730a548210cbd9345ba211180de67385a6be2aad623; + 0000000000000000000000100000000000000000 + eeb6ee8db37ba7df8caa911e25dc2fa0077b3931780d2ce06d4a15e89a2c859c + f4755374b79e4a32021ef5a228d8eda5e7aafebd43f4c6bad599e957e3b1adf2; + 0000000000000000000000200000000000000000 + 6ba41750ef7da69feb66952b1ed18b75e20086c0bab3481d8211a686f317166d + 278cdb6ba1b4a9b624564a5a76a713887abdeca0ece63a6f0aeca268d8ada97c; + 0000000000000000000000400000000000000000 + 872c1762ef5842c8c9f7117ead43024f8ad0734be8d1dfb48b2be8fae98cd374 + 7cf31344e19d4886a0b36cc6b4777658216be3a32048e89dda78470379c0c653; + 0000000000000000000000800000000000000000 + 5263be92980bc943839a9024fb1140864999ff02fe7ddaaa35d3d89f9f345c13 + 9a9012f7b455a4b8c50d5917fb5969723b70ab3e0cf18cfd5a1b841aa6c0e1ff; + 0000000000000000000000000100000000000000 + 451146802e160f788555b58164ff946820a782bce9ae691a2969fcb250b66773 + 1f85560430ebcb39c18ad9bb8dc49c0b1e1d730bf8cb43121a8c94a62daf56a4; + 0000000000000000000000000200000000000000 + 83a737dc4f27d59528e688c55a52e4c44d518dbbccbf81bde212b87e9c63bd53 + 9fb8cee4a538fe0add8823986f50ee648c36504c1ef9054b748cc437ff31d25e; + 0000000000000000000000000400000000000000 + 83154c350ea26c88f23c2585c4c1ce85f7febba6ccec68b960f2bd2ae6284c15 + 9243e796bbe38ca38d0d517116510236b81b5e84d662a059c9834cd57eb2408a; + 0000000000000000000000000800000000000000 + 78f73dc4ddcd6357d1cb4fd1e61d2456cc37d84babbf5a6e70f9609ff9527602 + e0f9f54c77861caefe4ba8ea6a870a5831cdb61ff0658ae74177562676c049b4; + 0000000000000000000000001000000000000000 + 24203a6fcd8ea87e057f38fa775d88c1caaafcd57982d97ed5fa6b99a2814e10 + 7d327425d003904c745509c265bd70ace892a7ad23496f335386af2b3fd8a2c8; + 0000000000000000000000002000000000000000 + 832c6e20ac336d8d215c1b618870c33857ff4e616df40dba963cc422f9cbd3b4 + ad1f44b624941028a116896f053305978f382b85ae3b24330fbbb328fc835cd7; + 0000000000000000000000004000000000000000 + b68daadcf692eb67c1a69e854424f45a3cc07fb7c042563ce5db29811909fa5d + 4e62699870105da1c27da11a482a5c79f174881179d3448d9518547b12341eb7; + 0000000000000000000000008000000000000000 + af03141ab732bbae48789b2efd96995ef50977d07a7d9ee741cdc1440904c599 + 8b295745e425a4b798d230f62adf6cf8ed49183098666157987fccddec8f0113; + 0000000000000000000000000001000000000000 + b69d0bbfed16b59a8772777e09c866fb51391d77552a32d8a971678776e97a08 + 1cb999bb1e7e9dd64a64302e09447755ee9c1744139de4cdbd61088bc17fc24c; + 0000000000000000000000000002000000000000 + 5c982237e3d812369a5084f68792b88f33fdb8278bab9c069572c4d2d4e8b1fe + 7a4c0dbbeaae1b31858f8a8e4628b56ef552d738301b4462ffd682af0d26e871; + 0000000000000000000000000004000000000000 + b502c31e76e20b5cced9f96fcf49e786b477dae329aa612edc58c8c4b310c881 + 3dc3b0f31b61c28bf208b35ad68715ae247a8bd3ece8c6d38f4d03281e0eaae2; + 0000000000000000000000000008000000000000 + 1cf7cb0fe06fb987e82a7097abebff97b074e00d32ca59e259bb64baf610b932 + a8f685fdb0fd2a5090ccc7d7635431954e6eb4b58ca2110fe691562800725f89; + 0000000000000000000000000010000000000000 + 0fec5eeeffe04cab0fff3d6cae817db15a4151fe22a6e3ccccdb2e56b36c3ad9 + 7df075f7326a189ce1f5ed3b8428731f67d743e2bbb3037043aefc55a401b534; + 0000000000000000000000000020000000000000 + 3ea8f911b282f21db8709031e607c193b4604a8b44ec36be34cf0eac039346ae + 1ea420045663890821dd21eff43b2fbb86568519bdef2a13dc2d141c05e36830; + 0000000000000000000000000040000000000000 + 8a84fd4bc516cb8fc163352c8fd600c8f1a07861f052964727d61a91d155e7a6 + 3b8683901243ba7aa8705259365f64ff8daa64604c34bedbf4d655c20ec28b99; + 0000000000000000000000000080000000000000 + de1e1860d637140cbc270026885c391982d0855c7177106b1a38103d3cb5d956 + 21c1f9266ef014b9bb8f9b9fbb884679d1e411f96e1173ece0609fa01cb0b16a; + 0000000000000000000000000000010000000000 + 4e62340d4fe3b25f02522336c45b8f18b5944d41a72e0af43e2c1dbf4c32a504 + 185c48576c96afd58a5209a255a7324f850fc9a3be04080f9a744a5da8ab71c9; + 0000000000000000000000000000020000000000 + 9c44e17c60b2e4a25454659dc72aa415c4701d1c31170d9d403a2f16adc6521a + 092e70d956ecd2c938d1ab9b95588dcbb1fed47a6cbef019cb538c1bce1b20fb; + 0000000000000000000000000000040000000000 + c60d7ec161b0ae0e347bcba7755c40cdf150d67901070ac4698f1d7c593e6d33 + 1892f5f715f53024bf4b04aed4605e34539b21260ead7e00c4fede1b58f3f3f5; + 0000000000000000000000000000080000000000 + 7b4709c2543c6c98e858392f44244e3a4606e5459910badafbca6422762af235 + fa8b0b95b7d3897667c8798b5288bea05b8585264f1067592e70584d45e54468; + 0000000000000000000000000000100000000000 + f6a82f150ce106cd0b67c6251144cd0934623f64a7c0c02cf20f88c5b81b8f9f + d08611f1a55c0fa0022732787866879f6057bcb0d3bd8be4950de988f2703b5b; + 0000000000000000000000000000200000000000 + 036d8796288546f6c8faa0137f542b79232b1f710f00d993bdd209d608b2a983 + 0e4ee8dbde805bd218495fb6e0c012da36af3118fe3abcead1cb9b1d0d9ad7e8; + 0000000000000000000000000000400000000000 + 93bf0d046d56227e10a60b6724d8195732ac7497dafbc5f0415aec8f721feab3 + 508975892533164bd482c18d17b1190de8ac5c603e22dc78dc033dd56d70e498; + 0000000000000000000000000000800000000000 + 92242df9e82635f00fd079b03fb3e4ed2e479076a756daf823ef97e067bc0a9d + e52168fc1c39bcdaecc13f07ad602234f0d6fec3ab60edcc2703b2ebd9a428a8; + 0000000000000000000000000000000100000000 + f20f59b1d2d69ab79957d62fa9a683180b95d772f33205637f3bd211a570c182 + ba077c245b7cb7030d882130b15298bcbf15f4dcdf2df67865687956f2d68f8f; + 0000000000000000000000000000000200000000 + 0c5eb80aa685a53d856cadb59327c84b33379abcc06329cc10af1096ab8e9454 + 8d8ef3a1486b1ba3e3423ee8e188036bd06a73abc506cfdde791de57f35818e0; + 0000000000000000000000000000000400000000 + c1b93bce555e86197fbe389b926c37d918d88bbf3d704496986c0cf3bd959840 + 3a7a664d89b1acdb853c6bba7c7de3322545bf58971c93f2b8c9085d3734e31a; + 0000000000000000000000000000000800000000 + b9ad33f00c7029630ff7db4528327cdccc612b607e63faf35978fd27810f345b + 291fda0e13c6a6aa8354acd6be229759e97a52cfffb3956dc6a1dae438e26565; + 0000000000000000000000000000001000000000 + 3f7e83921a8fda45c6681ceea340a1bed22ef6ed784fa8ec0301cff998bef05a + bba9ed3d86edc3e850c58372960a340aa75046aeb845b53ac521b8b05800ae48; + 0000000000000000000000000000002000000000 + d504cbfa2d69cbf0108df37bd476fc93db12df17eac4a10f52c5d9e8560b7a93 + 81b71096f284866b1423cd41da22f003afacab0911f08c98a23bc508866a2d82; + 0000000000000000000000000000004000000000 + ca5c7b0f2e05939fb7b30358930f2db8461c4a8735971b7d0ecb429ad519e9ab + a7b781dd1aaa84c9ea0fc8977f9ebab91af4910197205e5fdf90568e51106c2c; + 0000000000000000000000000000008000000000 + 96e9e78698c3eb928ac8bf2a6572d1c153f6311d3d250115e502ded03dfc2e74 + e20aabbb2137804b4493fe7b17e3b9331592f8f44ed1903d1d1209b26fbe9a5d; + 0000000000000000000000000000000001000000 + 07334423e99b879202679cc4e3f674a82a731d02ceb5e74cab08c90b6228f0ae + 74458c222e857b9033a9f0453f366f4ad8b4cdae922b8a80e46aacbdd6f647bb; + 0000000000000000000000000000000002000000 + 68c3f9679c7a21ca77da909fe45578928bea63c882d577d08049a05103efcd56 + 3d0ef4fd9b8359f4aeb1031c31508876e8f0ef38f8613bf027823e9aeb005445; + 0000000000000000000000000000000004000000 + be2bf2722cd6eab12cf20d28cbed792662bc26f0b92295e53411267d4c72cebf + 2187e559b2130dae8142fb0757341c0a1e6df31508e6a19aba5ab2cbb0a9c872; + 0000000000000000000000000000000008000000 + cc30e166ad1cf014644af5c3b6c65b45fa594e5e371e404388e8c051e7dfa4a2 + fbd37c904a34800318acec016ed34c12de8d8d1241256d4a96a1ef02d707d53a; + 0000000000000000000000000000000010000000 + c3b8c49a86a432001397415ccc1eea4d77c5e7b1e6b8dc208d69f2865a6b8678 + de5469250f0cc42d2e202f29af0e13b31ae5acc68fd5107819880d3db6e0b8ce; + 0000000000000000000000000000000020000000 + c169eabc1437d7301865ffe544bffe0767cc733500d6a67cef204f6078d58328 + 4c09cd0d212dd836a6e4af52c5fb1ee851f5cb07465e5f592fb8024d1b0c1dc6; + 0000000000000000000000000000000040000000 + 758c11f8fe1f10f109d8df4790de952c900afc7a985c6844195a86c66bb0780c + 6985483375dab29f2c9ddf2e4acfaf9ec9ec0b90d0ff59a51f76901449125973; + 0000000000000000000000000000000080000000 + c818f59d0447e726d2839c82a4c12360f7ff8012d84bbc1a367cdb2299457199 + d1e7b740f3c2549929ba0d3210f259df6ef2322e9ee4d6f317ea4fc8ec4d2998; + 0000000000000000000000000000000000010000 + 3aec597f7d31483f810f14fcddf9be067f56080a048a9e3b4098e6e28918a800 + 7e85288628803f83717499b69f17adcd5a66ad8dac68d0851db8eafcdab3cb08; + 0000000000000000000000000000000000020000 + 0b6e2edb89d22c535a5a68e75ebcb0087ef1f236d2a2266a9d543d6adf24f479 + ac7fee6480f401eb8902005f7b8d512094017f3caacb8249082606c36d98d51e; + 0000000000000000000000000000000000040000 + da610e5a8a7a85ea2b84bbcf3b40098290a15d4ab3bdf91d7e21fa524937c783 + 477e7784dedbaab64f19ea69b8761c66d5da3c5cb51551dff47e3fa0c68fefdb; + 0000000000000000000000000000000000080000 + 0e8f5819b7a66f25281862c132d5f339cfd0fd4ac4f91c14f226ac0033dd1117 + 42352ac10368ccd3b833fec7b048741501711ab1036dc7d159e150055a11586b; + 0000000000000000000000000000000000100000 + f546da839861af04600c9417e0fe884b8c1b6f4a9a9d36c4da7b6ee24ff3c4f3 + c543450e77a3e87a7be1d6233b79b3e42597228f0e08c4f833622194f64afa71; + 0000000000000000000000000000000000200000 + f4dd95284ab89c6c53d7ae177d25aa3739dc721ac0870c2793f3723b6e093363 + 48118b3d2203906c7b319273f372bddae10266d0d8065e636cf0bfd747c7c984; + 0000000000000000000000000000000000400000 + 14094297b5bed9c5d7651a2787c232c9c9089f542b76f39b264c1b591c4f2e18 + 09a61a1aef6ad53d3e2b6e93389a279752f78c62bcf530b7cf0c1f3bd3e3b529; + 0000000000000000000000000000000000800000 + 212101a1952ec6158effde6a7d48a4929304fdeab258257266530262a8ad48f3 + f991e1ad77a2e13b92906767da523e4d057eeaa263794a087a02bb0339972b9a; + 0000000000000000000000000000000000000100 + ec652827a0f5cbec1068ec4193a152e4a80d797867646412d18367645db6df2d + 033741b62e08f79b8d6192c93775508f23100fc3a4f35c3073cb7130a5211abe; + 0000000000000000000000000000000000000200 + 646046dc56a8b7a4186e481ebf943949eccbe7147e0220de8dd05fa656e92dbc + cb5e4fef77193f8256bfc49a91e001a036582e2e3eff8173b27af708b7e8480d; + 0000000000000000000000000000000000000400 + bae05fa0ca832ff9875fb1c886d8ec8eac6b730bd2427b9cfa8696d3ab3cf5b2 + aa4ea07107c3b1cc519fbecddf7c966aab50188cdd0d46bc866b19e882deab36; + 0000000000000000000000000000000000000800 + 1f8b6b9b95efdc182d35f1ec5104489893c70bf1fe7ccaa67ae55ceca5152981 + 100e51e4e6d5a44653b9c51ba6c9f070bea9d470bf1ee0faeee1d05122cdde50; + 0000000000000000000000000000000000001000 + c1703da3b5c222872d09d493d03d07e36e6d04e8901a248ce5fc620c5dafc381 + f282d2b589be28bf64c3f8a454be2101322666b3c7b71369496d630cb5c5fdb3; + 0000000000000000000000000000000000002000 + e76669b223af08035c5deb05e10666ad09a99af191a3ff30bbb7202b65a25033 + 15240875b0e1b9427a28e2123f85f74a1b5924e3600453ee45556bb328e8e941; + 0000000000000000000000000000000000004000 + 511c0362a229d88ba90a523f862d35c0305b08dcf4b9e37bbe2efcb0dea8e6fb + e8eb57458b73a15d4eea4dbfc95dfe99ea52b7f07cb3964d1c0caa83de2fefde; + 0000000000000000000000000000000000008000 + 45d00f70b107ec873736a23b9ec02b78e68c6ffbbda1778e4a96d01d42b20eae + f5d0539741362a0c93861d3c167aebc148a5b34fb3299e600abce538bef5fc5e; + 0000000000000000000000000000000000000001 + 41ef971618e7923106427505bc765943909724f81c8bc9b0de756867d40b444b + 8bb9e4dcab530ed4e491e020b59ceaefdac18d23ed01acde992f20f44dc74004; + 0000000000000000000000000000000000000002 + 2536ff6dd06c356f864fd003738e87a81c5bfb44bb7714838c5d068300abea93 + 291f63a30d86a1aa7347a9483d8cba05eb27375c43adc7fddb0ea9bc50e5a794; + 0000000000000000000000000000000000000004 + 55dbca7e091006fe395367c4250fec2d1b994aacdf8026072d1f3d92fc7475f6 + da7cf09785d9b6792e20dea6dce0fd4e65bf87cf47ac674a83588f3642d6d50a; + 0000000000000000000000000000000000000008 + f662573e1d83a2b58697b4f1923396b7d89c56fbcb21a5a3834232c8c0451f57 + b6f749429a2d9ba1b479cfc96886c679c7431b93a95b87f9187680c1a7b7c792; + 0000000000000000000000000000000000000010 + a398f5779517a7db0f56007407f9cff857fd68803441d31bb6a4752a77dd3495 + 89ccf7cfec665a5dccbdef72ebb60388a3e2a892d6030574bfa92f4e61efe6ba; + 0000000000000000000000000000000000000020 + 58a9c4323b56584a8d5378d2004c1d6f491752ab9f1b750b9745f6b5f4c21cca + acd8d6b0c04002442e0c3c983fe656d5cc54c2782c60d867cf7445cb57feef1d; + 0000000000000000000000000000000000000040 + 98303a1f445013eb3be40cff0d6f4395501b83b825d4897520aacd6a36703962 + 1d92ad624dd448b62117c533e70c0d13ea5b3a66310a979edff479a50b99ea17; + 0000000000000000000000000000000000000080 + 11c40125db6ef51d57e603b8beec27babde3fe9ab63fc52a0cf7f76854c936b3 + b9dc8672196f58cbcc5708f68f510d6f908b8a7cc0df0ff83d3a7c8303e78777; + 010000000000000000000000000000000000000000000000 + f9e96db294715055a91833db0fb33e9c91b54bede26f9a06abdab80a60311e1a + 90b679951b11be0bea2a87a3eb8c22f42bfd07e51f33362a1ac0d7bd959b5191; + 020000000000000000000000000000000000000000000000 + 0c38a41f055332c76457a13f95ba264155c979c9124b5dde77318c49d1f4c01b + 405919405dc48814b279e93f34899237ad9ff2f2aaab9a4d7b04d5572a34c541; + 040000000000000000000000000000000000000000000000 + 1dae71958a2d1f4c332bd9f343abb658590e874b4bb4ab807773e95bb42cf82b + a87bef2e0ce41b11221e01b86192f0eca8c89fe36b119933e832d9b317abe3e4; + 080000000000000000000000000000000000000000000000 + a77d1b5d96eef9626430b7e785c2be959a590145b9a61bcb9fb5044f3b923908 + c9cb7b952ad619267f7a7ba9420f6e3933d66c3a3bd4c4ae3229bc2b462db40a; + 100000000000000000000000000000000000000000000000 + c1eada4d6ace84fc75d62263d98c696e2df8207bd62981d48abd2523dde36862 + db58cc33ea77f996d3d7688c7b6072a5e7d17ab605ecc15437b5bbd4dcdc5b99; + 200000000000000000000000000000000000000000000000 + 8b76cf095a4d226114ce825b21d0548fe181ac262ce014fea4d3a4245abeacb4 + 17584d0428af390a9d0f8c51a493870f7feafea51c183ffd9594fc1e7f41d8a0; + 400000000000000000000000000000000000000000000000 + 386b7fb85d0c186aed83e7c88ace5d6246ec46fcc3ba61b5e92da090a0754071 + 17d13a676e2a474b6ebfb05c4011cdbaeab55275c5f702b2c40c772a76b08339; + 800000000000000000000000000000000000000000000000 + 874247921bb170b486c9e211aaf4f27133550367d8d759894b9e429ebe34908e + ff52d5217ebff26f8f5be14884fc05a9771997a062892f75700ec9d0f4d1173f; + 000100000000000000000000000000000000000000000000 + 399895248799ad09b0e0a870717c7093e959e07b7ebe416cabdcfb57286a4f34 + e3702614230bc36ef9b87cb99d79aa4cdd9e9d18d18ba4ca94f250ebdf04d890; + 000200000000000000000000000000000000000000000000 + 392524e09fc57d2bfa227523fef0bad4155ea55f8a848464b7b7c005f6130579 + 9d595d7b010214a82e295f3440a682601764080288a2bef2fc208f9ed728110d; + 000400000000000000000000000000000000000000000000 + f49c44ceca01eb2d6ca71ae5b9363445261b39be75c75f0c054c1de37d95ed5a + b1de2734994d1d0d8b0ec0057ba4fbfcc1fb6ac30620c327c9161c18ea91e942; + 000800000000000000000000000000000000000000000000 + ff5b158392cdff642112789624b80d177aff782cc1a0ded6ef5a6da5230abbf2 + a844ebaf2b4f0c005d5e0345f7b3268a401181cfca767970bbec2c65e739ee1d; + 001000000000000000000000000000000000000000000000 + eee541e6da8eb4d6ea2d0bfe3eaf5c29df99da4b258190ba5da5da8e8ca97819 + 04e41aaeaa28c8e1c7e113e3cc1734121fc73804d9aa9ca4ffe8ddc896eb723f; + 002000000000000000000000000000000000000000000000 + 89f6a98d1287e78538d98345aeef5ea194a30bdd61d708010f3a3e8abe347774 + 1ccae829fff9e409ddac526fa4b4393fb9b91783d8ec6ff842321b830979e4ef; + 004000000000000000000000000000000000000000000000 + ceeebaa4ef1833984f356d6cbac91c98b032f8179a2f0ebb078b45d361059b6d + 57c5a1d7c45a9cb0cb1ca9832f23d598cb253512372406d791539b5ba788936f; + 008000000000000000000000000000000000000000000000 + 12455456daf8787770ef743ccda298d054122db7520cd1bcfb87d81da2b94aad + 4a849587efe4291325f12ab50cefdf56cfea5e2137851021cabcd8e93230b3c1; + 000001000000000000000000000000000000000000000000 + 07ebcbd8034e24f2af24d3722dc24e897756aafe2f6c7b22174b319dda5753a4 + 85d342b06d631f4975fc5ce6b7c6839cfe3a5d3837a132aa977a631719233573; + 000002000000000000000000000000000000000000000000 + e5c7b3af8f548c6684e5026f317cb0e3a27fe8c0550a5527cc9dac57ce767143 + f215844a8622bac9330dcaa70e0fd34bf732a9556a6f653d798b48f23659a643; + 000004000000000000000000000000000000000000000000 + 348bdff0e8f4b4490b2ae937b1ea6ae55a05301efd0342787184e8b8fe98f561 + 1f71659657bc15ce1c9e3d2a6e7a78fc0c8d337899b9268eb3bfe0b6326c2bc7; + 000008000000000000000000000000000000000000000000 + f72265f6266e5e3d810f5a65540206134d7e6f0b61335b646a5cea952986e5f0 + 1afa3d7fd71b74805878066b66cdbbe1151d64324ab82ffa6541a5e43622bb2b; + 000010000000000000000000000000000000000000000000 + 71fb92a42e7522fc907b549b8e21be2f5e20f926eb1db7e551196c4c6f9fd49a + ed2e6b920912cb498db549b149bd50d7dee9c2065643968fdcf6144e79e60ca5; + 000020000000000000000000000000000000000000000000 + 31d89b14ae2f205e80b1ea8bb265781350078058040cfd6cfa007e590a0d2975 + 8b57df307a928b8f04640d5602a31077f62538d711dedb4b0684a1f20d65ac57; + 000040000000000000000000000000000000000000000000 + ac0fc0e2bfff393b95228ec598d065969643d940bce158b882c4214dea7afece + 34eecde2a39bb9c4714f1f071f152c0058d1eecd56cdbdda05e747b0bc6b807f; + 000080000000000000000000000000000000000000000000 + b8379d824ecdc66d335d64670d4fd20d3d1a2f632c845d9630688ddd5c64a661 + 9332b14faf54b15574702406ec02a7500defaa0de2a53ec1ad906ad8e6158e63; + 000000010000000000000000000000000000000000000000 + 55adce8670eb35789c2b4f3c3f2a3c461b1a88131cb4bde0a54d3f4c886216fe + de33b8f153920f6f4a3fcea1b31618990d933db5a20828b143e5349e85384f0f; + 000000020000000000000000000000000000000000000000 + 0e72d86ce21c254b393a2078c148cc6158d33ebc471e74ea9e7edf7bf936218c + 7d19909092cff079bfa3854e6753967012a66277cb65771cec208e379c671f9c; + 000000040000000000000000000000000000000000000000 + 6c5d6c93ef13bde1eb5f205ab7379e9764aa5cb4bce63fd68bddebf71ac6d750 + 64bc9c9bb728abb28fd2da7f958c16d120269d103e406aa17107a4d7f8d1b4ba; + 000000080000000000000000000000000000000000000000 + 290a101970cb6dacbd175f3ca67860e10cc5ffa6e7829a40df0cc04345744de7 + f0d4fb87d679b178dd0fb39d754e35638266ddd66f61d616419c867c52398c38; + 000000100000000000000000000000000000000000000000 + 2c9c6a93c3c41f66cae82a912625b939203193e4cd0bc67dcc1ab882af0fb2a8 + 00307a8c0c9904b84973bd324a8397c4aa159176f0ba3cf4771f40a652151342; + 000000200000000000000000000000000000000000000000 + 061dd076bec69c3870f387a1d74a5a506e0ae64912b850829113b9db9988e869 + 029977f0d27d81a985781061a05477fb032c7a5b6bea7365510be2ce8e3611fc; + 000000400000000000000000000000000000000000000000 + 99e9d96e330e25d7d4d74a82232a6012c7b0332ac209985fa99a3eb4cdae4285 + 045480ead04b22fd287620db1e4b333d7d191fddca5539cd9ddb1b5ac51ba37d; + 000000800000000000000000000000000000000000000000 + 1b3b4e1eb2ceaded0eb41e2d4ae3169df36d87db3fc7c6c5df7e06c27e68c60a + 4b7087216d8396b8274fddc2fa2c300eac624313e62eb924e09eb6f608895aa4; + 000000000100000000000000000000000000000000000000 + ddbc04456d25f8af3cbd2fdf819256750c07fede724710b370b767ab6f3e777b + 80e07a753961ac4a46dbc1f3c2ac510ee59a4e6c06672e67acdb2f9d393947ea; + 000000000200000000000000000000000000000000000000 + 355e89d48b6ad74e2c253432722b3896ae7296c9e83e76f14e78b0f7e5fc8580 + 5d0307032aa30386ebf5f07b4a05175b4d3f460c95599b9de4a5098d645754bf; + 000000000400000000000000000000000000000000000000 + a692bb60016d3849f8e31b5c1956f809264aa39ee0096120e3c04466b4b72e0c + 0183ff6d49c4bf650117e1ed085ab2b3d2d4614209db86689c98d9b859b3a5a6; + 000000000800000000000000000000000000000000000000 + a1f561c977e24c5da0b75ea3706804b868223245259dcb6350eef44ceda2c248 + 2a4d332bd753a98daa3e3d4cc3fce08319b0aee1b6a710af18f6604e6cacce51; + 000000001000000000000000000000000000000000000000 + d60a120d9cd41286c8a39d0a177c75304383017cf1fcc07cdaaf8a69290e7ea1 + b1c53a187c59bb9490c50a8f10cc3ca1c6a5a3970a059d461318ba7a32b1e8da; + 000000002000000000000000000000000000000000000000 + 57bf964c24d87f4e1bc0c301d912b61ce9244022f0b566ffb0c0f2e6acde4ffa + bfc70c61151cf16bfc039483b8a00f3906a2d151c44b9e684d0195e0794c2862; + 000000004000000000000000000000000000000000000000 + 08af63069dc10fbf50e649321cd8b1ee039b7691fd6399d81e3565edf94b8193 + 54de4c85b5666702354f8ec087cbc0640faaf8e8d6c304ffbc21aa439943cd18; + 000000008000000000000000000000000000000000000000 + a77e3c5155aae9fe9baa0fb81cf9b2b60a70d9adf420844e9f8b01883706550a + 403b00473e00a57ef3822d0bb6d75a99963974ffddacb9d4e5baa9ba47deaf2f; + 000000000001000000000000000000000000000000000000 + a667891d3c97262683fa83a7b781d6f6b987888dcfe9f6b58b4ea8bbfc22eb26 + fca3b57ec70df2d5093ca93b2235be57883e1dc46f11a9eae73e047f1d2c5cfc; + 000000000002000000000000000000000000000000000000 + 1af42c0f7468eb361d4f56f3e5f45f5daeb1c2a25666804d685f1584d5ba30e9 + decc0c6bf3e04078c839acd2a62a4184aa1a1097a630a4e40012e9beaaf26a0d; + 000000000004000000000000000000000000000000000000 + c15c4ae428c067595c5fbcc12bae69ad529b7b114d30274a70a0a51e4f87a7aa + f02e1d8e8fe536918a9e62bf48195e8e45f8daad77718d78f223acbb8b8390d6; + 000000000008000000000000000000000000000000000000 + fe4a31645836d26c668ae9348047765294d707d38587c30e31493e3b9efbd239 + 021cfc4d6d24bff9ed344a57a62b9e9adc0fe0fb8b0d2a4723ef756126fe28c7; + 000000000010000000000000000000000000000000000000 + 2bb1292e04c105a871dcf6a366745441995c46e94ade34d4f7ef353e3732fb12 + 8edc70cc753d1a7499063ca76a49c49ecac4797045b9acef9bf93b363e1baef4; + 000000000020000000000000000000000000000000000000 + af7539c5952da58d8074de796697cbde1a991e0216edaf51ea363734035fc41a + f39beaecd22482bd6e1851c739a1a8de9d11c3d9c11a4cdb45f3bc0010cbe5b3; + 000000000040000000000000000000000000000000000000 + bfaa17172e854602a411f39bfe808176a30726ab4139799c2ae294bfac9066df + edaaf454146e8d399df89babdb13498cf57ec6419d6faa51a8493fe3f55e968a; + 000000000080000000000000000000000000000000000000 + 52280d21e201c397e77d527e62c85c23cc479fc81dfa10e19fb9d1ae84fe582a + c906c9878e2e36ed742c8ad5e39357e0188c0e5a59fa9d6c0cdc5831457deca9; + 000000000000010000000000000000000000000000000000 + ea223c68adf66b076da0eec9f38467139bfc51a4056650c25b1604fc7009b983 + 7ea0c34ab6f734dd80f82709f23a7ea3b3a426b2d2561d839eea4b33114d8e11; + 000000000000020000000000000000000000000000000000 + 9fa09dba1210f7cff3b54575cff0e91706f96ddee75d625dd98b55058c04641b + 707785567fd0c4d6982267bbedee319bb65be7e40cebef299b051edc5ee19674; + 000000000000040000000000000000000000000000000000 + 0462dc1e6dbac8d94b9b3f6f36909ee367cd21fe348a37f8eb149ecf77459c15 + 6f7287e3838fd23a5de96afa60eeb3e3eac80346645cb729849cf06e4574f93f; + 000000000000080000000000000000000000000000000000 + 5bb868af6de2f9814b2d53de8c4eb53597ef6bd7ad1a130b0f006b1e71b6f344 + 3e882386e07775def74428bfbeb380ddde3526cffa40ed4fcc0e98642dc9d29f; + 000000000000100000000000000000000000000000000000 + 2e5ad6aa5701ad5cfb42c92f6e1142cc2e0dd24d57a28430d3c4aba7818a11a0 + bf294d4623f8e6c683b29cbf1ebcf82338210199efdce2485f0c096b40bd3535; + 000000000000200000000000000000000000000000000000 + 6ddac861bd903abb303e8d7faa58939f6949bbcaa60341c2b9e2f32254154e61 + ce0f3955956a0e9b92d0611bb7d400bc782a61d688790a7293821accd4dd3ab8; + 000000000000400000000000000000000000000000000000 + 6c34fb5023d0cbed7e5fe09bca96c261a22706ad118e4f8e813fdf578f6a9222 + 4d53255e814b9e35f5fada8f444266a11450e21fc8cdc11841071cbaa7392b17; + 000000000000800000000000000000000000000000000000 + 1d9e348d053585d72af0d606e2a9792646fb591ec72c39e73895100c538e929f + 6cbdde875e20309dcd32d18fe4c31c98274f10cc88811a14db03b002d1651bad; + 000000000000000100000000000000000000000000000000 + 624c21fc425a9fa178eb5d8346050301d655bdf9e948fa79dd2b659122ae5864 + fd411dad007bc21eb90442ffa404e205a4c6037dfec390ca055c2d1ba0d835fa; + 000000000000000200000000000000000000000000000000 + 05a695c429b54c6ac459fec77cdf33a0e44d5d1f4dc6679fb4d1f3d07b35c984 + ec983376a5c111ea502fb4accc49d7d465f1645b747192969ffdb7ddda5769fe; + 000000000000000400000000000000000000000000000000 + eb0221e48c3562cacc4c31e2dd24cfc04aff04addc4751d747033be31d7ff0b9 + 6d7d733c19b709ff780ea3d71e47faa447fae866c5bf76089abf4c09bf6e7f15; + 000000000000000800000000000000000000000000000000 + 852be3267c18c0a005af19266019311e17ae0a266688398def4fe1a6d0f5ff8e + 6ad20d62c5ca5be801698d6f43654c4e8b895a5bdd7bc1d7d9ea04d876f8bf54; + 000000000000001000000000000000000000000000000000 + 2ad2d89c102216f17a52aee77b8e812d1d0102ab13c65fba559cab28682300fa + 9b95e0998f7112dab5de7f64457634205d654ea4ec4a32076ba30cafb218f801; + 000000000000002000000000000000000000000000000000 + f61d03a67d0209e4986cd503c3a0d6d5314563e11a473d7fbd5fe4d913eccd05 + a3c39a8321366853d78f1ffef9e2df9b09abe5a0d67fa0b0c0b02a653c23a8e1; + 000000000000004000000000000000000000000000000000 + 8053b9bb606dd5f3e6fb5ba949485fb0be1bf2f3be881ef57d8ff653a7a2ad97 + 29c8a343460b0eded72a0f80b0b266899424195a8b3f5662abae0d58286c2517; + 000000000000008000000000000000000000000000000000 + a52ab95b69c30484126546b9151f9fea89b6d479391b097c9f636abe89b123b8 + 1f76b1e1d8e7eb427115a8e7fb239e461f67bacece83e576979623f86badd31f; + 000000000000000001000000000000000000000000000000 + a7ce6c6eac537320138e72f4ed71b57497132c19f58a3a0e864ccfee8f13e243 + f31e719aa7b0aed4e324c1406fb38c7b574706555561fb57ed4fd59565b285a5; + 000000000000000002000000000000000000000000000000 + db419afa205c8ec1b824f9ab843f1bc377062337149291e559600148604b93cf + b54b0859085a9a0581286feaa0d2375f0e73ee1d306803f405021050406f6760; + 000000000000000004000000000000000000000000000000 + c97eb377cd16f86cd7efde7438d678933d5a76cb0cbf4938b00756b42d3986fa + 5535c0c0f43ef9b8b78b532ba60fcdc5dec4428ad62fd36af221378e13b59cd2; + 000000000000000008000000000000000000000000000000 + 9c379451bacebe09fe466301cbd2f15be7637a6d992b7e67ad25efa503e19da2 + e8ed8e2367fda7b029bdcc7fea10bfff2fb9ee44017f63794fa45464e60e906d; + 000000000000000010000000000000000000000000000000 + d806c06a1f28c1a7a03d11529e298069f38713d0113255cd7260fe11dccd2459 + 0a6d37fc381c2cfdea6d2dcd4ee9873da18c46d028fead0861e3c0ed6d4afae4; + 000000000000000020000000000000000000000000000000 + 3e26ea35664eb065ea94e6c8536af313c938b01a4ddb2145c907321084d1effd + 3d7efc858d2c97fc00f2f0edf39d38e5ec673c99de7238f704b809140e3698a9; + 000000000000000040000000000000000000000000000000 + c21ed702582aa1d8259b2c892c6b4a0c55aee1382fb64d4c9ef218a8bd8fc0f2 + b71a4d0e405d55d5001e92bc2cbdb822b65cf12501b8186943fd471568d82b42; + 000000000000000080000000000000000000000000000000 + 0595bf54addfb813ce8cf9a40a072e1eac4022f848bf4a9955617e1fa4a64f0d + a888376775afac427e11eaf788eee2854e2c3dbb03a2116e3f082a24459e79e3; + 000000000000000000010000000000000000000000000000 + f7c300b01efb460b636c7af17379662cd501c7e6a0c7b86315127ba7a20f238d + ad9876d442b0e84db1eb82d3c3f98f768cb4243107d05ce90952f4afb89e3206; + 000000000000000000020000000000000000000000000000 + 7922dbdb167fb4c155e062c0d5aa8b2868b893ca2cae86df02c776871b48a8ac + ae3720bf2f5b7a2fc753e87251e810e3c5d3e0960a4cf6c1985a2a0e7838ce03; + 000000000000000000040000000000000000000000000000 + 8c8a5188f9ea500e7ba44d0c5c5296292b602bea998940826972ac75a55d19fd + 75bacb58ec93ed5ce9c57a4830e0385998c3c92b6284601461e7ccfa234673b5; + 000000000000000000080000000000000000000000000000 + 855b265da2e77cec64a7c96360221ad7c08bc343ffc173ace59cf2c1f94d7248 + 6967ef1cfebbc0ad1f54833c93232d5623abe3f2a34e0a24b9688783c3a9e5a1; + 000000000000000000100000000000000000000000000000 + 81db501d3f871e765776d8d7750860c36ca39a73baea80df76168436e1dc282c + b12600493e0d643ad4c5bce38f4ff6170d582228eb9f4fab66eef8b1e6e60399; + 000000000000000000200000000000000000000000000000 + 69fa38fc792f646a679f2c69f886f1e46d0d98ae7648b7ad51bd3d92ef09e2ab + 2ca758e5230bb97262bf6ca5c4ddd5d3fc8f566561b297bc139cea05cecd517c; + 000000000000000000400000000000000000000000000000 + 07fa8e571b3b715b7adb4a0c1a42a0f5617db1ab04a3ad9d6e3f99dc392643ed + fadeeb6d2032e571c2461e588e7efea5e38b2214ec23fe7b4a7b60c512e8a66a; + 000000000000000000800000000000000000000000000000 + d86ba78cf143fc53aa651f018248c67331e69be66a33b44b3dac4f3f86b293bd + e91b1044bd8bed5ae2cfb269d6fdbd229cc6c5a0cc560acddaff1fcc7dcc939b; + 000000000000000000000100000000000000000000000000 + 4474e5926f15e979554b25ee62ca5895d69ba5f7b7264d52e936a5d7e218b7d1 + da76d56dd52888a891d31d09a2698d6605e279d90ae2f55bdc01775dd816e433; + 000000000000000000000200000000000000000000000000 + 5cf87fb984e1765a31e392dad79752549f6f9537aa800671cdbb0d89cb9ee6f7 + 309de2c3260c2a08340ce164b7cd17ff93d1939f3949fd5dbf46f75c5f13861e; + 000000000000000000000400000000000000000000000000 + fdef588c63309dab2aa804e9d897034fc81b6f1d168cb3f9976eb5a6dfdc52b8 + 83564b42d78039e88afc04e3f34b8863e7f94b4dfcc8c8c22e22f7dd17a9650b; + 000000000000000000000800000000000000000000000000 + dc29b2dc786b940f80371a1b1994e59cc5ea72348f1415dc9b9cb13af8acc81b + 0656387e108812013b668a343044ed99e7239bc1c4e8e2698e8cb7998993b1da; + 000000000000000000001000000000000000000000000000 + 309bd7d5cc9be260f1b43a255989368fa3a0fe7451c982fc7393b6bc6c784f60 + b1327d75358cefb96216f21b4432b1b603ef504186470991c12e21f4d42c609a; + 000000000000000000002000000000000000000000000000 + 2a4899c9dc7dfdccc936fb1308b9b43c8df1eb6537fdd1b5084b44c71905d71a + 50b7d28d9599ec0558f1cdb5bd28b223585b7d7f4e3a11c2f63941d99baf82a9; + 000000000000000000004000000000000000000000000000 + 8413c2819f780bb3a7d51aa0144d74dcc8f66f2db12a5e2dd739df4002355aff + 8a15145629c86c5c699ce2a012ee46dff8d81d86f08c5d9b7580d30558adb269; + 000000000000000000008000000000000000000000000000 + ab65bb89011ff73cd9aab4fc39f31853f3214768a6a0fec7454551dfc1c67648 + c92067f0ed0db296e72556344a39ee1e85f3690e568a47ec635b6a38935699f2; + 000000000000000000000001000000000000000000000000 + 6ef6fcb11ce017ae7067d34547b1e996d045b193281ea44245a348708d896bd7 + 5d85c3700c5cc45a069469a7039f84334f7f068de6b5bb9c76c2af5345eba955; + 000000000000000000000002000000000000000000000000 + a748292aa251b84a1a518074dc24d42c9a491752d2c2c12511b2e6bab39c7157 + 03bf62836deb2ebffe32fcafe5db76b8a6e1ce3f411dcaa429fd14d0c86df3a1; + 000000000000000000000004000000000000000000000000 + 44a8fdd43b3829bfa1290f00d3f796d1a4340d81221c0b1e0428bdc16960558a + 96f6822810f9d3851b97c08616ff80f5f6810486347890cc682d551e34cc6655; + 000000000000000000000008000000000000000000000000 + 44fd0991d1c3e30e50af350e41c0676b016478fd9ec4c9c66b5fbb6fd0c9eab7 + 921055ef1b383f9de45cda31c5ca372ba5ac67918305cc1817dadf8346380644; + 000000000000000000000010000000000000000000000000 + 6535a47b9ff05940f35e68f6830b1edd6c1a3cca3c69008d77cfbc90813f2c70 + 7b3b359c5ea3575d730a4d6c206ae731f59cc538d7e7ea7065c16adad980eae1; + 000000000000000000000020000000000000000000000000 + 9bf44b4910301b9f2e6ef3841a6bee5733b34459acff031c39b9ebca609a9ab7 + dc57249ff0a59f590d2d1ab020e3beba7e95598c75bd0567055285e44de4fc5c; + 000000000000000000000040000000000000000000000000 + dae9a5b164e39be36b1acbbb357d414486098d20de2634d16cb9d04d0b5c5b9e + 0a0877b39f37f8a142fda7618e6c4a06fe02921461264fb7f0a68de184d2af64; + 000000000000000000000080000000000000000000000000 + 5e90bed387aab9681116b7f1e2fdbb47fffffcd40c35856c25ea58b452339129 + 318899c5f84a5ea7de2b391b4cd069ac2f341a820a3ab3241058d21018d5de59; + 000000000000000000000000010000000000000000000000 + e89f195b0e9bb3d7487aa791f436e5757e22ad78a5c525c367476383b88923b7 + 751b55b6122f2ca9459abeb94d4a65188ecb7a02ff43cfe10ad4adf68a9ddac1; + 000000000000000000000000020000000000000000000000 + 0906b6674e6538ea82a33a89a47ffce4fbb489e6c2efdb5d1b99031fd4c5f99a + a75f0ccb1495e7cf617a8aa9ea4ede5a2665ffbda0c4e7328a86395485f0d852; + 000000000000000000000000040000000000000000000000 + 9f58ae0629353e100d7e769c61b53516bb2a0c6b843c3d54dcb8049cc98d1446 + 0298031326cbecc865a64b254af3c187f97c7fc1370c48a67fe137985eba00ad; + 000000000000000000000000080000000000000000000000 + 6e65f3a436d028afa3cf36e14fbb09484c6d60c656d405530da442fc3a95827e + 4d44aa7d331fddc2b173191d70836ac2062093823e88f42418b1b2b624be7d2f; + 000000000000000000000000100000000000000000000000 + 0d84cffdcf30d929475439e5ac19e65414b1a987c17d39ac5fdcd1f88fdbea61 + bb2c7066132af737383955b50aafc2629f62ae9a0906cf063af6950c7d93edb8; + 000000000000000000000000200000000000000000000000 + aa89078f9b49ba132929b8cdc17f0c72f03485a3f30145eae08a37b8077b1e7a + bf3d4ea78a22782aa1978b42b88fc58ab4594bce39dad5b564c9603d9f18bcc5; + 000000000000000000000000400000000000000000000000 + d54d3dfdffaeab5ece06009b61de0b631d2503251e08f5d946439dc3e23c93c5 + eb4e97cd5fb0ade077a1e463b46642785d5df66693ca3cafe4073148d4ecd8d6; + 000000000000000000000000800000000000000000000000 + 2546c7077b11fda1d13fc0a58757bf47408f4fa6801c6240a31b0821d7294bbd + 7d6f42de54cd407eed7ffd603a9cf2e2e03d5bfa3f7a2a1adff261292f5e30a0; + 000000000000000000000000000100000000000000000000 + 2f8eb8d9a3f973e0657700dd113b1fe4a124979e54206ee368c04b5507539ae2 + 65398aa3cc2250c82a47a3812637c270959613211682d1d14fe9f70524e72df1; + 000000000000000000000000000200000000000000000000 + cd7604e207e7e65de5458e56b470deb55562d2fd0f7de38468badb7d30c1107e + 04e11299732ac33fbfafd8b73ea585ad11202a865c4d633c25e690580b527654; + 000000000000000000000000000400000000000000000000 + d0f99bf98c30dcfaac9a4f14693febd6e44eed176f86d7a9b7d0ff38f7ef9b10 + eb250f8278f8602594b53456dab86a4714943910985144ad7e1044877949c9a1; + 000000000000000000000000000800000000000000000000 + 20078dcf344356d93c8874fb3ba99fa55446d9082e96981d6e4b0bf25241dfcf + 1ef8439de2abc9ee2a524e76eb98773c851de2272e9ff82872de69120dba2e3f; + 000000000000000000000000001000000000000000000000 + 6ecbc7d196fd0ec594426f8ef67f04e3fb0b187616403c3d770f07ef83e839f6 + 74f801a04bdfc3aa70c62c8111989822e36dd3954a18c03817b4958900ea6fc8; + 000000000000000000000000002000000000000000000000 + bb295bdde6c445e83709b56a027ac1491e3da32d1e27a2d40d4c604e534cf5bb + 091799a866abd7ebf18e6ac9421d394b1247deaf31e8a65ea3ea5156b78ffd67; + 000000000000000000000000004000000000000000000000 + 34d2916c9570990e5a2ce1f8fd3f4d92fd55227835ae79729494c2a56f3181ad + bd9dc29b42443bdf687aad6aeb0de8dcac403e13f40dfab97d289f5d8905d68a; + 000000000000000000000000008000000000000000000000 + 6e8e0e6a1bcab3b9c4914c1b7dbad41180fd39f4077920381e6e5d43ae29056b + d331837650a86a752e106d56056d34f6c60daee1f2ca2f5d32fa3d4c4b11f590; + 000000000000000000000000000001000000000000000000 + d15117718cda91b580c8ee37b7e92a92aafb1bacef081c8dc4efe8d9035cc3cc + dc40f2cba1490588030c77a2deba609aefda9dbb2de7caa20a27dc78b0d6a35d; + 000000000000000000000000000002000000000000000000 + 85e78f287d6dc01f23c5a7e0f3a79f7cec29705c18210ae5da37a5e787c7b900 + 4b0f88ed23950fcd28af65ed71b102b108dddf354464430823ac654c89f8146e; + 000000000000000000000000000004000000000000000000 + 674696bdfb8b749f045e4901d5327e907608abc8a441acc85298c4ec38207d7f + cc25d43dc704c71f4e18d3bc796c5d12db5771d929aac483f51b11923ad032bb; + 000000000000000000000000000008000000000000000000 + f59b32955794603eec1664d94b565126b08f689979381d4d7371a1f02d5939bc + f6a18c580d6b019f0ccf24d0585b612a9d0194292880c2bcd329b16d32d32eaf; + 000000000000000000000000000010000000000000000000 + 8331de42dd7f34562c261a24c4206206fd2f7c82077daaf793a8c13cb7736658 + 64d0688016e1fbaa84efa02d12f38becf1cc3b49af8095c645e006245d04e7a3; + 000000000000000000000000000020000000000000000000 + 33f329a6f1febd546b8dfe981052f456f1cf068257d61e4215d0270b731cf416 + 8a1bbc62bdff88601e65eacb63f3b81188df1715dc75e46e80e8d4bad7d080be; + 000000000000000000000000000040000000000000000000 + e13972f07f517f8e11951b51107feb546906c2c9c9fedded414c099e65ac612b + e0cd462d9c2676ccb8f3395ee3793469dbd0ee8bfe9b70ecc64c1a3a7cbc1afb; + 000000000000000000000000000080000000000000000000 + 30dc82438a0c01fe8916bd3d50ba378ba74c7902fe123850134bd254de36010f + b49612b958bd2f20a3662304ca13b856c325fad90020638ed5824963a8e047fc; + 000000000000000000000000000000010000000000000000 + 8bfc581db5e81ad346b934c1567c30409d0f7260895d7ff5900791730d3a780a + fe79bea87199dda2ed990add427118e574a293bcfb9a7cb74dac47ceeca73c19; + 000000000000000000000000000000020000000000000000 + 074c4229882668f1d1b2fc749d8a839f23d247e01efd86bc569422904fe86499 + 420687e93a67c0b5c4e4c4f39f596f314ac56a18f1fdf78a671b50465d200f89; + 000000000000000000000000000000040000000000000000 + c60780f4ac3b1507ce3d9e899af33930a44aea6cfa09ea11df9894f06d54286b + 9fda5c99d571f89a8b5a38f4fac48c5c21ddc91fedc481a951a8d1fa6956bdb8; + 000000000000000000000000000000080000000000000000 + fc3f7afe9eab56e59f7ac6aac5255e74dcac9a467887fb1e047531aa6b7c946d + 200436b4ccbab5f0cf2d8f6987364e88c650e5c432372a30d9aa9bb6e1c2665d; + 000000000000000000000000000000100000000000000000 + bd0f3ea9e305732b6f99f6d27d4e29cfedf59b3e6b24052ce0fac6b055ec9eec + 57ac440ffebd1a3babc1b39aa1c19bcc9086f3a841190949d3fd70387a69435d; + 000000000000000000000000000000200000000000000000 + b06265193cdafe2055c504f94068ba76858ce5e8c1723ce078821158c653051b + 7457c97d616c01e642a7608045444fa985ce002df0a8b87033a31fa4110c742d; + 000000000000000000000000000000400000000000000000 + 5478345da67f4dd32024104c5c0eb13cf4165f29ad5f0c946e35eb44a6a4e97e + 0e56f1fb7c9245ac5fcd148ec00511ed693a82a2390deabfcf2f7525a4bcc0e4; + 000000000000000000000000000000800000000000000000 + 9f583a1aaab317311422672cb6a29c036551d7653bc11274a53c50aa28958310 + e381e3727134a1ab4dbb3944447d869cfcb9cd8baf5472f1ea55d0c3911b2aab; + 000000000000000000000000000000000100000000000000 + ef31cb4447629b94a8c2bf6c2479e8d0fca2a9c3bed40506bdd009b859c1a234 + 2be2a20df00a0b9473601282902595bd30960b6eebff3eccd2772047e91bbbfa; + 000000000000000000000000000000000200000000000000 + 822f1e0b80d284ab77242e6ea6a31c7b9478fbeccd019640bd790721b94fc602 + f81e837b98de88119be6906594a26b93342990a9e432808df9bc3ff8f794fbc7; + 000000000000000000000000000000000400000000000000 + 1b048b3da8ac57c867d65c7054771b0e0f0160b7a389b9cd0c2a4c2230ecee02 + 14d4fe78bb906ab8a1174bcb83b11dc828e284f7799be720784d2c8c8c9b60e4; + 000000000000000000000000000000000800000000000000 + 6d572bb0230a9c543f278d4e44d25f07a3e337fb6bfb62443cbf9f63d54d3d23 + ec8fbf1c617dfce2e2888692f4233252500f6370f9ba9aba9976346f0b45db5d; + 000000000000000000000000000000001000000000000000 + 8f0737b4a2c72a5401388a64943d931cca5100f896ffaacab6bc6857163cb364 + 4961e5c5d4983ffcefa36d2d31f013b55d339192be61f2d7d525c9514851b9a6; + 000000000000000000000000000000002000000000000000 + 865fc49a982f200c0ce91ca8389997385cea07d2054e215624ba915da86ab56e + 9f9f408687229eebcf6d6b11a2b0e0983f8166fa538fdabbf24b5faf7a5729f0; + 000000000000000000000000000000004000000000000000 + a265014d381bf64416498ec6cd0d8280fcccff8ad00a8af1b87ffb279a5f44db + 0f96100cad1c7d79f2c7d266c2676a1aa04e507613cdfc88a9a5b032749a6849; + 000000000000000000000000000000008000000000000000 + 69c3ce6588db62df37606f44388b5d743e9589338f479a42b1994a8649b35353 + 03e557b5d65d9ce0ed50e2e77365e6dac2c5534dd29ea0ff6d6f3191ecdf3ff3; + 000000000000000000000000000000000001000000000000 + 3abdda974690d01044e1283d277823fa099234b137298cd9edf814c7df994f1d + 0624991cab7a0f9eaf650bfe2329966038ccff5599c66af5fbf77ab2a7028ee9; + 000000000000000000000000000000000002000000000000 + ae97a705ea10bf85929124addd1d620aadd98c35157e1ec67827243a013a1a55 + 1f33262e18666311dc61128867b31a015996924ea43a468fac7f06421b117a79; + 000000000000000000000000000000000004000000000000 + 1b11cc975752a04198e012614cc5a52c7570af58acd7a52cd479ff25f422a84d + 036163f34610434f92b23d88b6b9abab66dbcdcb1b3681ab63f8126ff5f3ceca; + 000000000000000000000000000000000008000000000000 + 726d34090d8de7bd8892b9e20cdd176e425b49147ff02714e13e3ba4c0176094 + cd95775f2b5274867a6485b92d8fb68c43e5b18dae52cf2a9aecdf82fa2756e5; + 000000000000000000000000000000000010000000000000 + 438b7eb9e29d625f827dbea30ee486dea4b8fba4432b35b3f1f598a49d1e3efb + f27446705c795d27c75f4e152c40979f838a577485e87154ad49e141f3906bad; + 000000000000000000000000000000000020000000000000 + b3e751e53ca877bb58140b3830ed6ca88828ee8eedc414e46f4530368559724e + 1ef875af1f5a2bb7b3705060dca18a0bbd2944e9510d1cec7d5dca01fd030abc; + 000000000000000000000000000000000040000000000000 + 0d85bc30d372bc51fec89036f8dc2a9a0c44dc732a35dc986c3308aa732dbfc6 + 41e311175cf4715f3a63de6e9d09a8f1e1ed35c7dff4ce55452dff184c67ccfb; + 000000000000000000000000000000000080000000000000 + 2911634025868ff4d90af8f03797e04facdc14c995031b8c1d399a8fb54f7945 + a23be5413808deebd664fb8bf8a44616086bd9fcd7012a6b019a288f179a61e0; + 000000000000000000000000000000000000010000000000 + dd1c1f9aa7639f84405b4ee50a0af7c1da71bc4ca4d7a84037390039073926c1 + 1cecf7f9da8b89b1793380b3ec02a069dbf91804af70248783c6eac500e72b54; + 000000000000000000000000000000000000020000000000 + 357fb20348241fab58252324b651366750f5fa3cda129beb249fd55c520ee8fa + 7943f92bda9aa429f4c67f6c60fb64f467eac75cf674f24c7e7d2b96afe230ae; + 000000000000000000000000000000000000040000000000 + 08933e7505bc9dafaa5cd4742c4321dfeed5eab0db0e8a06922f66e9b2f1d449 + 80060d8f8c9c4e78eb37a9a0ab618a212a18b809b653ba6fba4f9223a895fd55; + 000000000000000000000000000000000000080000000000 + 1a75b005be0c2e4d5ecfd57407a92c1261cb94edc3fdb86201e4122d10f178b4 + 68507c27736ef6d31e5c4abfad5e6494659724880f0e14f7cd92e4f81780216e; + 000000000000000000000000000000000000100000000000 + 4168cb291d201eff8f05e4266aa8a1f458cb66e3b01ce233ffb41f8aa6e9a12b + db84289b819e513d5116ca4aeb480616a03d7804b41e4125b03de8cb3852d6d0; + 000000000000000000000000000000000000200000000000 + 44a8f5928c2dc60ce18587c8f558258d0a5718773644b028fdc86d3aea135a4e + 0fa47daf31ccc8ec352c84e860b704b52dea2f15969bd08ed94063edaa5eb891; + 000000000000000000000000000000000000400000000000 + be7aa43951c4bee8cb3d2fd3a4869f498bf59994128cc3fa0abe0c9a317ca562 + 8c8f3694ff0333cae80183e03542e563a3bc3c25dd36c016300987445b1c0385; + 000000000000000000000000000000000000800000000000 + 279595b2e3d27000ad59360b237948d578dbfe442129ce09c963ea2467883447 + 5b0366c4833db132340334597fa4ae42c9591952639e86c7a5c5aaa67eeff61f; + 000000000000000000000000000000000000000100000000 + 3d0e6083f6dd8af24aa64f4f95c02de180ff34db8a5967bf47a38f048ba1907f + e16eb2abd16c38a5a13461b1992bf3622545c338c06bddff3c31ff4f11bfd7f0; + 000000000000000000000000000000000000000200000000 + 7184ce9462840f4f061fd8ab9053c7074a6a3fcaaf1bb7c660cf0237770f16cf + 19919262f08dab0f920541fdeb8f12b7a01e2f4350c9e42bf08819fa3d7cdbed; + 000000000000000000000000000000000000000400000000 + 7e6d7e42393e2e8cf0dd13f0f8c175796c07312be0d038162018f9f059192bb6 + 222f78b280402f19ad7ef8fff7bb9baa080925eac811f9d07a0e2625b8d0d3f9; + 000000000000000000000000000000000000000800000000 + ea6608f32a44501ad7d272ae5d4a02ba172c0da0d2ebbe99e6acc74d782b0a25 + d9b0c977617742962071dd97d359a589f323442201ed8c049ddd19986d6a7e59; + 000000000000000000000000000000000000001000000000 + ac34522fa1a172f61671921a073eebcccffea629c88c3efb024def587e85815c + 5cbaed86ba8d85fe7a1b7598344b467fc75c425bca2e057e4d29583c1339e2df; + 000000000000000000000000000000000000002000000000 + 8ef6979bc1593327ddf83f3582ca3089bd28441d603a68438b6b8963d5d5be7a + 2f35459f0fe78ed10cc345dbe5bda63ca032064173ea2222d8a44183efad70a1; + 000000000000000000000000000000000000004000000000 + e7137bbea6d5f12f35607bc208a48f9af232ba192552783ec1f1cb2ed9390abe + 400a562793f9a5340981d297af0bf0cef8ddd966b4245192676aceb0b830cd29; + 000000000000000000000000000000000000008000000000 + 0c10c073d596ebf8e92b9df89659d7e395c9755f0bde20386da97e61e28edcd4 + 1c16a91cabc951a2cad46336e8b8d63e442bde79569c953ca9040638fe7a6854; + 000000000000000000000000000000000000000001000000 + f2c778bed0cab8b49b63bbd4cd2e4b3839737629c76af97e41256fb5a51fb135 + c459e872e3d85d83bd6c02678ce707d4b55cf8baaa990a1bce85297089777032; + 000000000000000000000000000000000000000002000000 + 48ea086a4b426c28b7a789f863d6078fa557c8075f151bb376c19b0333c7617f + 3619d9a633fd99cd676764ebf0bde6392726c71c09edf1cdf6a83082043c8837; + 000000000000000000000000000000000000000004000000 + 88887c189b997032785c0211647d16f01dee57453dd8ae457904181346e3387c + a01ea4e80af98fd522c73f363fe1f67ca74b2f550cca01e1a831a371818f0a67; + 000000000000000000000000000000000000000008000000 + d1cc08438475d0a365e113a4f6cd2b3f8dd0fd16f11a7a91a24d7d57bc299a76 + 5211117b058e16a42041313422e59b867c25234913f19ce0d3e8ba2c83a1b604; + 000000000000000000000000000000000000000010000000 + a08d0c7258596d8ac11e99955d27dc5e58c1a94f3122821cb62bb7750f8c86a2 + 828f22a04c97d1608bff3c343450975b321b1f1078f4b8bb8e392bfc3d6ada6b; + 000000000000000000000000000000000000000020000000 + cfa3d2646ed862a2f5e1a0012446f25b320368f817a9f6aa34679e8256b31713 + 18ed4648e98ef43131ea244158d550f391d10aff20a786b49a7206e0cb810a17; + 000000000000000000000000000000000000000040000000 + 9f3a7d42e935c1f2e486976714115dad69a44ab16a251d2ee8d59f09f752d43e + 9d28bedbe24fdb9b7d428a5bf6f290a0d3fcd4c5d3083e8dad1deed29278352b; + 000000000000000000000000000000000000000080000000 + 5c99b3f3fe50e3d2337417eda4801ebac775bb7505ca0dc7d42bae82ae9ab9af + 8f3d15786baead2a7a7a821f651b2cdb354da45133f8f41886362285e8ae0303; + 000000000000000000000000000000000000000000010000 + 465980c12032bfaff4119e7a258e0d9c9d10ebdd694c594eceb203e3b44ce3ae + 9a2ba16d5bbaef21e0c7c28cfbab685e91840ed1c6c7e2d9afc52110f000543a; + 000000000000000000000000000000000000000000020000 + 72a31c0f8e054b278ebd35af35661bb0bb23890d62bc4ff567883e8d6df3a64b + d5a094453f00fbd672acc45fc68ca31e00260b6fb0bad3e6c1adf2a6cb873a5a; + 000000000000000000000000000000000000000000040000 + 51ee7d952e9d6ab691ae0af0cd24daa737043475b208ff66adb3fa5c09f3647f + 36a7317d1f7e27f7cbe2745adfdc49ddbff3e6406da0f0bf79b5b64877ee94fa; + 000000000000000000000000000000000000000000080000 + 03d5fefc307c92f49299cb1561e8925e4b333530d1d39e6576d999d6b18e9566 + c80301e64d2a3c192dba0fa08c12a1ce1410185174b5e97f1b7e124418566dc4; + 000000000000000000000000000000000000000000100000 + 02b1c0b7e3d4c64bedd8ca69dbca551dbb34c54007c70dfeecc64f40ec689040 + 7d9f113f627086a13dbae2a8d59a60f0d9c59693dc38db1262a6cf63ce1e161f; + 000000000000000000000000000000000000000000200000 + 31aec9854efd20aa692d58e5f35f9715aa6744763e80a2b84c52e7746024e4f0 + e298bc6d65a88ef0dda69e3cdf8f39ec836881da986c94aa8e55ebeee896f376; + 000000000000000000000000000000000000000000400000 + b6b7b784d08b13e5e9bc1de7c580a2a84bf0ce0863ace791eaaa5c448e419b12 + a7f496e466a7d3a93f52a704b165bf1798f159d1fad3e3d33cda5551e6e81b33; + 000000000000000000000000000000000000000000800000 + 7edbb0b8915926a8a2e8fee143b729415135b88414a2009f0d5d1c0683973534 + 21b1c8e53b342159b8bf091b43534ee08f4584ab504dbcdab6ef108edd7addf7; + 000000000000000000000000000000000000000000000100 + 66b011b48e7c4d63065e119be7d76dc2fe5f4832892e521b3919a567f28d78cd + 883378f113fb173d55e21afac17b6bcc13c5b825b7b39c4587e36a7bf56d33f5; + 000000000000000000000000000000000000000000000200 + 36b722f7c39d54cb3b5fd4a891b3895d6da18a6206cd9228b5f890a04a732d2b + 5ae23efac307c817a93408eaab3c71fb182b8c339c6ecd86a04dac2ea551974c; + 000000000000000000000000000000000000000000000400 + 8c62713ee186f9c9b85d3b39433a8fc48005e4b772243e2c59a0b6c9c5f8d945 + fd48ec5913d2c5a24898454ee7d127a2b3faafeaa51f1eb6bfddfdd89f29f55a; + 000000000000000000000000000000000000000000000800 + 6cb6e49700ea40fc2250f75122c7658603d210b28fd5a7d330e7eb7270571b92 + faa3c13c45e6a6058fc008d29710e17df435ca6fe03c802390e66a1f5d35f448; + 000000000000000000000000000000000000000000001000 + e209f79562f3acae829c8ac46326527581961f6a9c50efaacf05cfc299770d3d + 47fa35bd28db056ad2c960ffbf195b6726b8ba70d0e1036deb00191e1007bc73; + 000000000000000000000000000000000000000000002000 + 039ac5fc8be0833d2b344b501949b94965ee8ca968d41f799bdf4788c69dc9ff + ea9f5b28839e0ce7da245f22957bfaa6f23aa9e91797f94ba41c563ff207eb24; + 000000000000000000000000000000000000000000004000 + f8b3de78e36105f66bfb9030186225b551c54719d03a327e477a15cdae4c442a + 558f352e51df92eaf816878a8117507571e77ed0af9196f621172ab63c57e96b; + 000000000000000000000000000000000000000000008000 + a95ec4094654e78134ebfcd6d99696b59ad8922953c88d4676e690235a07bec0 + 0904f4197e14bf542f25be01e01f2902e389f872389040754b4150ce17e8a8b3; + 000000000000000000000000000000000000000000000001 + e4e55a685ce73b8e8c38484cc3a095ec77d79d4213bd7e8509e634cd22794e76 + e52aea0a67ffce6c423f49f19799b5cc144430a97a4a11cb81a15325ba58182b; + 000000000000000000000000000000000000000000000002 + e82db75f9ac6e522e32c0bb59d526efb83041531ca7f8c10b50206fa1f5c0f95 + afff3847b075d3ba60d574c58dd38734e585c6835e7080ee22dd11fbaad76187; + 000000000000000000000000000000000000000000000004 + 11c10caddec7e7df6e2b3cead72466db28943603073b181c54586cd97668913d + 4892b31c3728824d569af42be89c87986ec1d7e3ba680d77269b6d66a8674a87; + 000000000000000000000000000000000000000000000008 + 8b10fe1f2dd03e24b962a91d341424db2fb31a98e99cc36ece76fce644e7626f + 42f3a523c2108ffcc693ac50991144dee446980819ca6748337b75212f426d7f; + 000000000000000000000000000000000000000000000010 + 268ca8eee4d8bbecea331da0299a3c7722ecc81f6d9e0f360365ae115be736e4 + b39d8ee9b20baf88f8073d5c50091a4ac02e050680ec0483f13896fbd08ee022; + 000000000000000000000000000000000000000000000020 + dcb7c3ee50078883fc516b99f8ddda0cacd6df989d7408b90ba4b79ca9aeee25 + a306a8182bf7d39636b924b1398bfd4a3eb54ca10a2a92deb6394ae6ae5635d2; + 000000000000000000000000000000000000000000000040 + 3e8bbb3bdd23331becabe027092f9600030a29cf101d49a0645fb19839aba819 + 3d0ef0e093c0df6b7a6efaa547dbf7f96c77a195e7f32791c02e8d6d84bbd999; + 000000000000000000000000000000000000000000000080 + 3001310564521f5f6cc2ff5138270e2b01c98f1e0e0df104f218a7bbd4c528cb + ca56375249968d85431fda8a0f5a94a676f725730eb2387673e8e2196530d40a; + 01000000000000000000000000000000000000000000000000000000 + 2464195fdfbc0fc81a28fb4f56453d5bcc3641a478bb8e217a12e81d209a0d69 + 764217beaa547cdc74d61dddb77759fa4a46818fd71b77ef19a66ec61bad44ec; + 02000000000000000000000000000000000000000000000000000000 + e093cbcd15d9d26d2299aa256ac0ffa9479e82a7e6921c22330459282c643640 + 2d6e17704b89f170344a816657e838141938dfcb7710fbd748230abd423a8327; + 04000000000000000000000000000000000000000000000000000000 + bfc89ff49188394972ac2fcc77e4275e8b7e190ad88ec18dd46cde1e8d08fb3a + 240721b9d03626e7222eb91b29b1b56effaa86b815c8041ab46f92fd86ef6fa3; + 08000000000000000000000000000000000000000000000000000000 + 4f8fae102a0f00b1ea06377d3d331df3b492d4038a01467998878f9ca6101860 + 2b928f67b786b6977666abcc44bec615d27ac4ee3f6e3e0620a32174b0428d08; + 10000000000000000000000000000000000000000000000000000000 + 1580bccabd91d69db6608f185b39e46bb8c2822fdb63f55fcfbfda08897217d1 + db3cffd2dd7293de5ac9b47dc91e8c8c12a4890e67a5ff9399821dc7282e3125; + 20000000000000000000000000000000000000000000000000000000 + 6b99c58f03c9ade53b87383363db9b60a1cc3ef8b81b13c146b2f3356becde35 + f77668010fc0f6ab4438ba294b19a62756316746da733e22eb9432e4b8d92665; + 40000000000000000000000000000000000000000000000000000000 + e711df4d46fa41caaaa9ef1db1abe8fa9d73fcfc2c8f7bc0bcaf238d88acf2f0 + f923b9ffc408776d2e79903cf46bd57b4243142de89554a6c42c535469f4afb5; + 80000000000000000000000000000000000000000000000000000000 + 6a3a9121b368c3513dd88522b3a9d1fecc6403f30eb1dfafabdb2467db85c4b0 + ffc4cc0d9b92617db41d1d9e1f71ea3962f57624f85c06cc774e0789bad7d70e; + 00010000000000000000000000000000000000000000000000000000 + 4cb64c389bcf6ff3c15f28ccf61486e2aace7c54492d2e52f91672fc1ef68c38 + c12c3d78af5ed1c2a1b8f03127a2b183ad5876c181ddaf0b55b7d275b1270406; + 00020000000000000000000000000000000000000000000000000000 + 39e2ac45e699af272119c0f264488b382a93468433ffb73066e1b052f0b95114 + e4859a08895657b444b0a92cd027ad01b2045cafc91d5a58a70d4881df7f749d; + 00040000000000000000000000000000000000000000000000000000 + be12959b811b7990538165d11ad379332c729f72666c2d177bff7c6585c4fdcc + 2da68a259c2a68a877d5387f01faa64ab6a537e11e2e4620b4edc957dadfc1c0; + 00080000000000000000000000000000000000000000000000000000 + bd27f6928a39f0404957f340701b23f529af3a4ddcaf3176f7e5b78f31027cef + 9df676b4ad16eef5fc3d9074ef1fd0286dbb7714679449b8059a86187013cfd7; + 00100000000000000000000000000000000000000000000000000000 + 0f6c337b825811e0f4afc216133a38726cfb6d6de0da7bb8f33961a2c21be234 + 14b48beec8faeccb9500285799ef73532853b8c7cf630d64ad934884eff923d5; + 00200000000000000000000000000000000000000000000000000000 + 96b9131980599233f75d381de365ee5d71706e880840e6f97365628a1929fd32 + 651b53f4d5f76fc3eead20ef4f8bdfce994a9f4411d9ed9d9a82e2d39966295b; + 00400000000000000000000000000000000000000000000000000000 + 90131368532a05827eaf2ae0c7f7486def928c0cc3c97364fb3a33ecdce76a41 + 1070e529c583863ea11745c08ad3511e25f00fb1f6566e9a65d15c4c5b9db9f0; + 00800000000000000000000000000000000000000000000000000000 + 9e194d490e2e1a13f067736c1b4c02babbaff92656b39f2cbfbf79bcef509d32 + d68bf125bc9d18f357263378f1418d0407554c006bea0d57fce3284ebb23e996; + 00000100000000000000000000000000000000000000000000000000 + 9edaf8d2affd9975fc6edc4d7551d745f3ef5c1c2e9b6e866ecac4370718f00d + 11538a9cfde310ee1af5b1bdb89fdf7235b65f06804c1717b50a3a7bada18be9; + 00000200000000000000000000000000000000000000000000000000 + 699a6253b34d53c925a3ca885546ff6f075ec5f8f2512556f5c9939dbc66521d + 94fae63abb388be332f694d27344004f9cff783d7e0efcaccf6869622f1a7a21; + 00000400000000000000000000000000000000000000000000000000 + c8fa8a591d52dfbdd4de31dc5e7e2e34c1116f9136872d482adacf6c4ae5ea4b + d5a6965f1bb3023d6fd54c871732bec898a322a815adc5ef4ee92fbba3292ca4; + 00000800000000000000000000000000000000000000000000000000 + 755e57fa2b60ea3d49217a983e01ecd990b9f801b4bd418ed9218b0e0ab6aedc + 4dd53d0bce528d27e721a7e57dc1cc996de9fe7a1a9b68bb166e4ca3883273d8; + 00001000000000000000000000000000000000000000000000000000 + d7fcd3441c6e19f5fe50a13e8df8efeb313ea4c3d5c98a4d0218a15d2fba0501 + 03b82200d043d05cd925deb405da6fe465da86a542a99138286dd3c15180b11e; + 00002000000000000000000000000000000000000000000000000000 + 5c2aa4b1da995bdb48012fb3597f0c293ad32d35ef0b1d18818389bf293c06f4 + 5cb31ce813dabc594db8769257f0f8d6f56228968032ec3faa6089959fd312b9; + 00004000000000000000000000000000000000000000000000000000 + b492eb88b267d7e8d5b2c4f627e0134f0948dc958c3f9c3b9d53cef81d395fe9 + c17fe250e789278e9f00eb8c4031415a534797685eb90b531e6034b72bf11a45; + 00008000000000000000000000000000000000000000000000000000 + b37285ea7dbf2e60444ff339c6675efcc427f8fa6d0dbd4ec23f0936b60a1f36 + a18f8cec0b0886c08e43b9ebac17c592b95e87e8eda9dbedd9d05982f8769e0b; + 00000001000000000000000000000000000000000000000000000000 + 5cc14e4f6ef530df34196f17746dd9b10e10890beac586e16603b0a28754538d + 8397bdd286cc5961b1414830586eb2114cbbe9f626ac355da9596861320277c7; + 00000002000000000000000000000000000000000000000000000000 + 18c5f953553658bfe311783c54e1d3b988b7e13e5b1a05ff7b725a1b3fb97815 + 14f9a5aa033cfc16b02ef4d7749e136521607a74e1d874d18b257ea98078376c; + 00000004000000000000000000000000000000000000000000000000 + 986ed4e41b1925be50769c2b9f3bf9c42060e69f4825b0b27eab36628f43e727 + 0ba3f96bba6070ab9f18a6a8a3bd38db4174456c0eacc8c52ec067d8f0baf138; + 00000008000000000000000000000000000000000000000000000000 + 29dc264f8b38836ca14e4635397a48a18a489adce20717d417c004cf39c9444f + 971c02c844cc79d7464f0b7ae3ebeb6ba461d1c257ae052127d6c35dacc7931f; + 00000010000000000000000000000000000000000000000000000000 + 23c02c0924ece0eca2b9a113953f86926c7db6973ef792b7ad30ac5146bc8c1e + d5b1e384a939c12b9eea540dd46dcadf861831a2eebce73b0ae8de42bd83504a; + 00000020000000000000000000000000000000000000000000000000 + a8001a31579cd64e94ebd9e4a18818749bb0f0fc01ebeb456b8c0e065142c220 + f124e79fcf5f18fe452ee9e6593b1b2b3ecd0f68a8faecdc09c04ff179b9b01a; + 00000040000000000000000000000000000000000000000000000000 + 1f01e394b147f07da857c34896d8dee3f7888042e609ab70df48268ca31dcc5a + 04d77d393666c558f69724357158eb7bfbbb05a8a38c5f5b48e082d2ddf39ff6; + 00000080000000000000000000000000000000000000000000000000 + ba3d2f96d7bd899d2d6142369471c133bdf1ab5a9a584745538c78631b095aa4 + 1f008bc2a6ae865927fa85b29a2c45304f09b8275e5ecfb62eb44ca5244b0937; + 00000000010000000000000000000000000000000000000000000000 + 8fe14f887a1b802593b62ee61d7bd8f2733db0babcd41652ac1185d2d18f578a + 1103c814cf73455d6dd34ba8846b724fb00d6cbfeca562bc97d118f4cad784d4; + 00000000020000000000000000000000000000000000000000000000 + 8f767cb1db48efa0a1c5d642152edd3a050a1114facc07cd41409bcac7147f58 + c08e42a5019bbe1275375549b91dd15819b71b8a7592152cf8d94e964860535b; + 00000000040000000000000000000000000000000000000000000000 + 82b7a2e84536cc2d2758df01658bae073b29b11339f212e320a3d7de2b14971e + 20aec4d43c582e1cef05b6e268b61a2f9633221ca785943ea7885f690242cd00; + 00000000080000000000000000000000000000000000000000000000 + 76ac83b90aea0742f8ade2be9b160a297d8fe8b98daa5c54b4be2e44fb88cc21 + 18d1c8486e2b6f25e3f0164c2c0417af50f2438431deb4d4965f0cdf8cbb39d8; + 00000000100000000000000000000000000000000000000000000000 + 0c2e937c9717fdd4868c019ee1bdddcc7ff68d5df4bf8175a59c13fe9ffa9ec3 + 1c754234c085b09ee98fe2049b0722502e0edc5508cca7190eaafaf90df3d310; + 00000000200000000000000000000000000000000000000000000000 + acc18876ae7cc4f1a183357d04e461987b1208b2b99f8d77a5544a07bd8fe89e + 9f73b6c96743fdf8e1dc88e0022a45e19349ca3ec2bd691f2e5d5b08114c99f1; + 00000000400000000000000000000000000000000000000000000000 + 88ad33df55b990c06a2d16d9978913c23b287c7b1e220c42477c46104503a766 + f0042fdfa21c7405dbb441051b9e0f9a31e6f007a0a8fa43f97c86eae96acd38; + 00000000800000000000000000000000000000000000000000000000 + a3579b6a7d1d0efb2ff2cdfcf23612c9b2650beda7a67cc46e1844ed0dd12e69 + 1ab34729d9777a4009e98a196bce38d4431729e5ea6901824c50bcfb49b657e6; + 00000000000100000000000000000000000000000000000000000000 + 966dab579c1d3702ddbe8656f9240b4efc6704391715442a66bec541456b5710 + 06345acc4e0e9682b21f66a220fada9b4f6d82504d3b73c8f6c89311dfcb1352; + 00000000000200000000000000000000000000000000000000000000 + 12e01acdffc14a9fa3bddfb492bc348bc0c95eebbaabd17948113e63ace4c51d + 9d40be7abc07a4cdd77219952ec81d8e1ef8178df21a2cbc927587c116c5e08d; + 00000000000400000000000000000000000000000000000000000000 + 1f9f2968843c0133d070e8f0617a545b55fbd9a659e1ba9be16313d7e24a33f5 + 1eb163f3918a775d7c2cf6bad06d42359d9e4d0f0596822bb90d0db104156652; + 00000000000800000000000000000000000000000000000000000000 + 1f007682755a014c1b88d7b541b296c7cf6613e2d5644517a49e0caab2f84392 + eaa620472fc4f60a17390cdabe5a9410646b2754f26d6490bd89d8bd14d63824; + 00000000001000000000000000000000000000000000000000000000 + 8071f28971756eac7456c7e41a8157cad949b67902f67b0186cb5ff521814381 + 7b3b7fd81181c132321b9e97ccfbe4983aab6c72dcde30e9172271de5ffcde90; + 00000000002000000000000000000000000000000000000000000000 + b7c03ef5de01672dd35370e37f77309ca808868dff56bbb094f9b0ac7c37872e + 653410001ff58bd0701ec54a5302c5dd95994b6fdcb271447477dc1d35f32b28; + 00000000004000000000000000000000000000000000000000000000 + 5057644476a033599dfc0b2dfe388660dae6c40828a464c931623997a3b2b1de + dcc23d1e17bceedee546c8452cdcfc43dfe3a36f0623371066a857a592b44c87; + 00000000008000000000000000000000000000000000000000000000 + cc9d90401fa604d973e99f78ea9d9e0945344f4098d2307f7402956de7ca915c + d877bc8623e95266ed10ed810f144ea4f7889636f63b36b478819200b06b2dc0; + 00000000000001000000000000000000000000000000000000000000 + 270edd6834636fc90df711b57e4ec2a70c66189d9f149b8c6691ee901dd76c97 + 776b8906523e21663f84527687791c7f625a3eb1d456d430711212bfa0b36ff0; + 00000000000002000000000000000000000000000000000000000000 + c8d389b72ccbf5df09926294aa3a548cc07fe5693ddb4a4e69f82f736399fbf7 + 5177a1928aa122ff0281da5954ec854b2fafc3065b9d636f08bf7c6892054894; + 00000000000004000000000000000000000000000000000000000000 + 99cdf287f3a952867f4aca8fca230fdd2799829786a09a778df717200910f704 + 3369a095516c39906e537b571b36537076baf3e00e634ce403017204cdc8a2cb; + 00000000000008000000000000000000000000000000000000000000 + 23613557e1e34d83b979d4740aacf64ff2e7c353418d351932af432b4c3feac0 + 84bb895e1e113c431bcdd2f3bb02259efdc882fdca482085f64bb3490217e143; + 00000000000010000000000000000000000000000000000000000000 + 1fddf34a6c90b4d87235c5851c031e9c6c9608c22b6bcd1f1988211f8025d381 + 4687c0880f5e092eb50faef790418e0dd5ef304b7e52cd7733cbf60c29e336a1; + 00000000000020000000000000000000000000000000000000000000 + 7a448bca6c19369a549a89ce4c077fac787ff47683238cbde1bf4109d66fe10d + f5814b2ecb0954cd18dd3e633bc67890f30350c7fa2a4e2ed7fda17c4c224572; + 00000000000040000000000000000000000000000000000000000000 + 6fae8a02043b344c817ab30fdc3709eadfd9dc3e50a260ad4ceb503f0dda2ca7 + 3a167f36f5c524677eb0acb05c715e614573e2c0a685a7e30bb9b111df493c9c; + 00000000000080000000000000000000000000000000000000000000 + 8dc4aedcc4b4e7b7f96ba908e1ddcf7f07d8d26db0f599c5228404fa2e5e7fce + 244309f24c16fd9ac28cb4c01c7354833be4d339754b8439d61c88afb7082679; + 00000000000000010000000000000000000000000000000000000000 + dd772809159b566a07beb6411bfb77d8511601aa33886ff217f3d6bea6b0348a + 512926d3ded3f02d9aff5795050f2d1b8c0a7be7f7ed31b3ba085acc7d54ed8c; + 00000000000000020000000000000000000000000000000000000000 + d74853e986ef4ed4fe6e23538677a9b1800fd309e46d7cadc0be6ebce447fa58 + 6fe50d1ee521a88ae60582ec2e89acf5bb55dc13db2c5f45b01f2e95b4c3469f; + 00000000000000040000000000000000000000000000000000000000 + 3e4b0bcf8c7de8760cc7262618235b6c76807130470bd84928652849bf2c424a + 88823ee8d85199139edd4f77810ba859047ceb0cc640d10a9eb418c08280bd8c; + 00000000000000080000000000000000000000000000000000000000 + f417f0dec902322fb3754d0b5f1e841837549ac42efaa46d2c31cbd5cdb7bbbb + 4da04434a336e640bda841c17baab0c0e71f048c092782019016ca6fb89d8e72; + 00000000000000100000000000000000000000000000000000000000 + e6a2f06bbd9b5d79ea935d8d53cf2098a4a838229e4b257258d5978c850f7086 + 9087fb1b85be7c7cf4fc0c3b89da6e36c7256190477b7d6a74fd1833c19bbbad; + 00000000000000200000000000000000000000000000000000000000 + 1ccda6c45abbc6010a3267ee4e43af80f52499a819fd9bbb4c3df8a063fe0881 + fa616cfd0404f965e3fec16148c60189850611b2d28f87dd1fea7f53218a53b4; + 00000000000000400000000000000000000000000000000000000000 + 4e98a243a3167f35843ce0ead838066ed5747725daa3298eb97fadfeb2a47b8b + 13b78a61908c40108d7bdae03e85ddf8d164ad161a6de1ca1f0e51a9d04010a9; + 00000000000000800000000000000000000000000000000000000000 + 1bf5711f13594876f995324a6f688ef78fae8ba70ea49c175a27ef75ec85493d + 6e3cdb2bbcc44b41b6e307fa774296889b4b5e92ba079789f60e9006b04d13cf; + 00000000000000000100000000000000000000000000000000000000 + 442d9ba00e7313b035ab128ba863df68c0a19f1a7e572198086d7f79744cd088 + 02bdecf5b7f72546612d60fa301e01abbfbbfe27b4710d26f0c5bd50ed50dbd3; + 00000000000000000200000000000000000000000000000000000000 + 246185ae4fd65b354b04f4fa186d700c49d3d9f5018a917a31042af8e33be63d + a9264216ce3b8a5ed76ce229955191d9ff66391b9792979dfa5d7c1fbbaf9c22; + 00000000000000000400000000000000000000000000000000000000 + 1515f8b044f42fcbc8f04ac3ee3b89ce56e87f98b72134225603777fd1d66c88 + 3cedbc3b1cf63d957f2366876810213b778aaefd83f5c889dfebea8c35d2d4b3; + 00000000000000000800000000000000000000000000000000000000 + 037337c0a20e54350483349a393194c5ce8f0104f3bbf2e9cdbdb4f8c93b4eb4 + a52ee568f98bcdc658f48700b7b6062d2951a110bf0f3e48548325ab9212be1d; + 00000000000000001000000000000000000000000000000000000000 + 9afcb8f2fb0c8f7957bfe3972ab4831c47c35f1deb5f01674637bcf4d0626d6e + 7239fe3b5aab7daeca3c9016771b1ef6e67b3e3eddda777e12e8657b3f84336a; + 00000000000000002000000000000000000000000000000000000000 + abf8f708cf84184fa21b16ce492317060ba039e0815f186b162efdb47be5ca34 + 03a023c9dd6ce45f68000261b0ee2f1a8fb549c8469bf539a785feca009d289c; + 00000000000000004000000000000000000000000000000000000000 + 115090529147724bb2280029f146ca67d19feb98e1d68991e3557b7f31c65731 + e4db5a302db7910a999a6b04d5302132b3f1a21d416f4d70d2ca6c9500b4658c; + 00000000000000008000000000000000000000000000000000000000 + f8c24f3510ab36e692191e520edd4b8f7ca62e4c38976ca74f5b45fe75f0336d + 0a20e557bf3112da79d211fafce885b2d2857270912da2301466294ab9bb6bb8; + 00000000000000000001000000000000000000000000000000000000 + 006d35fbc723cf42718e015af9aa85a58785fcf5139f031de5913f4a4c9cee1f + 79d9972f8ef149e5bdb2aea1855694834e88bc28d97f7506fd016e63984a3b09; + 00000000000000000002000000000000000000000000000000000000 + b6a8633cfd175b9d20f60805043ae68cd2e4b19d7306af279a476a1467147162 + ac59474a091105832d53ca2ad5e4ef74ba1c7e227bd484d582523c8e8814062f; + 00000000000000000004000000000000000000000000000000000000 + be3e898c1f7be5fea90ea6dba94fb56d73af2540130004c2beec5244d402f219 + 2e091331eacada55955eaa588b2d7a0b60cccb37bd8ac7c1c29d5567adb7d0c7; + 00000000000000000008000000000000000000000000000000000000 + 3173147bf3d87cfdaca80b6eb38a83f935844f04cbadae7f1de427533de75e13 + fd7dc829a4cdca020ef6529b6f556393640d97049ae1c0ad75bd202f09cd3557; + 00000000000000000010000000000000000000000000000000000000 + 597eedc7cd929393f4c1293f2dc579fa4f2afe807d5a2fb5bd0a896439be3183 + e8c9cfc002d3eb8da47c8528600f0947d6049d34f6e1b1fb0c2e1fcf2691c3c4; + 00000000000000000020000000000000000000000000000000000000 + d3e7c0f4191f1a9fc7f2aa84a60daf5162b8b591cb44e7af87738378f7804c23 + 2cf8bedf4b3a75974868365f6b5baaa8c4594812130330352f3edbc791a01892; + 00000000000000000040000000000000000000000000000000000000 + 35e398c0d94aac9865c5c693f3763923f32555817648121efdc2ecfc35fc354a + 395e5543d4a31c9539f5c0a62a407abccc8fa71f52c075d5ddd927ad17e56fa2; + 00000000000000000080000000000000000000000000000000000000 + 50ddee1bdc4c0f8f0d0c3bdb456a6e0a30c71b1e08d247841eda50a85c761ebb + 6926a97fe085da68d6527a538644790ca8f8a4c68f3ecf49c3cf876a53d97479; + 00000000000000000000010000000000000000000000000000000000 + cf136f837e9c0078534bb9fcfef063fbac5dd5b7eda010502e4aed7819745a28 + 9b1a9914ba2586855e1f108998000010796c128ec5e822c3c49f1483ea7da01c; + 00000000000000000000020000000000000000000000000000000000 + dafd823ea2231a3d6590214a7bc68b9ea6159daad95778f44f3c287476b24e36 + 47906dd563422e0aee32cfb8b7cccf6c27c33e07189ab94dbfdb3fb348076c13; + 00000000000000000000040000000000000000000000000000000000 + 2ea591c02005a5a83c6a5fd17025aee427825c07ecda07b78bc540013256314b + 79af8d2a7eb63c32ce27f241dac9162dde7cb6bf0430a1ac59689807c98c3b6b; + 00000000000000000000080000000000000000000000000000000000 + 340b58195ae4140093e1224f811e8e01fefbb3a61f87aba168836442c42fa094 + 4cde591cfdc70d3c8ad8f7fa942a84f5416c3758aab6c685e1c4cb9389a9aab2; + 00000000000000000000100000000000000000000000000000000000 + 2ab8b78dff91d272586a56a661ac935a75ca0ec6c2dc6bef69b2d27889499aa2 + 3da491825757927a27b452da2e8e72e5525264af26739977392968c0351a90f9; + 00000000000000000000200000000000000000000000000000000000 + a151a348620cfe87d074baa730916f8eb8373970261759c8079b0a88eeff2741 + e7d0a61a9258933ce905ff235b0287f215cada2453030a5c5aacbfe8fd93a4cd; + 00000000000000000000400000000000000000000000000000000000 + 68185b88fd6b8ebe0ec150d966f3d48e03c51e5fbbf61d272bddc84003951168 + e74bada25673f8bb50492cbed8b197af930133b104da958ed64f47b5dd61e68b; + 00000000000000000000800000000000000000000000000000000000 + 8ca43156c06749fcce60d345cea15ecdca2cdea81b1bdf82025900fc856dd365 + fd4c9ddd669d86d2298f5ef817e4516f8848a541d0eb4375eb2ea06eb1c3d681; + 00000000000000000000000100000000000000000000000000000000 + 722563e1f5a521e0084ae6699bdbcef49147bc2db9d08eca8a155a91eff9e707 + 2053cb249b323faae9778c1bff22eec9759a6d04f67487197004fc6cf790e1e1; + 00000000000000000000000200000000000000000000000000000000 + 3abf333bef3ae7f4f7c92a57195f758f1d116ee9c40978c24f435152b511ad98 + 417aabbc6aff1f7dd197c89c16fbcb87ca9b121dd19d21501723feb8a339dfac; + 00000000000000000000000400000000000000000000000000000000 + 2a1a82d29a6c710fb7d35b1b66aa836ae340d4a9cfcefc5045a954d5988fad3b + 64d9d9567db3b4372cff3be7c789a8bc6451311fe0ad9e527edd2c6a3e97820d; + 00000000000000000000000800000000000000000000000000000000 + 92748e1df36ce322398858729265955801e70528990c15e102e1bfc6949126ec + 944ec92f07e11a517fdcff7a41c72c02a3be354a2e3fd92cc2b6c03ae35a5738; + 00000000000000000000001000000000000000000000000000000000 + 93a79e8843e5e49a7c61b9adbf5869b70a24b1786f2a476dc9b2b4b7a6d6147c + b44c96b6fc150dea743d84a3406926377ed403eb619b870ce414ad0bed5c6149; + 00000000000000000000002000000000000000000000000000000000 + 613f858f69b87d4f2ea1287d2817ff708af8ca2292388c60ff64bbf772ad0014 + 9e98afbf45a14662e33355be5aac0e67a93389037ef6e04d72cd53c9f2091b4a; + 00000000000000000000004000000000000000000000000000000000 + 26a5c693be3a5082796dea97f05cc2da9a8e1d3ef60e810d104d2105ebf81b63 + f8765cb141bb16f91a002fbf0996a7b0ff8889c4545e2625bb870103ed996f7d; + 00000000000000000000008000000000000000000000000000000000 + 6d6ae36d361da7f12442c0c5a389f6aa4967d9e1b538512ccc4f86058270d714 + 4a5be549a0f0b646e97933d3b4d645a0552e3b1b9d5474950ba154b3fb243f6e; + 00000000000000000000000001000000000000000000000000000000 + cd97ad2ab79d5e6893bc8676fc1756902033f5e502f48723e0c8f1bd636fd5ed + 702acc3d216d71a16db827a4e53b16629923fe73b2f5ad3b5147c9d40b043841; + 00000000000000000000000002000000000000000000000000000000 + 69bfe6dbf88d693e34ba867a3faae2a545c630c033a168fbad9a000b0a3d63c9 + 8c11ba612c0113627f0703c930a595f03b132c77677385b2f55eb951295b50bd; + 00000000000000000000000004000000000000000000000000000000 + 474504641ebd7e5e886cfac4e8ab717829d7afc4653051a7ec4cb6136c5725cf + 2f671c3f45b8f697207dd3edfdcbd228fbace746bc9982b107eac863a755a645; + 00000000000000000000000008000000000000000000000000000000 + 403c4c767ab1fed06a95d0a42e6fb058092996c1e7f9cd74023bd7f7f5e65cc9 + c767847b6384b478668f053277ed1e655e0e0822d6504a73c2a97adb344c0c50; + 00000000000000000000000010000000000000000000000000000000 + be00a382ce11f4b574bfff2e48e622d25d709fa043d2fc7c8ecdce33a6ca7272 + a8a42c740d6fce54fa53651fb2b0cb0d8888d8999bde23cf6f5b42c8e2d1297b; + 00000000000000000000000020000000000000000000000000000000 + 823eba2a58a9c7a43b4781255bb178a00ec401692a9f3cb64eb6b86146a89c3b + 27e4c00de764619ff0956cdc0599bb20e92d2e39e2f6a5461311b357ba5acdfc; + 00000000000000000000000040000000000000000000000000000000 + 1b9c442bfd36d7b57e185468b3fceb4b928718b24e8fe9618648119df1d75345 + 7d89665bc3883b2d57e3eb097f3f66289e08c21ecc3d641dc2ee301be9a0b7a1; + 00000000000000000000000080000000000000000000000000000000 + e52301462399a0fc87356c8d3015aef445c71699a0016598756a1a89ba3f717b + 884a598ffbbb2a2ffc52fdcc89b46ea399ac6f46e73bafc7a851a6fbab090165; + 00000000000000000000000000010000000000000000000000000000 + 02429ab56ca22bccd71cc987d3d38b99bc6144e2c70e2bbd1158a9c8020c17da + 9a2f84e0a9669cb81d36359adef338a98a82da479028e3dd8485adbd89d05bb0; + 00000000000000000000000000020000000000000000000000000000 + 124eda8fdf5c7db30c8223cecc62cc5cd66c26cd29b4d0ea304f277c77fbb6ee + 442969316b10b8bfb2a65611b09a098910deb26468ac2fa906087f4c85e634c7; + 00000000000000000000000000040000000000000000000000000000 + 52d01eb026e4dcea52de1a1f1435fc008d246693f38ef05f1957dee04b1e7a8e + 3153ae837aab345e33a38cb4d4e7277dbec1fc15fba9a5d9124dde3d4681ca8b; + 00000000000000000000000000080000000000000000000000000000 + 5e15dfa8d87cde6e726bec2aab6d7c23d059af8ea25fbdfe349f9ee20d1fa3b6 + ce57c0f4eda33d4a4f89336649d50334ee4cbba06c2e3e61ab7a9406507b5a74; + 00000000000000000000000000100000000000000000000000000000 + dc9fa20173488d514672039328f6d51b58f8e08468543cdc74840178ecfda865 + 7faa9670311e55c500d83c0dad131081666d5e3efae876d5d4aceebb108caea2; + 00000000000000000000000000200000000000000000000000000000 + 18f4ceb5efe6105f7557cfad6a335da2a84939887aa9ea69bd72aefe2c2e5d94 + 782f9a52b35d7966ab285611567cc7ab48fea542533da985dbc14945c4fcdd72; + 00000000000000000000000000400000000000000000000000000000 + 770c3b2300ffdfad2c87e1b06245d4dae9c0bf98c8a0ed071c94356e24b35cb4 + cecf717190bdd7b0e9bded5bf59751254f10563f16e4d4e8439e69bc7a269aab; + 00000000000000000000000000800000000000000000000000000000 + 54c6058fe589f2fdee3379bfba956f77f6d752501e76ebc124d65ef45bb407a1 + e269e946d75ef8fcdd9ced031c21f7d14a4640b7fbf34d45236c2cef1e6e5df9; + 00000000000000000000000000000100000000000000000000000000 + 22628fc8d9ccc487132ce5b75fc6e16d729412de93b644c9152d216587f57eff + 1b4c46083ed8c87b31820641c90a5891f82397582d827dc7e53ed4690f12f8df; + 00000000000000000000000000000200000000000000000000000000 + 4c4c2b14336eeffe279cbbf23bcdff9f77e73e7e2b01f27ecceca8adc189b3cf + 9368b0e82b3bac88ae4d521a8a834f53ef6040f120c4e40513a5cf3f7f13b930; + 00000000000000000000000000000400000000000000000000000000 + 30d18017f87290383852b0ecd0a8b284c85a590073c4aabceb860b6b59edfab1 + fe477785fb346cc1f00550f7ae473f0d6c7406ecd2b85774ec9d70057bb30ada; + 00000000000000000000000000000800000000000000000000000000 + 30897b2e3c37ad2ad3d990e71a5a5d87fb696e43430200b63840b6a90ff6f687 + 6564eadc218e0753d51b472c3b8a16f6ace1f08ca436fc43d4ab566423063056; + 00000000000000000000000000001000000000000000000000000000 + 6b86652d2308db067793d8efbabc60c248487a662844d65731c9f352a0b11082 + cbd3b17629ec688bf2404446edc156cf2dae31b7d9e251212fa6e720a16caf0d; + 00000000000000000000000000002000000000000000000000000000 + 902742d8e4b5a14e5b2f6444cd5770169d82b4a084a754b334cd25cea9c4ed81 + b80ad89010cc9ce05d6d7976205c975e1a6c5dc5134d2a67dd0c984591ad8615; + 00000000000000000000000000004000000000000000000000000000 + 7c820a4af9bc911ba3f5848386da8219e0b46d39ce42dec61cde449f348159aa + dee9870c0c8fed693fa8354d3bac82102bbd56eab88b8127e4cd706be81c70b7; + 00000000000000000000000000008000000000000000000000000000 + 6eae2da5a59fc6b3f482c8807fc30add517914fce8b45d346e19b03680f7a08c + 3d8170b8496ae73d6be7e048e61c9a21072ef2023e2b76a744f2012c3a7cc3bd; + 00000000000000000000000000000001000000000000000000000000 + dc5e94f0a7bce3155d87e4e5a274a4bdd20b6268a78265ab00d8f0aba23b9a31 + ba700f0a95807925d6e72db3eada829f80050470b8f13db0a7f9528eae284e06; + 00000000000000000000000000000002000000000000000000000000 + 409bca4c7a1cc9d627010605c790802a9e91e08d6c7febaf6ff507c441b83c3f + df58babb7a632afc991ef13c3ff7f647ed1e073c027225ed5e713235328ad697; + 00000000000000000000000000000004000000000000000000000000 + 7c0429fd417a0023263089551cc9a497c6aa70aaa7f7dd1f07d3b760524a41b7 + dc5b1bf2dc4280dc044c094d4eeab87c9c54b8d1977fabfa3376c0f07ce2042c; + 00000000000000000000000000000008000000000000000000000000 + a287c270e99030621f52acf1588bb8e0aac7dc1859c49e331aad589ea94426c1 + 0d9779c3cb59c8589c6a336c9c459ce19d3db33697815b3a459996d24e950701; + 00000000000000000000000000000010000000000000000000000000 + 06923622b8250acedbdff5cad2f88a8327d7e07ceff7a40520eef9ba4ca7c7a7 + d4738c1a3aa671759b15fe887963eee5782fb1eda3421ee372a5217315e832e9; + 00000000000000000000000000000020000000000000000000000000 + 52660b96d56a3032a48e3c1ccca1ce1fafffd43b05d96e8ecda1123898cca637 + c5d66379ce7c299d4a1958bfde3b035d7e07af1bd640511fb12637ba7a28ed8c; + 00000000000000000000000000000040000000000000000000000000 + b7bc824845abe7aded1676ebeb1b5db28f7eda76830da2348c873d1d1bda24e8 + a3c9daf34c78459933f3d113eca779b8f0e412a140c04430d8c0369697c4f762; + 00000000000000000000000000000080000000000000000000000000 + b9b434ddbd0d969547f4e575819e2012d3429bc172cccad53ffafe9fae9eff87 + 38ebcfba6197d3dabc8dcc1bc22ceefafcd9734f2b0c2f91728480e35bc43d92; + 00000000000000000000000000000000010000000000000000000000 + 2058aadc3e731b05017d412a720696d297ce2975efc4bd202011d3aa43d12ed0 + 3ca5d92cca0b200af76f87b19ca01c328e44b4ce171d8444a42ea529c4586bfd; + 00000000000000000000000000000000020000000000000000000000 + d351e7ecdd3aa6c0826526115dee7a6064988947a22728073ad5d85c77bbc934 + 62fc94852584bee32bd1977fbf330e782385bad2fff9acfd2e62183a5b07d52c; + 00000000000000000000000000000000040000000000000000000000 + 4af5b6af3be9dc3516f7d0785c3211b8c86486b6d171d8653a603903bd592cba + 1815168c3e0c51a6c52848fa4c0c2459b1149854dfe234ea15e9c67be9fb9766; + 00000000000000000000000000000000080000000000000000000000 + d19f4e25914afa257fe634f5b88909444c4670540dd0775b67eba234441a78cf + ff79f959dd28be8a30311b64a9a47f9836966f0effcf80f003144a562ede9dc7; + 00000000000000000000000000000000100000000000000000000000 + 4664cd40879d3e2cf76b67e617ad300b071758be8dcdf76b2d2c3ef3f4538c53 + c4cb7520809efae915b15fdf7d45ff8df6c506e522d72dbaf576e6c724135df5; + 00000000000000000000000000000000200000000000000000000000 + 69fc75db35df38c50e9400caa21e4255adefd3932f01830f79bbe438c5c341f3 + 4e67c1fcb607d92f3107b3f7a84e02c7c2424b59a7beed3e4ad07435fca755b1; + 00000000000000000000000000000000400000000000000000000000 + a6db7bc42c9a02150177bcdcbff996d4e63639367de8a3459d5a422c0a391a60 + 390e3998a3a6b2e5a99719ca25e065ed20162053efd9e64574a679b0b5d9d66a; + 00000000000000000000000000000000800000000000000000000000 + 409ec85f059ce5969f275f36bcec4b7d623a4e2dd6ac4f68abd8d5d7a0a422e7 + 5ad305c93905815c67ed4c67208c50350e71c48ef9c4b4d2fe846dcac41a6cf7; + 00000000000000000000000000000000000100000000000000000000 + 59a81ede728ccae99bedba5ee8d3ac4499579316ae5f7109e2656c558a7a0733 + 2307ba4eba7da1e4a566e99eeebdecff041fed0f1549c595b14230fca2a1164b; + 00000000000000000000000000000000000200000000000000000000 + 0c6b0f0151ae8ee876698da2eac5eac9ba1227e13e98336a93fe3793274a43d4 + f3baa2841495261d6b156a5886578662bcbcd13fd68ac542cd03f4331273f847; + 00000000000000000000000000000000000400000000000000000000 + f510f5e9b370b1b34a4cde599cef0b80c4f657688239f3de82a12376140fd934 + 7ee1e4a96f8b73817a2b57e3e4d0982cb92e05ebb06348681d097d7f55cf12cd; + 00000000000000000000000000000000000800000000000000000000 + d7b38ec40b465126d428dad054a190a25bde83fe1f2ae87db9dc3adcc0bb660f + 04d42fb3907165cd7c1d75da7087da71ba524cbfee56fed771f16dc3e8e176b7; + 00000000000000000000000000000000001000000000000000000000 + 414f693e93a088ab8bb5cf5049d6f3ac67e654e786fce08559dfcd96dc6a3b23 + ccc0fdf2941815dd9c050fd1c9d1e9414492912cdee277465583384a15d761d9; + 00000000000000000000000000000000002000000000000000000000 + 00a7a468282dd455b469ed76c0d67e0f507a53bbc7fd1941e8bd600bea43b982 + 4c8795a55684958d392aea1409dd01020912380b5c81bc868629ccf393594930; + 00000000000000000000000000000000004000000000000000000000 + d1bff2f245ce0690ba74588794d7306c934ec83dd8d7811493726c95822a899c + 856c5179cdae63a65f1b107e0859a1ac790b014746a7bc7bb4385bfc9fff1630; + 00000000000000000000000000000000008000000000000000000000 + d873980acedd7383fdb371beabef1cd1fbb5dadd665f2f118262ad539a118153 + 59a325d64f1e454646459c72f81b797d534a6f8f0ccccc38a8ff47298f1dcb9e; + 00000000000000000000000000000000000001000000000000000000 + d8c4dd99bfdc3bc0d25516a7980651bb545077500e01e3b543cd72ca97844486 + f0334ce2c74691e3aa5fbc12a25d5d6a14fef43bd4df05a2f3f2c9b34d4f2c44; + 00000000000000000000000000000000000002000000000000000000 + f6959bea04ef9ce9e73c363959e28ab6404e8dbca900dd2284f2b848a109f768 + 81f4bfd5b8b0df8b32299d101d339ef40f9655962916b5219145ae074338bf40; + 00000000000000000000000000000000000004000000000000000000 + 411c1c715da711eaba6972e77e408d6f5a76371d10dc7a165f2150c89154db7a + 3d1b85da27fd34e9ffacf8703b958073366ed819459b1a153db135e4a5835ed0; + 00000000000000000000000000000000000008000000000000000000 + c57d8cec898496dfa1331457c00b2d1962c1df9788d36f155ab8b94e985aff15 + 92e1ca0643703a1bfc56842a4d6f87d2acf0ae3dc58935fcba5d847aab6bf920; + 00000000000000000000000000000000000010000000000000000000 + c16ad6e1a87c475ddc84d7664f11932debeed6d987cd05e9c6fc493b0a68e261 + 3c984416b43aa267eb6e0c6a68f8a41ee2a34e14d93839ec47d2b256289b4827; + 00000000000000000000000000000000000020000000000000000000 + cc414cc5970efd4418917369edcffce4be969ef4fd721b376e85f9eb1ea7d483 + fffe4d5022ba7bf9feb0d5e8c8a87df1a49dc2353edf5a2b9cb66863cfd64661; + 00000000000000000000000000000000000040000000000000000000 + b2c9d7c5d8ff0bb054ab8f440915839840e7c9489ac78045fd1b49e0581809cf + 6b0de74a81dbc155fb23b033b45f6b3eb6256fca7fbffb4fcf0ddfadc177659d; + 00000000000000000000000000000000000080000000000000000000 + d68ceb6c0de43d2a62284fc86b872f6686ed0ee6710539cc295fa290d46f3d17 + 3f70e4f08444b9bb7d03552aa0272fcdf3f30803e2608cb299c2880e63f7e24a; + 00000000000000000000000000000000000000010000000000000000 + c6dfe5c3e64ec36a7c043ffe4b119f4cb7e40acf0d1b61fd12bde9f8253f6387 + abd8bc56bc0d4c5d136fcb6af803493efc80f0f0d00fe47ec4dd70d455ab04bf; + 00000000000000000000000000000000000000020000000000000000 + c75facc882297be6c90d4d00bc8acc443c112d7f58a20f819a987fdb01ee14df + 2aedc8d591536166b58e3bb5fca7e63b348357762912aa6a83458186ef315c34; + 00000000000000000000000000000000000000040000000000000000 + 43113d85e6094d67cd03a9111397b014557a6850a8d796e16736cfc40fe0621e + 89730f25612fa04d00a1cc4732efeebba1b80c993238786386cfce09bf10359d; + 00000000000000000000000000000000000000080000000000000000 + 60794b89b36592975d54a0448e7708e6017d4027fa3891b0335cad062ffe8db4 + 0d3401a2c417efe1859b4b165e676a7a5ac031a89094a0173bf46529e0078adb; + 00000000000000000000000000000000000000100000000000000000 + 6bdfe911c6703becfeb5c205f11d2aecc6a81dc22c365b48c1929a81dc67f32c + 61c6c80e40ab88b27bfbbf703522570fd971e8af2b460ea72ec59a92b3701558; + 00000000000000000000000000000000000000200000000000000000 + 24dbbd8de57a959b62a1668e29ebc7514c71ade4fd64c40b482bc98057d77b34 + 671e53090529d3258abd0349e9ec5ecbd0506d211d6228f4e2babcc68699e5ed; + 00000000000000000000000000000000000000400000000000000000 + cf4174ad172064185cb5c1774f08f4e47767579f5ccf71a87e622605041ee5e7 + 8617dee6d4146da406e826d90003fd4f3a77a566d21b8e45649aac687450da4e; + 00000000000000000000000000000000000000800000000000000000 + 016f5989221bbcab0a3cc90a99f6e1f21c9cce56249855bea90eb6b0e3ff925b + cf450821f51f1c80221821fd04d9676d3a81f9c003b692a33d21f21d7054e6c0; + 00000000000000000000000000000000000000000100000000000000 + 00d2fdd6d13ecbde57f8346b651c3d21fac7c08c0d5624d27b77f70583a58c21 + 89de016c263121254e78dbc2df605a71de36313d855994e9ebdc45556e721749; + 00000000000000000000000000000000000000000200000000000000 + c5d03f396dc1b171f23ed0a25571c3f3bd773bb887aac4ba4320afa817e9b460 + c223bee85f757c23c67c009f1b0912d4370315f91cdcbde866c35ed0e205a848; + 00000000000000000000000000000000000000000400000000000000 + 701df4f85e7de8ab8887806541c49911f6c0f3038751d9c109216059df06cacd + a5e35984cfce2a1000a593cfb80f79e6e8c38d5791bb7e96344bfd3dfbea88b9; + 00000000000000000000000000000000000000000800000000000000 + b58876deb62a3c880f51acb743ad9eaa2119321e096d591b06f3dbca6ef924d1 + 829c940bfc3409ec73391740d7652466113ba5a5b03118376c726351747b8b34; + 00000000000000000000000000000000000000001000000000000000 + b6bdcc6d4af946d02f2ce1f8c04df35f1c1790a663ca40bcb57697d780365439 + 99624b3c7338e8f23faf22b4a89deee5fa8bf7022903db3fa36c6f9957a819a1; + 00000000000000000000000000000000000000002000000000000000 + 79d9fcfd5ddb19aa8a8eb84496eed8fc1d815f7fbfef3162273fb108bf230da5 + 9534a0ae4ba8babe4308789f732f6197c6867d222ccbc2eaa064d598a4c24ee8; + 00000000000000000000000000000000000000004000000000000000 + c6c6b524090066e3b3cf196fba642cb3f8c5aa63e734b47d45279e7debcbcb4c + ff20409e1bd929705cfc445c37924f4b2b9151b08839c53b464eb68a807f977b; + 00000000000000000000000000000000000000008000000000000000 + 4c14e7b11e9c079bdaf893fc1e6dfbc38f205e04373760e06afb6c5fefcfdaf4 + a01f116e3bef972205aabe1494f76b70f1c6372b74f79f4a23904c58b1b51fb3; + 00000000000000000000000000000000000000000001000000000000 + 2ab3bb7f3211b75c80b01b15ded624e8046bfcac7c5f88ded7d5e5e030992b95 + 374d7ca16d59e8b6b128b7035caded032134dacc94c88b549e3891282e92cac3; + 00000000000000000000000000000000000000000002000000000000 + 06bc1a54e4a68178acc810f2f9144d01fe6724ebf72225b67a0b138df10dc6fa + 27f3b1d7e61cd1c3b73f72e367a9a4f6fa4010c94a2cfe173850d832e45e89d7; + 00000000000000000000000000000000000000000004000000000000 + f9c484b67e531856f5134b4ada1a231f6f66e6a1d383fbb1e7fe7a7399a39918 + f4c1eaaed3e8c5e62c5573b0779afcbd197aefc1cf881392e00659e0749b2256; + 00000000000000000000000000000000000000000008000000000000 + 8e00b017b4c601c6ab9e606f19e1210ca98b5cf020a2874fbed90f3e9ee0af9b + 2998fbafa21326c14cc0eccf3db5bca7daa744a086e58adbd15537576a5129a5; + 00000000000000000000000000000000000000000010000000000000 + 7fd2a56e82a8a82c0ab027ccfb68acf4b894bcaf0c03ceab68ad3f198d9336e1 + 0ea3d8f711178f80f559bc8f4402dfbe51c6dae84e3fba861050513c4b63f8d6; + 00000000000000000000000000000000000000000020000000000000 + 12eb27967c9c4c286496836bff364450b767e969aa8b53f7dcc1101cdc535eb8 + b30dc7c5d8e4bfb50f29b1be19fd953c6f6d6250ec2f1b9a1fb4b457d928e98d; + 00000000000000000000000000000000000000000040000000000000 + 1630f9a365245fb0b5f8684e3b467ac06d34651076feff3f6718a9c37a1b58c6 + 3240790bc28be631963ea289f5a3266f65bbf0f86e169751cf7512e4c12419d1; + 00000000000000000000000000000000000000000080000000000000 + 8cfd772627622c4ddd26eea011ed6160ede81e488b3c651d4526a34449921724 + 5081e4d0a86395debd81de249553a4936a510f15d07c031cad7caa563ebe0668; + 00000000000000000000000000000000000000000000010000000000 + 2bb3f8ff8c4fe0f4e66073bb662cc09311adf20fb22d6464b4d778250b542537 + 69f83515e69eecadeec5eab86e2f0bbf11ba2bad521a6f21da06ac02331db838; + 00000000000000000000000000000000000000000000020000000000 + fc635cbb01ae965a24eb7e27c1f20b45fd2f2722918ecd8eb362bb52216ba279 + 0a97f58b8cecbb100f67b8d4d46ba01a8f68d6b4c7bd06e28ffdedd28e46f076; + 00000000000000000000000000000000000000000000040000000000 + b35aea1e5f09265b3b7b6748baaaa97ff46d7118491875464590bceec70b93cc + 962374c521986b0cd478f4353c06a28a1203da79cb98a198f3523206b22606ed; + 00000000000000000000000000000000000000000000080000000000 + 89e462fe5d5c5325c5ee9252c73530692c6c29a1a3c7f389f83d533ca1b1a83e + dfd663c857be90d098b8170eaeeb7ed8a6948c8a314a74599691335a8a18c2b8; + 00000000000000000000000000000000000000000000100000000000 + 47d9c74cf8b7148a6427408e3aeb790b355bf02b447bc57c6f8c05b7c51ee8be + 28e4223e24ad191369fffebf62c84059c519f49018427b41bb8b67ee9c820222; + 00000000000000000000000000000000000000000000200000000000 + ff3ce376a28ece62a73a9c00a6ffc69767e836a8a17b49b824a4ad20c0ff0a21 + 630c092e5521f6041ede8c61e73678198e19fb339a04daf94f9f923854f3d7ef; + 00000000000000000000000000000000000000000000400000000000 + fadd0fbf5f7d4eca5fc145d4aa79f7f529950335b9d45d592f3eab084c4e883d + 0f9c8706d1385a2f0ad3a0407460f86def321d3ec5072694ee0272740a12427a; + 00000000000000000000000000000000000000000000800000000000 + cd6248d7199c68291a4d828f24d534f6fa28e4b8706974f439e28625cf8e2310 + b9cde77e2e12ea77ef2ee43e153a26bf09071198249550603c63c7709ec6d090; + 00000000000000000000000000000000000000000000000100000000 + bdc4b06d8fc5e5d3b3285ab19e1210271170c1ca306b61c888230f1d1a6b4c11 + 2e393090c2212bc3e2ae80d367d4a0821dbc121a0b4b7efb989f980918fc3412; + 00000000000000000000000000000000000000000000000200000000 + 2e0b37d02fafd0b335c0e3da36d1b67ad4ff988f2dccf9dfa5722247133f71f7 + 52e68f282e5c041eb7c8d8bef21ef3c7ac045101b3f32211507f781f0f347815; + 00000000000000000000000000000000000000000000000400000000 + 327e75a7c2c7df51c76632e55ce0f3e54ca2cce1ca5bf9bc4dab9bb4c68713de + 49bb9922ddff6cd9b917a2697b399c7f0cd803a0f9ef25bbd06cad0c8a97d2e4; + 00000000000000000000000000000000000000000000000800000000 + d95ad5b34ade4fd38e6c02bce505bef6454349dfe71aaaeeea53daf6944c76ef + 5774340daa33bf6056a6f415c82df4e48da319997b38664fc2a9dc0acbe03212; + 00000000000000000000000000000000000000000000001000000000 + a52178fc875cd004eed999610933fe8db73387b935d06ea14abdaffd7d870452 + a1a6144b8ab070d6a8cde942e6443e72bee40937eb89c3760c94f5fa74c1a6b4; + 00000000000000000000000000000000000000000000002000000000 + 588d9c2260a9ecfa95da0f3ae80ed811fdadc55a6b19ca178d705ddb4f7827fd + e21dd6f24a2344b05df56af868b16c9566c3e93562894bcd82a945ba514c5a87; + 00000000000000000000000000000000000000000000004000000000 + d15499d0351be2608940d7460b38cefdf5ee7503fce68579fe3a186bae4e5998 + 95d149362856e80e436470d08205d79591520d67694178863d929c1283d5a541; + 00000000000000000000000000000000000000000000008000000000 + 0bb9403874309bdac289a847e6be5642e67f71443097d7c1cc9e0787b6c4252e + 600cacd782749f2f91a3a26a67ebe9d31593fd520a8046f5a60cface42853a89; + 00000000000000000000000000000000000000000000000001000000 + 9b9613f244651fd3dbfebbb6dc96b52b1a771aae0b6f4bfb7d71342a0462b013 + 44d70fcdc3c9308e2e6229b2214bf6fa9ac83fa7d3dc0b7a29f2c5f3ec090b1f; + 00000000000000000000000000000000000000000000000002000000 + 259d92266dc21f7d30e7070a48a58a0a739ef71aa4e0c1bf919df19bba0c6e35 + aebd1c82b24831566492dd4b424b824fe95a52c44aa1cca0b5542e1090cc1fa9; + 00000000000000000000000000000000000000000000000004000000 + 27be0b934efa113d8c8101dd8d56c4076398c8d6e7977f347e23749b5a73f313 + ba77447b42e23157c2ee9b4c0037f4c9ea37a9a22e9abe2a23f94d3bddafba82; + 00000000000000000000000000000000000000000000000008000000 + f5430f15301470f840f91e7b75ea4cc7395b43f1edfe9bab362e8939969484a0 + ba43279cb5c71882e6c3ea7a43e456e6e5c8fd15310e38f1a8537f52993e1b5b; + 00000000000000000000000000000000000000000000000010000000 + d3fe3b4294f674572da05aa1617fecde382a03e2a429a7f5257c8aa906057091 + 7a033fd229116872c2c1a18b74fc37213c903e59ccbf0d382a946fc4204967d9; + 00000000000000000000000000000000000000000000000020000000 + 68645bb3921c1c55b0ee6e262e71b654cb8236f1844dc8b83eb012659a1db873 + c8375d6b2755a13d69f6d2027211bc5a331d0bddf05ad8a79244eafd075e07a2; + 00000000000000000000000000000000000000000000000040000000 + ea6fa9dce63e87a3aec87ca45455b89ebd39631a914824edce01560edd20f6df + 1b37c1283b94e96ce366845d3b9bdbb067a489c33c00345e310a2c9086c987c2; + 00000000000000000000000000000000000000000000000080000000 + b4398d7d35ac622252854e8e113cba5a8946ce716e3858105e4261cefdff24dd + 2d6c9392643deb1174875897917c864d9e75e9eb22dc83f754cba0605f800265; + 00000000000000000000000000000000000000000000000000010000 + 57ec1c68ee07d85bc8ed73c0ee1c0b3d7b17ee95094a1b027d00e3359bdc68cc + 76693250618daf58a86d6b7dcea6f4cde1663615cc771996f2bab17cee73c4cd; + 00000000000000000000000000000000000000000000000000020000 + 1939a6b965e7e13d46f888ceb7f41bff97a46a6ace11d3786097761e47c0d4ee + 4783bd9c5b469d4a03fde86a90fab3dd73d009004d333771155889bc19fed805; + 00000000000000000000000000000000000000000000000000040000 + 887c0455fa369ad1a63a89fe53f5c1f1f873e36673a554c19d3251ca1f401781 + 90697bd7073e82b723503b0fb86c3106d6d4d39036e9e8741b9d76f79dca96c9; + 00000000000000000000000000000000000000000000000000080000 + 09ed519fdf745461e1fb8e10471c54d52f3455fb7aa6db264b2757b02829ed41 + e36c4cfbbc607b301a28f6c0f96774722d7dfbfedde89e97674438ed31fc424c; + 00000000000000000000000000000000000000000000000000100000 + 61b58f25174e379b185ce40c08717b11460e6839c1dc0d0a7430a9f367960376 + eb6bcedc9b1a70fbb749f9535f59d60dde1a6a3de6cf21d083bb43b696d0d455; + 00000000000000000000000000000000000000000000000000200000 + 98e164ed01ec6f3a53ec5eb1d7930aa8f7689ef6d3b3f5359618d53a6f291180 + 539a4febceefe3e49cc2dd3100b1873ec5a6b03c04544bd9930e213bcf79c5f4; + 00000000000000000000000000000000000000000000000000400000 + e9956f811053405dffb566909338e93bec1c4ba2a02cc5c6bba8def3570ddf29 + 8aea5d2e8e322dbc2454e236228a6661c2e49bec36749e784398b8afde823e69; + 00000000000000000000000000000000000000000000000000800000 + 423e3d2da9cf293c881cbabc625ebc58eb58f68cbfdf74eca77d0c85def81286 + 138283360cc8db7f3cb1845cc2d7e3dd55698564c62ff10cefacbc7e754bda0d; + 00000000000000000000000000000000000000000000000000000100 + 459fb60e8f40da7efdd66d01a15959a3ceecda42ae8bae622510e92bd4374c43 + 058ffc8eb9c8c74755f80ff096b1ddd1f9ec9746fdd63f81fe94f5aaff3a4455; + 00000000000000000000000000000000000000000000000000000200 + d56a4841787cdb240d452797278e2065d92d94284b60ac78bb0d90775dbc9172 + 6414921eac73dba768b88d3753b4b61bee16ea189676d58c85f758cd4a04891f; + 00000000000000000000000000000000000000000000000000000400 + ea53b043630e6f958784f0f7dc6354418901f654c4b06ff40ab6c4909f917ff3 + 50eba9af77a57a86c497ac90e535e47645a967e5a678735e9db13175da4eaddd; + 00000000000000000000000000000000000000000000000000000800 + d7f30fa8111469c48de76fe0d1148ff48675cdfddca0ac977330d094ff796b81 + eaa3b53439f65b9d8b47a24ac6ff75a66e93aab097670ccf484197c868a0216f; + 00000000000000000000000000000000000000000000000000001000 + aef29399dee534bd8ff17b1b2057787a151255bd76bfce66f6344194009935fd + 7489520edaff91fca342b7a90edfe649756e561662f41db5b12fbecf99219897; + 00000000000000000000000000000000000000000000000000002000 + ff1026c8390f4688f025b03a0758bf56c2ae84c580ade19c22332eb5dabb2d65 + 44c179aa7070f032236520142146813b55a0a9a58209d3e869b8969e66935073; + 00000000000000000000000000000000000000000000000000004000 + 43a11b9a09783a0d7d079eecff5933c84b52f96efe0e38a21cb97b6410663128 + 2216c885bc941c655dd6d0ba0b32944c2e501823cf9b5322b51827445b74ff7d; + 00000000000000000000000000000000000000000000000000008000 + b8af4aa7c1fe35b031ee050dbd2d247091f173179686ef8d0659446d643f2e14 + 73044c40077491735fc44b1471a94c5585d0b267971270e18a54b67954e52a80; + 00000000000000000000000000000000000000000000000000000001 + 896855032d11655c16bd94f994b8f47e2f82be1c0b3a296bfcb18e0a1e9b4edc + 75ce1a2f4d77d032b86cd65dbfd97936e82d76f16f87247e1a9fd39b95307577; + 00000000000000000000000000000000000000000000000000000002 + 0082359d931ab3fc8791ea89c01e74d7a6ad0e40c7a0fc369055c28f8714c679 + 648955a8ddf7ac11dff9967156faa35f1e5bb74eb92e395099575b87799ff709; + 00000000000000000000000000000000000000000000000000000004 + 7bbd0fa76452768bdd69cd448b13b28f1ffd689df6e4f4c0c0201924078a702c + 3e9efedff4cf93e8bd34c4a1a8f06916410fa99d326a4ba831aec1c1d9c7d60f; + 00000000000000000000000000000000000000000000000000000008 + 5cf1e70d83b64b87b5b4533a0d0974a871fce3d68b085587e4434d1789c5a036 + 2cb01ab75e4ac0d2d248b1e2fe2c3a43cbb99a90ca7485357eff8f4bcf001ea6; + 00000000000000000000000000000000000000000000000000000010 + 15ad3287e48777b536309c26f3d4cd928f9f11c2d88eed60e4ee42151a78ad6b + 135d93ca9bd490f23afd619476cb934e42f7b383cde0c5db99503b3fe325b34b; + 00000000000000000000000000000000000000000000000000000020 + 7206c6beb79aafd394150835d6f2bccf7d7454b6c5b80afe0c8afc311430226f + 95373efb0b18c40fd7a2c98bf86805c0b8e6d964e12e025df90f1f63e631abb8; + 00000000000000000000000000000000000000000000000000000040 + 34adfd7c6b2ba94580eea815dc441161d91e427412f54c42df398360f43074b7 + 635bd00a91fe3410088ee2dafce819f26a2f44e194fc39732cb56ac470536592; + 00000000000000000000000000000000000000000000000000000080 + bd56867e5c02612bd20abce0a51c8c0a9a5c3ebe27af33b743d22f1862bc9b40 + 393bc6a1c9cef4829b5586e99952006b7e4af3056df28511fee2902eb5d30940; + 0100000000000000000000000000000000000000000000000000000000000000 + e15988e471d6475f8094d5704775b2ea578ada4ccd7fb6bdda530b250688c0a7 + 9b4c62614948194ec5e0d4672100f4cf032166ee1bad7d12ac3c3c292992bb01; + 0200000000000000000000000000000000000000000000000000000000000000 + 384fca7c5554145250796aba74422059a6152117b9bbf50b492d8dcc4fcd9fa9 + dc2c3521c82fa8613489e815af3bf6bff23a61a31e136870e7b88df6d2c9ef50; + 0400000000000000000000000000000000000000000000000000000000000000 + 12390d4e80fbb7ee99c80a68175dcc167177486d618d1baa5009587cd2543496 + 7ca3a28cffaf1d2d71aefcacb467f7176bf23325406236a468f9a2b75ca67eba; + 0800000000000000000000000000000000000000000000000000000000000000 + 8c43057345f8ee64b5e04daff7d9758b663e27d9249c68401e17650d38418597 + 75c3b729c8e8da036b60b63af24fc564a3a4ac1eb2e92fd59158474f744c5a12; + 1000000000000000000000000000000000000000000000000000000000000000 + 2b7e0219d0d2dfff42597690df40e53c8bae17d0d363eb001636f91658fd4d78 + ed444d40e243dce63b77c45a4eb89fc5a0af2bab390e32903c7ed80ebe3fd989; + 2000000000000000000000000000000000000000000000000000000000000000 + c0af2ffcdb963b3f836f09d07dd7529ca029baf32d683a030d8b70f64115319e + 81adeaea6574660ebf126d45700aa212d7df72cfb15ac7320544f901c87b364a; + 4000000000000000000000000000000000000000000000000000000000000000 + bdab381ffe13374b4c0fb2befb836b2a5676f551d9879230574063a7da33f55e + b73c6979db28f0090352ead9194481458c53a75716e82eec0d392f80cd7f414d; + 8000000000000000000000000000000000000000000000000000000000000000 + 059590c11ad59af788160a3dd52ba242f35e9d7c9ac2716732d45892fb7e311e + 1cf8b9d052386a37bad7006fcf1a5ed0b2ca509fa9b408d164928465b7df55ec; + 0001000000000000000000000000000000000000000000000000000000000000 + 2f59734e38211765d309b8885c0d7f12802adcfd236259e710b60f215b17e91f + b7543107d7a8d59fc58ccb5bf9cc9cd3b0aab40b936519018321e67ee4212f3b; + 0002000000000000000000000000000000000000000000000000000000000000 + b459777f2e4be5802ec40b675b180cb7362d58849b5a1002e9006d684803d1a1 + 263e0b651894b849ebcdda7de136f12c2b417864d0bab6d752676645aa44663c; + 0004000000000000000000000000000000000000000000000000000000000000 + dded78e34b5117415696866ab8277777298ba600ef8ebb0a833ada9f0fb14abb + 048cfb659677a1f6021da5cbbe7c045a6630d62c12354ba889f16dfae298f0cc; + 0008000000000000000000000000000000000000000000000000000000000000 + 23f9f9b2c9a37dbb2c46156eb1e369247bc9e3ab18b392d900933fdb2319dcb4 + b9116aea9a465f603f0d0b5f2b432bbe2eb8b5b7150cd41c88df744d1d157458; + 0010000000000000000000000000000000000000000000000000000000000000 + 00d9408d7012e74b3587b5549ee41a45150149b07a71b11b5a6787d0180405c1 + efb7ea812e9772898305defb02e62520cb5518f11bc7d1cb72aecb2a230786e8; + 0020000000000000000000000000000000000000000000000000000000000000 + 0e1acef35626a60c99bb971a72fbdb80d40adb9e1566e522f03d0d9781abb92b + 39e66a48d565bc75e2e307de3555f1bb2161fab013186e827ef720b5e67af7e6; + 0040000000000000000000000000000000000000000000000000000000000000 + 147cade7c9326104bf45afe6b8c180cd7a8a45ed9e1798846af473f241424325 + c8b47d8c7fc71f2650dc9fcd2e76656486f7f2cf79d4fc3e5b0397bf19a268f0; + 0080000000000000000000000000000000000000000000000000000000000000 + e435935752dcf49c03afe77b217af4fe8bfe3b83be1f237e80b1c5396aa60635 + ad3294a5729d4b56f5cbe417867b2895150207493091ca5b2da71661a837ea45; + 0000010000000000000000000000000000000000000000000000000000000000 + 2b0962a7233ae8f0f0c6f82d96f1fb6788b57cea3e20b18d21c01fb20c523e45 + e282636fae01bffda7e59095c3b46c85ee2df7e2f3f4eb5e9c423459dd085ae4; + 0000020000000000000000000000000000000000000000000000000000000000 + 150ec1d69180c1f65fd412fabc62eeb80146a46fd5fd7a7035c887da5d712812 + 95aefd097ac6ca69d1dc282ae7ccda8409ef4ec0a4e8d7e052a52313c3d5fea2; + 0000040000000000000000000000000000000000000000000000000000000000 + f21b883c84743f00ae25aa937c88eeff2820c8b7ec16f485d811fd58f5758710 + 5ceab4fbe84572e441c6d31bab9c213a29aeda39b5369cd5a036f0d5d3052ed4; + 0000080000000000000000000000000000000000000000000000000000000000 + e3790ad0decf178ff259a5c7340f944c253551a0e2a0efeacfafe6cb49774d8a + 93ce491989013119060c84df54e1ccf3627ce8149ff44100c08b903ec868dc29; + 0000100000000000000000000000000000000000000000000000000000000000 + 3eecc58989f78b6969f687ee0aa2c1230af4bb0efd5e26008e798b802996b458 + 55fb0121a5c2f72d1c830f431ae990c24071ddd60fe7ed997d92f433aa53e66c; + 0000200000000000000000000000000000000000000000000000000000000000 + ccef63e7caef39a6ade4da89f2fa47f4132fd354b4d594dffcd40db73171b787 + baf36d6cd4920d94301b649592ba1e990742357ea55191c40538a761fde817a2; + 0000400000000000000000000000000000000000000000000000000000000000 + d39bc7cd53aeafe63933d8bb7130a1d2fc85bf58bf76cda3683349a5257e5feb + 4e8a84d2bc89a1b2ffd5fe2e8ad3c5315bbaa5be3e9688291fdea97b19ec425d; + 0000800000000000000000000000000000000000000000000000000000000000 + a3d929cdd10fa4b13adc1df77dcaaf9348cd8993305d3ade70ccec50d2747d88 + ae241bb3dad4d6400c3d3ecf5587ff814f71708d9d85003b461ed4f714bc2830; + 0000000100000000000000000000000000000000000000000000000000000000 + 641578d6f15bb8f26e1a4e96b798f7f7e1dd592ffcd472f4af3bb90292835e38 + 8b66ed19f74864e216e4c1962326876c3d015c84f368992a51a3a7c66809c8d5; + 0000000200000000000000000000000000000000000000000000000000000000 + 81f3b791c83a0dc0da90a8e5b1460033240aafc65663b5ef8ae4b0988acc3070 + 4ba6a9d06282dd9854b5e75e3989a550a37c1a00c12199ea5c859f47408186b6; + 0000000400000000000000000000000000000000000000000000000000000000 + 59359a60897c5d84c7c3a2cfc44408a9a07f3020d2b7c5f1eaf41fd08aa482c1 + 836e0c9e8c3a7974cc99bd938a7c9c596d21d1fc7e8674321b1faebb9aafe0e6; + 0000000800000000000000000000000000000000000000000000000000000000 + fd2541c2421b5a58f8e9c89f9bd93a3f214690c86a30505050809f0e17965ec5 + 52b5f31bec989a9c167fb3bda2d145ed912e656435e4c2720b109c4161ea6499; + 0000001000000000000000000000000000000000000000000000000000000000 + a7870f4f9859f4c90747cd5a3175576969893f21f80644a85ca361c64c2760e5 + c025483295777b1b75c3f4c1311c1621d40ef55a8a74dd0f85afc16c33141731; + 0000002000000000000000000000000000000000000000000000000000000000 + e7ae0b42a64b89f72741ff01fa56ed16cb405d7de6af172da31d28b6624394e1 + a3bbf26da16b92b30f5be3f1b5a4b82ca60fa12330f546f6dbe21692397e6007; + 0000004000000000000000000000000000000000000000000000000000000000 + bea4feb7093ed08d59b1a9e367ccd59c81ac315e4fa6bff4dcda083a54ce7713 + e17743b422ba9726647323c9d863b28f672f0635965bdc5e99fd713a890fa807; + 0000008000000000000000000000000000000000000000000000000000000000 + bd7d0e194ab34c866664434679054a512ff4520c382a2c16164e3b92579986ea + 2b901d39fe9d3ad0f151be728cc8bf052a5cad3fd622da0bce99df60f5d0b900; + 0000000001000000000000000000000000000000000000000000000000000000 + 26221c4832d8daaa40a4cdf52027ad389342882b578d50690bebc93df5bfae86 + 906cbda011d3f989b85301d147e5f89c16e0d5f5236ee549f463d8e7c1230ab9; + 0000000002000000000000000000000000000000000000000000000000000000 + aaf7fd79a7ee0cf2622f61a7dde9ddd110cf585989f9fbcaba4bf8c87f97a6ca + 9221202cf78d38d22b97d3634615cdd7a1b327d0cf2edaf7ba665e2ddc98ffb9; + 0000000004000000000000000000000000000000000000000000000000000000 + ea7e4e250134fd0a6d57d45877fc13e83bd8eae4bd096371ac85d09b634888b3 + 3295b4d323d829813a3c0bc074075c3e133979d02137237ddf6abaa52c3d6633; + 0000000008000000000000000000000000000000000000000000000000000000 + 3944e76bdaec5b16c8c76c7e06452163f22ce79092bd9e3a024aa5c208eaa795 + 6f8a8a7b2dddfc1018cb4e0b7757f3e1444514c3ea056ce0cae81b8701de92f9; + 0000000010000000000000000000000000000000000000000000000000000000 + 3b4c4ac914d85958a0b5e7b8876575573681f0b313cfc0fb7f444c9e7e268615 + 312e801156e12476a12b20be7468806e9f28bd00e3c0647ba9220be6167045fa; + 0000000020000000000000000000000000000000000000000000000000000000 + 91bef844e50dfbc56fd6e2f3b7bdaa1276c316876dc81e1d6403ca7d91dd0e3c + e9dc7208167be2abed48d00beb3b9859b9e4eea2b54ae8c8bf78d59f5fdf6bd6; + 0000000040000000000000000000000000000000000000000000000000000000 + 9e024081abac727a02f619c51ce63bed18745597dce3b48ede6f61f808bf9dc4 + 2c6eebd23f08b4e8a9ba12c04ffe281c6fd241a1bfffd7850bca3e8e9b258c1c; + 0000000080000000000000000000000000000000000000000000000000000000 + 1659ebf81126d5ab0ebda35420c9be79e92a439b50660ba62dbcaa62ebbb6bce + 30972cf1c7ff5ca04ad0636279a0a6e4c9fe9a41af9d3d357f286fc68ebb0a6a; + 0000000000010000000000000000000000000000000000000000000000000000 + 114312df5056368e8facf69d0dafd7f99954ba6188579e70eca4daaf63a4bf8d + 6ed87684e24e9e8c80e7a974280a4a7210b2fb50578cff2e87f3c4f86eec23b6; + 0000000000020000000000000000000000000000000000000000000000000000 + bb6e664338c2483b6619919cff1cbd4a133e9bd461184b040fdbf08711a53c0c + 5a6a0f2f51d127d55e7659c4cfb59a4e17d329bc299ab38e18e3140c562596dc; + 0000000000040000000000000000000000000000000000000000000000000000 + a467e32c18c448d11324ef06f11efe402e7b8a9411ca83e52ae20a82eb5df7a6 + 84c2e9f00dcc6856f70ccc51f498d85679c79240f371937fd4179c5c45b0cf25; + 0000000000080000000000000000000000000000000000000000000000000000 + 0eac2d63862bf03c7d9acbb84b3ec60624a40941764d1fa716d6e08f5039f114 + dc89b1858f887d16f98b1f068e27f7d46dbb8a0df469541423d0c811298f00ef; + 0000000000100000000000000000000000000000000000000000000000000000 + 97537e552910025fade2073196f52788773bbae3ce6c7b1fcc72b55ff7ef3f0b + 49d9bb818972c65f846c31dd70412de0a193fdeacaf609dd401e929b23914e9a; + 0000000000200000000000000000000000000000000000000000000000000000 + 9408c086b3246cdd588066e449a9be69377a74c14b1f00994ff2094af3747861 + 74bc32c2914794908ac3ef670a00f9dd28e0037add9eaacfe07da756042b050c; + 0000000000400000000000000000000000000000000000000000000000000000 + 7ad5a463142244224dd5abd8342df7126e0156d92af07aa012d63b5f1b44fb6e + d82d65ada9a01bd4e9b3e79fe2d15a2075c392865b647e357099b3f1d61c92f1; + 0000000000800000000000000000000000000000000000000000000000000000 + 6d65afe3a94c84045bfe3b6aa7b159c68a64464a71f4b5a25de424d4b8cf7d3b + b80da8204dbe46d527b120b4b025c01541f6d51bf962303cc276f8610558aeed; + 0000000000000100000000000000000000000000000000000000000000000000 + afaedc6195d899fd7a085f180ffcaa940345956b194d340a2deee29c0dd2d971 + 7b88861666b09d3dd874eee025910267da0de663f3762fba0d5183ac81b59a24; + 0000000000000200000000000000000000000000000000000000000000000000 + 6ca33fb495f9b49ab2434c86bd50f1c68bf627fb423d5785d9a94557bb789a32 + dda8002e8a2c6ae938a347121e2e6a191b11a47fe0f2609d8df6504eabadcd4c; + 0000000000000400000000000000000000000000000000000000000000000000 + 048745f71e427f377631cf8b93d762ed69b23d5ce92cf88bbbd1c39d83c50962 + 9b467d9f35a61cad87273246229d0a666e7d37b4a3c3ee48e89f7316b59f9258; + 0000000000000800000000000000000000000000000000000000000000000000 + 199409ed0f69f84c55ff5816d48f78d7b9ba691a2f4c9d41f38f20e01cab00fc + 8168a685bce08ec00ab7e7fbc20dad4cf1a9af5ca3cc7fe72ab7a770bdac10da; + 0000000000001000000000000000000000000000000000000000000000000000 + 130e28c699dce84779ddfaea0a45be76cbbf3fd14a9c71b50c9ced5eb2cf6edf + 9d17f71aca5b6175d82e6a7bad34a8d21a4bc1bc404462807035c0c855033865; + 0000000000002000000000000000000000000000000000000000000000000000 + 4a376dc814c679fb3fae93836a06bad1cd77db067f76ccfe60987559ed4b7cbc + 26932158e76eaf55cfba5398b06d11ce6c88b078aaead0ddedf5e5b2505d5ed6; + 0000000000004000000000000000000000000000000000000000000000000000 + 5a04e963f90bbd5bdb3f616f3d52f23dccbc4652fa313de5d1fbf70c829f6261 + 0c65c4f4d6adbfbeb91488a00e16e978a75dcdaa4ed9302148aead46d3f8e8a0; + 0000000000008000000000000000000000000000000000000000000000000000 + f4efa7971e1b1cbd41d9ccc7c84b46ca24781c118409fdc8d86ff3825c033e85 + 0393c2f10ddc2c93911de8c22b192dc78be826d84405beb42e5cce91e0234620; + 0000000000000001000000000000000000000000000000000000000000000000 + aab379abcb48184edc2400e7942943710acaf92763cb82368779535b2fc1f3b3 + b29bde1e9b5ec2d359a8be97db7bcaa7bde9f2c3e88c6536b3a58d62bd7c1501; + 0000000000000002000000000000000000000000000000000000000000000000 + 308e739a98aef258e547d0bcd9e204da0f2c7d983383650506e66e9dbd9b0857 + 9089ef809029209d37c2895b5f098e38d68ecaaef8c2d6fcc04d72928b921c59; + 0000000000000004000000000000000000000000000000000000000000000000 + 1f7a8bef337a14785dee818be84bc9350fe1951a9a6272f797ea1f5e71a1b022 + 39148fbdfc0e0acf1f30123f11b67d72651b0d87b0e8541c9c232f07e2f93549; + 0000000000000008000000000000000000000000000000000000000000000000 + 4f0c06166efdb1bece929d31c2981e96b4a5935f1c314e4ec0b10c0c761c8f7f + 68cf4918507324eecf2cf991b5731b368a1c6bef35fd1f1c940929b1e45b1332; + 0000000000000010000000000000000000000000000000000000000000000000 + 7714ca9fa1ea7c235585ade167931ea4435a61d1d983aad7dd5452b0a291befb + 32f56751d799fe84ce7075cfe927fdb57bbe7e06eb9c88dfe4b14497a3d8d6d9; + 0000000000000020000000000000000000000000000000000000000000000000 + cb00fdf9a48bb507803079638584ba025d303d2b0cd5b81de2b644a61ac5d891 + fd821a3c9d6d04bd07a28669046eb4a7764de97e056f0aed9356d06046365ccd; + 0000000000000040000000000000000000000000000000000000000000000000 + 7af41ede49449402d065d70e9617be50ea74283c639f75a4dcd794950a2ad075 + a9126f01a04a287ba196d148de77256dd86b41a4937fea307e19c40dbdbb253b; + 0000000000000080000000000000000000000000000000000000000000000000 + b5736b632b346a2210ecdeb95a0337903449fe2154ba97da8ac5213a5cca2453 + a4a924f69ed450c80e1c090b327b75ae8c900bc0530bc580ad9096545e60dc4b; + 0000000000000000010000000000000000000000000000000000000000000000 + 305cce4b3deadb80ca17a1f06bf1a8dcce2d1d66f2c25e7b2703062460f0b7e2 + 9071f39206f73eb7e1af21cbfdcc006a017521078254de35af24593f093ebae5; + 0000000000000000020000000000000000000000000000000000000000000000 + 17fb9295d4f1e2c6717227dc01503b953dd54b327029b8577480a4e87d7ca1c0 + cae92b888cc88e686a780206dcbd4d301e03ed5258fe0d8df01c8d8b9d6c63b2; + 0000000000000000040000000000000000000000000000000000000000000000 + 27cb60b2e45fe4d7580ecab6446613dd2e9c773ba905a724458c51a2dcc1425b + a57c7f3c84048bac329e1e463f0c7226c51c9e6549d3379b78c89176ec316d08; + 0000000000000000080000000000000000000000000000000000000000000000 + 893d82ceaf9116fd2b78f36c570da29b84d7fea87ee8f0f6678652879b8d50c6 + f3f98c24d5c885055d318006e2cdff776412208b714d286cade4d3541686e281; + 0000000000000000100000000000000000000000000000000000000000000000 + f8dce549ef52a9912c8aa83f82c818dad9252b7f9711c828179329141e3de5d0 + 819acfd983335211dc97948e599fa664319a9c589ee11c181c5c0780d379d77d; + 0000000000000000200000000000000000000000000000000000000000000000 + 2915e806c01c17a353729c6c3f943b9c34e9cfaeef6becae2935d471a34f0940 + 548123fe86f653b4b0a10e361369be8f0863b4b5f15c34d7ca2e48e9e25d1b5e; + 0000000000000000400000000000000000000000000000000000000000000000 + d9a23e63ca5828b15fe38ad7e48d44659263d27f0390af84066154585087e771 + b26569bb88ab49ee647671a9cfd14764d60efa99e7aed11ee373af93ed061f22; + 0000000000000000800000000000000000000000000000000000000000000000 + 1d24835d30eb9201019d8444bb92f2598bcb1ed42346acf53810e4aa8788ff73 + 8e0c78cbee01d9ee871f2457743ef0362c15d9c93d23a12626c4e80623903181; + 0000000000000000000100000000000000000000000000000000000000000000 + a0cecac4bfd7aa747230a7c795997255068dbbba5997633ead02ffb3454619e6 + 018a38a0e5ca7db27847e3eb2854a4d6a64c0a41b3c59cc3d38ea58ec25dc93b; + 0000000000000000000200000000000000000000000000000000000000000000 + f9a9da5740a32c62bcda5efca357870d8725965abc40aaf260a18fd4ac42aa43 + 1eca828dee97965f8e8d7c1b0e87125f8f9ac3b6bee8b0b730bf3afc905cd19a; + 0000000000000000000400000000000000000000000000000000000000000000 + 4d2aa6eae1040cd338063d6cb66911fc026027db5a53b91b3612d11b2be3f710 + c749d747ca70eb7bbe5a160bf61c1e1f573366a473943ccb60129e46ff757792; + 0000000000000000000800000000000000000000000000000000000000000000 + 21b0debd7ab6d7149c058c9d69f466f9480b9ad20a59e807c9186496023f7b79 + eb1556e90beab9b3b1c5f9e520de345877a2ec446f0976f76bba0e11fe056186; + 0000000000000000001000000000000000000000000000000000000000000000 + 612a8d66984e3e664af0daeae9bd903e04f63a761123d7536639d027ced1d682 + 1577663f2b58aed2fa1b2eb87d1e86d8af977ff7439c52d4947a29f7f3ea2605; + 0000000000000000002000000000000000000000000000000000000000000000 + b502222789a36d5a9a245c0fff70ea43c2e96e5fb57fb81510aab99f80c35a32 + 0303b621ed6b340068159fdb857eb2a5479dfa6183604730b72d01233fd71586; + 0000000000000000004000000000000000000000000000000000000000000000 + 3df5c158a338ceaff80de71a2918dcf210ea5001716256b445c82ac4691f1fc0 + af811728f6e887608a5b6795b8ac6b07ab68ef95394effbf6d46b50418a77a46; + 0000000000000000008000000000000000000000000000000000000000000000 + 39b25d1e214df0a0283bce92879f056beac64269f127b0494c5e8fd4ac4b6ac4 + 5e3e7c6d0dc7ade448def91c280287733a78bba5fc3f636f9d8a6552b0142b7d; + 0000000000000000000001000000000000000000000000000000000000000000 + 00fadb701238f00fbb1d1096d3e451bed024b66aa9274760dab49ddac5c3946d + 020e78dc0f6e465fe54cc7257f547f1b48e908bf6052d7e3a5f55b58cdd507aa; + 0000000000000000000002000000000000000000000000000000000000000000 + d1c21ccbcddba34b3862b0d3c0e11e309458ad69d5ba1d42fbf33f8d8a592eb7 + 8427323b69e874b89fd3c981244e6c1a98e9baafc9cd7699028b54d5a80c4bf7; + 0000000000000000000004000000000000000000000000000000000000000000 + e783e2f80223d3bac0e249c4af0fdd6f765199defa2831e1285aa7969cd57c63 + 44935fe4ef59a0979502daba5dfc7c16ec69c1af8af85a3fd8bebd486929ea5e; + 0000000000000000000008000000000000000000000000000000000000000000 + 27bcfbd734964e7fc8a634b2ce3fa63ee453235af33b689fdcb47d6aaca6a6df + df37ee8f5ca3e21e7948163c9a189852f7df18b117e4743dbba2c770f670b8eb; + 0000000000000000000010000000000000000000000000000000000000000000 + a66846baae257774b4cdbf9ed5257c9c18c070836e35d580b95e2a7b961ff402 + d77a334ad77df938ce6042c2c06c868c507b298c59010a47eafee4203c9f47f0; + 0000000000000000000020000000000000000000000000000000000000000000 + 0dbac39c772bbe1c52105d00fa32d51a03191ed6707e175680397623e793e9bd + 0efe80fdaff4975cdcbaf28286917ad218a6bfe685fc5bdf616a40e2171297ff; + 0000000000000000000040000000000000000000000000000000000000000000 + 8db6613e226d37bb68c89e455efc591f7e2b7b7da543c3be7d9058105ccc2388 + 0d74d3b700d64545bf4a06f0625edf7d7e3a8828de3b6c95ca42e1e5b19a06fb; + 0000000000000000000080000000000000000000000000000000000000000000 + abb71c9c7f39df0dc16a00939f50759ab116eaf2024b7e690c0469fd9c6477a4 + b2432584bf1f12c9f50b9f51db6ec5082cbfbaa85202d903fd3c790a7e8c3008; + 0000000000000000000000010000000000000000000000000000000000000000 + f0a0ee6776fc98821b1695e6b253eb7eb3055f779fade81bae006e98f6dfe53a + 4e38aa14fe50a3ede3998e72a989dc77300dd5e216b4b41fd23dae7d59cbad7f; + 0000000000000000000000020000000000000000000000000000000000000000 + c24fb46f0f7d123468c9e4ec68fccc7eb4986e44c8110733d1268c124f238711 + d0aa9dc510363f80f3bd100f4fd816faf90e32b941b8e5501a171edd01ea91d3; + 0000000000000000000000040000000000000000000000000000000000000000 + cbaee780343e98edb69d95e50fe41cadf820f8e7959bb0f2580a14014df68335 + 0b13c8fd89a314d72478401f4e39d5817a9a98103ab45a458f8d23b2ebd4353d; + 0000000000000000000000080000000000000000000000000000000000000000 + 06b5fd3436cb561d100e3d1034d4c790a35e3e634fe76ccb028112818c581ddd + 2238d8f8aade266f01cd8f189bb04ce9fb8c2f30b5290a6011f2ea392cb5d716; + 0000000000000000000000100000000000000000000000000000000000000000 + b0d0316c92cf2844091b87d25ebefb5a0dfe2d60782962b7f65cf974ffc5394d + 7e6a4fdae611b25c6d62fae841a2a8b0dd5ed0f56ee0b652b2233624e9e55717; + 0000000000000000000000200000000000000000000000000000000000000000 + a0687fcebbfc5d0ffc70dfd89701eae4dcc0e0897a61f7d02f3a200e1fbc0195 + 52991b10dda46ae9a31210dd90e997745dd7a45d6782f621baec5e1b09c652ac; + 0000000000000000000000400000000000000000000000000000000000000000 + 7885103c2ddbdb34f21679c908148b48affd3030f33135ae6aeab813d76e4c7d + 32662258f351ed45638fbd08f4a9ece8cbf4259973336276ef51883445b067f5; + 0000000000000000000000800000000000000000000000000000000000000000 + 1d166eb905ee23d8608ba8df50d9ec70a29423bd25cc87cdacd5d8b3df321535 + 587b6f652ee658e4ffa3a16b95d717bf692eddb0f85fea3498ed89e2debbd053; + 0000000000000000000000000100000000000000000000000000000000000000 + 8470559686b1ce1f8297a3a2b32087cdcad147773001dd844fb4fc61bc0fe45f + 29ed1711366d01a87565165de5cdd0c817ab620aae1573be16d28cd51cd0e8cd; + 0000000000000000000000000200000000000000000000000000000000000000 + 45c7e02ac7f22af7a8fa1b6dba56ecba6be159a7a4537cc34d5970a0aab038c7 + 477d6fa3adbad6057928cbcba71d116fbadc96bec9ebcf5f1bdedd39e32d1cb0; + 0000000000000000000000000400000000000000000000000000000000000000 + 162c6b51feb10bf69bcc8fe12859b447b03af9c63d12239f1ad5ac948f3763d7 + 643e17074976de5a5ce66320e5ec38b631016e2d3caabe52f0ba8e56a9d0badf; + 0000000000000000000000000800000000000000000000000000000000000000 + f9299e0e09e8e4d408da8f4dc9e15c11b8d8e4708ca5c73bfc8714cbe42b9457 + b64579adcf37e3bdb652e15fd7221d9bb23a149b9d0cd1bb621aa60fbbea3374; + 0000000000000000000000001000000000000000000000000000000000000000 + 700ee74a28732eedefb1926e5557a613e00ffc91cc3d9b18e2f51d89055b9eb9 + d52db33d671e9c012ecc5f594b12fd563e5cf1807fd161a863080398b78bda13; + 0000000000000000000000002000000000000000000000000000000000000000 + e6e8a4eae096448cecf973ce287a7ef8e9fa41de4c3b05501654edb2c1271af2 + 1fc805e11047c0d487a61fc552569975636ab111c186231bbf05b32c95d2ff45; + 0000000000000000000000004000000000000000000000000000000000000000 + 1c1de2c45285d57eed9cd013370e3b8a57d12fcd0050ed324d641ef797fa6d57 + 1fb31c871cb66f8b0d651001bc2924b413075cb398d6a03d77b298e6b28d8bc7; + 0000000000000000000000008000000000000000000000000000000000000000 + c2e9773c4f7fa499d72af9a0487d4b02aa43ef91c5902875fd2c85c022a7be79 + 7f4575691fcbe4ac4ae9ad4f8e49d403d1d41eea43fba36c671e6a826fd16442; + 0000000000000000000000000001000000000000000000000000000000000000 + 0ee9c279b05d527706f721ac45b2b75c55cd9b1906ccdcfbd29aca32f69053b3 + 1d7ee6cedb4c2c169a5d0e511b62772e4b40c4bc8940aecafaf2e1e09b5e79a1; + 0000000000000000000000000002000000000000000000000000000000000000 + 278dbffbcb601500a725942fb302ba2ab0c6d206db5d7878979d7b2ad8d4d199 + 6f74aeda2cc6ee5704d685bec0de4363cb79679200f0ed5530a36e516ea86d68; + 0000000000000000000000000004000000000000000000000000000000000000 + e8c8c0fa175ebd8380573e7932d219a3f116d14da69693f2995471d9be202d05 + 5e1c3a0b22708722d1611b66af966d1f6d9f8faa851ddb01830b97e2d9bf383a; + 0000000000000000000000000008000000000000000000000000000000000000 + 283d859298c1e323a493a2e949ddd4c2ffa4a5da29669b348b5a72ed8c8eb1d2 + 272552fb9fe36123cbcb0e43db68b2233336f6a84c99ebd01080c0eb508fc7f3; + 0000000000000000000000000010000000000000000000000000000000000000 + 79125cca9c3c680a61d21951a4cf0b7230b578ce2e80fe838b337fb7c36a77a3 + 2ab45fadf08ebbcc5121b076806d50927df6310214f73aafb0081633cf98299d; + 0000000000000000000000000020000000000000000000000000000000000000 + 6769fa85ec1c637bde75471d0b22903895ecae1462912caf6a6bc6251a58258e + a65b3b54d75e58eb478cfd6032d291f5bd46a8c8c5765fbb2487283e46c26de7; + 0000000000000000000000000040000000000000000000000000000000000000 + 4e30e6abd785654640eca58ef491e13378f8526c2af3f51c0043e687bcb1c168 + cc48a52ff696f88d51559c46494cd51dc3291266046c085fd51e9f8baa1e1e5a; + 0000000000000000000000000080000000000000000000000000000000000000 + 96a57e2149916713b979265d60743727bb6b7aa91634dc415b408338329e82cc + ea571b458893e10883a717f3776b808cfdd26d9bec4cc64e16a72448c2211b48; + 0000000000000000000000000000010000000000000000000000000000000000 + e8883a8ef799dc1b6d2fe5ddd18acd3ae58b24e98e1e812494f8a74f4ae372be + 93fa5ae2d6d71da3fdeed466453b7ad9f4ac8ea3aeded25a15c4bbd040018fe4; + 0000000000000000000000000000020000000000000000000000000000000000 + fbafbe69b71d604c13e1cb82292190c18cfa9bf6145714aec7249a56ddee4ca9 + 6336a21084584fb303718743e6e96f479c7fe0ddd8956ecf703fad72221d64f8; + 0000000000000000000000000000040000000000000000000000000000000000 + db9b68d716130e6b173cccb08de59eafb3af28019e87c152dc3ff5d5088e3b58 + bb3fe5aef0a82c6adb2f68c9bf43548a06e7fa503ca61b48a946cdaf37e8f24e; + 0000000000000000000000000000080000000000000000000000000000000000 + 9f7bc36611372d91d4b4c0cccc840759285cd03b3e2e27afe204ae448d0f9286 + dbd6da143b4cbec22deebb4d50290a42299669dacf03fe2a2307968143d4fb7b; + 0000000000000000000000000000100000000000000000000000000000000000 + 78d8a2300ad94cfef66b3164c731377ddb2e4b275d4e701391953432347b9223 + 50f62201950be294408f88bdb661cc3296c6be60d3012075a801b5c0834ae350; + 0000000000000000000000000000200000000000000000000000000000000000 + 12e33f7ddcb2f8d174625428a62b88949f125ef8ed08fdaa354599949ca0ae66 + 06ff56ab47bc89455cf58af988b568b2ecfc06e7df27cf710a25022d87557da7; + 0000000000000000000000000000400000000000000000000000000000000000 + 56eded2b02168d3bbeacf0d9daa6af71edc952a831840440039c498f4e7f7ca4 + 704dee5d192940b0a69ab883c75151d8d6cd140362b2c1654041f43f2069f4fa; + 0000000000000000000000000000800000000000000000000000000000000000 + 755d75672e5539950e3738c9f08391595fe8666fa3630d850bc54f51db1c85e6 + 9be04b998cbd1d657d9eb034eaba6870641da53e310eade9dee5013a8c053790; + 0000000000000000000000000000000100000000000000000000000000000000 + 59a5be52f38efc387f5681e5efee14564bc0124d21a853433576752ffa429c9d + 2c8e95bc932d31e629cf4c519bfbc19b1356e82b24e4b0a0a3f0e7bff87cdb9e; + 0000000000000000000000000000000200000000000000000000000000000000 + 6a8e931278edcf28e271b3af14ef2a4c3a32187f2e99a9eed8f8bf5cc9caf92f + bec4947e08bdce74baaa30e8067010ea1a5f0a510f3ded81e1531f7c70a579b8; + 0000000000000000000000000000000400000000000000000000000000000000 + ce10996b404a63f524caa19cb2bb9ab0278718cd618687588deb24dd0acae4e5 + abee46ec2bd7acb5a6b81e03cabd1cd4c5b27255c0c53245bd1fc2b82fdd37ce; + 0000000000000000000000000000000800000000000000000000000000000000 + 322f564e6e45b4d7a556e3e0d673c24762e6aa9558221939a6e207af108ef047 + 045bdd23eddffdd2e5fe6035781a4c3f67eb5063ae2c35c4f167524c359ef09b; + 0000000000000000000000000000001000000000000000000000000000000000 + c38a5f9c6637d72c43bdf52c75f8a01a5c017202825ff09eaf27bb6a5de32c9c + a362cf96447d76f38c0ce895b2fa6bd21a02d6fcee561bba4bd20e224ce24bfb; + 0000000000000000000000000000002000000000000000000000000000000000 + 71f79d68098b9e011bb7c9400ddb9e3493dfa52fae11dd9ad77430857a136c68 + cbeba998096d1bf54c3f5202d5b06c38a8f81f7f9a729c030bc916b43544f325; + 0000000000000000000000000000004000000000000000000000000000000000 + a877f654b01488d3bbe0104bf788a18c250a453f2068bc81f2f096ef5731bfe2 + 9081748a46ae87a2524c0b27af4d4af310d5384ec8e8bfd6bdec56f7e4060ba2; + 0000000000000000000000000000008000000000000000000000000000000000 + 8ae90f0c8d8ccd1268ac98f999bda54594e219ed8cec617c13cea31a606db6b2 + 1fc23a6581656dc0a72abf427d6374ba7d3aff387493204e1036caf860ad0f86; + 0000000000000000000000000000000001000000000000000000000000000000 + b6d4e59d418667855067491c8df18244c64b1bfd728a3625161e47d4a32712d7 + 1f3752a6044179cdbc6b05ba5cb21c894be977699e1401eef6412a0397fd1287; + 0000000000000000000000000000000002000000000000000000000000000000 + bdb69d9fc2ed427ecb6848b5c2f9687c3e873271e8a3261073a05ebc4f75e244 + 023140291efee7ea2d02dc4b54d5d4cddee02c88767c33b72d0e028dd97633fc; + 0000000000000000000000000000000004000000000000000000000000000000 + 925ea1f098046aeb00899bec3d4f97ae64290279272a9dd8ce9d79b6837b3ad0 + 370a2405d17683bcd5baa70c29d57f49f9847641fbd6884173e2adc11995f203; + 0000000000000000000000000000000008000000000000000000000000000000 + 1349f44857d80fd3a0405217a8248339f70d227635af2411dc6c4214a42c2e2a + f6fe27b251602fc9c9e870f5cb4b62c43e3e875c47b775fb8d9f546b52807e02; + 0000000000000000000000000000000010000000000000000000000000000000 + 74699f36e9636c3206287bbe13384e18ced1120706175c0a65576ea86776c612 + dbe9d11b3884457e03b84deb23858d704169d7582a300c8673a7f544435dc3d3; + 0000000000000000000000000000000020000000000000000000000000000000 + b792ed127f2ea24411d063cdc2617d702230f3fb9d03387e3d0700777d97a70a + fdb09f976a749a232305946db9f7bbdb2429fecd28e584d937997446740622af; + 0000000000000000000000000000000040000000000000000000000000000000 + dcd987801779a92f86d879abdf28b9cf66f7d0318f487be0ce27c63a27fb5200 + caad8eec3c351be1e60e70dfdf98de671d2ca5d3fbc21fd440713f55df8c69fd; + 0000000000000000000000000000000080000000000000000000000000000000 + bf85c351d0e74eb5430e55479b50d0fd827578e982ebc8e338f32116ef570e46 + f81b47ebc5d2887a45aa67d0b7d0fc8a07146f30b37f1a036ce9fc236f0d7d00; + 0000000000000000000000000000000000010000000000000000000000000000 + 6c6291cc83e0314b06e19ac68fc170b93e84609fa80ae0349e86cdffefe6a193 + 67ef3467e8e0b571c5d110ea08133e0156e486310d05e07eb3a9417e4749a3d6; + 0000000000000000000000000000000000020000000000000000000000000000 + 6b71719c717d62a10a688fe8f9563571195edc246f7e8006380a1bb14dc3b8fc + b8189e40e802d55d545112e6cab102254477c52f7536d019e06512c83742975b; + 0000000000000000000000000000000000040000000000000000000000000000 + 4a2086948673804f8a97a07b16b36c31096cc0610e2d240bf1fa440fac400f33 + 395dc8ec9ead16a9cee85b07e7da6b1475f525234bc4edf65ece264e72838ebd; + 0000000000000000000000000000000000080000000000000000000000000000 + ca82c08abf42285892485b0d4e4f3a5f5877ef51e0a501e3fce14e4a8b7efd06 + 1271158ab7223bf43fe3f689e9307aefe4233b46e864cac13d234544c0af18a7; + 0000000000000000000000000000000000100000000000000000000000000000 + e7a2d99bec6b59b14475e6a1a6fc28d5394ea5a8557882ae6e9e67d34b18c949 + 0ee608417c070fd9f04a73510cfb900f3773f010e074dfe70a333df6aff09d48; + 0000000000000000000000000000000000200000000000000000000000000000 + 9ac8e222a63951e1b7c2e16012ac90436dcbbace3f0318d2aee3e0bef53d5950 + bdd3b18e99e5fcae550234719e903e0ac7f83fde47ddb396b65eb8af1373d30a; + 0000000000000000000000000000000000400000000000000000000000000000 + 7e48facca309371083f21cbc0bc25ed09d09e03f996f4dc023f54ef7217ded8d + 8dcd9aef8e729df03810d6273f1f6125a35c797606030d653eab344320297a30; + 0000000000000000000000000000000000800000000000000000000000000000 + d1c032fab24525d378aed7266f49d5f7d03de6001ea531676f845fbd8578fa80 + 16c95820117c70da72373689b04c1e6f494b3f4c165d6aad39b5ba8bc8d5cf6c; + 0000000000000000000000000000000000000100000000000000000000000000 + 904091d32d5265cea53274748694757fad2e1c22566b1908f4f9d35538e89b06 + ad3b3c6e85d8afc210b3a22d1fa0c51076bd79c6641ed3481d1533ec7fe6b7b5; + 0000000000000000000000000000000000000200000000000000000000000000 + ca0521aec053c66badec9f3c89d952e0eb69afa9ea41080397071da57161b35a + 6641463de2ee581e2748259471425e94d9fb9d79093e0cd0a19b96ec510d5de5; + 0000000000000000000000000000000000000400000000000000000000000000 + 19fd13377a56d0aa15ac4e62b99eae76dde81f2ffecdc24504051da4b9652c76 + 3f1d6001995209adb152a06b48eec5025b3f755d8e2a01e4bd3b0b536f3ba333; + 0000000000000000000000000000000000000800000000000000000000000000 + 37a40e8139fbcdba67429f72b56509f5af081173ec4bd18cb6e9e3a826bc83c0 + 35196621c8a1dacc251ebe5bed3f5763659303b6e54a10dca061c2f5517cc417; + 0000000000000000000000000000000000001000000000000000000000000000 + ab0439f8eb335ac24b73994949e1eebf0614eef32a7bdb497960791f8db18e82 + 36f36ee2dc7d53583645d308735dbd7a2c88f0a3f407e8bacc2a9737c63fd51e; + 0000000000000000000000000000000000002000000000000000000000000000 + 104c04190e24ae90c2f87caf2cc314680a748cbbaef9298320dad36f660a243a + 3cd0909e1251efd2c9b631abfb0ddffc751ad3c77ac022ac47dca42682159b14; + 0000000000000000000000000000000000004000000000000000000000000000 + 337cf2622058e3b65d83499b927011407fd627c5e77d9e657fe1bb6a224478c0 + a3f95204f3120e370abfe9115eb31f39f5db8a92aad8c525b903581069001acb; + 0000000000000000000000000000000000008000000000000000000000000000 + 2b5bd6ccf9c26f31a167e7027426aae9865c0dfb14fb3dc6daeabeae5c1c8b69 + 5eab14eec32e833ad8cce68fe95d44c7cfdc997e0f5a8386817c3b679dd9771b; + 0000000000000000000000000000000000000001000000000000000000000000 + dc2541bdba0e4d40e8cb4fafc93d0a8a60a5530b3fe27b95f6a88be92f6f36c2 + d25f0a8d66d9fed6790560b86b0d08677c65f72e090426c88cb18cd756965e7d; + 0000000000000000000000000000000000000002000000000000000000000000 + b545e6c9514c66196058a3c3a7289be91d5c5e21da87797e3373bf6e24f5d590 + 9c64e96615ada88bca95405fce376291d5ca05e23356b0ecb94983c1610d07a7; + 0000000000000000000000000000000000000004000000000000000000000000 + f34e2420486825bbe7a24b40c50a84c28c80e2f298c30f4f78bf27c0ed56afb1 + cfdeec976acd4bf09bfa70ad96558e3198c1a4203784ceb5af21657c3a54c3df; + 0000000000000000000000000000000000000008000000000000000000000000 + ab041c33802ab7dca2d6d59863404616f94bf48ac727aed1a85f3b5aa4c6250a + 1797812dff75debcdf59a7b1714d3db08f4b4830801cccd3ac74d37527d3d784; + 0000000000000000000000000000000000000010000000000000000000000000 + f943ca8fee60cc92aee5b0301fa25b129993817b9a1c75cf8528fecbb7563821 + 8c00b2753f4f23b48423836c28977481cb073f3c3693ea03d33db3b5b31f6ed1; + 0000000000000000000000000000000000000020000000000000000000000000 + b1fbd227465ccfa0e934080e315073d99faa55be4fd38e93d210db20f4cbcaf5 + c4e7c620deedc6244fbbcd829105ada603825e64a044ed864c5ee465be50141d; + 0000000000000000000000000000000000000040000000000000000000000000 + a9341c312dd5c879b6b7305557080ac059eb7d48da0d044ce4c53d46ee682a77 + efc45cb2d180e546a8e60450da7859233b04ecb5a21a11d517a6752fe5b56ba9; + 0000000000000000000000000000000000000080000000000000000000000000 + fc0d7e148270279e6a8a0bb30102642a7f1481fc2617341674319a8496b2483a + 6b32c7813bfa42592b2558adf16918b1c56686e70b2fd6cf4d9c57ef4079ef4f; + 0000000000000000000000000000000000000000010000000000000000000000 + 55702bc90512de5e92dc5106f128997ac822b95d89ea8e924bc329174da48ee8 + e009220efb6aab4487ead7b8ef0b82843d16684ef57de55b2fbc2e981aae1c6e; + 0000000000000000000000000000000000000000020000000000000000000000 + 3be68900844eed0843ad0b2ef6d0b683a3112ba3b8a35a52f40007104586ab85 + b10b32f47822dac5b5db3d240bb2d8f05a408c2c20439563bd97e96a1f4ab84b; + 0000000000000000000000000000000000000000040000000000000000000000 + 5c451eaa6c8e993e837371b4f231e93e2ae7407b930f07bd87ef5ba134d9f6fc + ff89a9dc0895b13c20a7af15ae8e860d74f9dce289c1f43bdb35025d7086490b; + 0000000000000000000000000000000000000000080000000000000000000000 + a8ce9c065e6c91129d0643c04cf73150df86bf2f5a1a947a1fbecb1aca90d26a + a1301654d68563bfb7f2110e5d9ef96635d24ba8b56320cd070b25b6be28623e; + 0000000000000000000000000000000000000000100000000000000000000000 + 2aa48f6411a0ba5040eb83e2a2b20f14e93554953c8873e8879f355678badb0d + dbb22baa33905a9740d5ff475ed0517107f413690af9b95f717e4cdbace8405d; + 0000000000000000000000000000000000000000200000000000000000000000 + 7965be05896fcc9b9dc334f9c2a43f813d5c248963e1317f798c4f9fc5f8e7fd + 34125fee23f020155f248b4cc5dd4370ed530ca871be46fd93e7a006edfea7b8; + 0000000000000000000000000000000000000000400000000000000000000000 + 1541c80be3e5c8e221540f92b631f360c5b0370223263e771b1b92d4fb73a453 + a2bff0682b9d6e3eaf8d183efaec91667808f9d026ff20c1d65f7e6e2a4676a3; + 0000000000000000000000000000000000000000800000000000000000000000 + f283204496fe825836a3aa8377f4f2db5cfb14b41c6b9f5f53e565c852db6598 + 6dc375d702992c7e30ed6cd188fb27fd7a3c4e4c7fb2856f67244fe3c7f8b760; + 0000000000000000000000000000000000000000000100000000000000000000 + e234f1c1d7ccd4ce1ace58850dc28d2abc7e2dfd171877710704282a12bab9a0 + 8d51c164dc8ae5ec5bdfcc25fb1ee9a6d9cefa47abdb748143ec18b91c72fcad; + 0000000000000000000000000000000000000000000200000000000000000000 + 4cb4412669289a6250900c8713f56cb57f5b962137b828b46a1b1dcb41bbbca0 + 2b1ea7bd9d0cd83de33ccc5415ba625c6c4d2bb211e5464c39b2bf9325aa446c; + 0000000000000000000000000000000000000000000400000000000000000000 + a6c52188edc54c3e88d4424ac378f85b690e1b6b46e552f4c855aa9e4e0b2c36 + 75e118baa53204bb91b283c80d3baf3e70c4cc204f25aa71ae6ebe0655010d9c; + 0000000000000000000000000000000000000000000800000000000000000000 + 58449e523e08c99109ca6570b8bba4011a7cfb2203257e8b93d3131bb16219aa + b1f0f1f930fbe5566ae5ab46e7a6981ae14d51dedc62a4b1786c032d16cfb829; + 0000000000000000000000000000000000000000001000000000000000000000 + edcf56d94c31b0d201066b648da08d43e0ece64dfefd3a542852fb3f945ab216 + 122c6c4b6b019b18cb0e925d191f3599d9eee57eb7a6506fe1fac494f037327d; + 0000000000000000000000000000000000000000002000000000000000000000 + b178ca20a3bb67c4f34a816d1c4636cea7642cfa004cde16efe32a6c613c9eef + 45912f3f092fd64dfaba7cd7abf0534fa7f8571d8d01949d5204223bba068166; + 0000000000000000000000000000000000000000004000000000000000000000 + d925287721da5f6117f951cddf410018ee8cd147f97305ba2f0aac26c1859312 + f3878c9586205c2f92b27656df61bd94b00a01b86202079ca1926968a1b52c08; + 0000000000000000000000000000000000000000008000000000000000000000 + 359f4ea466e0f07d6a0de61e99ff4e2007cc5dd90c59a1e4d0d5b46f03b5aa99 + 33816ce4fbfc40b806bd2bad025b9477b051dd55d2fddfe007287e66e1814afa; + 0000000000000000000000000000000000000000000001000000000000000000 + ae77a98a68d9462b74bdd4f7d124746e1c5765406cf1b9ef547d52f00b45d4d7 + 2d58c0e474a33f1957bddf17a850871ea050580f4f8d48380261189a271d4c01; + 0000000000000000000000000000000000000000000002000000000000000000 + 0bf35dc3d5fdea4d60f14bd0759906c1625c44cbb754f4087645b551355844ee + acae4ab9b17e275e54968b1ef6a2422f3bb97eefa6b0007bce18e8162a8bfa50; + 0000000000000000000000000000000000000000000004000000000000000000 + 4ed4cd19fedd9fce8b979f698f2f167909331a7ab8dffbb7fcb56a2c5afc1428 + ddb8a8c89b629b0711f72b3328b22727e1c5965dce9b3843667e1b6492962416; + 0000000000000000000000000000000000000000000008000000000000000000 + 6af47d0713e05fb4a2974110b0860baedd2597820ff5c600f9049d7d425ee100 + 2d0cf3e4db588dea89cabb0b0ad58acc1d0b83388fb6af32b367e21f7f14f41e; + 0000000000000000000000000000000000000000000010000000000000000000 + 96a82f4432529492f6a8a17fcf155ef8a6bf11bb73a77d3dd8bf3e986ca3dbbd + d8fd1163036b81998a1e5e3ed3d787fe270f05b8095f0cb853a0b934b4016dbb; + 0000000000000000000000000000000000000000000020000000000000000000 + 23e6baa1a8a67122a9855247124ec59a1dca649570c6a1a4fb089a76c81a6014 + 3583e5c1cc5e397b2b5864960caf7aa66ebe6467d4065e67008fa737c053a7a5; + 0000000000000000000000000000000000000000000040000000000000000000 + 86118f4629dad8a873b1649b9c039fcd4dd8ba032b9f6819115c3af0d1b6595b + 071740e3ca823edfdabfabc0dc10924348fbb023b6ddb344d4f42e9572de3e08; + 0000000000000000000000000000000000000000000080000000000000000000 + 982d814b00c91517c08aa4c87087069c01c6a045cbcd3d7f26a4a1c6cc97d2b6 + 3d20e5791747d98b9ea3d2026594b8ce462c5ba6e62a1c361cf5fba5ca0f1d11; + 0000000000000000000000000000000000000000000000010000000000000000 + 2dfb74f1332f7930be2ea7a1732ce3d56fb12d916d2796d1e1fba64f2e66ac20 + 4be4d901963da689112e1fc54d852a70c0f60b501b915cdc141fab94b43d0106; + 0000000000000000000000000000000000000000000000020000000000000000 + fe6cc968de80a13cb0e7a1fd4eeac2a1d1ddca48c53e2bd5f4230c4f51d1f4c0 + 8af8f0ce706f35fd089f8d8aa07d07d9a7015d4ecdc7e9548cd0f3992073aaa2; + 0000000000000000000000000000000000000000000000040000000000000000 + f8f84d21d697ff9862c223ed476722077f5865800c34d36a6560a0a975d90413 + fb9e5f6b3e8f8e78f715226d808f98c389883d65e2c53aab4ab018fa941d28eb; + 0000000000000000000000000000000000000000000000080000000000000000 + b934372f8ad78e178eebbeba49db0466073fc8e29e78a232bbfffd59b9d72d65 + 95d2ff2f7e24735bcde0d3766c83a128104bbc8ac1944f3efbc3e174517d08ff; + 0000000000000000000000000000000000000000000000100000000000000000 + ef204271d3588603c5f43eacfde91e3306723c7f074fe2088ab95fcbb45eb6be + c14741e0daa9c84264b877e8a503ae78c6c7b2329f0bff9476ba2dad653ecf12; + 0000000000000000000000000000000000000000000000200000000000000000 + 0515648007e5e5e8e37e9056a4f23232a07083fce238e2dd3853b3ab1734ea70 + 0f4f15ea46ccda314f7891ca7d0091a6215d341788a3acb732a93a14da0a0d18; + 0000000000000000000000000000000000000000000000400000000000000000 + 67b53797fd010597b38fd94cf1686270f0992e6c6666e9ca4a105a61d510d9bd + 28069c2ded2405e0ef95abeab23f36bd752b15119e4fa69b43d731624ce5178d; + 0000000000000000000000000000000000000000000000800000000000000000 + 7a47769ca3509d8811e6c23c3d5adf38da76e8d481fa13afdf60813a8b59792b + eae7e513eb59d8ba54087cb66c7c00edfda452731b93f34698b477d234dd7faf; + 0000000000000000000000000000000000000000000000000100000000000000 + 8dc1de423e5ae630989be11bcd4be30d3f62efe9d38fc26396b123810df2768f + f0c952d27a250c3f4d914d537fd04a8cdc6c057af35ba4410bab0ea89e6d7d54; + 0000000000000000000000000000000000000000000000000200000000000000 + 48571b94f3f991ca6e992e60358fa4b3255999983d5f9b9b1268e61f3db3bde8 + b889b82fb5f1e8d78eafee9275c889e23c7a2555d78487b9cc4f701d7d1f00e1; + 0000000000000000000000000000000000000000000000000400000000000000 + 1e41bd7ebac2a488c52acd8a99b336469d9fc35c98d9cfff269a6b8e9377309b + 11ec65507e8b6393c7f12023f8ce9f0985ff92b8a3ef9c78cb1f2883694878f3; + 0000000000000000000000000000000000000000000000000800000000000000 + b6eab1e877e719a42d935523dc8c904b35a30e3b02148944a6e46459e35c5f40 + 04da7f3786ccae4982a8e75aa55549a89708915b1c6f19613632cde018ff5269; + 0000000000000000000000000000000000000000000000001000000000000000 + 925e5596d9660e28a1b6c1a9e33fc7beea001f1cdbaee6c6fa7938d66e4f2e7b + 0473cfc0964e7b3f9b505789fefa176f735b564678ce0b89223c073175e685ff; + 0000000000000000000000000000000000000000000000002000000000000000 + ce02c8aab250c3d07e84fd4a8475c1cffd00a20b1f215df5feb3e93e287f6c46 + 7b9d26b50cdd0eb37a1c6cb01807017bb70760c2892b114a944b183e80392739; + 0000000000000000000000000000000000000000000000004000000000000000 + acab6f16ba40e29b015d0289c82f03f54baec63d322c1a70792094d229b2b17e + 41e4f7bad8838666d798ed77a6d4129a4a97b7740611539d9a21064ec837072c; + 0000000000000000000000000000000000000000000000008000000000000000 + beaa65cfea3e972077a48ec8d99421a5cd6e234e2ede51c080d0d99ed5fdbc5c + b83d02d1b94ace563287cac9ef6b175a7cb60c84343976f97105c2d78aa1e683; + 0000000000000000000000000000000000000000000000000001000000000000 + 9165a45f535f24531daaa5fed2621c91755e15ba9f85e57d848172c9846327b2 + f496291c25156383b867c10bcf82466c138555bfd5fecfc9c01dc2e65aa43929; + 0000000000000000000000000000000000000000000000000002000000000000 + c17d79761600447acdaae4ec9398c1743a432e58752cc8082e45d842b43f0e66 + e5ea6f466307a34d36ab278aaa884ec07a494ea17216eb405790320d8fa2fed4; + 0000000000000000000000000000000000000000000000000004000000000000 + d6868ca98e49ab85e60f5411b17d644b613f6101107c70f514b12d1b3e4133f5 + 1305d1b51ced2666839b11eed182da902e864a74e35e06e9d4137996ef50dba8; + 0000000000000000000000000000000000000000000000000008000000000000 + e35c518d1abdec18c07645ea79f07071c2967d1045ee804694dc5d43e96610ac + 1908ede77ee9510ee12f3d3f516002356731e164a9ea4f63171550ee2ee90552; + 0000000000000000000000000000000000000000000000000010000000000000 + 06eb73063502eda7c71d450742a79c9c7fa03f682efae6cb0b65f44e95fe4a74 + 31c5681726dfa952c0c2285aa56cab4eb107095337c624ea81ad277664b2a264; + 0000000000000000000000000000000000000000000000000020000000000000 + 4e7269b1930a4415947740c02e07f5a648071b525ef02c169ed6464d8b27bb8d + 6abc498904e605e1b5e28ea8628b55c7e5e029623f77cd462691d3a7fc278674; + 0000000000000000000000000000000000000000000000000040000000000000 + 826a3104a79da8022158b60aa55187dbd1fb2bced56c4690560cc83fda92e492 + d3fb967cae7452b867c88adc8a11e5b5b95989bdde92639ed95305ced7cfdc60; + 0000000000000000000000000000000000000000000000000080000000000000 + 0b92142c4fdbc92e7156469124819ba920edc66c427430c017d6bb294085ac19 + 6f327c30503e8cd50af536583f510545511e8d70da1cc285bcce2d46f92d2b2a; + 0000000000000000000000000000000000000000000000000000010000000000 + c7b17c0628edb82798962e54e097372b3860bbc02b0cad3f87dfc81b3d25d93b + 4ea78d7501f8fb379e7725fa971af497596116c475b4796ccbc7e10d1a2a21d9; + 0000000000000000000000000000000000000000000000000000020000000000 + f9286bb83357f5ba5e9fdd2c7944ca1d75d9d2375710a2894d282c85a1f94b7b + 5293a298473e7efcde744290da3a51cb3c798cfdb1fc9a4c7aaf4f7b3008297b; + 0000000000000000000000000000000000000000000000000000040000000000 + 64be8cf1fb77d638f68b6fd80b57f21adbc420b5e99d4227ac0ae6d82adb0f71 + d9de4fa7124fdab3c5473ed50c41b53fe346ced59941d71a8191a8f6ade215d8; + 0000000000000000000000000000000000000000000000000000080000000000 + 16e491e25d6f79d9a33018ae66f6a78a87e4ca6d4b225f26a70acf757eef8754 + 86fde1681d4c26c001abbc93e967065f985b607441d05683f971b05b7c5e556b; + 0000000000000000000000000000000000000000000000000000100000000000 + a499e877391ec0170d41b8e03af321fedbda237b675123018902af35d59acf9e + 78e154919e5bceb7b20a4c6f94aec7014a4e03cba4fc668ed69644f20de31abe; + 0000000000000000000000000000000000000000000000000000200000000000 + 8b058ddb6648ef4583b44e5332784c6872c52589fb2d1e7b107ff5ee64b59e6d + 4a022b951253940108f3a795bc4f39ae3baa2cf656d3e2d520138853fba56a93; + 0000000000000000000000000000000000000000000000000000400000000000 + eb530cdefc2656bdae8734131668a5833ae26f131b2c8fb50999da0106591fcb + 739475c5772aeede0aa39c19c120c20aca995eb3e7a90d4048b0a4e1efd7cd29; + 0000000000000000000000000000000000000000000000000000800000000000 + 2eb1c5426bbd82ff9526b482d3dd71bf52af1cfb1fa7f68acc457b08429d0ddd + 5ac3c96e0623ff40dc8dff86f1d4ddfb90312c1443243c89231b16efa79f0bdc; + 0000000000000000000000000000000000000000000000000000000100000000 + 3b9b9773dac3e4954d4168945e276ca5c9e1008aff8be8034d0856868bcb7dca + 65a19215b091c569c84da60a64b874091906c6c23fd975487d877e91a64e43c3; + 0000000000000000000000000000000000000000000000000000000200000000 + d09fb1b66db34ab57f57a2fc98945fd2b610ca739452954d3dc32e6d11b1cd08 + 7cc4d6e0660454281087046c740ae0cf3ade676dfbd2fa46d4d0f5ca1cf4fa5c; + 0000000000000000000000000000000000000000000000000000000400000000 + 7d02fbc809080c5e21522ce33eae610a47f7c059433bbac3ac30c5637d8aa3ae + ee4b97a5049fbac0137eb688cd389bf104afb2ef754a30dc4e72e60267efbb0c; + 0000000000000000000000000000000000000000000000000000000800000000 + 97e7a1f5b2c9d77294a3131298479c8240e33800f4e95b76462d3f0f9899abee + 669f11d848792de5621440aa51b628b667f9fa28e6c43070215ca6b52da59760; + 0000000000000000000000000000000000000000000000000000001000000000 + 92d91bc3b83ee7c8512c0dd87efad9952a41f38aaf3ff737b1bf232484b3ced6 + 6e417430040e5bdce9e6f4df84e09323e254e2c75b7ab7916dc5fc84f0dc7f2e; + 0000000000000000000000000000000000000000000000000000002000000000 + a201b9a8fe87c900acc1937c5fe32563f4f52ded3f9f7c484cad259adfd81a59 + ce267b0cf6d5e06d6a980db8fbf00a6609f8e91ac1e0dd705b53428c8a69baa9; + 0000000000000000000000000000000000000000000000000000004000000000 + d84985bd7e97e581e034d5f7b27d96bb78719cbff19e37abf66395654714ea20 + 919b92ccce355fdb77913cddd41e0fcc3d7b468dc8f6406782953388dbf82927; + 0000000000000000000000000000000000000000000000000000008000000000 + 506c7f563c6254e18d5b50e8c294a97a3634322709189dc2e6af7c1166cc846b + ec220577d30e07409eb06ab77477eb8a4d4357443fb64d739692458e82e5fd0e; + 0000000000000000000000000000000000000000000000000000000001000000 + 671217631c0840c9c9828f78a714f1bb67b864d646efe8de3c432ac20d55f133 + 39064a3dee432a3632fe78fab64d637c933bad5d44e2118a1247dd10c51adb8d; + 0000000000000000000000000000000000000000000000000000000002000000 + c5e41aa3e2d7a37c82e7a41ef0db3c81fe9b9d2948dc5c1d7b8bd862142c5603 + 0eefaadfe8682f723c8b407d90da3dce9612965c770987ed1a0f1ea66745103c; + 0000000000000000000000000000000000000000000000000000000004000000 + 762a716822e4798d1493f81f7daccbba1becbd4fbc4a478ee30e4aeaadb0b0c2 + 21e19764af6c956a9ca8c31f3344cb0fa30195bd868b524d8d8de89090944918; + 0000000000000000000000000000000000000000000000000000000008000000 + 221e93fbe263c8a6c92a87c6492e7d17fee75a585cea8f311cd79f595b42495d + 58dcbe9cc752afd2aa2008bc9f95c2e70d38fea1d5c3b87c1e6f29f9c0bc4373; + 0000000000000000000000000000000000000000000000000000000010000000 + 72b80c94d6ff97f97e9f76e139c037a3fee9a53e48f0e57266e24761592cfbfd + 1eb856387f0f0208987725a13f796cfe420ea65fd338fc594fee3667325add23; + 0000000000000000000000000000000000000000000000000000000020000000 + d147908d20daf77c962b21d4997f7b84fdbed2cb07cb06e0e59032641b9dcb3d + 5fac3709cbc5b5f3ef21ae198d9234feb1a82ea4957684891877e2ef2b3c0332; + 0000000000000000000000000000000000000000000000000000000040000000 + 7374263f1b8c9d4d21f52f1ec6f971d9dc7268a8af79ac1c1c535dc4dff5cbf8 + 241175e0afa2ed5af43ed388a818f128e6d99731dff319644fdb983951d8e765; + 0000000000000000000000000000000000000000000000000000000080000000 + 752aeaa1cdbb7d024fe734668cd9f63d61ff4b335e7f42d0f545ab81b9b234fc + 4ab2772f9d610f0d618828a10dcbf20ce04d4f78f71565a8379680ea225801ac; + 0000000000000000000000000000000000000000000000000000000000010000 + 7ec933c4574148f27c412e2a4289def909ad7cefc54387dd5f0dd2c832488790 + 99e2a4d15571d1098f1defc1d29b07c40af145ebb2edf81258d5afccb97919d6; + 0000000000000000000000000000000000000000000000000000000000020000 + 954bd7a24edf58f58ebe343632e606fe97936b2500658ff9b11ad67617d221b0 + f63398643b341b0a948cf22f5e9fdeeb8fd4fe21a3d946cee2f365e75537fe1b; + 0000000000000000000000000000000000000000000000000000000000040000 + e65323be34b117fad1cd194caaa254c7ec53fd96b65430e5703ef4697c4596e9 + dad3ec2e51bc681c018f9ebf6d137999d6234dd84958737bb438c3232d377187; + 0000000000000000000000000000000000000000000000000000000000080000 + 4b4306c5d55af9bf63dcf7c7c20268ef10b372b59ac10695d2b83277ded2b85a + da842a5af1d93e0f945101c202771981b4bb7645d9a59bf0939cf7b35cf1de41; + 0000000000000000000000000000000000000000000000000000000000100000 + 20b0a0a6c9fd63ee745798c9248c988b1aaa9dc976f783254711c57f755728e8 + 83bc5c2254747422499230ac0abdd29de42b8896a9abf47cae6811a5e7986325; + 0000000000000000000000000000000000000000000000000000000000200000 + 92c046c878b2f54671c4287237e200388bc1b03807c0e961b6e8ad336d6b0dc3 + 517c911a62e8c951bd0bebdca4940a49bd0d34eca5d7fd42f53b63a674588ad7; + 0000000000000000000000000000000000000000000000000000000000400000 + 07faa395104ee08dbe87821fe9f4bc657a0a026de98a1b7eafecdd0a0cd90950 + b8dcfe3057cff32a8346fdda5cde697a0f5daa99073a12602a14fc2c098e8d37; + 0000000000000000000000000000000000000000000000000000000000800000 + 7b66faef189ff1c27797957691d2a5393a51cc46d1fb35bbbdd9c18c5d6be3b0 + 30d0516447f18c0140c56a2d3839f19713b2777507afd01bcd3e2b5f3bf565a9; + 0000000000000000000000000000000000000000000000000000000000000100 + 4a7db25fe6b7f7195642b302df9ae60721be3bc0a0c03c0bfc02774f0770672f + 5e9e9a73d8482a46bed4f5a3d111f5128d7ce25b459cefa8dee41e8a20530cb0; + 0000000000000000000000000000000000000000000000000000000000000200 + a3666ad211b46b616702ba5460e2153563ce71527ca411720095408409c1c1eb + 9b5b488a37a2639e60077e50b3cfc23e0ca6b15303ac57d6a861d27bce87f4a6; + 0000000000000000000000000000000000000000000000000000000000000400 + 5621077387c09f1b7de44f33ee44726fb24d4f13faeb59888c94d6867c7b4989 + 0e01ed6bc6527eaff1dbce5ce7a23df23e6369f51c250ca01e757c7ea6d2b3de; + 0000000000000000000000000000000000000000000000000000000000000800 + 6ac275dfd387f63219d26d8f2bef9e73e17c026ae17707ba80ccf24899a9db69 + 63d189cbd05260d003546c599da6d7b574fa0037104cf6300f9f5f5edd6eef02; + 0000000000000000000000000000000000000000000000000000000000001000 + d9f2fe1ca70220a4471cb888f5ce568012b30c31c485977f5bb3e0310195b5a8 + e8a1128025fa4a2431858de3c7253371b487b2e49bfc477e9b5d6734e2d17d34; + 0000000000000000000000000000000000000000000000000000000000002000 + a3ab3112e4d31f85ebc84e7e43015c687276a54a96b77b462d2e1ec71b88fdae + cb586bb26463168f35f52a962e040278ea2e476ad53a6161599ebda329c46070; + 0000000000000000000000000000000000000000000000000000000000004000 + 93bd82cdc5d4b50b83eb98b2ef0735c9d95f7aa82e857a76b033b13467eefd14 + 9b3955c74930f1448504dc3e1486e9f861d25f437dd8c2db6d67ca70b4a83014; + 0000000000000000000000000000000000000000000000000000000000008000 + 9a47b3563a9a7ac67a73109c79dd36c0a4445dff6b0677ca76e30cbdbca7ba07 + 4063046b6cd73e682fce54e3ced24880627ff6ab50a9b9de367300ef07e9b9d3; + 0000000000000000000000000000000000000000000000000000000000000001 + 1e21dcd5b4cb8628bca386ab818e8b64b693a784e38c1bfa01b82c9d95846083 + 30af87491adddc2f86988318c2e7ce9f4f4d19e84eef873ce0732599a097f3f5; + 0000000000000000000000000000000000000000000000000000000000000002 + f9aab3d341f85f5fd8cdee460a5667595483f277b0f79f7b6df89fdd35a134f5 + 16f23b237ea5c03cd5ff1304890453a8311c456a2935a65c73c99e3fc12bfb3b; + 0000000000000000000000000000000000000000000000000000000000000004 + 935d4b978db6e8f84dad228410ff15093f40ed89e2a2f8d1cb8410643b74a039 + f01d8a43f5ee23843f8df421f468bd2c052677b2a993256225f34966000ab693; + 0000000000000000000000000000000000000000000000000000000000000008 + fffaf07ed7971e764123fe4e7aa181de2b0b0ab8704ffd9b82ee49495dc1f920 + 8c3bbed3d1a15e2e5d203e7d964b9b481d42e945b28fab114435df28aea6b023; + 0000000000000000000000000000000000000000000000000000000000000010 + 6e6d8318c270135985a84e3a2541053eb8b58fad367fdb2e81dbe723572421c4 + aab06f5557fb72c450d68ec0b706c97d8e7e260f70db34e3ecd28ba5473c9268; + 0000000000000000000000000000000000000000000000000000000000000020 + e8d4277d5557864cf02d3f4cfdf4a998f82777e9fc4dfe06d856091634634141 + 6f6aaf2b2ea7ee54ba5e4c28de990437e17f685194c76160875acbb35bdf4d93; + 0000000000000000000000000000000000000000000000000000000000000040 + 6e32a77e600cea713325d09408312bae15cd75d28d2c04a5f604990e65be3d89 + de71f5f1814b9a73098ea50c4d3605bb764387f317ee2f08b90b88ada605c105; + 0000000000000000000000000000000000000000000000000000000000000080 + 92128b45f2af927df41f3b200a872673a744956e2c58b0099f243b7911c50436 + ce408d59a184170a267df8713a787464af6d75f5f46b8b64ddac88daabb50ecd; +} diff --git a/symm/t/rmd128 b/symm/t/rmd128 new file mode 100644 index 0000000..3dbac5f --- /dev/null +++ b/symm/t/rmd128 @@ -0,0 +1,108 @@ +# Test vectors for RIPEMD-160 +# +# +# Taken from the authors' web pages. + +rmd128 { + "" cdf26213a150dc3ecb610f18f6b38b46; + "a" 86be7afa339d0fc7cfc785e72f578d33; + "abc" c14a12199c66e4ba84636b0f69144c77; + "message digest" 9e327b3d6e523062afc1132d7df9d1b8; + "abcdefghijklmnopqrstuvwxyz" + fd2aa607f71dc8f510714922b371834e; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + a1aa0689d0fafa2ddc22e88b49133a06; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + d1e959eb179c911faea4624c60c5c702; +} + +rmd128-rep { + "1234567890" 8 3f45ef194732c2dbb2c4a2c769795fa3; + "a" 1000000 4a7f5723f954eba1216c9d8f6320431f; +} + +# --- HMAC mode --- + +rmd128-hmac { + # --- Test vectors from RFC2286 --- + + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + fbf61f9492aa4bbf81c172e84e0734db; + + "what do ya want for nothing?" + 4a656665 + 875f828862b6b334b427c55f9f7ff09b; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 09f0b2846d2f543da363cbec8d62a38d; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + bdbbd7cf03e44b5aa60af815be4d2294; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + e79808f24b25fd031c155f0d551d9a3a; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + dc732928de98104a1f59d373c150acbb; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 5c6bec96793e16d40690c237635f30c5; + + # --- Test vectors from the RIPEMD160 home page --- + + "" + 00112233445566778899aabbccddeeff + ad9db2c1e22af9ab5ca9dbe5a86f67dc; + "a" + 00112233445566778899aabbccddeeff + 3bf448c762de00bcfa0310b11c0bde4c; + "abc" + 00112233445566778899aabbccddeeff + f34ec0945f02b70b8603f89e1ce4c78c; + "message digest" + 00112233445566778899aabbccddeeff + e8503a8aec2289d82aa0d8d445a06bdd; + "abcdefghijklmnopqrstuvwxyz" + 00112233445566778899aabbccddeeff + ee880b735ce3126065de1699cc136199; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 00112233445566778899aabbccddeeff + 794daf2e3bdeea2538638a5ced154434; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + 00112233445566778899aabbccddeeff + 3a06eef165b23625247800be23e232b6; + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" + 00112233445566778899aabbccddeeff + 9a4f0159c0952da43a8d466d46b0af58; + + "" + 0123456789abcdeffedcba9876543210 + 8931eeee56a6b257fd1ab5418183d826; + "a" + 0123456789abcdeffedcba9876543210 + dbbcf169ea7419d5ba7bd8eb3673ff2d; + "abc" + 0123456789abcdeffedcba9876543210 + 2c4cd07d3162d6a0e338004d6b6fbc9a; + "message digest" + 0123456789abcdeffedcba9876543210 + 75bfb25888f4bb77c77ae83ad0817447; + "abcdefghijklmnopqrstuvwxyz" + 0123456789abcdeffedcba9876543210 + b1b5dc0fcb7258758855dd1840fcdce4; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 0123456789abcdeffedcba9876543210 + 670d0f7a697b18f1a8ab7d2a2a00dbc1; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + 0123456789abcdeffedcba9876543210 + 54e315fdb34a61c0475392e5c7852998; + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" + 0123456789abcdeffedcba9876543210 + ad04354d8aa2a623e72e3594ee3535c0; +} diff --git a/symm/t/rmd160 b/symm/t/rmd160 new file mode 100644 index 0000000..d6c7882 --- /dev/null +++ b/symm/t/rmd160 @@ -0,0 +1,109 @@ +# Test vectors for RIPEMD-160 + +# --- Basic hash function --- +# +# Taken from http://wwww.esat.kuleuven.ac.be/~bosselae/ripemd160.html + +rmd160 { + "" 9c1185a5c5e9fc54612808977ee8f548b2258d31; + "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe; + "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc; + "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36; + "abcdefghijklmnopqrstuvwxyz" + f71c27109c692c1b56bbdceb5b9d2865b3708dbc; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 12a053384a9c0c88e405a06c27dcf49ada62eb2b; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + b0e20b6e3116640286ed3a87a5713079b21f5189; +} + +rmd160-rep { + "1234567890" 8 9b752e45573d4b39f4dbd3323cab82bf63326bfb; + "a" 1000000 52783243c1697bdbe16d37f97f68f08325dc1528; +} + +# --- HMAC mode --- + +rmd160-hmac { + # --- Test vectors from RFC2286 --- + + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + 24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668; + + "what do ya want for nothing?" + 4a656665 + dda6c0213a485a9e24f4742064a7f033b43c4069; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + b0b105360de759960ab4f35298e116e295d8e7c1; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 7619693978f91d90539ae786500ff3d8e0518e39; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 6466ca07ac5eac29e1bd523e5ada7605b791fd8b; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 69ea60798d71616cce5fd0871e23754cd75d5a0a; + + # --- From http://wwww.esat.kuleuven.ac.be/~bosselae/ripemd160.html --- + + "" + 00112233445566778899aabbccddeeff01234567 + cf387677bfda8483e63b57e06c3b5ecd8b7fc055; + "a" + 00112233445566778899aabbccddeeff01234567 + 0d351d71b78e36dbb7391c810a0d2b6240ddbafc; + "abc" + 00112233445566778899aabbccddeeff01234567 + f7ef288cb1bbcc6160d76507e0a3bbf712fb67d6; + "message digest" + 00112233445566778899aabbccddeeff01234567 + f83662cc8d339c227e600fcd636c57d2571b1c34; + "abcdefghijklmnopqrstuvwxyz" + 00112233445566778899aabbccddeeff01234567 + 843d1c4eb880ac8ac0c9c95696507957d0155ddb; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 00112233445566778899aabbccddeeff01234567 + 60f5ef198a2dd5745545c1f0c47aa3fb5776f881; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + 00112233445566778899aabbccddeeff01234567 + e49c136a9e5627e0681b808a3b97e6a6e661ae79; + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" + 00112233445566778899aabbccddeeff01234567 + 31be3cc98cee37b79b0619e3e1c2be4f1aa56e6c; + + "" + 0123456789abcdeffedcba987654321000112233 + fe69a66c7423eea9c8fa2eff8d9dafb4f17a62f5; + "a" + 0123456789abcdeffedcba987654321000112233 + 85743e899bc82dbfa36faaa7a25b7cfd372432cd; + "abc" + 0123456789abcdeffedcba987654321000112233 + 6e4afd501fa6b4a1823ca3b10bd9aa0ba97ba182; + "message digest" + 0123456789abcdeffedcba987654321000112233 + 2e066e624badb76a184c8f90fba053330e650e92; + "abcdefghijklmnopqrstuvwxyz" + 0123456789abcdeffedcba987654321000112233 + 07e942aa4e3cd7c04dedc1d46e2e8cc4c741b3d9; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 0123456789abcdeffedcba987654321000112233 + b6582318ddcfb67a53a67d676b8ad869aded629a; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + 0123456789abcdeffedcba987654321000112233 + f1be3ee877703140d34f97ea1ab3a07c141333e2; + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" + 0123456789abcdeffedcba987654321000112233 + 85f164703e61a63131be7e45958e0794123904f9; +} diff --git a/symm/t/rmd256 b/symm/t/rmd256 new file mode 100644 index 0000000..c998667 --- /dev/null +++ b/symm/t/rmd256 @@ -0,0 +1,59 @@ +# Test vectors for RIPEMD-256 + +# --- Basic hash function --- +# +# Taken from the authors' web pages. + +rmd256 { + "" + 02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d; + "a" + f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925; + "abc" + afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65; + "message digest" + 87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e; + "abcdefghijklmnopqrstuvwxyz" + 649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + 5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8; + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" + 06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd; +} + +# --- HMAC mode --- +# +# I couldn't find any official test vectors. These are therefore generated +# using the Catacomb implementation. + +rmd256-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + c1829c0d5a203bbf6e874a721d55ffec22456f3a0987e30a4861a40cad5dc9e7; + + "what do ya want for nothing?" + 4a656665 + 932d3e799272765675dd63c33f8d2815ea38181494f43271dd52fde91392619f; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a30051679681f54ad62088438a308c3dd38cc0eb2d352fbdcfb2811abf9c1e29; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + d55d1a9b2082105103d8331581d9522d17b4cce92e95f0f4654ce8da187ffbbb; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + cc8e435de509ef9a974cecb40cdecf55c8e6a22d5458e74cb7b0a306453ad67d; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 821543a295eccf093af9b461f630d7c49206fb2158e5ac89e73a02cf089528ed; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + ca26edc0129a781f1224cc6c9f655052f120edb5842bcfcf4b8d0f8b8be551bd; +} diff --git a/symm/t/rmd320 b/symm/t/rmd320 new file mode 100644 index 0000000..783bc7b --- /dev/null +++ b/symm/t/rmd320 @@ -0,0 +1,59 @@ +# Test vectors for RIPEMD-320 + +# --- Basic hash function --- +# +# Taken from the authors' web pages. + +rmd320 { + "" + 22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8; + "a" + ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d; + "abc" + de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d; + "message digest" + 3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197; + "abcdefghijklmnopqrstuvwxyz" + cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4; + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" + 557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42; +} + +# --- HMAC mode --- +# +# I couldn't find any official test vectors. These are therefore generated +# using the Catacomb implementation. + +rmd320-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + 03ec929cb94837c2acd709d03f4a26c3e38c7cec4fe2f5caff3b64e168321c8591b1d3ffeb87b9f4; + + "what do ya want for nothing?" + 4a656665 + e440b00b6326e4f7dad3a6591e8189e9708fc17e3cab306fc67efaf70947aad2ea89e28f79d03bd3; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 8c7ee84fb76703386f01f088cbe0ed9a694d6e0c9bfbe1c7785f56cafc5908db2e16afcb0721edae; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + 714f482ff865edbbcbfb344948ce3c8b9d2308650f2f0ed2111a6983509c967416e092e9f6b307d0; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + f0b1c83e3cec672db53c259746de4d13841e01dd6266c360fda76f3197ac47582c5e9b59d7a8a7b9; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a61c1123c1a23ffdd9af5fb28b62b95f989876ac322452f5e4f4470c25182ef4816aaec7f0377167; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 5e5d0fe86d7f8ff85108bbf75cf25dd99e8029237b93ff0d93fb779264a103082cc62ad8914feed3; +} diff --git a/symm/t/safer b/symm/t/safer new file mode 100644 index 0000000..1279b75 --- /dev/null +++ b/symm/t/safer @@ -0,0 +1,8 @@ +# Test vectors for SAFER + +# From HAC 7.114, and Richard de Moliner's implementation + +safer { + 0807060504030201 0102030405060708 c8f29cdd87783ed9; + 100f0e0d0c0b0a090807060504030201 0102030405060708 4a99b15cce9ada19; +} diff --git a/symm/t/safersk b/symm/t/safersk new file mode 100644 index 0000000..ac83b5b --- /dev/null +++ b/symm/t/safersk @@ -0,0 +1,8 @@ +# Test vectors for SAFER + +# From HAC 7.114, and Richard de Moliner's implementation + +safersk { + 0102030405060708 0102030405060708 60d04ad7c49b8ded; + 100f0e0d0c0b0a090807060504030201 0102030405060708 b260740f80d2445d; +} diff --git a/symm/t/seal b/symm/t/seal new file mode 100644 index 0000000..c338c32 --- /dev/null +++ b/symm/t/seal @@ -0,0 +1,6 @@ +# Test vectors for SEAL + +seal { + 67452301efcdab8998badcfe10325476c3d2e1f0 0x013577af + 9505a0379cc4849b051ebea40f537306fd97b05fbd3fa1f6cdde2c6c7ceefd81e7c3bd2aff9a20648322a100855067ef534b63c1e6599028d95eaba7eb010c48; +} diff --git a/tests/serpent.aes b/symm/t/serpent.aes similarity index 100% rename from tests/serpent.aes rename to symm/t/serpent.aes diff --git a/symm/t/sha b/symm/t/sha new file mode 100644 index 0000000..9ae4f4b --- /dev/null +++ b/symm/t/sha @@ -0,0 +1,61 @@ +# Test vectors for the SHA-1 hash function + +# --- Basic hash function --- +# +# Some of these are taken directly from the Secure Hash Standard +# (FIPS 180-1). Others were generated using the SSLeay implementation of +# SHA-1. + +sha { + "" da39a3ee5e6b4b0d3255bfef95601890afd80709; + "a" 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8; + "abc" a9993e364706816aba3e25717850c26c9cd0d89d; + "message digest" c12252ceda8be8994d5fa0290a47231c1d16aae3; + "abcdefghijklmnopqrstuvwxyz" + 32d10c7b8cf96570ca04ce37f2a19d84240d3a89; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983e441c3bd26ebaae4aa1f95129e5e54670f1; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + 761c457bf73b14d27e9e9265c46f4b4dda11f940; +} + +sha-rep { + "1234567890" 8 50abf5706a150990a08b2c5ea40fa0e585554732; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +" 23 f74d36bf17ee23c46ec166a48a24da6ab999eaea; + "a" 1000000 34aa973cd4c4daa4f61eeb2bdbad27316534016f; +} + +# --- HMAC mode --- +# +# Test vectors from RFC2202. + +sha-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + b617318655057264e28bc0b6fb378c8ef146be00; + + "what do ya want for nothing?" + 4a656665 + effcdf6ae5eb2fa2d27416d5f184df9c259a7c79; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 125d7342b9ac11cd91a39af48aa17b4f63f175d3; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + 4c9007f4026250c6bc8414f9bf50c86c2d7235da; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 4c1a03424b55e07fe7f27be1d58bb9324a9a5a04; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aa4ae5e15272d00e95705637ce8a3b55ed402112; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + e8e99d0f45237d786d6bbaa7965c7808bbff1a91; +} diff --git a/symm/t/sha224 b/symm/t/sha224 new file mode 100644 index 0000000..35e1171 --- /dev/null +++ b/symm/t/sha224 @@ -0,0 +1,72 @@ +# Test vectors for SHA-224 + +# --- Basic hash function --- + +sha224 { + + # --- Test vectors from the definition [FALSE] --- + + "abc" + 23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525; + + # --- Other tests to trap regression --- + + "" + d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f; + "a" + abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5; + "message digest" + 2cb21c83ae2f004de7e81c3c7019cbcb65b71ab656b22d6d0c39b8eb; + "abcdefghijklmnopqrstuvwxyz" + 45a5f72c39c5cff2522eb3429799e49e5f44b356ef926bcf390dccc2; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + bff72b4fcb7d75e5632900ac5f90d219e05e97a7bde72e740db393d9; +} + +sha224-rep { + "1234567890" 8 + b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +" 23 + 5a86156c37c95ab356e003d569370580737794815f46de7f4834d634; + "a" 1000000 + 20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67; +} + +# --- HMAC mode --- +# +# Autogenerated, unofficial. + +sha224-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + 1abbc7c42cf4ca9f9d7b624564cb72d7b0945ea0a615095904a0fd34; + + "what do ya want for nothing?" + 4a656665 + a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 5121d4bc8e43ee3ddcc2b0d312c110e961fc34b19ced1cce11c7a55c; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + 6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 0f081672137307d07aad12880537cd43f454823de00c038424741e17; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 9ed2eebc0ed23576efc815e9b5bc0d9257e36d13e4dd5d5f0c809b38; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 7358939e58683a448ac5065196d33191a1c1d33d4b8b0304dc60f5e0; +} diff --git a/symm/t/sha256 b/symm/t/sha256 new file mode 100644 index 0000000..f4561e8 --- /dev/null +++ b/symm/t/sha256 @@ -0,0 +1,71 @@ +# Test vectors for SHA-256 + +# --- Basic hash function --- + +sha256 { + + # --- Test vectors from the definition --- + + "abc" + ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1; + + # --- Other tests to trap regression --- + + "" + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855; + "a" + ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb; + "message digest" + f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650; + "abcdefghijklmnopqrstuvwxyz" + 71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0; +} + +sha256-rep { + "1234567890" 8 + f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +" 23 4804a2a4759acebe127b62ba651ae601a756ca0b509e4987498224acaffb0d98; + "a" 1000000 + cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0; +} + +# --- HMAC mode --- +# +# Autogenerated, unofficial. + +sha256-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + 198a607eb44bfbc69903a0f1cf2bbdc5ba0aa3f3d9ae3c1c7a3b1696a0b68cf7; + + "what do ya want for nothing?" + 4a656665 + 5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + cdcb1220d1ecccea91e53aba3092f962e549fe6ce9ed7fdc43191fbde45c30b0; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + 82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 7546af01841fc09b1ab9c3749a5f1c17d4f589668a587b2700a9c97c1193cf42; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 6953025ed96f0c09f80a96f78e6538dbe2e7b820e3dd970e7ddd39091b32352f; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 6355ac22e890d0a3c8481a5ca4825bc884d3e7a1ff98a2fc2ac7d8e064c3b2e6; +} diff --git a/symm/t/sha384 b/symm/t/sha384 new file mode 100644 index 0000000..f3148fd --- /dev/null +++ b/symm/t/sha384 @@ -0,0 +1,72 @@ +# Test vectors for SHA-384 + +# --- Basic hash function --- + +sha384 { + + # --- Test vectors from the definition --- + + "abc" + cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7; + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" + 09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039; + + # --- Other tests to trap regression --- + + "" + 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b; + "a" + 54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31; + "message digest" + 473ed35167ec1f5d8e550368a3db39be54639f828868e9454c239fc8b52e3c61dbd0d8b4de1390c256dcbb5d5fd99cd5; + "abcdefghijklmnopqrstuvwxyz" + feb67349df3db6f5924815d6c3dc133f091809213731fe5c7b5f4999e463479ff2877f5f2936fa63bb43784b12f3ebb4; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + 1761336e3f7cbfe51deb137f026f89e01a448e3b1fafa64039c1464ee8732f11a5341a6f41e0c202294736ed64db1a84; +} + +sha384-rep { + "1234567890" 8 + b12932b0627d1c060942f5447764155655bd4da0c9afa6dd9b9ef53129af1b8fb0195996d2de9ca0df9d821ffee67026; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +" 23 + f77d169c73427bd30cceff74f822a0209657dfb78c07980509bf8452a3c5d671b7198081898d0a0034e0f7151211fa0f; + "a" 1000000 + 9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985; +} + +# --- HMAC mode --- +# +# Autogenerated, unofficial. + +sha384-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + b6a8d5636f5c6a7224f9977dcf7ee6c7fb6d0c48cbdee9737a959796489bddbc4c5df61d5b3297b4fb68dab9f1b582c2; + + "what do ya want for nothing?" + 4a656665 + af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 809f439be00274321d4a538652164b53554a508184a0c3160353e3428597003d35914a18770f9443987054944b7c4b4a; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2122232425262728292a2b2c2d2e2f30313233343536373839 + b8405cddb33af1a68a1a71a8a4e6189a724fe28209671d701f7ecd4582d4db61b3a31ddca42a0db4efa2c5caf7a0482c; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 3b44c978360a9da6eba51d8186dd879bac52801ba2cba0afcb0f612f3305668accf4d5367a686e547426abfe7832f8ba; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 39cc73806611492e9179e2c23cebddd61c240b0b9c5a095db35f978d48642a1a49a2dde075f2b54cefbae7fe0aed4909; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data Bearing In Mind That This Hash Has An Extraordinarily Large Block Size So The Standard Test Won't Work" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + f9ac83e56d205edb71774e0d1ee102330583c474020bcbe52f02384f6fdf09e7e8b75495d74eea4788c17e48e64d6888; +} diff --git a/symm/t/sha512 b/symm/t/sha512 new file mode 100644 index 0000000..dcf3f04 --- /dev/null +++ b/symm/t/sha512 @@ -0,0 +1,73 @@ +# Test vectors for SHA-512 + +# --- Basic hash function --- + +sha512 { + + # --- Test vectors from the definition --- + + "abc" + ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f; + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" + 8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909; + + # --- Other tests to trap regression --- + + "" + cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e; + "a" + 1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75; + "message digest" + 107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c; + "abcdefghijklmnopqrstuvwxyz" + 4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1; + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + 1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894; +} + +sha512-rep { + "1234567890" 8 + 72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843; + + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +" 23 + 4def32cfb1107a104eae530fe04326a57e839a0bd9675f6770ff18d0b3b3ee2d4343bf99e9d54adc272617d49d0f61eab4b4bc177f9d2bac086cd2d902b5780e; + "a" 1000000 + e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b; +} + +# --- HMAC mode --- +# +# Autogenerated, unofficial. + +sha512-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0bb0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + bb969b8e6b99529a2e09757ef582257aed4f66cb62f1b32150b969eaa7dd683d46a776726cbf0f614f784cfa0759e84ba1d0baf07a1391ed998da6ea2fd7ff53; + + "what do ya want for nothing?" + 4a656665 + 164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 2ee7acd783624ca9398710f3ee05ae41b9f9b0510c87e49e586cc9bf961733d8623c7b55cebefccf02d5581acc1c9d5fb1ff68a1de45509fbe4da9a433922655; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2122232425262728292a2b2c2d2e2f30313233343536373839 + 005a43d33fe40a285dc0947121984509698d4533519662c5eda2f8fac7a6b69f78ce84b61b1427d8dc88046aa1f35c6513b467185de195deb4dee3367b55d38d; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 54701368cc706f527661ec9617d506ab255890b7c0cd8318f2efcf2b1bfbac560a77c369bdc01220d652e79747c0fa465da176e34b0de91cf075db0a12ac0ab5; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + ae52fbcfb432b5963d1fa0b38a584554752d41f5b4de82483ec1f32de676ae708fc20ffa3bc6525f3d4115eda6b145bf123ed5acf6cbb0ee7f7bf625402609fd; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data Bearing In Mind That This Hash Has An Extraordinarily Large Block Size So The Standard Test Won't Work" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 062d5553721e9512a061feaa8a236a5c2c5a45f25ed3ebe9c7337f3bc26b65d8ba3e1bd061b53fe45ac03800aeee4b48c6f2f3bd955c32991bd2bfaf2b1c05a3; +} diff --git a/symm/t/skipjack b/symm/t/skipjack new file mode 100644 index 0000000..63ac0cb --- /dev/null +++ b/symm/t/skipjack @@ -0,0 +1,101 @@ +# Test vectors for Skipjack + +# --- From the Skipjack definition --- + +skipjack { + + # --- The official Skipjack test vector --- + # + # It's a bit piss-poor that they only provide one test-vector here. + + 00998877665544332211 33221100ddccbbaa 2587cae27a12d300; + + # --- From KEA test vectors --- + # + # The Skipjack algorithm is used by the KEA to derive the final key. + # Unfortunately, the test vectors given in the Skipjack/KEA spec don't + # match my (or anyone else's!) implementation. These are the values + # which seem to be generally agreed. + + e7496e99e4628b7f9ffb 99ccfe2b90fd550b 60a73d387b517fca; + e7496e99e4628b7f9ffb 60a73d387b517fca 24c90cb05d668b27; + e5caf4dcc70e55f1dd90 b71cb0d009af2765 64f4877ae68a8a62; + e5caf4dcc70e55f1dd90 64f4877ae68a8a62 fee778a838a601cd; + + # --- These are the results expected from the KEA spec --- + # + # A `?' indicates that I don't know what that digit's meant to be. I've + # derived the top 16 bits of the intermediate results from the spec. + +# e7496e99e4628b7f9ffb 99ccfe2b90fd550b 2f30????????????; +# e7496e99e4628b7f9ffb 2f30???????????? 740839dee833add4; +# e5caf4dcc70e55f1dd90 b71cb0d009af2765 8e27????????????; +# e5caf4dcc70e55f1dd90 8e27???????????? 97fd1c6bd86bc439; + + # --- Some more test vectors --- + # + # These are dreamed up by me. The above tests don't actually exhaustively + # test the F-table. There are 16 entries unaccounted for. The keys and + # plaintexts were generated using fibrand with seed 0. + + cde4bef260d7bcda1635 47d348b7551195e7 f17b3070144aebea; + 7022907dd1dff7dac5c9 941d26d0c6eb14ad a055d02c5e0eae8d; + 568f86edd1dc9268eeee 533285a6ed810c9b b4c22f4fb74c35dc; + 689daaa9060d2d4b6003 062365b0a54364c7 08698d8786f80d16; + 6c160f11896c4794846e cfa14a7130c9f137 d6db848b7cecdd39; + + # --- And some more, posted to Usenet --- + # + # Message-id <8m7slq$1i1$1@hecate.umd.edu> + + f8da02647722f7103adf 1ddf39abf5cd711e c92d22324c6b31ae; + 82760ac137948821eee4 dd6c6cce8f83e69e e32877c1d9527fff; + 843c1687d3cdca5fc5c3 beaacf177fa41a11 4745783f75b8861a; + ae870cd7ff33a995f7e5 c4c09f216c1bc60a 5c101636b8a57a72; + 5ccbd913ea8b73bd6391 d3f814b000245856 b4fc0f8e54728f91; + f65e74cd599c68a40cc7 356ec7d93832329c 93b750608f5701f8; + aa106e46d7087c4e93dc 209ecf1c537ad56c d823d45510099e61; + a93f9789a20c3cc34fea 892eea9d64e17d66 0959e231b275d95f; + 88b163cbd61616888899 991390fd760fc91b e7700209886767ae; + fb6cd1ff70487561df10 daebc947ddca9c9e e7cc49a56bd6a322; + 5edc1ac0c4e7ef5f002c 6419ddefe2cd8f2e e48a05cf26e242fd; + 8e3090c19aa32f94496a 322998ecbd068112 62c0e537b14df2c1; + b96e3fd46fa4263f9092 3aae2aee20da93cc 54d1e58a6b624d71; + 9e6635baee28c5bce2bc 14311112ca11f727 5d0f235a9d221ce0; + 04127ce16dc1b1726a66 300e4313e7ad6796 8e5b03522e68cbeb; + f0b89d75e979ccc9b172 09cd1c1accbe7797 572c9b4025a9134b; + f9bfc78798cbf1bcd4b5 31b30ca354af3cd8 8c959c904789fbda; + f43a51b4273bde27d2b0 08c59b0db99ec267 b7d7f5fa342988fb; + cd51f0a75aa73c48edd2 9784b1e3e7e60e60 763aa8ee109397b3; + b3319a3f6622aa726bb3 f65216373d4b43c7 0325600337b8ad3c; + 493254c9596e993f5f9c cba4c1215d5d36ce 68e1c551c59108c0; + 76150c2c3ced1c7ca021 82294851288e75cb 7eb6325d82a2096c; + 7140d6c5486305872df6 c3a7b7e4a52e407b 2483f385a42ee3c6; + 3c2c3901f0ee9a3b2b0e 1bfde32ab559e13a d6fa9db8685fd88a; + 606a8b4bdfaae8a0ba51 d205f7486c782838 0330489170b85293; + 7847a47a0fe79ab770ce d96ff1f7c7fc60e0 1f9b3301c9b2708c; + 73b9ab0c36c99e91a891 241d4bde19a75f8f 2b86c57ffe168895; + a37f2ad5a85e170741f5 7be1b8d58321c619 5af7ceb3eed9dca1; + f7b0c2a8170e3c4e48b3 c9214ea01ec14948 1b587736e116c04b; + a1fc67e44eacacf4a902 e2a3091feb581588 f3ecf0f1789a3923; + f14430affc5fe82a9ae9 3cb466d301b60854 e8d114c20ffa1c79; + fd26df50486a4cd96d9b b0684f8a5e63d935 222903994d64fe3a; + a6d46d46ca287e1a332a ba1f37e88edec55f 91f2baad6fa0de55; + 83c3f1cb8d06efc6196b e9fed8501b7a6579 83f9f08f89a854ee; + 0edfa44c7d4a4ef0725e eb5ca8b3fa1fcdbb 2b1b6670a6be0324; + b8edcf167d99a711ccee b8b525c6382af277 211a695da473766f; + 4f639e0d5a5d2ad7e9a4 9162e781ff683853 eb2976370d22ef22; + 37e006256a4ae6d320c4 c9f23a20a39ded11 dba4c0ef0ea098c0; + e41d0bd25f931ba1d85c 5a6f12f32f7eefdf 923daee8000709f9; + fdf65bbc5fe600f3cd68 cad5414c1c64f194 d5771e78b6f1fe1e; + 1c269af2ff166acb27ef 063a58a20b45378f 634f7a3861af97a1; + 1179f64acb6122ccf649 08fbf42b4313347b 3a803a4bd0e8c3e6; + 078c87265eb8da323e90 6d4ed0e9930532d1 f4fa372e7e1441a1; + 2fff35f8eb774c843bb0 40b699812345661d 63a9197f7b75f53f; + 09f77346a4393ce99856 22ed54626a51e505 e91a050a7481b3dd; + 5b878e0b22a705acf8fb 0c489b66e2da531b 6e9370a91b994878; + 9d72c1ab2092c1b10877 c64b10f8b191bc2c 5bdecded96d656c9; + 72865f289725e1b55502 91fdf7236f85bdd6 1a5680e51736026f; + 06e3c0e541f4aae6fe93 40009f8a465a9feb 0e7aace421bc79d8; + 2ea09f1cc89e064f09bc 543208b05bfa3858 a95d87fad12c3593; +} diff --git a/symm/t/square b/symm/t/square new file mode 100644 index 0000000..7b348e2 --- /dev/null +++ b/symm/t/square @@ -0,0 +1,523 @@ +# Test vectors for the Square block cipher + +square { + # --- From the reference implementation --- + + 000102030405060708090a0b0c0d0e0f + 000102030405060708090a0b0c0d0e0f 7c3491d94994e70f0ec2e7a5ccb5a14f; + + # --- From the validation data --- + + 80000000000000000000000000000000 + 00000000000000000000000000000000 05f8aafdefb4f5f9c751e5b36c8a37d8; + 40000000000000000000000000000000 + 00000000000000000000000000000000 60affc9b2312b1397177251cc9296391; + 20000000000000000000000000000000 + 00000000000000000000000000000000 d67b7e07c38f311446e16ddd9ea96ebe; + 10000000000000000000000000000000 + 00000000000000000000000000000000 39207579067031706fab8c3a5c6e5524; + 08000000000000000000000000000000 + 00000000000000000000000000000000 fc4f2602a3f6ac34f56906c2eeee40c5; + 04000000000000000000000000000000 + 00000000000000000000000000000000 6f2431469f4a0866632216c59c18ff11; + 02000000000000000000000000000000 + 00000000000000000000000000000000 c745f6f339d1bb9524e1b2d2b0dde843; + 01000000000000000000000000000000 + 00000000000000000000000000000000 241e113a1bb5c32cc45d95d7734165aa; + 00800000000000000000000000000000 + 00000000000000000000000000000000 5e16777211c67ae4609f6a47bf5df2c4; + 00400000000000000000000000000000 + 00000000000000000000000000000000 272330139236c300cd161f0266b62494; + 00200000000000000000000000000000 + 00000000000000000000000000000000 15115b9e29524325e7c992ead262ade8; + 00100000000000000000000000000000 + 00000000000000000000000000000000 acdcce277b801ed53dfe0fc12f4c957b; + 00080000000000000000000000000000 + 00000000000000000000000000000000 9cadb290cedd6f7ca6c10d42fe4c1a70; + 00040000000000000000000000000000 + 00000000000000000000000000000000 d70d4c24ffbf3de6e6bd54ec03b8492a; + 00020000000000000000000000000000 + 00000000000000000000000000000000 602455a418a99a942fed27123b9f73e6; + 00010000000000000000000000000000 + 00000000000000000000000000000000 f239c4efd3729d43081544104378f0ea; + 00008000000000000000000000000000 + 00000000000000000000000000000000 70259a9572990099ac563114074db3d2; + 00004000000000000000000000000000 + 00000000000000000000000000000000 932d3644863b6377100c64f243445e7e; + 00002000000000000000000000000000 + 00000000000000000000000000000000 47100bf12f2e1f718e9430f4127535be; + 00001000000000000000000000000000 + 00000000000000000000000000000000 2ed60ffa71c162a53c3a8bba2b0b042b; + 00000800000000000000000000000000 + 00000000000000000000000000000000 e2992d6bdc7c65b70b62685c0d84425c; + 00000400000000000000000000000000 + 00000000000000000000000000000000 c552ca3d805e456f5239dd7956cacd71; + 00000200000000000000000000000000 + 00000000000000000000000000000000 95b577c2ed3c2d9d96c2106e091b1f72; + 00000100000000000000000000000000 + 00000000000000000000000000000000 3d550ae470bfb0306c3099c8d5a471d8; + 00000080000000000000000000000000 + 00000000000000000000000000000000 fc13974afe73a92598aa95edcb2102e9; + 00000040000000000000000000000000 + 00000000000000000000000000000000 ab0cf3a0cfef3aa3d10738523e624a1d; + 00000020000000000000000000000000 + 00000000000000000000000000000000 72fea53144f673e283547f08da30bdda; + 00000010000000000000000000000000 + 00000000000000000000000000000000 389fef99fa1a3dbf664673aa39d848d1; + 00000008000000000000000000000000 + 00000000000000000000000000000000 041152bca8440e8de572dce9dcc88cdc; + 00000004000000000000000000000000 + 00000000000000000000000000000000 845b37c1338a0ba0f295be273841b940; + 00000002000000000000000000000000 + 00000000000000000000000000000000 e2e3a1c7998040ee6bd8714e65ebd8af; + 00000001000000000000000000000000 + 00000000000000000000000000000000 0b2b34c480648dc91f938dd368464780; + 00000000800000000000000000000000 + 00000000000000000000000000000000 96bad4a54376917044b1076727a91e2b; + 00000000400000000000000000000000 + 00000000000000000000000000000000 dd8c3dff69c3fda2802dffcdef1b1631; + 00000000200000000000000000000000 + 00000000000000000000000000000000 da45872e48af2f0ec7fc395d03ff9451; + 00000000100000000000000000000000 + 00000000000000000000000000000000 b25194c0f1953f35bc4c0871cd2d4a40; + 00000000080000000000000000000000 + 00000000000000000000000000000000 3e09af82736971f2847834082d6ec6f3; + 00000000040000000000000000000000 + 00000000000000000000000000000000 fa75a64f778b914dc4b926626bc8b4c0; + 00000000020000000000000000000000 + 00000000000000000000000000000000 d21542857f03f6a92cacd2e783e33e3e; + 00000000010000000000000000000000 + 00000000000000000000000000000000 1ec0a5b9781c5e90b1e15731e0625c36; + 00000000008000000000000000000000 + 00000000000000000000000000000000 e1c58917e586b6c46c46982fa303f14c; + 00000000004000000000000000000000 + 00000000000000000000000000000000 72ecc0d267b445482924c9969de97a15; + 00000000002000000000000000000000 + 00000000000000000000000000000000 a52af631193375dd59555e2753acde65; + 00000000001000000000000000000000 + 00000000000000000000000000000000 033b8482c4010eb20a3edd4ba35a3db7; + 00000000000800000000000000000000 + 00000000000000000000000000000000 56534a944796abdf51ad247b8c9ee9bb; + 00000000000400000000000000000000 + 00000000000000000000000000000000 9eda6fd2cd4eabf8218b98a165e82b9e; + 00000000000200000000000000000000 + 00000000000000000000000000000000 60043a7e110e1321bc41e4ac47d1f45e; + 00000000000100000000000000000000 + 00000000000000000000000000000000 90e685c8f990cedeacc8a2bfc8e46ca2; + 00000000000080000000000000000000 + 00000000000000000000000000000000 b9e77e32f721c0a7a02b50925311e834; + 00000000000040000000000000000000 + 00000000000000000000000000000000 001d2fe95bb39ef0c3548307ea7580f3; + 00000000000020000000000000000000 + 00000000000000000000000000000000 a5dd651290a063f4e7c5e714c9c398b4; + 00000000000010000000000000000000 + 00000000000000000000000000000000 aa7b3b9f459ba0367ff2a332ef725da1; + 00000000000008000000000000000000 + 00000000000000000000000000000000 a424f80b0048756879ed6343768bbe08; + 00000000000004000000000000000000 + 00000000000000000000000000000000 ea4590786de7f8a68439b4616bf7e4b9; + 00000000000002000000000000000000 + 00000000000000000000000000000000 7d15058fe884dcf0976105a816cf6366; + 00000000000001000000000000000000 + 00000000000000000000000000000000 a07d1b74ae6a3f26a8a25e1e778a0d4a; + 00000000000000800000000000000000 + 00000000000000000000000000000000 61f13db32828961c3e35d9b7ab77b57d; + 00000000000000400000000000000000 + 00000000000000000000000000000000 0e2979112efb29754605011a358093fc; + 00000000000000200000000000000000 + 00000000000000000000000000000000 a878c8a8a5230917c56f7eb74fdada25; + 00000000000000100000000000000000 + 00000000000000000000000000000000 34343f73232790e6fa44d8f606a24de9; + 00000000000000080000000000000000 + 00000000000000000000000000000000 d569b991761c26dde723cca0c262f195; + 00000000000000040000000000000000 + 00000000000000000000000000000000 f1a0f35ada018c5df56ffe0dc95636bf; + 00000000000000020000000000000000 + 00000000000000000000000000000000 b26af455039312e1206290a921459e1a; + 00000000000000010000000000000000 + 00000000000000000000000000000000 594049c7e3a34e1b9bccefaf5e75b373; + 00000000000000008000000000000000 + 00000000000000000000000000000000 4e4e037f07ff26e8e9065f26afedaf2d; + 00000000000000004000000000000000 + 00000000000000000000000000000000 ddedc3ca10ec011ea24dd4566d21409c; + 00000000000000002000000000000000 + 00000000000000000000000000000000 3660f51bb790f275a55aa435db6da193; + 00000000000000001000000000000000 + 00000000000000000000000000000000 a9a7cfe07ea640498e832ae25e2906ed; + 00000000000000000800000000000000 + 00000000000000000000000000000000 3863d1c222a36338ea6d402073341f42; + 00000000000000000400000000000000 + 00000000000000000000000000000000 ced5dfdf8b5d1d60e9ad51830a7965a9; + 00000000000000000200000000000000 + 00000000000000000000000000000000 4ffae5d7a5689a5584330cb0a5cc9cd2; + 00000000000000000100000000000000 + 00000000000000000000000000000000 1dd688d47541463915f658bb656420b4; + 00000000000000000080000000000000 + 00000000000000000000000000000000 ef3a1c1800dd3cda748fbdf17086ba4f; + 00000000000000000040000000000000 + 00000000000000000000000000000000 f9aa9b3e76543ef12f7f8b87ce393328; + 00000000000000000020000000000000 + 00000000000000000000000000000000 1813935bb67dc40dc37c68cc2999758a; + 00000000000000000010000000000000 + 00000000000000000000000000000000 8c4916d59fce8eb913b128f2d7b3d464; + 00000000000000000008000000000000 + 00000000000000000000000000000000 bb88da704c5ce031c61954efcae6ed2d; + 00000000000000000004000000000000 + 00000000000000000000000000000000 4e463bceb0f52c3f722e2926c2bd04a3; + 00000000000000000002000000000000 + 00000000000000000000000000000000 4a6181492a454604293396bbd21c4956; + 00000000000000000001000000000000 + 00000000000000000000000000000000 801f29d5462365735a6ca7a64288f48c; + 00000000000000000000800000000000 + 00000000000000000000000000000000 7933733c4daab746ef048edba2d05538; + 00000000000000000000400000000000 + 00000000000000000000000000000000 4127c1d95431fd2632f2b5e5085a3dd8; + 00000000000000000000200000000000 + 00000000000000000000000000000000 0588168ca7525333460c4030af266388; + 00000000000000000000100000000000 + 00000000000000000000000000000000 32b3f193d7237b48883de002b3cbe1c3; + 00000000000000000000080000000000 + 00000000000000000000000000000000 7ca557bc05b845a233c01412022da825; + 00000000000000000000040000000000 + 00000000000000000000000000000000 54f11361ad6dfbb069be67536cc98d81; + 00000000000000000000020000000000 + 00000000000000000000000000000000 a9df031b4e25e89f527efff89cb0beba; + 00000000000000000000010000000000 + 00000000000000000000000000000000 7da4d0d6309906d935ba27ae00cfaf33; + 00000000000000000000008000000000 + 00000000000000000000000000000000 e231ea0fec29d983d3236bb15e7cd1da; + 00000000000000000000004000000000 + 00000000000000000000000000000000 fe1b963a4f596422a6cd7787f4ab3377; + 00000000000000000000002000000000 + 00000000000000000000000000000000 848833f2f7a247d2e1d0c8614694139f; + 00000000000000000000001000000000 + 00000000000000000000000000000000 630bb1dc4e60d3272b6b673bdb918b20; + 00000000000000000000000800000000 + 00000000000000000000000000000000 500251a5c6ad5a6d2f218a3fd5765727; + 00000000000000000000000400000000 + 00000000000000000000000000000000 d019ef316e84149cfd0e85665aa2fff5; + 00000000000000000000000200000000 + 00000000000000000000000000000000 db0b5ac0e8ef011d710323fa3b8bb3a7; + 00000000000000000000000100000000 + 00000000000000000000000000000000 207e46a533617374d2c9da0c92ffd620; + 00000000000000000000000080000000 + 00000000000000000000000000000000 8273ca155249f9f1ad8cc2ca114984f3; + 00000000000000000000000040000000 + 00000000000000000000000000000000 82a73a18aae84ad671e226470f246e1a; + 00000000000000000000000020000000 + 00000000000000000000000000000000 3e0e1206e333917d4c250bd82fef6afd; + 00000000000000000000000010000000 + 00000000000000000000000000000000 2182f67239be15c796439ea3791202e1; + 00000000000000000000000008000000 + 00000000000000000000000000000000 486fb3fa7b1fe1a304cb4e8960c3c6bb; + 00000000000000000000000004000000 + 00000000000000000000000000000000 c1de50e456c4308d5d70da141cef0b4f; + 00000000000000000000000002000000 + 00000000000000000000000000000000 a623f24515a27cee3dad277429000218; + 00000000000000000000000001000000 + 00000000000000000000000000000000 02fa5762f9cd90201565bce71140c6f4; + 00000000000000000000000000800000 + 00000000000000000000000000000000 a643a0ca5154a7d10b251d562d58ea53; + 00000000000000000000000000400000 + 00000000000000000000000000000000 48660e32b1c7ee7085e5b5e9f719c790; + 00000000000000000000000000200000 + 00000000000000000000000000000000 a96366bb17b67e161fd8e33c3e1f3d2a; + 00000000000000000000000000100000 + 00000000000000000000000000000000 5659ab825fc2de031a6998cacd741ff6; + 00000000000000000000000000080000 + 00000000000000000000000000000000 1253e9e4079e9b573a73cf4ce08dc015; + 00000000000000000000000000040000 + 00000000000000000000000000000000 28205442270c735d4ba79042dce81509; + 00000000000000000000000000020000 + 00000000000000000000000000000000 98cfb10f3ed70bb82cc90597b463a1f6; + 00000000000000000000000000010000 + 00000000000000000000000000000000 cab40433631fe3a272fc401255a58064; + 00000000000000000000000000008000 + 00000000000000000000000000000000 abb041d85114da88e65e8bdcf1c67cc8; + 00000000000000000000000000004000 + 00000000000000000000000000000000 00f0926f0f9eaa0a6238dfce79c8f596; + 00000000000000000000000000002000 + 00000000000000000000000000000000 7c662d01b12d9845705b2bd4d7aef43d; + 00000000000000000000000000001000 + 00000000000000000000000000000000 8f1cc7a0fbe7d70a894d09e12fb22bb8; + 00000000000000000000000000000800 + 00000000000000000000000000000000 ebe03d0c6752d0edfebff879c33d8c07; + 00000000000000000000000000000400 + 00000000000000000000000000000000 b74ce7f67bbd969e8ff8862d1fb1715c; + 00000000000000000000000000000200 + 00000000000000000000000000000000 63ad5ea9d599ec848a40d489c0b85e8a; + 00000000000000000000000000000100 + 00000000000000000000000000000000 4e4167f091ea5776e80fb2fca38c2a04; + 00000000000000000000000000000080 + 00000000000000000000000000000000 dbf0cea3a5ed5b884ac13a2a62c32d51; + 00000000000000000000000000000040 + 00000000000000000000000000000000 7e86285068a376a3b9fe8641a38e3f90; + 00000000000000000000000000000020 + 00000000000000000000000000000000 aec1ef8d651a2cf7b5475fcc7fb7a81a; + 00000000000000000000000000000010 + 00000000000000000000000000000000 fda539d910181ce1a1e1db4c3459600b; + 00000000000000000000000000000008 + 00000000000000000000000000000000 f8072bf053d5b5163949ff0b9bb3f81a; + 00000000000000000000000000000004 + 00000000000000000000000000000000 a31eb966d34ed6a6132a6b6e9128e997; + 00000000000000000000000000000002 + 00000000000000000000000000000000 673aebbff82091a19e758ece151811d0; + 00000000000000000000000000000001 + 00000000000000000000000000000000 369bdb6f102d6bfea7645b1a6753bf37; + 80000000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 ffd90e8a92a1b025108168714f7923f7; + 40000000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 64e10ab587bc5d996cf2186c2ff2dd58; + 20000000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 eaa404b51336a16c963735588b0b2a0c; + 10000000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 51aaa1e37cb08cf5c6ec9241ac36b4c5; + 08000000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 c21b34c3c077b30add67d0e2e75e59ec; + 04000000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 f33ccd4771932f5e467552e93ae367ab; + 02000000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 b70b9f3a5814ddeb6d3549d88c5b4656; + 01000000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 5c01c66e9bf9617b155d3902722ccadc; + 00800000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 1f47def31d2e7e286172b38119fde307; + 00400000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 bd3c2f005cf0eb5ef737c29f457ed549; + 00200000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 1d409243f79ce876d13b0fdfea26ccf8; + 00100000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 b879e37c2f435b0cb941f74892c1476f; + 00080000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 58c6a8884bf8b110c9127893976a9e4e; + 00040000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 7a258ac14cb88a31432ba1b320d254f6; + 00020000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 ff382f1b4bbb54c9f42b73b256f80d25; + 00010000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 0cef334bcbe5d38e23a9780d2e3e9097; + 00008000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 3225e13778d2a3bab1eb375e034478c4; + 00004000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 4ef73320931377f64e296e49c286e5c9; + 00002000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 adbf2c07f2f42eb7d92acc07f9df7a5f; + 00001000000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 bfca14ad6925ddb4f563048db1c6b485; + 00000800000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 63f01ea46c82dc3b1d81eac5e4f1d687; + 00000400000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 b2f6eb69ce81accc720e705146cfc2a2; + 00000200000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 85b1ff06090504848fdda74dd830e960; + 00000100000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 5bcb44ab29d7c31def58c902c2491333; + 00000080000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 4d982cbc7c1455cde7c0de3f83fcbc5e; + 00000040000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 32f08276e0633e1d819fc6227e631503; + 00000020000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e6bebd4cddc205399126bfda486ed37c; + 00000010000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 afe39df4f356aea5f07069455010d9ce; + 00000008000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 a8c7b2c1e8e1ade5e28e4104ff716ba5; + 00000004000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 fbb3e4ca3e710a5bd94b50726de5fdb1; + 00000002000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 2091d65d6fbb8672d84655f33dc1473a; + 00000001000000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 9c74519acc53498333791febfd0e5e8b; + 00000000800000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 ed44022a82468ed54203b5863b63061f; + 00000000400000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 eae325499a1a9e8e1bd4d6f018e65551; + 00000000200000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 b134fe1498d7a1d926d3a623ffa5723e; + 00000000100000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 343f8d08a35c272c5cd4064a42a7b6d8; + 00000000080000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 79230ea5d7f6b5d85922ed7679aebe08; + 00000000040000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 d3f799e3579c68e10fb1c770b1cbb7c7; + 00000000020000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 90c24054dc24772ecd92a67a43335320; + 00000000010000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 bf38cfda7b75a478fa73316801883d34; + 00000000008000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 4323a85f7921a4a1fc072b72b6b46f50; + 00000000004000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 3e10218fdefd9a0b91d9032d793aecc8; + 00000000002000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 66a759ec5e5cdd9c27a4e97ff0b5aab8; + 00000000001000000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 3730876a26727d44a46404f69ba99f09; + 00000000000800000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 b277bd5a0e78eafc049bd9aa3393870f; + 00000000000400000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 af05cdd3a6dd19fb0199933bdea3c20f; + 00000000000200000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 0d962ec5f824d922924f3c39339fa934; + 00000000000100000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 de695dab525ffebc039f63c3defb200b; + 00000000000080000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 f8ce4303ff6a523a60e3526a28c1c1de; + 00000000000040000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 c00c5250a33165254408992f6aa1fb97; + 00000000000020000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 7e81d9c10bc3ac8fcac65079867183ff; + 00000000000010000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 42f91fe46e5f6485973123b586cc2517; + 00000000000008000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 0900c5c4bb963e1e421571056aeda9f0; + 00000000000004000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 933312932700ef9c82333913782fc8fb; + 00000000000002000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 d78181179ac4cc05f38a1d134b29b70a; + 00000000000001000000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 411b9bd8a8c3d3c9a2c375d28a336c4a; + 00000000000000800000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 632433f8708bd47d6a083adbdf3a8982; + 00000000000000400000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 f037e3fcd3db611bd777420b8170df1b; + 00000000000000200000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 31da207bfbdbb93157408ad2d7e559df; + 00000000000000100000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 2837b13cb713b5fde1bc07cb7b2613d9; + 00000000000000080000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 c31906513814506753848c50ab7c8d13; + 00000000000000040000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 014b54ca9f1d87c7711af20119b03afc; + 00000000000000020000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 060903be7b215ee51fbce79205b0515a; + 00000000000000010000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 f91da002995fe07969ff63b8673fa75a; + 00000000000000008000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 65a8b07ad4f77c8be4f27f975a42f2e7; + 00000000000000004000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 31a157653449da846b5dade80e2f3ae8; + 00000000000000002000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 1be98428352aeab7534e12463898bde5; + 00000000000000001000000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 a7a50bec385145e784486d6d70552fbf; + 00000000000000000800000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 eaacafae73701d566b24ab68350c4cb7; + 00000000000000000400000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 deef8a7a5de90caaa0e3412356518d9a; + 00000000000000000200000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 8d4373f4933353f589e42471ef35836c; + 00000000000000000100000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 01436b7d351b9ff0fe85dab7ef77a020; + 00000000000000000080000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 a6b2b93c4c6dafea4db5a4ecfee2c561; + 00000000000000000040000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 7b0f7781683d890db4582d4399b07fab; + 00000000000000000020000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 01c82b395331de265555d72df29c7efc; + 00000000000000000010000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 5d9ba76d5b20b4b88b70b80c20c5e350; + 00000000000000000008000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 92b2a69dd8a75d2edb01644a0b975c15; + 00000000000000000004000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e2f6e46a2a899615969f4b751d55d57f; + 00000000000000000002000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 97427298315d058eb2f7cdabd4a851c8; + 00000000000000000001000000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 8f0f710a0cc1d6049ebb01974b76caad; + 00000000000000000000800000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 2cf62d9d02afb40eed66fedb53c2db5c; + 00000000000000000000400000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 fb215ab9ec3fafc5fd91cd9ad3cee2be; + 00000000000000000000200000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 4a37472335edaf7393a304d45a233085; + 00000000000000000000100000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 d22a878d2ca3a88f34acc92a4e26c738; + 00000000000000000000080000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 f1a95970638dcbc69c4675e895370904; + 00000000000000000000040000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 1660060085c0e241f88462bffbe67602; + 00000000000000000000020000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 a097acb2eb5f779090f886beae746ae1; + 00000000000000000000010000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 9ffe05163407ba53b62a35d857f58bc6; + 00000000000000000000008000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 dfed8392eec1b389cbc261faf97c5c9e; + 00000000000000000000004000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 d2c1b3159129d86959f3aa9b70219a74; + 00000000000000000000002000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 98c043b2e86cff626abf5fbc745d98a6; + 00000000000000000000001000000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 35c5aed481c801a0ca78842273e0186d; + 00000000000000000000000800000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 ddaac5c7f13943e80d2244a4a19e9980; + 00000000000000000000000400000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 51dbf12fc81e5ffe9b1ce9963636205f; + 00000000000000000000000200000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 38ee89874d644ccdf9694280a6c48182; + 00000000000000000000000100000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 c3bc93ca8e8800622c92c56b99262ae2; + 00000000000000000000000080000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 dc2c2b7558f75b71a9db34e971892171; + 00000000000000000000000040000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 609bd72078f92ae345dcde14e6aba0e0; + 00000000000000000000000020000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 cabc8bdda6e1979199f5010c3f8b8a31; + 00000000000000000000000010000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 c993d659ba4426dc30f8dc7ea03cd2ee; + 00000000000000000000000008000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 5dd47466cbb15dca1485e04231d7491c; + 00000000000000000000000004000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e1351ce84ded187e0f5aab9bb7198387; + 00000000000000000000000002000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e5222c68fda26e5e62929c70233ad097; + 00000000000000000000000001000000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 78cc456147db73850328241bdff861c0; + 00000000000000000000000000800000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 4f10436e3ba4f38cd96744b897d5a136; + 00000000000000000000000000400000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 12b698464abcb67c3956c5d1b9c62dfd; + 00000000000000000000000000200000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 49de5db3e7d997c56dd2f82935e6617f; + 00000000000000000000000000100000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 71ea115e54775680f16b1b9d7b2ee367; + 00000000000000000000000000080000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 45b7e46c664a472af948b0c393f92af1; + 00000000000000000000000000040000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 db3678b993ef5e48931b5bf84cece6eb; + 00000000000000000000000000020000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 051c9a17d4ca77eabd8b9d9a1bce52d6; + 00000000000000000000000000010000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e805aeeac134761ff7b3260bb4308a10; + 00000000000000000000000000008000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 3301700109b460c7e41a51059f33004f; + 00000000000000000000000000004000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 d71f178093314e188bae26dde5a78927; + 00000000000000000000000000002000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 31bb9cb46fbf607fcaa5932851899420; + 00000000000000000000000000001000 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 ea77bcd0ce469ab47a828dc6324c3651; + 00000000000000000000000000000800 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e4596b0d33bdeb062a7ddb93e6efae94; + 00000000000000000000000000000400 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 24d04f34b837461cd3b8d9c13afe6fe5; + 00000000000000000000000000000200 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 ffb68c9ae4d7d2642bf5bee57d2bd914; + 00000000000000000000000000000100 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 c008d35eb9de15700c0491319e6415f0; + 00000000000000000000000000000080 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 92bfbbfcd2bbf54fff06af097893e9a3; + 00000000000000000000000000000040 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 d2475279191bc4da183ee2dba75fce6d; + 00000000000000000000000000000020 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 7b8adf2ef0e1f5fbb19cbd4b8fab1426; + 00000000000000000000000000000010 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 0b07b9c4385bdc86447f535e09a9f424; + 00000000000000000000000000000008 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e7308875d8d6645719c076dd1660924b; + 00000000000000000000000000000004 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 bc50d54a891d6102d0c02f471f1f0567; + 00000000000000000000000000000002 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 2b14534ca7d9821a40b101035f681f0d; + 00000000000000000000000000000001 + 0f1e2d3c4b5a69788796a5b4c3d2e1f0 69bd984641e0aa887bc23738f60070db; +} diff --git a/symm/t/tea b/symm/t/tea new file mode 100644 index 0000000..9eec55d --- /dev/null +++ b/symm/t/tea @@ -0,0 +1,74 @@ +# Test vectors for TEA + +# --- Generated from Needham and Wheeler's original implementation --- + +tea { + 00000000000000000000000000000000 0000000000000000 41ea3a0a94baa940; + ffffffffffffffffffffffffffffffff ffffffffffffffff 319bbefb016abdb2; + 00112233445566778899aabbccddeeff 0123456789abcdef 126c6b92c0653a3e; + 00112233445566778899aabbccddeeff 67452301efcdab89 d667cc4e10bf6eb0; + 00112233445566778899aabbccddeeff b3e551c7d8378a6c db21fb2a3118e62d; + d94576cd1a5f99e4155dc7bec5d33df2 d51399607f7aa9d7 7d1eb12827ef2121; + 07ef12bc9d06d7da20131116b665e335 10b233473624ccd3 ae694e579daeff54; + c6462b48afd604b75fcc455506ffd411 3b905e951e4fafe7 d9633fcf13c30394; + be195f703d6fec2232cd0890c981b27d 15b623d1fa2df9df 916ffcb1abaf086b; + 5b8410f7a9eb92da120810c56fcaf8c9 7c1035940696d91d 460aa2db964b580c; + b85c9e26661889d0ff1054c6be27fdeb 90b245144895f3ad 87d7e95a5a4aa89a; + a8a1e956d54d238f6ceab186e7ec99ed 4ef2cfd120b8d4dc 1752f2ee188018de; + 8bc4879201a96368927ecceee67024ee f6cb5353f4a1c432 7cfa8e0718d59807; + f1372d85d8c3d1a60df57eedf317ab81 215c080cf158a09b 3b85115e0d6c5a94; + 017f01683f5e009d196feeaad385c5a9 568583061da98d0d cb0e345182f4bf0b; + 281c932ddd3c364b09f1896007ffab03 0558b306316b0823 e7adf267c7d841c2; + c1e95465c7ef8eb04254d1a5463c6a43 fdcb2764303222c7 ed48b228c11e7bc6; + 0f86dd6c96dd31164b656b0f25e4b411 eaddba89070ec46c 89fb864135a57e33; + fbacfb479ae21194c35b8184e58dd66e c6507bcf99b9c2a1 670da449ce74c658; + 2eb36c4a9598d471700a1330070fffc9 c380b0f1c21d4d37 d84fe611431c0b5e; + 0a7f48127091780617a1f534b3271bc9 e5b7c1517f24f298 4be47c656cef6ffc; + 303fb24822a1b8a84d0ece77b86380ff d14ddf77fdda17bf 1cc73315c9f72ab1; + f04ebf798c193f199c1f532af383555b b9682750bb15caad 2b5f318fb66806b9; + 200c0ce59717d5d9af6813cd207fee73 9706769a18a2d03d 8e17eeb5008dc0cb; + 2828d51f98ae0b33f4de2b7fbd18a529 edb76c54847da59e dfa6c29beb40f9af; + 61aaba6be48b0d0d14fe5d27fab852a4 178a49bafba53f23 c3bbce6715d90ce6; + 2080e2409ba01c8532fc84403ee8c06a df4cdb61a5f38536 b4e6359c9d9458aa; + 271ad15192c4d1204a4a2561e3db6ff7 7c944d08def34c0c 195c0e8f49761539; + c1e297c0c761777d8a76fff02d22b859 f4c76c1d47fe568f 551ca67c7756ff56; + 23c807a2ef0a551f858fd52d125a47d8 cab16583e15d0074 de472175d55372c9; + 9fa5d4d8cbdfcecd559e3ce88bf78ee1 97b05c60774164ad bc4bd30cb50da39b; + 24f4e91083139099d663647a7ffac321 7017a263985b735c e47fdf06a51d8c24; + 7cf8626de76d8462218ed5c9dc8acc26 15475a90df04cd29 4df54282eaafa235; + 3c6ad7df17332a3e1e3de06007387357 87ca0aaccf146cc8 f7360f57cfcc09ac; + 24237a762d8a89383a2949f5a0f5ec08 9268af048ecbae67 e98e428a9d1fee9c; + 209a2833a39472d9720380ffb2f74761 af0062cd77a84ebd 44cd624b87cbee77; + 22ebe7a30e8855b3b453a6e926d4f187 f922ca875b991a31 1e92c0c51185f7c7; + 1b5e23ebd915c1fee59f57dd91af7347 b4ecc305c3dbd8e5 063d8f75a7a77501; + 6c21d105515290da29339f142685c135 a4c2f6dc597d13ea bf8ffec7550a496b; + 01f728a7433a47b13de34fcc08958449 3af7f1ae0f58ab1d bba581d07e51d8d6; + 9a2d4c50337d3ec337673782fd385601 791d8da8cbb0bc94 7d9a4f0363b6085f; + b3b99747560e246bcd0cdc3fb33e4910 91778f2bd9233375 4b85b79a58b1321e; + 4b269e2e8dbd68b94066c95244c3a195 abfb6a33e1471e96 53d089e9313e832d; + d10b956f675dc2276b6dd90442bece3e dbedddb6a1c15a21 b81739d49c10b4fd; + 28f8fab7541766f6dafbaa5b6f3bd700 2c14d5097ab11f61 c018b6e3cca4095f; + 2b61e60478fa0c0edb9531f26791eff9 b84c80b2d245fdfc 2301e2d68d241622; + a6bfb85fa91b8ca4197c8b502a62f972 3daadd7a9633e19b 65bc93b4dbbd652f; + 94e76e54d37f932cbcc069de6bf26d52 02739eeb468450fd a477a7ec244f1e9f; + 82760ea1560e8f9d1e35f20cad1f26cc 34aa5952b5a9110f 2564284b47152721; + 3aba91211327585e0f1270b59ef9277b b584d6b34b638ba4 c829dc4da560211f; + 727074f35cd523eb6f8aafbbf76fd5b1 f0e9268a27ab70c6 f24b80555fdcb67f; + 6e0aa1c91ea6315a4a7dd297ac5936a4 47374080f27fbb30 6fdb64c32920c0a5; + 63bd2d37271a250c8593b433188cffd0 776927909196eec5 57bca56240b39c0b; + dc7beb423c2053156329d7ab79f4d1d6 24c0adb3777860ad e040f57fe32f2158; + ed219454883709efe884bbc9d30507a3 587b1683dff7f178 e2c6512996117ba9; + 40509fc5c565e9b9f3995f3bc5d5c1f4 719a39f2302a98aa b8a9f3ab1b68ac1f; + f9f10ed2bc0193605913475fd54d69ae e35b94e2940a8db0 b23358feb43a29aa; + 23003c3fbe9661b6b9386748982ac3e2 d1dfd47fac22b9ff 4165de32289acf6a; + a2caa563c2f19b10fbac1427e2177858 f7743dfe957cc82b d88dcd158b0d81c2; + 8bb42b6937d65eac506e8326356071af 690a0fa32113bf34 9095cce6d70da9d6; + 219c7f982a0c352977b978b91fcb3c45 8fb4cb86db41ce30 c688b48de8ec7e14; + 157ff76f22538eede0528c541dbe7815 ea6cd44f238be18f 35578556b38660fa; + 346194289f6d865237cc673c45415003 71690fd4ba3d75de 719f1f0a6b316a58; + 032c8c1624f7f300d8a58d151de52d78 3c0f1746798ed5b7 62c9adb10b265534; + 019471106a5cd4ee3d1f627213649b80 558a8d7a4cdc0822 014521292dcbff85; + 45aa90191c449dbf9c541fb476d1bf74 bfba3dfd06e77671 b6a6825c69d9d5eb; + c86c21d8c26dc291f662c8f2fe79b74b 0993d3b68c1d4a5d d33c2e41dd5da131; + af4f4615c7c298639b9728251991419f 1e268f9e710313b5 a9478f8cf88b7e10; +} diff --git a/tests/tea-test.c b/symm/t/tea-test.c similarity index 100% rename from tests/tea-test.c rename to symm/t/tea-test.c diff --git a/symm/t/tiger b/symm/t/tiger new file mode 100644 index 0000000..46a74e0 --- /dev/null +++ b/symm/t/tiger @@ -0,0 +1,62 @@ +# Test vectors for Tiger + +# --- The main hash --- +# +# These are taken from the reference implementation. + +tiger { + "" 3293ac630c13f0245f92bbb1766e16167a4e58492dde73f3; + "abc" 2aab1484e8c158f2bfb8c5ff41b57a525129131c957b5f93; + "Tiger" dd00230799f5009fec6debc838bb6a27df2b9d6f110c7937; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" + f71c8583902afb879edfe610f82c0d4786a3a534504486b5; + "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789" + 48ceeb6308b87d46e95d656112cdf18d97915f9765658957; + "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham" + 8a866829040a410c729ad23f5ada711603b3cdd357e4c15e; + "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge." + ce55a6afd591f5ebac547ff84f89227f9331dab0b611c889; + "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996." + 631abdd103eb9a3d245b6dfd4d77b257fc7439501d1568dd; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" + c54034e5b43eb8005848a7e0ae6aac76e4ff590ae715fd25; +} + +# --- HMAC mode --- +# +# No test vectors available. The HMAC implementation has not been tested +# against an external reference. The HMAC code is autogenerated anyway, and +# ought to be reliable and correct. +# +# These test vectors are here to spot changes in behaviour rather than ensure +# interoperability. + +tiger-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + 0a402190741a498d6d4a09016b0895cb6419ff849b196137; + + "what do ya want for nothing?" + 4a656665 + 3a351b1dec6075d6290e68b604e553821edc39041b82da83; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + e09ab076337fba2b5c4a83e9dbfb62993710992934f0946c; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + a452fa58bdb38b70207c472c5ee54b1e40b1893e6d604b19; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 95981aaf2303d232824c504cc51459ea8275734336e92b1a; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + ebbb20db7af380b5dffff39f671e1224e994d840408a7941; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 308ebb428666c75b50d0442fe008777f4c208c7fa6d5ce7c; +} diff --git a/tests/twofish.aes b/symm/t/twofish.aes similarity index 100% rename from tests/twofish.aes rename to symm/t/twofish.aes diff --git a/symm/t/whirlpool b/symm/t/whirlpool new file mode 100644 index 0000000..5647787 --- /dev/null +++ b/symm/t/whirlpool @@ -0,0 +1,64 @@ +# Test vectors for the Whirlpool hash function + +# --- Basic hash function --- +# +# Some of these are taken from the ISO test vectors from the Whirlpool +# distribution. + +whirlpool { + "" + 19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3; + "a" + 8aca2602792aec6f11a67206531fb7d7f0dff59413145e6973c45001d0087b42d11bc645413aeff63a42391a39145a591a92200d560195e53b478584fdae231a; + "abc" + 4e2448a4c6f486bb16b6562c73b4020bf3043e3a731bce721ae1b303d97e6d4c7181eebdb6c57e277d0e34957114cbd6c797fc9d95d8b582d225292076d4eef5; + "message digest" + 378c84a4126e2dc6e56dcc7458377aac838d00032230f53ce1f5700c0ffb4d3b8421557659ef55c106b4b52ac5a4aaa692ed920052838f3362e86dbd37a8903e; + "abcdefghijklmnopqrstuvwxyz" + f1d754662636ffe92c82ebb9212a484a8d38631ead4238f5442ee13b8054e41b08bf2a9251c30b6a0b8aae86177ab4a6f68f673e7207865d5d9819a3dba4eb3b; + "abcdbcdecdefdefgefghfghighijhijk" + 2a987ea40f917061f5d6f0a0e4644f488a7a5a52deee656207c562f988e95c6916bdc8031bc5be1b7b947639fe050b56939baaa0adff9ae6745b7b181c3be3fd; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + dc37e008cf9ee69bf11f00ed9aba26901dd7c28cdec066cc6af42e40f82f3a1e08eba26629129d8fb7cb57211b9281a65517cc879d7b962142c65f5a7af01467; +} + +whirlpool-rep { + "1234567890" 8 + 466ef18babb0154d25b9d38a6414f5c08784372bccb204d6549c4afadb6014294d5bd8df2a6c44e538cd047b2681a51a2c60481e88c5a20b2c2a80cf3a9a083b; + "a" 1000000 + 0c99005beb57eff50a7cf005560ddf5d29057fd86b20bfd62deca0f1ccea4af51fc15490eddc47af32bb2b66c34ff9ad8c6008ad677f77126953b226e4ed8b01; +} + +# --- HMAC mode --- +# +# Home-made test vectors, for regression. + +whirlpool-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + f300802099638aa1df411accbae11c2947fbcb2a4186f1c9bc6daa75dc3ad46dd89739ae5fb39b5c4afc098435c3ba0f7f55900e8c719711cbaee6d473eef0ba; + + "what do ya want for nothing?" + 4a656665 + 3d595ccd1d4f4cfd045af53ba7d5c8283fee6ded6eaf1269071b6b4ea64800056b5077c6a942cfa1221bd4e5aed791276e5dd46a407d2b8007163d3e7cd1de66; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 4fb33849b7d0268ab9f3bc90cfc6ca90639338c32bca959b7bc47a61f4d946ca6c6a227e97205a18fe676907ce78d0f8892fcf73f44da714cb210188b92cabc9; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + 35bc33e2ed71e1cb01c140ddd3291ae3f84e9f0dce18005a1123df199983a211fe744b244449a1c093b17584069359bc6a95352271d78e2ef7a6f21dc28ab3c1; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 502a6d22d0f8e67196dfed2a9d9ef988714db9db2e2f0ad6c30e52eed830aa348ee98744ddd3ff1974c7fe275e078b79a6ba8c967c5a41b290f6edca01183b1a; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + dd90bd637cfcd27ca914c290f33402cf68576d6e70601af0295f6b9dafa9d988d8b8fb4fde8605ac544638158dba2baa90a2bf882546cd0b876d59ab3f18962e; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + faf529af18a0f569480fd001122bb446b32a3cf758c385cec4adad9c73c77327812e260b7082011a3eb1071e71a50e1c3d37a8963f8b6a64a31cc017db1d619c; +} diff --git a/symm/t/whirlpool256 b/symm/t/whirlpool256 new file mode 100644 index 0000000..b1b68c2 --- /dev/null +++ b/symm/t/whirlpool256 @@ -0,0 +1,64 @@ +# Test vectors for the Whirlpool hash function + +# --- Basic hash function --- +# +# Some of these are taken from the ISO test vectors from the Whirlpool +# distribution. + +whirlpool256 { + "" + 19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a7; + "a" + 8aca2602792aec6f11a67206531fb7d7f0dff59413145e6973c45001d0087b42; + "abc" + 4e2448a4c6f486bb16b6562c73b4020bf3043e3a731bce721ae1b303d97e6d4c; + "message digest" + 378c84a4126e2dc6e56dcc7458377aac838d00032230f53ce1f5700c0ffb4d3b; + "abcdefghijklmnopqrstuvwxyz" + f1d754662636ffe92c82ebb9212a484a8d38631ead4238f5442ee13b8054e41b; + "abcdbcdecdefdefgefghfghighijhijk" + 2a987ea40f917061f5d6f0a0e4644f488a7a5a52deee656207c562f988e95c69; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + dc37e008cf9ee69bf11f00ed9aba26901dd7c28cdec066cc6af42e40f82f3a1e; +} + +whirlpool256-rep { + "1234567890" 8 + 466ef18babb0154d25b9d38a6414f5c08784372bccb204d6549c4afadb601429; + "a" 1000000 + 0c99005beb57eff50a7cf005560ddf5d29057fd86b20bfd62deca0f1ccea4af5; +} + +# --- HMAC mode --- +# +# Home-made test vectors, for regression. + +whirlpool256-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + 9ab3bbb27b85df2edc51f2e05c880560439547e7c2772f8cec6ae00bead0bd7e; + + "what do ya want for nothing?" + 4a656665 + 977fd7f1d53e8af854404262630bfac20269ab3fc2fccabecd8feaa05b8cdabb; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 6d418c9fe3d422200ea8cf7d0d73591ca5714f49c38907c80fc96b3934ab8fc2; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + e0a3553419a54385ce04435bbb2bbf1d69d7626d8fab4f60e87a84fab731caab; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 2a4f40079e618c3a8467dd1a284af43662f84b137d93d54e5623884a047f546f; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 17564185de7d845576f42fbdcd027073bca1a059931ce4a901ae8662ad19caf0; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 0bdc8bf26ff0a71201fbeef2d51f35bcbc3e8b0daeddedcbec2ca2b2e8f457b2; +} diff --git a/symm/t/xtea b/symm/t/xtea new file mode 100644 index 0000000..be34740 --- /dev/null +++ b/symm/t/xtea @@ -0,0 +1,70 @@ +# Test vectors for XTEA + +# --- Generated from Needham and Wheeler's original implementation --- + +xtea { + 00112233445566778899aabbccddeeff 0123456789abcdef b8bf2821622b5b30; + d94576cd1a5f99e4155dc7bec5d33df2 d51399607f7aa9d7 782e4e131c5ba746; + 07ef12bc9d06d7da20131116b665e335 10b233473624ccd3 57733a1deece283e; + c6462b48afd604b75fcc455506ffd411 3b905e951e4fafe7 776f4965deb65775; + be195f703d6fec2232cd0890c981b27d 15b623d1fa2df9df 3bd5ad5c9ed6101e; + 5b8410f7a9eb92da120810c56fcaf8c9 7c1035940696d91d 5f93fa1d06991415; + b85c9e26661889d0ff1054c6be27fdeb 90b245144895f3ad 6105bfb0947828b7; + a8a1e956d54d238f6ceab186e7ec99ed 4ef2cfd120b8d4dc 51fae58a10f7c3dd; + 8bc4879201a96368927ecceee67024ee f6cb5353f4a1c432 550ad71ba8a34568; + f1372d85d8c3d1a60df57eedf317ab81 215c080cf158a09b 13d1e24ba9ff7b63; + 017f01683f5e009d196feeaad385c5a9 568583061da98d0d 6439b1dfe2ecb541; + 281c932ddd3c364b09f1896007ffab03 0558b306316b0823 c8f82fe4491a8917; + c1e95465c7ef8eb04254d1a5463c6a43 fdcb2764303222c7 244dbfa1d2c914e4; + 0f86dd6c96dd31164b656b0f25e4b411 eaddba89070ec46c 5a4909646763454f; + fbacfb479ae21194c35b8184e58dd66e c6507bcf99b9c2a1 6f08ec714e8a7c18; + 2eb36c4a9598d471700a1330070fffc9 c380b0f1c21d4d37 72d4d4bdf5c00585; + 0a7f48127091780617a1f534b3271bc9 e5b7c1517f24f298 64374b40bb732354; + 303fb24822a1b8a84d0ece77b86380ff d14ddf77fdda17bf 014f1e707d02c8d8; + f04ebf798c193f199c1f532af383555b b9682750bb15caad 9001d21b57ab5360; + 200c0ce59717d5d9af6813cd207fee73 9706769a18a2d03d 835fd788c089fd45; + 2828d51f98ae0b33f4de2b7fbd18a529 edb76c54847da59e b0c0125494d39ce9; + 61aaba6be48b0d0d14fe5d27fab852a4 178a49bafba53f23 ade26742f25efbe1; + 2080e2409ba01c8532fc84403ee8c06a df4cdb61a5f38536 9c895e72168b409e; + 271ad15192c4d1204a4a2561e3db6ff7 7c944d08def34c0c b784e23e00b3b498; + c1e297c0c761777d8a76fff02d22b859 f4c76c1d47fe568f 62f9e58b0364b0b6; + 23c807a2ef0a551f858fd52d125a47d8 cab16583e15d0074 4563be765e74653a; + 9fa5d4d8cbdfcecd559e3ce88bf78ee1 97b05c60774164ad 714807767366854b; + 24f4e91083139099d663647a7ffac321 7017a263985b735c cc68e1ed7f7c7832; + 7cf8626de76d8462218ed5c9dc8acc26 15475a90df04cd29 416eab1ebc155782; + 3c6ad7df17332a3e1e3de06007387357 87ca0aaccf146cc8 ded575554058ef42; + 24237a762d8a89383a2949f5a0f5ec08 9268af048ecbae67 899b9b877106c764; + 209a2833a39472d9720380ffb2f74761 af0062cd77a84ebd 26db40c151b74530; + 22ebe7a30e8855b3b453a6e926d4f187 f922ca875b991a31 2763f255636a34c1; + 1b5e23ebd915c1fee59f57dd91af7347 b4ecc305c3dbd8e5 fbbec8f5dbf4cefd; + 6c21d105515290da29339f142685c135 a4c2f6dc597d13ea 7409829de05ae6d1; + 01f728a7433a47b13de34fcc08958449 3af7f1ae0f58ab1d 950083fbd332a987; + 9a2d4c50337d3ec337673782fd385601 791d8da8cbb0bc94 13f87f8d3326553f; + b3b99747560e246bcd0cdc3fb33e4910 91778f2bd9233375 2b1f2747b356e119; + 4b269e2e8dbd68b94066c95244c3a195 abfb6a33e1471e96 8ce0dc718e757924; + d10b956f675dc2276b6dd90442bece3e dbedddb6a1c15a21 19df78dea26ea579; + 28f8fab7541766f6dafbaa5b6f3bd700 2c14d5097ab11f61 3a6fd0a5fef50079; + 2b61e60478fa0c0edb9531f26791eff9 b84c80b2d245fdfc f24ea37046b97a03; + a6bfb85fa91b8ca4197c8b502a62f972 3daadd7a9633e19b 4de5c07ea1564a64; + 94e76e54d37f932cbcc069de6bf26d52 02739eeb468450fd 0d4ef5d93f419069; + 82760ea1560e8f9d1e35f20cad1f26cc 34aa5952b5a9110f 7676f2746bfac3b7; + 3aba91211327585e0f1270b59ef9277b b584d6b34b638ba4 2cfa1f17178df25d; + 727074f35cd523eb6f8aafbbf76fd5b1 f0e9268a27ab70c6 609aee69ed6e2a8e; + 6e0aa1c91ea6315a4a7dd297ac5936a4 47374080f27fbb30 5d86f6451024e051; + 63bd2d37271a250c8593b433188cffd0 776927909196eec5 ec617cc3810e278c; + dc7beb423c2053156329d7ab79f4d1d6 24c0adb3777860ad 7f6f6083713a68ba; + ed219454883709efe884bbc9d30507a3 587b1683dff7f178 86a95a8f48fa13b0; + 40509fc5c565e9b9f3995f3bc5d5c1f4 719a39f2302a98aa 503f9481c7049890; + f9f10ed2bc0193605913475fd54d69ae e35b94e2940a8db0 59bc9b0bd5004dae; + 23003c3fbe9661b6b9386748982ac3e2 d1dfd47fac22b9ff 756ec1ac4fa8deac; + a2caa563c2f19b10fbac1427e2177858 f7743dfe957cc82b 57ae9c0144dbb9d3; + 8bb42b6937d65eac506e8326356071af 690a0fa32113bf34 5136052b310e7038; + 219c7f982a0c352977b978b91fcb3c45 8fb4cb86db41ce30 fa01561e5b9311ab; + 157ff76f22538eede0528c541dbe7815 ea6cd44f238be18f 0c3f632af5cee432; + 346194289f6d865237cc673c45415003 71690fd4ba3d75de c4448db8c1144435; + 032c8c1624f7f300d8a58d151de52d78 3c0f1746798ed5b7 e1bfbd2a7d414c8a; + 019471106a5cd4ee3d1f627213649b80 558a8d7a4cdc0822 c90e5257ea513ef8; + 45aa90191c449dbf9c541fb476d1bf74 bfba3dfd06e77671 bc715327ada1b56b; + c86c21d8c26dc291f662c8f2fe79b74b 0993d3b68c1d4a5d 2b4195c3d67e3f99; + af4f4615c7c298639b9728251991419f 1e268f9e710313b5 2536ccd8fdfe30e1; +} diff --git a/tests/xtea-test.c b/symm/t/xtea-test.c similarity index 100% rename from tests/xtea-test.c rename to symm/t/xtea-test.c diff --git a/symm/tea.c b/symm/tea.c new file mode 100644 index 0000000..4832674 --- /dev/null +++ b/symm/tea.c @@ -0,0 +1,122 @@ +/* -*-c-*- + * + * The Tiny Encryption Algorithm + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "paranoia.h" +#include "tea.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet tea_keysz[] = { KSZ_RANGE, TEA_KEYSZ, 0, 16, 1 }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @tea_init@ --- * + * + * Arguments: @tea_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a TEA key buffer. The key buffer must be 16 + * bytes long. + */ + +void tea_init(tea_ctx *k, const void *buf, size_t sz) +{ + octet kb[16]; + const octet *p; + + KSZ_ASSERT(tea, sz); + if (sz >= sizeof(kb)) + p = buf; + else { + memcpy(kb, buf, sz); + memset(kb + sz, 0, sizeof(kb) - sz); + p = kb; + } + + k->ka = LOAD32(p + 0); k->kb = LOAD32(p + 4); + k->kc = LOAD32(p + 8); k->kd = LOAD32(p + 12); + k->r = 32; + + if (p == kb) + BURN(kb); +} + +/* --- @tea_eblk@, @tea_dblk@ --- * + * + * Arguments: @const tea_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to teatination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +#define DELTA 0x9e3779b9 + +void tea_eblk(const tea_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 y = s[0], z = s[1]; + uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd; + uint32 n = 0; + unsigned i; + + for (i = 0; i < k->r; i++) { + n += DELTA; + y = U32(y + (((z << 4) + ka) ^ (z + n) ^ ((z >> 5) + kb))); + z = U32(z + (((y << 4) + kc) ^ (y + n) ^ ((y >> 5) + kd))); + } + d[0] = y; d[1] = z; +} + +void tea_dblk(const tea_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 y = s[0], z = s[1]; + uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd; + uint32 n = DELTA * k->r; + unsigned i; + + for (i = 0; i < k->r; i++) { + z = U32(z - (((y << 4) + kc) ^ (y + n) ^ ((y >> 5) + kd))); + y = U32(y - (((z << 4) + ka) ^ (z + n) ^ ((z >> 5) + kb))); + n -= DELTA; + } + d[0] = y; d[1] = z; +} + +BLKC_TEST(TEA, tea) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/tea.h b/symm/tea.h new file mode 100644 index 0000000..fdad8ac --- /dev/null +++ b/symm/tea.h @@ -0,0 +1,104 @@ +/* -*-c-*- + * + * The Tiny Encryption Algorithm + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the Tiny Encryption Algorithm ----------------------------* + * + * TEA is an amazingly simple 64-round Feistel network. It's tiny, fairly + * quick and surprisingly strong. It was invented by David Wheeler and Roger + * Needham. It's unpatented. The keyspace is has only 126 effective bits, + * and there are related-key attacks. If you want these fixed, use XTEA. + * + * This implementation uses big-endian byte order, following SCAN. + */ + +#ifndef CATACOMB_TEA_H +#define CATACOMB_TEA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magical numbers ---------------------------------------------------*/ + +#define TEA_BLKSZ 8 +#define TEA_KEYSZ 16 +#define TEA_CLASS (N, B, 64) + +extern const octet tea_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct tea_ctx { + unsigned r; + uint32 ka, kb, kc, kd; +} tea_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @tea_init@ --- * + * + * Arguments: @tea_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a TEA key buffer. The key buffer may be up to 16 + * bytes long. + */ + +extern void tea_init(tea_ctx */*k*/, const void */*buf*/, size_t /*sz*/); + +/* --- @tea_eblk@, @tea_dblk@ --- * + * + * Arguments: @const tea_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to teatination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void tea_eblk(const tea_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); +extern void tea_dblk(const tea_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/tiger-base.h b/symm/tiger-base.h new file mode 100644 index 0000000..49e05ef --- /dev/null +++ b/symm/tiger-base.h @@ -0,0 +1,118 @@ +/* -*-c-*- + * + * Common definitions for the Tiger hash function + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_TIGER_BASE_H +#define CATACOMB_TIGER_BASE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +/*----- Macros provided ---------------------------------------------------*/ + +/* --- The guts of a single round --- */ + +#define TIGER_ROUND(a, b, c, x, n, op) do { \ + kludge64 _t; \ + XOR64(c, c, x); \ + _t = s[0][U8(LO64(c) >> 0)]; \ + XOR64(_t, _t, s[1][U8(LO64(c) >> 16)]); \ + XOR64(_t, _t, s[2][U8(HI64(c) >> 0)]); \ + XOR64(_t, _t, s[3][U8(HI64(c) >> 16)]); \ + SUB64(a, a, _t); \ + _t = s[3][U8(LO64(c) >> 8)]; \ + XOR64(_t, _t, s[2][U8(LO64(c) >> 24)]); \ + XOR64(_t, _t, s[1][U8(HI64(c) >> 8)]); \ + XOR64(_t, _t, s[0][U8(HI64(c) >> 24)]); \ + ADD64(b, b, _t); \ + LSL64_(_t, b, n); \ + op##64(b, _t, b); \ +} while (0) + +/* --- One pass over the buffer --- */ + +#define TIGER_PASS(a, b, c, x, n, op) do { \ + TIGER_ROUND(a, b, c, x[0], n, op); \ + TIGER_ROUND(b, c, a, x[1], n, op); \ + TIGER_ROUND(c, a, b, x[2], n, op); \ + TIGER_ROUND(a, b, c, x[3], n, op); \ + TIGER_ROUND(b, c, a, x[4], n, op); \ + TIGER_ROUND(c, a, b, x[5], n, op); \ + TIGER_ROUND(a, b, c, x[6], n, op); \ + TIGER_ROUND(b, c, a, x[7], n, op); \ +} while (0) + +/* --- A step in the `key schedule' --- */ + +#define TIGER_KSTEP(a, b, c, d, op, n) do { \ + kludge64 _u; \ + XOR64(b, b, a); \ + ADD64(c, c, b); \ + CPL64(_u, b); op##64_(_u, _u, n); XOR64(_u, _u, c); SUB64(d, d, _u); \ +} while (0) + +/* --- The `key schedule' -- mangle the buffer --- */ + +#define TIGER_KSCHED(x) do { \ + kludge64 _t; \ + \ + SET64(_t, 0xa5a5a5a5, 0xa5a5a5a5); \ + XOR64(_t, _t, x[7]); SUB64(x[0], x[0], _t); \ + TIGER_KSTEP(x[0], x[1], x[2], x[3], LSL, 19); \ + TIGER_KSTEP(x[3], x[4], x[5], x[6], LSR, 23); \ + TIGER_KSTEP(x[6], x[7], x[0], x[1], LSL, 19); \ + TIGER_KSTEP(x[1], x[2], x[3], x[4], LSR, 23); \ + XOR64(x[5], x[5], x[4]); \ + ADD64(x[6], x[6], x[5]); \ + SET64(_t, 0x01234567, 0x89abcdef); \ + XOR64(_t, _t, x[6]); SUB64(x[7], x[7], _t); \ +} while (0) + +/* --- The Tiger compression function --- */ + +#define TIGER_CORE(a, b, c, x) do { \ + kludge64 _a, _b, _c; \ + _a = a, _b = b, _c = c; \ + TIGER_PASS(_a, _b, _c, x, 2, ADD); \ + TIGER_KSCHED(x); \ + TIGER_PASS(_c, _a, _b, x, 3, SUB); \ + TIGER_KSCHED(x); \ + TIGER_PASS(_b, _c, _a, x, 3, ADD); \ + XOR64(a, _a, a); SUB64(b, _b, b); ADD64(c, _c, c); \ +} while (0) + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/tiger-mktab.c b/symm/tiger-mktab.c new file mode 100644 index 0000000..5029330 --- /dev/null +++ b/symm/tiger-mktab.c @@ -0,0 +1,151 @@ +/* -*-c-*- + * + * Generate S-boxes for the Tiger hash function + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include +#include + +#include "tiger-base.h" + +/*----- Data structures ---------------------------------------------------*/ + +/*----- Static variables --------------------------------------------------*/ + +static kludge64 s[4][256]; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- The basic Tiger compression function --- */ + +static void tiger(kludge64 *x, kludge64 *ss) +{ + TIGER_CORE(ss[0], ss[1], ss[2], x); +} + +/* --- The S-box generator --- */ + +void gen(const char *buf, unsigned passes) +{ + kludge64 x[8], ss[3]; + unsigned i, j, k, b; + unsigned q, n; + uint32 t; + const char *p; + + for (i = 0; i < 256; i++) { + for (j = 0; j < 4; j++) { + uint32 z = 0x01010101 * i; + SET64(s[j][i], z, z); + } + } + + SET64(ss[0], 0x01234567, 0x89abcdef); + SET64(ss[1], 0xfedcba98, 0x76543210); + SET64(ss[2], 0xf096a5b4, 0xc3b2e187); + + q = 2; + for (i = 0; i < passes; i++) { + for (j = 0; j < 256; j++) { + for (k = 0; k < 4; k++) { + q++; + if (q == 3) { + q = 0; + for (p = buf, n = 0; n < 8; n++, p += 8) + LOAD64_L_(x[n], p); + tiger(x, ss); + } + for (b = 0; b < 32; b += 8) { + n = U8(LO64(ss[q]) >> b); + t = (LO64(s[k][j]) ^ LO64(s[k][n])) & (0xff << b); + SET64(s[k][j], HI64(s[k][j]), LO64(s[k][j]) ^ t); + SET64(s[k][n], HI64(s[k][n]), LO64(s[k][n]) ^ t); + } + for (b = 0; b < 32; b += 8) { + n = U8(HI64(ss[q]) >> b); + t = (HI64(s[k][j]) ^ HI64(s[k][n])) & (0xff << b); + SET64(s[k][j], HI64(s[k][j]) ^ t, LO64(s[k][j])); + SET64(s[k][n], HI64(s[k][n]) ^ t, LO64(s[k][n])); + } + } + } + } +} + +int main(void) +{ + unsigned i, j; + + gen("Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham", 5); + + fputs("\ +/* -*-c-*-\n\ + *\n\ + * S-boxes for Tiger [generated]\n\ + */\n\ +\n\ +#ifndef CATACOMB_TIGER_TAB_H\n\ +#define CATACOMB_TIGER_TAB_H\n\ +\n\ +#define TIGER_S { \\\n\ + { ", stdout); + + for (i = 0; i < 4; i++) { + for (j = 0; j < 256; j++) { +#ifdef HAVE_UINT64 + printf("{ 0x%016llxull }", s[i][j].i); +#else + printf("{ 0x%08lx, 0x%08lx }", + (unsigned long)s[i][j].hi, (unsigned long)s[i][j].lo); +#endif + if (j == 255) { + if (i == 3) + fputs(" } \\\n}\n", stdout); + else + fputs(" }, \\\n\ + \\\n\ + { ", stdout); + } else if (j % 2 == 1) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + } + + fputs("\n#endif\n", stdout); + + if (fclose(stdout)) { + fprintf(stderr, "error writing data\n"); + exit(EXIT_FAILURE); + } + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/tiger.c b/symm/tiger.c new file mode 100644 index 0000000..f9aa824 --- /dev/null +++ b/symm/tiger.c @@ -0,0 +1,173 @@ +/* -*-c-*- + * + * The Tiger hash function + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash-def.h" +#include "hash.h" +#include "tiger.h" +#include "tiger-tab.h" +#include "tiger-base.h" + +/*----- S-boxes -----------------------------------------------------------*/ + +static const kludge64 s[4][256] = TIGER_S; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @tiger_compress@ --- * + * + * Arguments: @tiger_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: Tiger compression function. + */ + +void tiger_compress(tiger_ctx *ctx, const void *sbuf) +{ + kludge64 x[8]; + int i; + const octet *p; + for (i = 0, p = sbuf; i < 8; i++, p += 8) + LOAD64_L_(x[i], p); + TIGER_CORE(ctx->a, ctx->b, ctx->c, x); +} + +/* --- @tiger_init@ --- * + * + * Arguments: @tiger_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void tiger_init(tiger_ctx *ctx) +{ + SET64(ctx->a, 0x01234567, 0x89abcdef); + SET64(ctx->b, 0xfedcba98, 0x76543210); + SET64(ctx->c, 0xf096a5b4, 0xc3b2e187); + ctx->off = 0; + ctx->nl = ctx->nh = 0; +} + +/* --- @tiger_set@ --- * + * + * Arguments: @tiger_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void tiger_set(tiger_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + LOAD64_L_(ctx->a, p + 0); + LOAD64_L_(ctx->b, p + 8); + LOAD64_L_(ctx->c, p + 16); + ctx->off = 0; + ctx->nl = U32(count); + ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); +} + +/* --- @tiger_hash@ --- * + * + * Arguments: @tiger_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void tiger_hash(tiger_ctx *ctx, const void *buf, size_t sz) +{ + HASH_BUFFER(TIGER, tiger, ctx, buf, sz); +} + +/* --- @tiger_done@ --- * + * + * Arguments: @tiger_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +void tiger_done(tiger_ctx *ctx, void *hash) +{ + octet *p = hash; + HASH_PAD(TIGER, tiger, ctx, 0x01u, 0, 8); + STORE32_L(ctx->buf + TIGER_BUFSZ - 8, ctx->nl << 3); + STORE32_L(ctx->buf + TIGER_BUFSZ - 4, (ctx->nl >> 29) | (ctx->nh << 3)); + tiger_compress(ctx, ctx->buf); + STORE64_L_(p + 0, ctx->a); + STORE64_L_(p + 8, ctx->b); + STORE64_L_(p + 16, ctx->c); +} + +/* --- @tiger_state@ --- * + * + * Arguments: @tiger_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @tiger_set@. + */ + +unsigned long tiger_state(tiger_ctx *ctx, void *state) +{ + octet *p = state; + STORE64_L_(p + 0, ctx->a); + STORE64_L_(p + 8, ctx->b); + STORE64_L_(p + 16, ctx->c); + return (ctx->nl | ((ctx->nh << 16) << 16)); +} + +/* --- Generic interface --- */ + +GHASH_DEF(TIGER, tiger) + +/* --- Test code --- */ + +HASH_TEST(TIGER, tiger) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/tiger.h b/symm/tiger.h new file mode 100644 index 0000000..d705cd5 --- /dev/null +++ b/symm/tiger.h @@ -0,0 +1,158 @@ +/* -*-c-*- + * + * The Tiger hash function + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the Tiger hash function ----------------------------------* + * + * Tiger was designed by Eli Biham and Ross Anderson to be an efficient and + * secure hash function which worked well on 64-bit processors. This + * implementation should work everywhere, but it'll be faster if real 64-bit + * arithmetic is available. + * + * I don't know of any really good analysis of Tiger. + */ + +#ifndef CATACOMB_TIGER_H +#define CATACOMB_TIGER_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define TIGER_BUFSZ 64 +#define TIGER_HASHSZ 24 +#define TIGER_STATESZ 24 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct tiger_ctx { + kludge64 a, b, c; /* Chaining variables */ + uint32 nl, nh; /* Byte count so far */ + unsigned off; /* Offset into buffer */ + octet buf[TIGER_BUFSZ]; /* Accumulation buffer */ +} tiger_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @tiger_compress@ --- * + * + * Arguments: @tiger_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: Tiger compression function. + */ + +extern void tiger_compress(tiger_ctx */*ctx*/, const void */*sbuf*/); + +/* --- @tiger_init@ --- * + * + * Arguments: @tiger_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void tiger_init(tiger_ctx */*ctx*/); + +/* --- @tiger_set@ --- * + * + * Arguments: @tiger_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void tiger_set(tiger_ctx */*ctx*/, const void */*buf*/, + unsigned long /*count*/); + +/* --- @tiger_hash@ --- * + * + * Arguments: @tiger_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void tiger_hash(tiger_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/); + +/* --- @tiger_done@ --- * + * + * Arguments: @tiger_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void tiger_done(tiger_ctx */*ctx*/, void */*hash*/); + +/* --- @tiger_state@ --- * + * + * Arguments: @tiger_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @tiger_set@. + */ + +extern unsigned long tiger_state(tiger_ctx */*ctx*/, void */*state*/); + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash tiger; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/twofish-mktab.c b/symm/twofish-mktab.c new file mode 100644 index 0000000..4453fbe --- /dev/null +++ b/symm/twofish-mktab.c @@ -0,0 +1,411 @@ +/* -*-c-*- + * + * Build constant tables for Twofish + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct { octet t[4][16]; } t_tab; +typedef struct { octet q[256]; } q_tab; + +/*----- Various Twofish tables --------------------------------------------*/ + +/* --- The t-tables --- */ + +static const t_tab qt0 = {{ + { 0x8, 0x1, 0x7, 0xd, 0x6, 0xf, 0x3, 0x2, + 0x0, 0xb, 0x5, 0x9, 0xe, 0xc, 0xa, 0x4 }, + { 0xe, 0xc, 0xb, 0x8, 0x1, 0x2, 0x3, 0x5, + 0xf, 0x4, 0xa, 0x6, 0x7, 0x0, 0x9, 0xd }, + { 0xb, 0xa, 0x5, 0xe, 0x6, 0xd, 0x9, 0x0, + 0xc, 0x8, 0xf, 0x3, 0x2, 0x4, 0x7, 0x1 }, + { 0xd, 0x7, 0xf, 0x4, 0x1, 0x2, 0x6, 0xe, + 0x9, 0xb, 0x3, 0x0, 0x8, 0x5, 0xc, 0xa } +}}; + +static const t_tab qt1 = {{ + { 0x2, 0x8, 0xb, 0xd, 0xf, 0x7, 0x6, 0xe, + 0x3, 0x1, 0x9, 0x4, 0x0, 0xa, 0xc, 0x5 }, + { 0x1, 0xe, 0x2, 0xb, 0x4, 0xc, 0x3, 0x7, + 0x6, 0xd, 0xa, 0x5, 0xf, 0x9, 0x0, 0x8 }, + { 0x4, 0xc, 0x7, 0x5, 0x1, 0x6, 0x9, 0xa, + 0x0, 0xe, 0xd, 0x8, 0x2, 0xb, 0x3, 0xf }, + { 0xb, 0x9, 0x5, 0x1, 0xc, 0x3, 0xd, 0xe, + 0x6, 0x4, 0x7, 0xf, 0x2, 0x0, 0x8, 0xa } +}}; + +static q_tab q0, q1; + +/* --- The MDS and Reed-Solomon matrices --- */ + +static const octet mds[16] = { + 0x01, 0xef, 0x5b, 0x5b, + 0x5b, 0xef, 0xef, 0x01, + 0xef, 0x5b, 0x01, 0xef, + 0xef, 0x01, 0xef, 0x5b +}; + +static const octet rs[32] = { + 0x01, 0xa4, 0x55, 0x87, 0x5a, 0x58, 0xdb, 0x9e, + 0xa4, 0x56, 0x82, 0xf3, 0x1e, 0xc6, 0x68, 0xe5, + 0x02, 0xa1, 0xfc, 0xc1, 0x47, 0xae, 0x3d, 0x19, + 0xa4, 0x55, 0x87, 0x5a, 0x58, 0xdb, 0x9e, 0x03 +}; + +/*----- Magic macros ------------------------------------------------------*/ + +#define ROR4(x) ((((x) >> 1) | ((x) << 3)) & 15) + +/*----- Building and printing @q@ tables ----------------------------------*/ + +/* --- @mkq@ --- * + * + * Arguments: @q_tab *q@ = pointer to output @q@ table + * @const t_tab *t@ = pointer to input @t@ table + * @const char *name@ = name of @q@ table + * + * Returns: --- + * + * Use: Constructs a 256-entry @q@-table. + */ + +static void mkq(q_tab *q, const t_tab *t, const char *name) +{ + int i; + int ok = 1; + + /* --- Ensure the t-table is well-formed --- */ + + for (i = 0; i < 4; i++) { + octet f[16] = { 0 }; + int j; + + for (j = 0; j < 16; j++) { + if (f[t->t[i][j]]) { + fprintf(stderr, "duplicate %i in %s[%i] (col %i and %i)\n", + t->t[i][j], name, i, j, f[t->t[i][j]]); + ok = 0; + } + f[t->t[i][j]] = j; + } + } + + if (!ok) + exit(EXIT_FAILURE); + + /* --- Construct the @q@ table --- */ + + for (i = 0; i < 256; i++) { + int a = i >> 4, b = i & 15; + int aa = t->t[0][a ^ b], bb = t->t[1][a ^ ((a << 3) & 15) ^ ROR4(b)]; + a = t->t[2][aa ^ bb], b = t->t[3][aa ^ ((aa << 3) & 15) ^ ROR4(bb)]; + q->q[i] = a | (b << 4); + } + + /* Consider testing @q@ for linear and differential properties here */ +} + +/* --- @printq@ --- * + * + * Arguments: @const q_tab *t@ = pointer to table + * @const char *name@ = pointer to table name + * + * Returns: --- + * + * Use: Prints a q table. + */ + +static void printq(const q_tab *q, const char *name) +{ + int i; + int j; + + printf("\ +#define TWOFISH_%s { \\\n\ + ", name); + j = 0; + for (i = 0; i < 256; i++) { + printf("0x%02x", q->q[i]); + j = (j + 1) & 7; + if (i == 255) + fputs(" \\\n}\n\n", stdout); + else if (j == 0) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } +} + +/*----- %$\gf{2^8}$% arithmetic -------------------------------------------*/ + +#define MDS_MOD 0x169 +#define RS_MOD 0x14d + +/* --- @mul@ --- * + * + * Arguments: @unsigned x, y@ = polynomials over %$\gf{2^8}$% + * @unsigned m@ = modulus + * + * Returns: The product of two polynomials. + * + * Use: Computes a product of polynomials, quite slowly. + */ + +static unsigned mul(unsigned x, unsigned y, unsigned m) +{ + unsigned a = 0; + unsigned i; + + for (i = 0; i < 8; i++) { + if (y & 1) + a ^= x; + y >>= 1; + x <<= 1; + if (x & 0x100) + x ^= m; + } + + return (a); +} + +/* --- @mmul@ --- * + * + * Arguments: @octet *d@ = destination vector + * @const octet *p@ = matrix of bytes + * @const octet *q@ = vector from somewhere else + * @size_t r@ = size of destination or number of rows in matrix + * @size_t n@ = length of row and vector + * @unsigned m@ = modulus polynomial + * + * Returns: --- + * + * Use: Computes an inner product of matrices over the finite field + * %$\gf{2^8}[x]/(m(x))$%. This isn't particularly rapid. + */ + +static void mmul(octet *d, const octet *p, const octet *q, + size_t r, size_t n, unsigned m) +{ + while (r) { + const octet *qq = q; + unsigned a = 0; + unsigned i; + + for (i = 0; i < n; i++) + a ^= mul(*p++, *qq++, m); + *d++ = a; + r--; + } +} + +/* --- @qrds@ --- * + * + * Arguments: --- + * + * Returns: --- + * + * Use: Prints the MDS/q table. + */ + +static void qmds(void) +{ + uint32 t[4][256]; + int i, j; + static const q_tab *q[4] = { &q1, &q0, &q1, &q0 }; + + for (i = 0; i < 4; i++) { + octet in[4] = { 0, 0, 0, 0 }; + octet out[4]; + + for (j = 0; j < 256; j++) { + in[i] = q[i]->q[j]; + mmul(out, mds, in, 4, 4, MDS_MOD); + t[i][j] = LOAD32_L(out); + } + } + + puts("\ +/* --- Expanded MDS tables --- *\n\ + *\n\ + * The table contains output vectors for computing the result of pushing\n\ + * bytes through appropriate @q@ tables and the MDS matrix.\n\ + */\n\ +\n\ +#define TWOFISH_QMDS { \\"); + for (i = 0; i < 4; i++) { + fputs(" { ", stdout); + for (j = 0; j < 256; j++) { + printf("0x%08lx", (unsigned long)t[i][j]); + if (j == 255) { + if (i == 3) + puts(" } \\\n}"); + else + puts(" }, \\\n\ + \\"); + } else if (j % 4 == 3) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + } + + putchar('\n'); +} + +/* --- @rslog@ --- * + * + * Arguments: --- + * + * Returns: --- + * + * Use: Produces the log and antilog tables for doing the RS + * arithmetic efficiently. + */ + +static void rslog(void) +{ + octet rslog[256]; + octet rsexp[256]; + + unsigned x = 1; + unsigned i; + + rslog[0] = 0; + for (i = 0; i < 255; i++) { + rslog[x] = i; + rsexp[i] = x; + x <<= 1; + if (x & 0x100) + x ^= RS_MOD; + } + + x = 0; + for (i = 0; i < 32; i++) { + if (rslog[rs[i]] > x) + x = rslog[rs[i]]; + } + + fputs("\ +/* --- Reed-Solomon log tables --- *\n\ + *\n\ + * The Reed-Solomon multiplies are accelerated by using log tables.\n\ + */\n\ +\n\ +#define TWOFISH_RSLOG { \\\n\ + ", stdout); + + for (i = 0; i < 256; i++) { + printf("0x%02x", rslog[i]); + if (i == 255) + puts(" \\\n}\n"); + else if (i % 8 == 7) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + fputs("\ +#define TWOFISH_RSEXP { \\\n\ + ", stdout); + + for (i = 0; i < 255 + x + 1; i++) { + printf("0x%02x", rsexp[i % 255]); + if (i == 255 + x) + puts(" \\\n}\n"); + else if (i % 8 == 7) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + fputs("\ +/* --- Reed-Solomon matrix with log entries --- */\n\ +\n\ +#define TWOFISH_RS { \\\n\ + ", stdout); + + for (i = 0; i < 32; i++) { + printf("0x%02x", rslog[rs[i]]); + if (i == 31) + puts(" \\\n}\n"); + else if (i % 8 == 7) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } +} + +/*----- Main program ------------------------------------------------------*/ + +/* --- @main@ --- */ + +int main(void) +{ + fputs("\ +/* -*-c-*-\n\ + *\n\ + * Twofish q tables [generated]\n\ + */\n\ +\n\ +#ifndef CATACOMB_TWOFISH_TAB_H\n\ +#define CATACOMB_TWOFISH_TAB_H\n\ +\n\ +", stdout); + + /* --- The q tables --- */ + + puts("\ +/* --- Precomputed @q@ tables --- */\n\ +"); + mkq(&q0, &qt0, "qt0"); + mkq(&q1, &qt1, "qt1"); + printq(&q0, "Q0"); + printq(&q1, "Q1"); + + /* --- The MDS/q tables --- */ + + qmds(); + rslog(); + + /* --- Done --- */ + + puts("#endif"); + + if (fclose(stdout)) { + fprintf(stderr, "error writing data\n"); + exit(EXIT_FAILURE); + } + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/twofish.c b/symm/twofish.c new file mode 100644 index 0000000..75e7491 --- /dev/null +++ b/symm/twofish.c @@ -0,0 +1,427 @@ +/* -*-c-*- + * + * Implementation of the Twofish cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "twofish.h" +#include "twofish-tab.h" +#include "paranoia.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet twofish_keysz[] = { KSZ_RANGE, TWOFISH_KEYSZ, 0, 32, 1 }; + +/*----- Important tables --------------------------------------------------*/ + +static const octet q0[256] = TWOFISH_Q0, q1[256] = TWOFISH_Q1; +static const uint32 qmds[4][256] = TWOFISH_QMDS; +static const octet rslog[] = TWOFISH_RSLOG, rsexp[] = TWOFISH_RSEXP; +static const octet rs[32] = TWOFISH_RS; + +/*----- Key initialization ------------------------------------------------*/ + +/* --- @h@ --- * + * + * Arguments: @uint32 x@ = input to the function + * @const uint32 *l@ = key values to mix in + * @unsigned k@ = number of key values there are + * + * Returns: The output of the function @h@. + * + * Use: Implements the Twofish function @h@. + */ + +static uint32 h(uint32 x, const uint32 *l, unsigned k) +{ + /* --- Apply a series of @q@ tables to an integer --- */ + +# define Q(x, qa, qb, qc, qd) \ + ((qa[((x) >> 0) & 0xff] << 0) | \ + (qb[((x) >> 8) & 0xff] << 8) | \ + (qc[((x) >> 16) & 0xff] << 16) | \ + (qd[((x) >> 24) & 0xff] << 24)) + + /* --- Grind through the tables --- */ + + switch (k) { + case 4: x = Q(x, q1, q0, q0, q1) ^ l[3]; + case 3: x = Q(x, q1, q1, q0, q0) ^ l[2]; + case 2: x = Q(x, q0, q1, q0, q1) ^ l[1]; + x = Q(x, q0, q0, q1, q1) ^ l[0]; + break; + } + +#undef Q + + /* --- Apply the MDS matrix --- */ + + return (qmds[0][U8(x >> 0)] ^ qmds[1][U8(x >> 8)] ^ + qmds[2][U8(x >> 16)] ^ qmds[3][U8(x >> 24)]); +} + +/* --- @twofish_initfk@ --- * + * + * Arguments: @twofish_ctx *k@ = pointer to key block to fill in + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * @const twofish_fk *fk@ = family-key information + * + * Returns: --- + * + * Use: Does the underlying Twofish key initialization with family + * key. Pass in a family-key structure initialized to + * all-bits-zero for a standard key schedule. + */ + +void twofish_initfk(twofish_ctx *k, const void *buf, size_t sz, + const twofish_fk *fk) +{ +# define KMAX 4 + + uint32 mo[KMAX], me[KMAX]; + octet s[4][KMAX]; + + /* --- Expand the key into the three word arrays --- */ + + { + size_t ssz; + const octet *p, *q; + octet b[32]; + int i; + + /* --- Sort out the key size --- */ + + KSZ_ASSERT(twofish, sz); + if (sz <= 16) + ssz = 16; + else if (sz <= 24) + ssz = 24; + else if (sz <= 32) + ssz = 32; + else + assert(((void)"This can't happen (bad key size in twofish_init)", 0)); + + /* --- Extend the key if necessary --- */ + + if (sz == ssz) + p = buf; + else { + memcpy(b, buf, sz); + memset(b + sz, 0, ssz - sz); + p = b; + } + + /* --- Finally get the word count --- */ + + sz = ssz / 8; + + /* --- Extract words from the key --- * + * + * The @s@ table, constructed using the Reed-Solomon matrix, is cut into + * sequences of bytes, since this is actually more useful for computing + * the S-boxes. + */ + + q = p; + for (i = 0; i < sz; i++) { + octet ss[4]; + const octet *r = rs; + int j; + + /* --- Extract the easy subkeys --- */ + + me[i] = LOAD32_L(q) ^ fk->t0[2 * i]; + mo[i] = LOAD32_L(q + 4) ^ fk->t0[2 * i + 1]; + + /* --- Now do the Reed-Solomon thing --- */ + + for (j = 0; j < 4; j++) { + const octet *qq = q; + unsigned a = 0; + int k; + + for (k = 0; k < 8; k++) { + unsigned char x = *qq ^ fk->t1[i * 8 + k]; + if (x) a ^= rsexp[rslog[x] + *r]; + qq++; + r++; + } + + s[j][sz - 1 - i] = ss[j] = a; + } + q += 8; + } + + /* --- Clear away the temporary buffer --- */ + + if (p == b) + BURN(b); + } + + /* --- Construct the expanded key --- */ + + { + uint32 p = 0x01010101; + uint32 ip = 0; + int i; + + for (i = 0; i < 40; i += 2) { + uint32 a, b; + a = h(ip, me, sz); + b = h(ip + p, mo, sz); + b = ROL32(b, 8); + a += b; b += a; + k->k[i] = U32(a); + k->k[i + 1] = ROL32(b, 9); + ip += 2 * p; + } + + for (i = 0; i < 8; i++) + k->k[i] ^= fk->t23[i]; + for (i = 8; i < 40; i += 2) { + k->k[i] ^= fk->t4[0]; + k->k[i + 1] ^= fk->t4[1]; + } + } + + /* --- Construct the S-box tables --- */ + + { + unsigned i; + static const octet *q[4][KMAX + 1] = { + { q1, q0, q0, q1, q1 }, + { q0, q0, q1, q1, q0 }, + { q1, q1, q0, q0, q0 }, + { q0, q1, q1, q0, q1 } + }; + + for (i = 0; i < 4; i++) { + unsigned j; + uint32 x; + + for (j = 0; j < 256; j++) { + x = j; + + /* --- Push the byte through the q tables --- */ + + switch (sz) { + case 4: x = q[i][4][x] ^ s[i][3]; + case 3: x = q[i][3][x] ^ s[i][2]; + case 2: x = q[i][2][x] ^ s[i][1]; + x = q[i][1][x] ^ s[i][0]; + break; + } + + /* --- Write it in the key schedule --- */ + + k->g[i][j] = qmds[i][x]; + } + } + } + + /* --- Clear everything away --- */ + + BURN(me); + BURN(mo); + BURN(s); +} + +/* --- @twofish_init@ --- * + * + * Arguments: @twofish_ctx *k@ = pointer to key block to fill in + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a Twofish key buffer. Twofish accepts key sizes + * of up to 256 bits (32 bytes). + */ + +void twofish_init(twofish_ctx *k, const void *buf, size_t sz) +{ + static const twofish_fk fk = { { 0 } }; + twofish_initfk(k, buf, sz, &fk); +} + +/* --- @twofish_fkinit@ --- * + * + * Arguments: @twofish_fk *fk@ = pointer to family key block + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a family-key buffer. This implementation allows + * family keys of any size acceptable to the Twofish algorithm. + */ + +void twofish_fkinit(twofish_fk *fk, const void *buf, size_t sz) +{ + twofish_ctx k; + uint32 pt[4], ct[4]; + const octet *kk; + unsigned i; + + twofish_init(&k, buf, sz); + + for (i = 0; i < 4; i++) pt[i] = (uint32)-1; + twofish_eblk(&k, pt, fk->t0 + 4); + + kk = buf; sz /= 4; + for (i = 0; i < sz; i++) { fk->t0[i] = LOAD32_L(kk); kk += 4; } + + for (i = 0; i < 4; i++) pt[i] = 0; twofish_eblk(&k, pt, ct); + for (i = 0; i < 4; i++) STORE32_L(fk->t1 + i * 4, ct[i]); + pt[0] = 1; twofish_eblk(&k, pt, ct); + for (i = 0; i < 4; i++) STORE32_L(fk->t1 + 4 + i * 4, ct[i]); + + pt[0] = 2; twofish_eblk(&k, pt, fk->t23 + 0); + pt[0] = 3; twofish_eblk(&k, pt, fk->t23 + 4); + pt[0] = 4; twofish_eblk(&k, pt, ct); + fk->t4[0] = ct[0]; fk->t4[1] = ct[1]; + + BURN(k); +} + +/*----- Main encryption ---------------------------------------------------*/ + +/* --- Feistel function --- */ + +#define GG(k, t0, t1, x, y, kk) do { \ + t0 = (k->g[0][U8(x >> 0)] ^ \ + k->g[1][U8(x >> 8)] ^ \ + k->g[2][U8(x >> 16)] ^ \ + k->g[3][U8(x >> 24)]); \ + t1 = (k->g[1][U8(y >> 0)] ^ \ + k->g[2][U8(y >> 8)] ^ \ + k->g[3][U8(y >> 16)] ^ \ + k->g[0][U8(y >> 24)]); \ + t0 += t1; \ + t1 += t0; \ + t0 += kk[0]; \ + t1 += kk[1]; \ +} while (0) + +/* --- Round operations --- */ + +#define EROUND(k, w, x, y, z, kk) do { \ + uint32 _t0, _t1; \ + GG(k, _t0, _t1, w, x, kk); \ + kk += 2; \ + y ^= _t0; y = ROR32(y, 1); \ + z = ROL32(z, 1); z ^= _t1; \ +} while (0) + +#define DROUND(k, w, x, y, z, kk) do { \ + uint32 _t0, _t1; \ + kk -= 2; \ + GG(k, _t0, _t1, w, x, kk); \ + y = ROL32(y, 1); y ^= _t0; \ + z ^= _t1; z = ROR32(z, 1); \ +} while (0) + +/* --- Complete encryption functions --- */ + +#define EBLK(k, a, b, c, d, w, x, y, z) do { \ + const uint32 *_kk = k->k + 8; \ + uint32 _a = a, _b = b, _c = c, _d = d; \ + _a ^= k->k[0]; _b ^= k->k[1]; _c ^= k->k[2]; _d ^= k->k[3]; \ + EROUND(k, _a, _b, _c, _d, _kk); \ + EROUND(k, _c, _d, _a, _b, _kk); \ + EROUND(k, _a, _b, _c, _d, _kk); \ + EROUND(k, _c, _d, _a, _b, _kk); \ + EROUND(k, _a, _b, _c, _d, _kk); \ + EROUND(k, _c, _d, _a, _b, _kk); \ + EROUND(k, _a, _b, _c, _d, _kk); \ + EROUND(k, _c, _d, _a, _b, _kk); \ + EROUND(k, _a, _b, _c, _d, _kk); \ + EROUND(k, _c, _d, _a, _b, _kk); \ + EROUND(k, _a, _b, _c, _d, _kk); \ + EROUND(k, _c, _d, _a, _b, _kk); \ + EROUND(k, _a, _b, _c, _d, _kk); \ + EROUND(k, _c, _d, _a, _b, _kk); \ + EROUND(k, _a, _b, _c, _d, _kk); \ + EROUND(k, _c, _d, _a, _b, _kk); \ + _c ^= k->k[4]; _d ^= k->k[5]; _a ^= k->k[6]; _b ^= k->k[7]; \ + w = U32(_c); x = U32(_d); y = U32(_a); z = U32(_b); \ +} while (0) + +#define DBLK(k, a, b, c, d, w, x, y, z) do { \ + const uint32 *_kk = k->k + 40; \ + uint32 _a = a, _b = b, _c = c, _d = d; \ + _a ^= k->k[4]; _b ^= k->k[5]; _c ^= k->k[6]; _d ^= k->k[7]; \ + DROUND(k, _a, _b, _c, _d, _kk); \ + DROUND(k, _c, _d, _a, _b, _kk); \ + DROUND(k, _a, _b, _c, _d, _kk); \ + DROUND(k, _c, _d, _a, _b, _kk); \ + DROUND(k, _a, _b, _c, _d, _kk); \ + DROUND(k, _c, _d, _a, _b, _kk); \ + DROUND(k, _a, _b, _c, _d, _kk); \ + DROUND(k, _c, _d, _a, _b, _kk); \ + DROUND(k, _a, _b, _c, _d, _kk); \ + DROUND(k, _c, _d, _a, _b, _kk); \ + DROUND(k, _a, _b, _c, _d, _kk); \ + DROUND(k, _c, _d, _a, _b, _kk); \ + DROUND(k, _a, _b, _c, _d, _kk); \ + DROUND(k, _c, _d, _a, _b, _kk); \ + DROUND(k, _a, _b, _c, _d, _kk); \ + DROUND(k, _c, _d, _a, _b, _kk); \ + _c ^= k->k[0]; _d ^= k->k[1]; _a ^= k->k[2]; _b ^= k->k[3]; \ + w = U32(_c); x = U32(_d); y = U32(_a); z = U32(_b); \ +} while (0) + +/* --- @twofish_eblk@, @twofish_dblk@ --- * + * + * Arguments: @const twofish_ctx *k@ = pointer to key block + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +void twofish_eblk(const twofish_ctx *k, const uint32 *s, uint32 *d) +{ + EBLK(k, s[0], s[1], s[2], s[3], d[0], d[1], d[2], d[3]); +} + +void twofish_dblk(const twofish_ctx *k, const uint32 *s, uint32 *d) +{ + DBLK(k, s[0], s[1], s[2], s[3], d[0], d[1], d[2], d[3]); +} + +BLKC_TEST(TWOFISH, twofish) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/twofish.h b/symm/twofish.h new file mode 100644 index 0000000..328d00a --- /dev/null +++ b/symm/twofish.h @@ -0,0 +1,143 @@ +/* -*-c-*- + * + * The Twofish block cipher + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the Twofish block cipher ---------------------------------* + * + * Twofish was designed by Bruce Schneier, John Kelsey, Doug Whiting, David + * Wagner, Chris Hall and Niels Ferguson. The algorithm is unpatented and + * free for anyone to use. It was one of the five AES finalist algorithms. + * + * Twofish is a complex cipher offering various space and time tradeoffs. + * This implementation has a heavy key schedule and fast bulk encryption. + */ + +#ifndef CATACOMB_TWOFISH_H +#define CATACOMB_TWOFISH_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magical numbers ---------------------------------------------------*/ + +#define TWOFISH_BLKSZ 16 +#define TWOFISH_KEYSZ 32 +#define TWOFISH_CLASS (N, L, 128) + +extern const octet twofish_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct twofish_ctx { + uint32 k[40]; + uint32 g[4][256]; +} twofish_ctx; + +typedef struct twofish_fk { + uint32 t0[8], t23[8], t4[2]; + octet t1[32]; +} twofish_fk; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @twofish_initfk@ --- * + * + * Arguments: @twofish_ctx *k@ = pointer to key block to fill in + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * @const twofish_fk *fk@ = family-key information + * + * Returns: --- + * + * Use: Does the underlying Twofish key initialization with family + * key. Pass in a family-key structure initialized to + * all-bits-zero for a standard key schedule. + */ + +extern void twofish_initfk(twofish_ctx */*k*/, const void */*buf*/, + size_t /*sz*/, const twofish_fk */*fk*/); + +/* --- @twofish_init@ --- * + * + * Arguments: @twofish_ctx *k@ = pointer to key block to fill in + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a Twofish key buffer. Twofish accepts keys of up + * to 256 bits in length. + */ + +extern void twofish_init(twofish_ctx */*k*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @twofish_fkinit@ --- * + * + * Arguments: @twofish_fk *fk@ = pointer to family key block + * @const void *buf@ = pointer to buffer of key material + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes a family-key buffer. This implementation allows + * family keys of any size acceptable to the Twofish algorithm. + */ + +extern void twofish_fkinit(twofish_fk */*fk*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @twofish_eblk@, @twofish_dblk@ --- * + * + * Arguments: @const twofish_ctx *k@ = pointer to key block + * @const uint32 s[4]@ = pointer to source block + * @uint32 d[4]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void twofish_eblk(const twofish_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +extern void twofish_dblk(const twofish_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/whirlpool-mktab.c b/symm/whirlpool-mktab.c new file mode 100644 index 0000000..cac72bf --- /dev/null +++ b/symm/whirlpool-mktab.c @@ -0,0 +1,231 @@ +/* -*-c-*- + * + * Generate tables for Whirlpool hash function + * + * (c) 2005 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include + +/*----- Static variables --------------------------------------------------*/ + +static const octet E[] = { + 0x1, 0xb, 0x9, 0xc, 0xd, 0x6, 0xf, 0x3, + 0xe, 0x8, 0x7, 0x4, 0xa, 0x2, 0x5, 0x0 +}, R[] = { + 0x7, 0xc, 0xb, 0xd, 0xe, 0x4, 0x9, 0xf, + 0x6, 0x3, 0x8, 0xa, 0x2, 0x5, 0x1, 0x0 +}, C[] = { + 0x1, 0x1, 0x4, 0x1, 0x8, 0x5, 0x2, 0x9 +}; + +static octet S[256], T[256][8], log[256], alog[256]; + +/*----- Main code ---------------------------------------------------------*/ + +#define S_MOD 0x11d + +static void logtable(void) +{ + unsigned i, x; + + for (i = 0, x = 1; i < 255; i++) { + log[x] = i; + alog[i] = x; + x <<= 1; + if (x & 0x100) x ^= S_MOD; + } +} + +static octet mul(octet x, octet y) + { if (!x || !y) return (0); return (alog[(log[x] + log[y]) % 255]); } + +static void sbox(void) +{ + unsigned i, j; + octet EI[16]; + octet l, r, y; + + for (i = 0; i < 16; i++) EI[E[i]] = i; + for (i = 0; i < 256; i++) { + l = (i >> 4) & 0xf; + r = (i >> 0) & 0xf; + l = E[l]; r = EI[r]; + y = R[l ^ r]; + l = E[l ^ y]; r = EI[r ^ y]; + S[i] = (l << 4) | r; + } + + for (i = 0; i < 256; i++) { + for (j = 0; j < 8; j++) + T[i][j] = mul(S[i], C[j]); + } +} + +static unsigned long w32(int i, int j, int k) +{ + kludge64 x; + LOAD64_L_(x, T[j]); + ROL64_(x, x, i * 8); + return (k ? LO64(x) : HI64(x)); +} + +int main(void) +{ + int i, j; + + puts("\ +/* -*-c-*-\n\ + *\n\ + * Whirlpool tables [generated]\n\ + */\n\ +\n\ +#ifndef CATACOMB_WHIRLPOOL_TAB_H\n\ +#define CATACOMB_WHIRLPOOL_TAB_H\n\ +"); + + /* --- Write out the S-box --- */ + + logtable(); + sbox(); + fputs("\ +/* --- The byte substitution --- */\n\ +\n\ +#define WHIRLPOOL_S { \\\n\ + ", stdout); + for (i = 0; i < 256; i++) { + printf("0x%02x", S[i]); + if (i == 255) + fputs(" \\\n}\n\n", stdout); + else if (i % 8 == 7) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + /* --- Write out the key constant tables --- */ + + fputs("\ +/* --- The key generation constants --- */\n\ +\n\ +#define WHIRLPOOL_C { \\\n\ + ", stdout); + for (i = 0; i < 10; i++) { + printf("X64(%08lx, %08lx)", + (unsigned long)LOAD32_L(&S[i * 8 + 4]), + (unsigned long)LOAD32_L(&S[i * 8 + 0])); + if (i == 9) + fputs(" \\\n}\n\n", stdout); + else if (i % 2 == 1) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + + /* --- Write out the big T tables --- */ + + fputs("\ +/* --- The 64-bit big round tables --- */\n\ +\n\ +#define WHIRLPOOL_T { \\\n\ + { ", stdout); + for (j = 0; j < 8; j++) { + for (i = 0; i < 256; i++) { + printf("X64(%08lx, %08lx)", w32(j, i, 0), w32(j, i, 1)); + if (i == 255) { + if (j == 7) + fputs(" } \\\n}\n\n", stdout); + else + fputs(" }, \\\n\ + \\\n\ + { ", stdout); + } else if (i % 2 == 1) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + } + + /* --- Write out the smaller U and V tables --- */ + + fputs("\ +/* --- The 32-bit round tables --- */\n\ +\n\ +#define WHIRLPOOL_U { \\\n\ + { ", stdout); + for (j = 0; j < 4; j++) { + for (i = 0; i < 256; i++) { + printf("0x%08lx", w32(j, i, 1)); + if (i == 255) { + if (j == 3) + fputs(" } \\\n}\n\n", stdout); + else + fputs(" }, \\\n\ + \\\n\ + { ", stdout); + } else if (i % 4 == 3) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + } + + fputs("\ +#define WHIRLPOOL_V { \\\n\ + { ", stdout); + for (j = 0; j < 4; j++) { + for (i = 0; i < 256; i++) { + printf("0x%08lx", w32(j, i, 0)); + if (i == 255) { + if (j == 3) + fputs(" } \\\n}\n\n", stdout); + else + fputs(" }, \\\n\ + \\\n\ + { ", stdout); + } else if (i % 4 == 3) + fputs(", \\\n ", stdout); + else + fputs(", ", stdout); + } + } + + /* --- Done --- */ + + puts("#endif"); + + if (fclose(stdout)) { + fprintf(stderr, "error writing data\n"); + exit(EXIT_FAILURE); + } + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/whirlpool.c b/symm/whirlpool.c new file mode 100644 index 0000000..4543287 --- /dev/null +++ b/symm/whirlpool.c @@ -0,0 +1,304 @@ +/* -*-c-*- + * + * Whirlpool hash function + * + * (c) 2005 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "whirlpool.h" +#include "whirlpool-tab.h" + +#if defined(HAVE_UINT64) +# define USE64 +#endif + +/*----- Static variables --------------------------------------------------*/ + +static const kludge64 C[10] = WHIRLPOOL_C; + +#ifdef USE64 +static const kludge64 T[8][256] = WHIRLPOOL_T; +#else +static const uint32 U[4][256] = WHIRLPOOL_U, V[4][256] = WHIRLPOOL_V; +#endif + +/*----- Main code ---------------------------------------------------------*/ + +#define DUMP(k, v) do { \ + int i; \ + printf("\n"); \ + for (i = 0; i < 8; i++) \ + printf(" %08x %08x : %08x %08x\n", \ + HI64(k[i]), LO64(k[i]), \ + HI64(v[i]), LO64(v[i])); \ +} while (0) + +#define OFFSET(i, n) (((i) + 16 - (n)) % 8) + +#ifdef USE64 + +#define BYTE(x, j) \ + U8((j) < 4 ? \ + (LO64(x) >> ((j) * 8)) : \ + (HI64(x) >> ((j) * 8 - 32))) + +#define TT(v, i, j) T[j][BYTE(v[OFFSET(i, j)], j)] + +#define XROW(vv, v, i) do { \ + XOR64(vv[i], vv[i], TT(v, i, 1)); \ + XOR64(vv[i], vv[i], TT(v, i, 2)); \ + XOR64(vv[i], vv[i], TT(v, i, 3)); \ + XOR64(vv[i], vv[i], TT(v, i, 4)); \ + XOR64(vv[i], vv[i], TT(v, i, 5)); \ + XOR64(vv[i], vv[i], TT(v, i, 6)); \ + XOR64(vv[i], vv[i], TT(v, i, 7)); \ +} while (0) + +#define ROWZ(vv, v, i) do { \ + vv[i] = TT(v, i, 0); \ + XROW(vv, v, i); \ +} while (0) + +#define ROWK(vv, v, i, k) do { \ + vv[i] = k; \ + XOR64(vv[i], vv[i], TT(v, i, 0)); \ + XROW(vv, v, i); \ +} while (0) + +#else + +#define BYTE(x, j) U8((x) >> (((j) & 3) * 8)) + +#define UUL(v, i, j) U[j & 3][BYTE(v[OFFSET(i, j)].lo, j)] +#define VVL(v, i, j) V[j & 3][BYTE(v[OFFSET(i, j)].lo, j)] +#define UUH(v, i, j) U[j & 3][BYTE(v[OFFSET(i, j)].hi, j)] +#define VVH(v, i, j) V[j & 3][BYTE(v[OFFSET(i, j)].hi, j)] + +#define XROW(vv, v, i) do { \ + vv[i].lo ^= UUL(v, i, 1); vv[i].hi ^= VVL(v, i, 1); \ + vv[i].lo ^= UUL(v, i, 2); vv[i].hi ^= VVL(v, i, 2); \ + vv[i].lo ^= UUL(v, i, 3); vv[i].hi ^= VVL(v, i, 3); \ + vv[i].lo ^= VVH(v, i, 4); vv[i].hi ^= UUH(v, i, 4); \ + vv[i].lo ^= VVH(v, i, 5); vv[i].hi ^= UUH(v, i, 5); \ + vv[i].lo ^= VVH(v, i, 6); vv[i].hi ^= UUH(v, i, 6); \ + vv[i].lo ^= VVH(v, i, 7); vv[i].hi ^= UUH(v, i, 7); \ +} while (0) + +#define ROWZ(vv, v, i) do { \ + vv[i].lo = UUL(v, i, 0); vv[i].hi = VVL(v, i, 0); \ + XROW(vv, v, i); \ +} while (0) + +#define ROWK(vv, v, i, k) do { \ + vv[i] = k; \ + vv[i].lo ^= UUL(v, i, 0); vv[i].hi ^= VVL(v, i, 0); \ + XROW(vv, v, i); \ +} while (0) + +#endif + +#define RHO(vv, v, kk, k) do { \ + ROWK(kk, k, 0, *c++); ROWK(vv, v, 0, kk[0]); \ + ROWZ(kk, k, 1); ROWK(vv, v, 1, kk[1]); \ + ROWZ(kk, k, 2); ROWK(vv, v, 2, kk[2]); \ + ROWZ(kk, k, 3); ROWK(vv, v, 3, kk[3]); \ + ROWZ(kk, k, 4); ROWK(vv, v, 4, kk[4]); \ + ROWZ(kk, k, 5); ROWK(vv, v, 5, kk[5]); \ + ROWZ(kk, k, 6); ROWK(vv, v, 6, kk[6]); \ + ROWZ(kk, k, 7); ROWK(vv, v, 7, kk[7]); \ +} while (0) + +void whirlpool_compress(whirlpool_ctx *ctx, const void *sbuf) +{ + kludge64 m[8], k[8], kk[8], v[8], vv[8]; + const kludge64 *c = C; + const octet *s = sbuf; + int i; + + for (i = 0; i < 8; i++) { + LOAD64_L_(m[i], &s[i * 8]); + XOR64(v[i], m[i], ctx->s[i]); + } + + RHO(vv, v, kk, ctx->s); + RHO(v, vv, k, kk); + RHO(vv, v, kk, k); + RHO(v, vv, k, kk); + RHO(vv, v, kk, k); + RHO(v, vv, k, kk); + RHO(vv, v, kk, k); + RHO(v, vv, k, kk); + RHO(vv, v, kk, k); + RHO(v, vv, k, kk); + + for (i = 0; i < 8; i++) { + XOR64(ctx->s[i], ctx->s[i], m[i]); + XOR64(ctx->s[i], ctx->s[i], v[i]); + } +} + +/* --- @whirlpool_init@, @whirlpool256_init@ --- * + * + * Arguments: @whirlpool_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void whirlpool_init(whirlpool_ctx *ctx) +{ + int i; + + for (i = 0; i < 8; i++) + SET64(ctx->s[i], 0, 0); + ctx->off = 0; + ctx->nh = ctx->nl = 0; +} + +/* --- @whirlpool_set@, @whirlpool256_set@ --- * + * + * Arguments: @whirlpool_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void whirlpool_set(whirlpool_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + int i; + + for (i = 0; i < 8; i++) { + LOAD64_L_(ctx->s[i], p); + p += 8; + } + ctx->off = 0; + ctx->nl = U32(count); + ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); +} + +/* --- @whirlpool_hash@, @whirlpool256_hash@ --- * + * + * Arguments: @whirlpool_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void whirlpool_hash(whirlpool_ctx *ctx, const void *buf, size_t sz) +{ + HASH_BUFFER(WHIRLPOOL, whirlpool, ctx, buf, sz); +} + +/* --- @whirlpool_done@, @whirlpool256_done@ --- * + * + * Arguments: @whirlpool_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +static void final(whirlpool_ctx *ctx) +{ + HASH_PAD(WHIRLPOOL, whirlpool, ctx, 0x80, 0, 32); + memset(ctx->buf + WHIRLPOOL_BUFSZ - 32, 0, 24); + STORE32(ctx->buf + WHIRLPOOL_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3)); + STORE32(ctx->buf + WHIRLPOOL_BUFSZ - 4, ctx->nl << 3); + whirlpool_compress(ctx, ctx->buf); +} + +void whirlpool_done(whirlpool_ctx *ctx, void *hash) +{ + octet *p = hash; + int i; + + final(ctx); + for (i = 0; i < 8; i++) { + STORE64_L_(p, ctx->s[i]); + p += 8; + } +} + +void whirlpool256_done(whirlpool256_ctx *ctx, void *hash) +{ + octet *p = hash; + int i; + + final(ctx); + for (i = 0; i < 4; i++) { + STORE64_L_(p, ctx->s[i]); + p += 8; + } +} + +/* --- @whirlpool_state@, @whirlpool256_state@ --- * + * + * Arguments: @whirlpool_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @whirlpool_set@. + */ + +unsigned long whirlpool_state(whirlpool_ctx *ctx, void *state) +{ + octet *p = state; + int i; + + for (i = 0; i < 8; i++) { + STORE64_L_(p, ctx->s[i]); + p += 8; + } + return (ctx->nl | ((ctx->nh << 16) << 16)); +} + +/* --- Generic interface --- */ + +GHASH_DEF(WHIRLPOOL, whirlpool) + +/* --- Test code --- */ + +HASH_TEST(WHIRLPOOL, whirlpool) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/whirlpool.h b/symm/whirlpool.h new file mode 100644 index 0000000..95b40dc --- /dev/null +++ b/symm/whirlpool.h @@ -0,0 +1,175 @@ +/* -*-c-*- + * + * Implementation of the Whirlpool hash function + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the Whirlpool hash function ------------------------------* + * + * Whirlpool was designed by Paulo Barreto and Vincent Rijmen. Its + * compression function is based on similar ideas to Rijndael (also + * codesigned by Rijmen). + * + * Whirlpool256 is simply Whirlpool with its final output truncated to 256 + * bits. This is, I hope, about as good as a 256-bit hash function can get. + * It isn't vulnerable to the Kelsey-Schneier generic second-preimage attack + * against MD hash functions because of its larger internal state (see also + * Lucks). + */ + +#ifndef CATACOMB_WHIRLPOOL_H +#define CATACOMB_WHIRLPOOL_H +#define CATACOMB_WHIRLPOOL256_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define WHIRLPOOL_BUFSZ 64 +#define WHIRLPOOL_HASHSZ 64 +#define WHIRLPOOL_STATESZ 64 + +#define WHIRLPOOL256_BUFSZ 64 +#define WHIRLPOOL256_HASHSZ 32 +#define WHIRLPOOL256_STATESZ 64 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct whirlpool_ctx { + kludge64 s[8]; /* Chaining variables */ + uint32 nh, nl; /* Byte count so far */ + unsigned off; /* Offset into buffer */ + octet buf[WHIRLPOOL_BUFSZ]; /* Accumulation buffer */ +} whirlpool_ctx, whirlpool256_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @whirlpool_compress@, @whirlpool256_compress@ --- * + * + * Arguments: @whirlpool_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: SHA-512 compression function. + */ + +extern void whirlpool_compress(whirlpool_ctx */*ctx*/, const void */*sbuf*/); +#define whirlpool256_compress whirlpool_compress + +/* --- @whirlpool_init@, @whirlpool256_init@ --- * + * + * Arguments: @whirlpool_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void whirlpool_init(whirlpool_ctx */*ctx*/); +#define whirlpool256_init whirlpool_init + +/* --- @whirlpool_set@, @whirlpool256_set@ --- * + * + * Arguments: @whirlpool_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void whirlpool_set(whirlpool_ctx */*ctx*/, const void */*buf*/, + unsigned long /*count*/); +#define whirlpool256_set whirlpool_set + +/* --- @whirlpool_hash@, @whirlpool256_hash@ --- * + * + * Arguments: @whirlpool_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void whirlpool_hash(whirlpool_ctx */*ctx*/, + const void */*buf*/, size_t /*sz*/); +#define whirlpool256_hash whirlpool_hash + +/* --- @whirlpool_done@, @whirlpool256_done@ --- * + * + * Arguments: @whirlpool_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void whirlpool_done(whirlpool_ctx */*ctx*/, void */*hash*/); +extern void whirlpool256_done(whirlpool_ctx */*ctx*/, void */*hash*/); + +/* --- @whirlpool_state@, @whirlpool256_state@ --- * + * + * Arguments: @whirlpool_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @whirlpool_set@. + */ + +extern unsigned long whirlpool_state(whirlpool_ctx */*ctx*/, + void */*state*/); +#define whirlpool256_state whirlpool_state + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash whirlpool; +extern const gchash whirlpool256; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/whirlpool256.c b/symm/whirlpool256.c new file mode 100644 index 0000000..48245f2 --- /dev/null +++ b/symm/whirlpool256.c @@ -0,0 +1,12 @@ +/* -*-c-*- + * + * Stub code for Whirlpool-256 + */ + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "whirlpool256.h" + +GHASH_DEF(WHIRLPOOL256, whirlpool256) +HASH_TEST(WHIRLPOOL256, whirlpool256) diff --git a/symm/whirlpool256.h b/symm/whirlpool256.h new file mode 100644 index 0000000..8091d74 --- /dev/null +++ b/symm/whirlpool256.h @@ -0,0 +1,11 @@ +/* -*-c-*- + * + * Stub header for Whirlpool-256 + */ + +#ifndef CATACOMB_WHIRLPOOL256_H +#define CATACOMB_WHIRLPOOL256_H + +#include "whirlpool.h" + +#endif diff --git a/symm/xtea.c b/symm/xtea.c new file mode 100644 index 0000000..7f95981 --- /dev/null +++ b/symm/xtea.c @@ -0,0 +1,120 @@ +/* -*-c-*- + * + * The Extended Tiny Encryption Algorithm + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "blkc.h" +#include "gcipher.h" +#include "paranoia.h" +#include "xtea.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet xtea_keysz[] = { KSZ_RANGE, XTEA_KEYSZ, 0, 16, 1 }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @xtea_init@ --- * + * + * Arguments: @xtea_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes an XTEA key buffer. The key buffer must be 16 + * bytes long. + */ + +void xtea_init(xtea_ctx *k, const void *buf, size_t sz) +{ + octet kb[16]; + const octet *p; + + KSZ_ASSERT(xtea, sz); + if (sz >= sizeof(kb)) + p = buf; + else { + memcpy(kb, buf, sz); + memset(kb + sz, 0, sizeof(kb) - sz); + p = kb; + } + + k->k[0] = LOAD32(p + 0); k->k[1] = LOAD32(p + 4); + k->k[2] = LOAD32(p + 8); k->k[3] = LOAD32(p + 12); + k->r = 32; + + if (p == kb) + BURN(kb); +} + +/* --- @xtea_eblk@, @xtea_dblk@ --- * + * + * Arguments: @const xtea_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to xteatination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +#define DELTA 0x9e3779b9 + +void xtea_eblk(const xtea_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 y = s[0], z = s[1]; + uint32 n = 0; + unsigned i; + + for (i = 0; i < k->r; i++) { + y = U32(y + ((((z << 4) ^ (z >> 5)) + z) ^ (n + k->k[n & 3]))); + n += DELTA; + z = U32(z + ((((y << 4) ^ (y >> 5)) + y) ^ (n + k->k[(n >> 11) & 3]))); + } + d[0] = y; d[1] = z; +} + +void xtea_dblk(const xtea_ctx *k, const uint32 *s, uint32 *d) +{ + uint32 y = s[0], z = s[1]; + uint32 n = DELTA * k->r; + unsigned i; + + for (i = 0; i < k->r; i++) { + z = U32(z - ((((y << 4) ^ (y >> 5)) + y) ^ (n + k->k[(n >> 11) & 3]))); + n -= DELTA; + y = U32(y - ((((z << 4) ^ (z >> 5)) + z) ^ (n + k->k[n & 3]))); + } + d[0] = y; d[1] = z; +} + +BLKC_TEST(XTEA, xtea) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/xtea.h b/symm/xtea.h new file mode 100644 index 0000000..768a526 --- /dev/null +++ b/symm/xtea.h @@ -0,0 +1,104 @@ +/* -*-c-*- + * + * The Extended Tiny Encryption Algorithm + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Notes on the Tiny Encryption Algorithm ----------------------------* + * + * XTEA is an amazingly simple 64-round Feistel network. It's tiny, fairly + * quick and surprisingly strong. It was invented by David Wheeler and Roger + * Needham. It's unpatented. XTEA is a new version of TEA, by the same + * designers, which fixes some weaknesses in TEA's key schedule. + * + * This implementation uses big-endian byte order, following SCAN. + */ + +#ifndef CATACOMB_XTEA_H +#define CATACOMB_XTEA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include + +/*----- Magical numbers ---------------------------------------------------*/ + +#define XTEA_BLKSZ 8 +#define XTEA_KEYSZ 16 +#define XTEA_CLASS (N, B, 64) + +extern const octet xtea_keysz[]; + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct xtea_ctx { + unsigned r; + uint32 k[4]; +} xtea_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @xtea_init@ --- * + * + * Arguments: @xtea_ctx *k@ = pointer to key block + * @const void *buf@ = pointer to key buffer + * @size_t sz@ = size of key material + * + * Returns: --- + * + * Use: Initializes an XTEA key buffer. The key buffer may be up to + * 16 bytes long. + */ + +extern void xtea_init(xtea_ctx */*k*/, const void */*buf*/, size_t /*sz*/); + +/* --- @xtea_eblk@, @xtea_dblk@ --- * + * + * Arguments: @const xtea_ctx *k@ = pointer to key block + * @const uint32 s[2]@ = pointer to source block + * @uint32 d[2]@ = pointer to xteatination block + * + * Returns: --- + * + * Use: Low-level block encryption and decryption. + */ + +extern void xtea_eblk(const xtea_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); +extern void xtea_dblk(const xtea_ctx */*k*/, + const uint32 */*s*/, uint32 */*d*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/tea.c b/tea.c deleted file mode 100644 index 4cb5ef8..0000000 --- a/tea.c +++ /dev/null @@ -1,124 +0,0 @@ -/* -*-c-*- - * - * $Id: tea.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The Tiny Encryption Algorithm - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "paranoia.h" -#include "tea.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet tea_keysz[] = { KSZ_RANGE, TEA_KEYSZ, 0, 16, 1 }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @tea_init@ --- * - * - * Arguments: @tea_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a TEA key buffer. The key buffer must be 16 - * bytes long. - */ - -void tea_init(tea_ctx *k, const void *buf, size_t sz) -{ - octet kb[16]; - const octet *p; - - KSZ_ASSERT(tea, sz); - if (sz >= sizeof(kb)) - p = buf; - else { - memcpy(kb, buf, sz); - memset(kb + sz, 0, sizeof(kb) - sz); - p = kb; - } - - k->ka = LOAD32(p + 0); k->kb = LOAD32(p + 4); - k->kc = LOAD32(p + 8); k->kd = LOAD32(p + 12); - k->r = 32; - - if (p == kb) - BURN(kb); -} - -/* --- @tea_eblk@, @tea_dblk@ --- * - * - * Arguments: @const tea_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to teatination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -#define DELTA 0x9e3779b9 - -void tea_eblk(const tea_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 y = s[0], z = s[1]; - uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd; - uint32 n = 0; - unsigned i; - - for (i = 0; i < k->r; i++) { - n += DELTA; - y = U32(y + (((z << 4) + ka) ^ (z + n) ^ ((z >> 5) + kb))); - z = U32(z + (((y << 4) + kc) ^ (y + n) ^ ((y >> 5) + kd))); - } - d[0] = y; d[1] = z; -} - -void tea_dblk(const tea_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 y = s[0], z = s[1]; - uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd; - uint32 n = DELTA * k->r; - unsigned i; - - for (i = 0; i < k->r; i++) { - z = U32(z - (((y << 4) + kc) ^ (y + n) ^ ((y >> 5) + kd))); - y = U32(y - (((z << 4) + ka) ^ (z + n) ^ ((z >> 5) + kb))); - n -= DELTA; - } - d[0] = y; d[1] = z; -} - -BLKC_TEST(TEA, tea) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/tea.h b/tea.h deleted file mode 100644 index 6d96b90..0000000 --- a/tea.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -*-c-*- - * - * $Id: tea.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The Tiny Encryption Algorithm - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the Tiny Encryption Algorithm ----------------------------* - * - * TEA is an amazingly simple 64-round Feistel network. It's tiny, fairly - * quick and surprisingly strong. It was invented by David Wheeler and Roger - * Needham. It's unpatented. The keyspace is has only 126 effective bits, - * and there are related-key attacks. If you want these fixed, use XTEA. - * - * This implementation uses big-endian byte order, following SCAN. - */ - -#ifndef CATACOMB_TEA_H -#define CATACOMB_TEA_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magical numbers ---------------------------------------------------*/ - -#define TEA_BLKSZ 8 -#define TEA_KEYSZ 16 -#define TEA_CLASS (N, B, 64) - -extern const octet tea_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct tea_ctx { - unsigned r; - uint32 ka, kb, kc, kd; -} tea_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @tea_init@ --- * - * - * Arguments: @tea_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a TEA key buffer. The key buffer may be up to 16 - * bytes long. - */ - -extern void tea_init(tea_ctx */*k*/, const void */*buf*/, size_t /*sz*/); - -/* --- @tea_eblk@, @tea_dblk@ --- * - * - * Arguments: @const tea_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to teatination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void tea_eblk(const tea_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); -extern void tea_dblk(const tea_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/tests/.gitignore b/tests/.gitignore deleted file mode 100644 index 8b605eb..0000000 --- a/tests/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -cast256 -mars -rijndael -serpent -tea-test -twofish -xtea-test diff --git a/tests/bbs b/tests/bbs deleted file mode 100644 index 7c46e0f..0000000 --- a/tests/bbs +++ /dev/null @@ -1,16 +0,0 @@ -# Test vectors for Blum-Blum-Shub generator -# -# $Id: bbs,v 1.2 2000/07/09 21:33:54 mdw Exp $ - -bbs { - 58618255351802153154518076227263324405595169368832105733339611861073310668957206153928098662820028322143309562326246028101842658621324089654810023510552099428926874474919949521150122806716423750640359105584279946965449493907636556236204117444242840921432253645386399913807490661488722966090824347967771475377 - 2 - 4a488784b0b74c53fe820e3416f67fb7f238898f711a8b5d3f3ea70b0ec264120b7bfaef30f841a979cb76ca9e9c6b01415e7618b5d6c4cc30db539852ca86d23b3527d566a76910d43ed9ba2b83596f3411354ae37c53cf0c2eab7e7e13ac7c58de83cbfd8b0a6b7cdcb7bcef92bf96a48e18124c2c21e7964a9b701b5ea4ab; -} - -bbs-jump { - 10300002644323831640029548502577413794096963710947992849414516873746495715149677373680896096678934650462228369293905743592335562158905193518665447759028003 - 8901308291494485065585437130459769427950766447948540080704500059827922533698081294071192603392538957644021072601596274962775430269633339980725226130767879 - 15 - 250; -} diff --git a/tests/blowfish b/tests/blowfish deleted file mode 100644 index 9f7075e..0000000 --- a/tests/blowfish +++ /dev/null @@ -1,121 +0,0 @@ -# Test vectors for Blowfish -# -# $Id: blowfish,v 1.3 2001/04/29 17:38:07 mdw Exp $ - -blowfish { - - # --- Main block cipher --- - # - # Taken from Bruce Schneier's web pages, I think... - - 0000000000000000 0000000000000000 4ef997456198dd78; - ffffffffffffffff ffffffffffffffff 51866fd5b85ecb8a; - 3000000000000000 1000000000000001 7d856f9a613063f2; - 1111111111111111 1111111111111111 2466dd878b963c9d; - 0123456789abcdef 1111111111111111 61f9c3802281b096; - 1111111111111111 0123456789abcdef 7d0cc630afda1ec7; - 0000000000000000 0000000000000000 4ef997456198dd78; - fedcba9876543210 0123456789abcdef 0aceab0fc6a0a28d; - 7ca110454a1a6e57 01a1d6d039776742 59c68245eb05282b; - 0131d9619dc1376e 5cd54ca83def57da b1b8cc0b250f09a0; - 07a1133e4a0b2686 0248d43806f67172 1730e5778bea1da4; - 3849674c2602319e 51454b582ddf440a a25e7856cf2651eb; - 04b915ba43feb5b6 42fd443059577fa2 353882b109ce8f1a; - 0113b970fd34f2ce 059b5e0851cf143a 48f4d0884c379918; - 0170f175468fb5e6 0756d8e0774761d2 432193b78951fc98; - 43297fad38e373fe 762514b829bf486a 13f04154d69d1ae5; - 07a7137045da2a16 3bdd119049372802 2eedda93ffd39c79; - 04689104c2fd3b2f 26955f6835af609a d887e0393c2da6e3; - 37d06bb516cb7546 164d5e404f275232 5f99d04f5b163969; - 1f08260d1ac2465e 6b056e18759f5cca 4a057a3b24d3977b; - 584023641aba6176 004bd6ef09176062 452031c1e4fada8e; - 025816164629b007 480d39006ee762f2 7555ae39f59b87bd; - 49793ebc79b3258f 437540c8698f3cfa 53c55f9cb49fc019; - 4fb05e1515ab73a7 072d43a077075292 7a8e7bfa937e89a3; - 49e95d6d4ca229bf 02fe55778117f12a cf9c5d7a4986adb5; - 018310dc409b26d6 1d9d5c5018f728c2 d1abb290658bc778; - 1c587f1c13924fef 305532286d6f295a 55cb3774d13ef201; - 0101010101010101 0123456789abcdef fa34ec4847b268b2; - 1f1f1f1f0e0e0e0e 0123456789abcdef a790795108ea3cae; - e0fee0fef1fef1fe 0123456789abcdef c39e072d9fac631d; - 0000000000000000 ffffffffffffffff 014933e0cdaff6e4; - ffffffffffffffff 0000000000000000 f21e9a77b71c49bc; - 0123456789abcdef 0000000000000000 245946885754369a; - fedcba9876543210 ffffffffffffffff 6b5c5a9c5d9e0a5a; - - # --- Key schedule test --- - # - # From wherever the previous tests came from. - - f0 - fedcba9876543210 f9ad597c49db005e; - - f0e1 - fedcba9876543210 e91d21c1d961a6d6; - - f0e1d2 - fedcba9876543210 e9c2b70a1bc65cf3; - - f0e1d2c3 - fedcba9876543210 be1e639408640f05; - - f0e1d2c3b4 - fedcba9876543210 b39e44481bdb1e6e; - - f0e1d2c3b4a5 - fedcba9876543210 9457aa83b1928c0d; - - f0e1d2c3b4a596 - fedcba9876543210 8bb77032f960629d; - - f0e1d2c3b4a59687 - fedcba9876543210 e87a244e2cc85e82; - - f0e1d2c3b4a5968778 - fedcba9876543210 15750e7a4f4ec577; - - f0e1d2c3b4a596877869 - fedcba9876543210 122ba70b3ab64ae0; - - f0e1d2c3b4a5968778695a - fedcba9876543210 3a833c9affc537f6; - - f0e1d2c3b4a5968778695a4b - fedcba9876543210 9409da87a90f6bf2; - - f0e1d2c3b4a5968778695a4b3c - fedcba9876543210 884f80625060b8b4; - - f0e1d2c3b4a5968778695a4b3c2d - fedcba9876543210 1f85031c19e11968; - - f0e1d2c3b4a5968778695a4b3c2d1e - fedcba9876543210 79d9373a714ca34f; - - f0e1d2c3b4a5968778695a4b3c2d1e0f - fedcba9876543210 93142887ee3be15c; - - f0e1d2c3b4a5968778695a4b3c2d1e0f00 - fedcba9876543210 03429e838ce2d14b; - - f0e1d2c3b4a5968778695a4b3c2d1e0f0011 - fedcba9876543210 a4299e27469ff67b; - - f0e1d2c3b4a5968778695a4b3c2d1e0f001122 - fedcba9876543210 afd5aed1c1bc96a8; - - f0e1d2c3b4a5968778695a4b3c2d1e0f00112233 - fedcba9876543210 10851c0e3858da9f; - - f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344 - fedcba9876543210 e6f51ed79b9db21f; - - f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455 - fedcba9876543210 64a6e14afd36b46f; - - f0e1d2c3b4a5968778695a4b3c2d1e0f00112233445566 - fedcba9876543210 80c7d7d45a5479ad; - - f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344556677 - fedcba9876543210 05044b62fa52d080; -} diff --git a/tests/cast128 b/tests/cast128 deleted file mode 100644 index dacd736..0000000 --- a/tests/cast128 +++ /dev/null @@ -1,17 +0,0 @@ -# $Id: cast128,v 1.1 2000/06/17 12:11:49 mdw Exp $ -# -# Test vectors for CAST128 - -cast128 { - 0123456712345678234567893456789a - 0123456789abcdef - 238b4fe5847e44b2; - - 01234567123456782345 - 0123456789abcdef - eb6a711a2c02271b; - - 0123456712 - 0123456789abcdef - 7ac816d16e9b302e; -} diff --git a/tests/des b/tests/des deleted file mode 100644 index 28cd9e8..0000000 --- a/tests/des +++ /dev/null @@ -1,64 +0,0 @@ -# Test vectors for DES -# -# $Id: des,v 1.2 2001/05/07 17:32:32 mdw Exp $ - -des { - # --- 7-byte keys --- - - 00451338957377 4e6f772069732074 3fa40e8a984d4815; - b6c74cbf60c1fd 328da675ff5abd2c cd3e9f9b670671d1; - - # --- 8-byte keys --- - - 0123456789abcdef 4e6f772069732074 3fa40e8a984d4815; - 0022446688aaccee 4e6f772069732074 3fa40e8a984d4815; - 0123456789abcdef 68652074696d6520 6a271787ab8883f9; - 0123456789abcdef 666f7220616c6c20 893d51ec4b563b53; - 0123456789abcdef 0123456789abcde7 c95744256a5ed31d; - b763d297f70606fb 328da675ff5abd2c cd3e9f9b670671d1; - - # --- Tests for all DES S-boxes --- - - 7ca110454a1a6e57 01a1d6d039776742 690f5b0d9a26939b; - 0131d9619dc1376e 5cd54ca83def57da 7a389d10354bd271; - 07a1133e4a0b2686 0248d43806f67172 868ebb51cab4599a; - 3849674c2602319e 51454b582ddf440a 7178876e01f19b2a; - 04b915ba43feb5b6 42fd443059577fa2 af37fb421f8c4095; - 0113b970fd34f2ce 059b5e0851cf143a 86a560f10ec6d85b; - 0170f175468fb5e6 0756d8e0774761d2 0cd3da020021dc09; - 43297fad38e373fe 762514b829bf486a ea676b2cb7db2b7a; - 07a7137045da2a16 3bdd119049372802 dfd64a815caf1a0f; - 04689104c2fd3b2f 26955f6835af609a 5c513c9c4886c088; - 37d06bb516cb7546 164d5e404f275232 0a2aeeae3ff4ab77; - 1f08260d1ac2465e 6b056e18759f5cca ef1bf03e5dfa575a; - 584023641aba6176 004bd6ef09176062 88bf0db6d70dee56; - 025816164629b007 480d39006ee762f2 a1f9915541020b56; - 49793ebc79b3258f 437540c8698f3cfa 6fbf1cafcffd0556; - 4fb05e1515ab73a7 072d43a077075292 2f22e49bab7ca1ac; - 49e95d6d4ca229bf 02fe55778117f12a 5a6b612cc26cce4a; - 018310dc409b26d6 1d9d5c5018f728c2 5f4c038ed12b2e41; - 1c587f1c13924fef 305532286d6f295a 63fac0d034d9f793; - - # --- Rivest's test vector set --- - - 9474b8e8c73bca7d 9474b8e8c73bca7d 8da744e0c94e5e17; - 8da744e0c94e5e17 0cdb25e3ba3c6d79 8da744e0c94e5e17; - 0cdb25e3ba3c6d79 0cdb25e3ba3c6d79 4784c4ba5006081f; - 4784c4ba5006081f 1cf1fc126f2ef842 4784c4ba5006081f; - 1cf1fc126f2ef842 1cf1fc126f2ef842 e4be250042098d13; - e4be250042098d13 7bfc5dc6adb5797c e4be250042098d13; - 7bfc5dc6adb5797c 7bfc5dc6adb5797c 1ab3b4d82082fb28; - 1ab3b4d82082fb28 c1576a14de707097 1ab3b4d82082fb28; - c1576a14de707097 c1576a14de707097 739b68cd2e26782a; - 739b68cd2e26782a 2a59f0c464506edb 739b68cd2e26782a; - 2a59f0c464506edb 2a59f0c464506edb a5c39d4251f0a81e; - a5c39d4251f0a81e 7239ac9a6107ddb1 a5c39d4251f0a81e; - 7239ac9a6107ddb1 7239ac9a6107ddb1 070cac8590241233; - 070cac8590241233 78f87b6e3dfecf61 070cac8590241233; - 78f87b6e3dfecf61 78f87b6e3dfecf61 95ec2578c2c433f0; - 95ec2578c2c433f0 1b1a2ddb4c642438 95ec2578c2c433f0; - - # --- The EFF answer to Matt Blaze's challenge --- - - 0e329232ea6d0d73 8787878787878787 0000000000000000; -} diff --git a/tests/des3 b/tests/des3 deleted file mode 100644 index 0f8b3d1..0000000 --- a/tests/des3 +++ /dev/null @@ -1,43 +0,0 @@ -# Test vectors for double and triple DES -# -# $Id: des3,v 1.1 1999/09/03 08:41:14 mdw Exp $ - -des3 { - # --- Some simple single-DES things --- - - 00451338957377 4e6f772069732074 3fa40e8a984d4815; - b6c74cbf60c1fd 328da675ff5abd2c cd3e9f9b670671d1; - - 0123456789abcdef 4e6f772069732074 3fa40e8a984d4815; - 0123456789abcdef 68652074696d6520 6a271787ab8883f9; - 0123456789abcdef 666f7220616c6c20 893d51ec4b563b53; - 0123456789abcdef 0123456789abcde7 c95744256a5ed31d; - - 0045133895737700451338957377 4e6f772069732074 3fa40e8a984d4815; - b6c74cbf60c1fdb6c74cbf60c1fd 328da675ff5abd2c cd3e9f9b670671d1; - - 0123456789abcdef0123456789abcdef 4e6f772069732074 3fa40e8a984d4815; - 0123456789abcdef0123456789abcdef 68652074696d6520 6a271787ab8883f9; - 0123456789abcdef0123456789abcdef 666f7220616c6c20 893d51ec4b563b53; - 0123456789abcdef0123456789abcdef 0123456789abcde7 c95744256a5ed31d; - - 004513389573770045133895737700451338957377 - 4e6f772069732074 3fa40e8a984d4815; - b6c74cbf60c1fdb6c74cbf60c1fdb6c74cbf60c1fd - 328da675ff5abd2c cd3e9f9b670671d1; - - 0123456789abcdef0123456789abcdef0123456789abcdef - 4e6f772069732074 3fa40e8a984d4815; - 0123456789abcdef0123456789abcdef0123456789abcdef - 68652074696d6520 6a271787ab8883f9; - 0123456789abcdef0123456789abcdef0123456789abcdef - 666f7220616c6c20 893d51ec4b563b53; - 0123456789abcdef0123456789abcdef0123456789abcdef - 0123456789abcde7 c95744256a5ed31d; - - # --- Genuine longer keys --- - - 0123456789abcdeffedcba9876543210 0123456789abcde7 7f1d0a77826b8aff; - 0123456789abcdeffedcba987654321089abcdef01234567 - 0123456789abcde7 de0b7c06ae5e0ed5; -} diff --git a/tests/desx b/tests/desx deleted file mode 100644 index fd77fc4..0000000 --- a/tests/desx +++ /dev/null @@ -1,24 +0,0 @@ -# Test vectors for DES -# -# $Id: desx,v 1.1 2001/04/03 19:36:51 mdw Exp $ - -desx { - # --- From SCAN --- - - 0123456789abcdef1011121314151617 - 4445535864657378 d8fa5084fad4b35c; - 01010101010101010123456789abcdef1011121314151617 - 94dbe082549a14ef 9011121314151617; - - # --- 7-bit key tests --- - - 004513389573771011121314151617 - 4445535864657378 d8fa5084fad4b35c; - 000000000000000123456789abcdef1011121314151617 - 94dbe082549a14ef 9011121314151617; - - # --- Equivalence tests --- - - 00451338957377 4e6f772069732074 3fa40e8a984d4815; - 0123456789abcdef 4e6f772069732074 3fa40e8a984d4815; -} diff --git a/tests/dsa b/tests/dsa deleted file mode 100644 index d61f510..0000000 --- a/tests/dsa +++ /dev/null @@ -1,121 +0,0 @@ -# Test vectors for DSA -# -# $Id: dsa,v 1.5 2001/02/03 16:10:12 mdw Exp $ - -# --- About the tests --- -# -# There's only one test vector from FIPS-186. The others I've made up. The -# tests themselves are split into parameter generation, signature generation, -# and verification. - -gen { - # --- One that I made up --- - - bbac0ab63411435cb72f1f95b16ab94c92c34211 256 - bbac0ab63411435cb72f1f95b16ab94c92c34221 10 - 0x84d192cd06ae59691897fa409da6198d5269325d - 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5 - 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e; - - # --- FIPS-186 test vector --- - - d5014e4b60ef2ba8b6211b4062ba3224e0427dd3 512 - d5014e4b60ef2ba8b6211b4062ba3224e0427dd3 105 - 0xc773218c737ec8ee993b4f2ded30f48edace915f - 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 - 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802; - - # --- And a full-sized vector --- - - d1a29e27dfe4d60124cc41a59e012ae690408acfc3266d07f4eaeefdc9f8c70d2d2a338d - 1024 - d1a29e27dfe4d60124cc41a59e012ae690408acfc3266d07f4eaeefdc9f8c70d2d2a338d - 66 - 0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9 - 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7 - 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014; -} - -sign { - # --- Quick simple test --- - - 0x84d192cd06ae59691897fa409da6198d5269325d - 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5 - 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e - 0x1234 "An example message" - 649b1058e0fe7ee849d3cb00b8ec3053ad0793b8 - 2718bf488b981992b164e664224dd00ca1ed4e1c - 5c085679fbfa9ee806781bdbd86a67dbf14df640; - - # --- The FIPS-186 test vector --- - - 0xc773218c737ec8ee993b4f2ded30f48edace915f - 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 - 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 - 0x2070b3223dba372fde1c0ffc7b2e3b498b260614 - "abc" - 358dad571462710f50e254cf1a376b2bdeaadfbf - 8bac1ab66410435cb7181f95b16ab97c92b341c0 - 41e2345f1f56df2458f426d155b4ba2db6dcd8c8; - - # --- 1024-bit modulus test --- - - 0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9 - 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7 - 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 - 0x23a252f60bae4907a8ed5b6203e2b1da32848cd9 - "A message signed with a 1024-bit DSA key." - 12ccb231683a3d9c13dca6fe882349537eebfd03 - 2a301061ac185440fbf595f8f7d894158b8d1897 - 51aedaa73cb8d47e07281d14dda5ea8c0ddf7503; -} - -verify-good { - # --- Simple test ---- - - 0x84d192cd06ae59691897fa409da6198d5269325d - 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5 - 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e - 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 - "An example message" - 2718bf488b981992b164e664224dd00ca1ed4e1c - 5c085679fbfa9ee806781bdbd86a67dbf14df640; - - # --- The FIPS-186 test vector --- - - 0xc773218c737ec8ee993b4f2ded30f48edace915f - 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 - 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 - 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 - "abc" - 8bac1ab66410435cb7181f95b16ab97c92b341c0 - 41e2345f1f56df2458f426d155b4ba2db6dcd8c8; - - # --- 1024-bit modulus test --- - - 0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9 - 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7 - 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 - 0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074 - "A message signed with a 1024-bit DSA key." - 2a301061ac185440fbf595f8f7d894158b8d1897 - 51aedaa73cb8d47e07281d14dda5ea8c0ddf7503; -} - -verify-bad { - 0xc773218c737ec8ee993b4f2ded30f48edace915f - 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 - 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 - 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 - "abd" - 8bac1ab66410435cb7181f95b16ab97c92b341c0 - 41e2345f1f56df2458f426d155b4ba2db6dcd8c8; - - 0xc773218c737ec8ee993b4f2ded30f48edace915f - 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 - 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 - 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 - "abc" - 18bac1ab66410435cb7181f95b16ab97c92b341c0 - 41e2345f1f56df2458f426d155b4ba2db6dcd8c8; -} diff --git a/tests/ec b/tests/ec deleted file mode 100644 index b3c6e0e..0000000 --- a/tests/ec +++ /dev/null @@ -1,453 +0,0 @@ -# $Id$ -# -# Elliptic curve tests - -check { - "prime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 0; - "prime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810" - -1; - "prime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee" - 0; - "prime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411, - 0xdccf19d3e76abfa05d529c07575f54c94fa5fc9f3decc246" - 0; - "prime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 0; - "prime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810" - -1; - "prime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee" - 0; - - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 0; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810" - -1; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee" - 0; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411, - 0xdccf19d3e76abfa05d529c07575f54c94fa5fc9f3decc246" - 0; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 0; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810" - -1; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee" - 0; - - "binpoly: 0x800000000000000000000000000000000000000c9 - bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1" - 0; - "binpoly: 0x800000000000000000000000000000000000000c9 - bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f0" - -1; - "binpoly: 0x800000000000000000000000000000000000000c9 - bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - 0; - "binpoly: 0x800000000000000000000000000000000000000c9 - binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1" - 0; - "binpoly: 0x800000000000000000000000000000000000000c9 - binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f0" - -1; - "binpoly: 0x800000000000000000000000000000000000000c9 - binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - 0; - "binpoly: 0x800000000000000000000000000000000000000c9 - binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0591168d4994637e8343e36, - 0x7fa8423c5ae194b56cdf21998ad8a721ef1201b8c" - 0; -} - -find { - "prime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012 - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"; - "prime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1011 inf; - "prime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - 0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411 - "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411, - 0x2330e62c1895405fa2ad63f8a8a0ab35b05a0360c2133db9"; - - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012 - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1011 inf; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - 0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411 - "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411, - 0x2330e62c1895405fa2ad63f8a8a0ab35b05a0360c2133db9"; - - "binpoly: 0x800000000000000000000000000000000000000c9 - bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - 0x3f0eba16286a2d57ea0991168d4994637e8343e36 - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7"; - "binpoly: 0x800000000000000000000000000000000000000c9 - bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - 0x310eba16386a2d57ea0591168d4997637e8745e36 inf; - "binpoly: 0x800000000000000000000000000000000000000c9 - bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - 0x3f0eba16286a2d57ea0591168d4994637e8343e36 - "0x3f0eba16286a2d57ea0591168d4994637e8343e36, - 0x7fa8423c5ae194b56cdf21998ad8a721ef1201b8c"; -} - -neg { - "prime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; - "prime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; - - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; - - "binpoly: 0x800000000000000000000000000000000000000c9 - bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1"; - "binpoly: 0x800000000000000000000000000000000000000c9 - binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1"; -} - -dbl { - "prime: 23 prime: 1, 1" "4, 0" inf; - "prime: 23 primeproj: 1, 1" "4, 0" inf; - - "prime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; - "prime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; - - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; - - "binpoly: 0x800000000000000000000000000000000000000c9 - bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4, - 0x49ed3be7f510e30e2462c517ad39038e493fc573c"; - "binpoly: 0x800000000000000000000000000000000000000c9 - binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4, - 0x49ed3be7f510e30e2462c517ad39038e493fc573c"; - - "binpoly: 0x020000000000000000000000000000200000000000000001 - bin: 0, 0x1ee9" - "0x18, 0xd" - "0x1bd555555555555555555555555554e8000000000000158, - 0x14e999999999999999999999999998d7000000000001fe6"; -} - -add { - "prime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" - "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, - 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"; - "prime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" - "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, - 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"; - - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" - "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, - 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" - "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, - 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"; - - "binpoly: 0x800000000000000000000000000000000000000c9 - bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4, - 0x49ed3be7f510e30e2462c517ad39038e493fc573c" - "0x634000577f86aa315009d6f9b906691f6edd691fe, - 0x235a3db7a94446301e666cafea5e12cb331f4a140"; - "binpoly: 0x800000000000000000000000000000000000000c9 - binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4, - 0x49ed3be7f510e30e2462c517ad39038e493fc573c" - "0x634000577f86aa315009d6f9b906691f6edd691fe, - 0x235a3db7a94446301e666cafea5e12cb331f4a140"; -} - -sub { - "prime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, - 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; - "prime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, - 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; - - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, - 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, - 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; - - "binpoly: 0x800000000000000000000000000000000000000c9 - bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x634000577f86aa315009d6f9b906691f6edd691fe, - 0x235a3db7a94446301e666cafea5e12cb331f4a140" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4, - 0x49ed3be7f510e30e2462c517ad39038e493fc573c"; - "binpoly: 0x800000000000000000000000000000000000000c9 - binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x634000577f86aa315009d6f9b906691f6edd691fe, - 0x235a3db7a94446301e666cafea5e12cb331f4a140" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4, - 0x49ed3be7f510e30e2462c517ad39038e493fc573c"; -} - -mul { - "prime: 23 prime: 1, 1" "0, 1" 28 inf; - "prime: 23 prime: 1, 1" "0, 1" 29 "0, 1"; - "prime: 23 primeproj: 1, 1" "0, 1" 28 inf; - "prime: 23 primeproj: 1, 1" "0, 1" 29 "0, 1"; - - "prime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 6277101735386680763835789423176059013767194773182842284080 - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; - "prime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 6277101735386680763835789423176059013767194773182842284081 - inf; - "prime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 6277101735386680763835789423176059013767194773182842284080 - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; - "prime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 6277101735386680763835789423176059013767194773182842284081 - inf; - - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 6277101735386680763835789423176059013767194773182842284080 - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 6277101735386680763835789423176059013767194773182842284081 - inf; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 6277101735386680763835789423176059013767194773182842284080 - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; - "niceprime: 6277101735386680763835789423207666416083908700390324961279 - primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 6277101735386680763835789423176059013767194773182842284081 - inf; - - "binpoly: 0x800000000000000000000000000000000000000c9 - bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - 5846006549323611672814742442876390689256843201586 - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0xd51fbc6c71a0094fa2cdd545b11c5c0c797324f1"; - "binpoly: 0x800000000000000000000000000000000000000c9 - bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - 5846006549323611672814742442876390689256843201587 - inf; - "binpoly: 0x800000000000000000000000000000000000000c9 - binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - 5846006549323611672814742442876390689256843201586 - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0xd51fbc6c71a0094fa2cdd545b11c5c0c797324f1"; - "binpoly: 0x800000000000000000000000000000000000000c9 - binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd" - "0x3f0eba16286a2d57ea0991168d4994637e8343e36, - 0x325f41d0ef702dc310254c42d65851a3b91471ac7" - 5846006549323611672814742442876390689256843201587 - inf; - - "binpoly: 0x800000000000000000000000000000000000000c9; bin: 1, 1" - "0x2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8, - 0x289070fb05d38ff58321f2e800536d538ccdaa3d9" - 5846006549323611672814741753598448348329118574063 - inf; - "binpoly: 0x800000000000000000000000000000000000000c9; binproj: 1, 1" - "0x2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8, - 0x289070fb05d38ff58321f2e800536d538ccdaa3d9" - 5846006549323611672814741753598448348329118574063 - inf; -} diff --git a/tests/gdsa b/tests/gdsa deleted file mode 100644 index 45df0b3..0000000 --- a/tests/gdsa +++ /dev/null @@ -1,242 +0,0 @@ -# $Id: gdsa,v 1.2 2004/04/08 01:36:16 mdw Exp $ -# -# Tests for abstract-group implementation of DSA - -sign { - # --- A simple and small test --- - - "prime { - 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, - 0x84d192cd06ae59691897fa409da6198d5269325d, - 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e - }" - sha - 0x1234 - "An example message" - 0x649b1058e0fe7ee849d3cb00b8ec3053ad0793b8 - 0x2718bf488b981992b164e664224dd00ca1ed4e1c - 0x5c085679fbfa9ee806781bdbd86a67dbf14df640; - - # --- The FIPS186-1 test vector --- - - "prime { - 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291, - 0xc773218c737ec8ee993b4f2ded30f48edace915f, - 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 - }" - sha - 0x2070b3223dba372fde1c0ffc7b2e3b498b260614 - "abc" - 0x358dad571462710f50e254cf1a376b2bdeaadfbf - 0x8bac1ab66410435cb7181f95b16ab97c92b341c0 - 0x41e2345f1f56df2458f426d155b4ba2db6dcd8c8; - - # --- A test I made up --- - - "prime { - 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7, - 0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9, - 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 - }" - sha - 0x23a252f60bae4907a8ed5b6203e2b1da32848cd9 - "A message signed with a 1024-bit DSA key." - 0x12ccb231683a3d9c13dca6fe882349537eebfd03 - 0x2a301061ac185440fbf595f8f7d894158b8d1897 - 0x51aedaa73cb8d47e07281d14dda5ea8c0ddf7503; - - # --- Elliptic curve test vectors --- - - "ec { nist-b163 }" sha 0x1234 - "An example message" - 0x649b1058e0fe7ee849d3cb00b8ec3053ad0793b8 - 0x12e2f4e865bf6e034712b4f2ba6f3c825452d6419 - 0x30e0d918fde3a33781f984b877f8501356b6fbae9; - - "ec { secp160r1 }" sha - 0xaa374ffc3ce144e6b073307972cb6d57b2a4e982 - "abc" - 0x7b012db7681a3f28b9185c8b2ac5d528decd52da - 0xce2873e5be449563391feb47ddcba2dc16379191 - 0x3480ec1371a091a464b31ce47df0cb8aa2d98b54; - - "ec { sect163k1 }" sha - 0x3a41434aa99c2ef40c8495b2ed9739cb2155a1e0d - "abc" - 0xa40b301cc315c257d51d442234f5aff8189d2b6c - 0x994d2c41aa30e52952aea8462370471b2b0a34ac - 0x152f95ca15da1997a8c449e00cd2aa2accb988d7f; - - ## This one's from P1363: - ## http://grouper.ieee.org/groups/1363/P1363/testvector.txt - "ec { ansi-c2tnb191v1 }" sha - 0x340562e1dda332f9d2aec168249b5696ee39d0ed4d03760f - "abc" - 0x3eeace72b4919d991738d521879f787cb590aff8189d2b69 - 0x038e5a11fb55e4c65471dcd4998452b1e02d8af7099bb930 - 0x0c9a08c34468c244b4e5d6b21b3c68362807416020328b6e; - - "ec { nist-p256 }" sha256 - 0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa - "An example message" - 0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c - 0xb30f954bfb624041e56f09ece884c17c74f866c24149bba0712303a9530142a6 - 0x1076bd32f298aaffa8c6242d881d928b1c4e0f5ad7e8ce3c4d815fe348a9666a; - - # --- Test for over-long hash --- - - "ec { sect131r1 }" sha - 0x85bd9fd28a7e7f915891208fbb2b05c0 - "An example message" - 0xee98d38c001731403af6fbf77356f8ea - 0x1cba36e768c0247d537a744b7ea62e3b9 - 0x216e5d02a0b1fb11d6d2fc4b383dcb168; -} - -verify { - # --- A simple and small test --- - - "prime { - 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, - 0x84d192cd06ae59691897fa409da6198d5269325d, - 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e - }" - sha - 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 - "An example message" - 0x2718bf488b981992b164e664224dd00ca1ed4e1c - 0x5c085679fbfa9ee806781bdbd86a67dbf14df640 - 0; - - "prime { - 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, - 0x84d192cd06ae59691897fa409da6198d5269325d, - 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e - }" - sha - 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 - "An example messag" - 0x2718bf488b981992b164e664224dd00ca1ed4e1c - 0x5c085679fbfa9ee806781bdbd86a67dbf14df640 - -1; - - "prime { - 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, - 0x84d192cd06ae59691897fa409da6198d5269325d, - 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e - }" - sha - 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 - "An example message" - 0x2718bf488b981992b164e664224dd00ca1ed4e1c - 0x5c085679fbfa9ee806781bdbd86a67dbf14df641 - -1; - - "prime { - 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, - 0x84d192cd06ae59691897fa409da6198d5269325d, - 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e - }" - sha - 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 - "An example message" - 0x2718bf488b981992b164e664224dd00ca1ed4e1c - 0xe0d9e94702a8f8511f10161c7610816943b7289d - -1; - - # --- The FIPS186-1 test vector --- - - "prime { - 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291, - 0xc773218c737ec8ee993b4f2ded30f48edace915f, - 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 - }" - sha - 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 - "abc" - 0x8bac1ab66410435cb7181f95b16ab97c92b341c0 - 0x41e2345f1f56df2458f426d155b4ba2db6dcd8c8 - 0; - - # --- A test I made up --- - - "prime { - 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7, - 0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9, - 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 - }" - sha - 0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074 - "A message signed with a 1024-bit DSA key." - 0x2a301061ac185440fbf595f8f7d894158b8d1897 - 0x51aedaa73cb8d47e07281d14dda5ea8c0ddf7503 - 0; - - # --- Elliptic curve test vectors --- - - "ec { nist-b163 }" sha - "0x1e7d847d0331a794852ded2b96c71d82e61f9bb4c, - 0x1a2370ab2e63f5aa8f348fbe83c0415a7d8ee207b" - "An example message" - 0x12e2f4e865bf6e034712b4f2ba6f3c825452d6419 - 0x30e0d918fde3a33781f984b877f8501356b6fbae9 - 0; - - "ec { secp160r1 }" sha - "0x51b4496fecc406ed0e75a24a3c03206251419dc0, - 0xc28dcb4b73a514b468d793894f381ccc1756aa6c" - "abc" - 0xce2873e5be449563391feb47ddcba2dc16379191 - 0x3480ec1371a091a464b31ce47df0cb8aa2d98b54 - 0; - - "ec { sect163k1 }" sha - "0x037d529fa37e42195f10111127ffb2bb38644806bc, - 0x0447026eee8b34157f3eb51be5185d2be0249ed776" - "abc" - 0x994d2c41aa30e52952aea8462370471b2b0a34ac - 0x152f95ca15da1997a8c449e00cd2aa2accb988d7f - 0; - - ## This one's from P1363: - ## http://grouper.ieee.org/groups/1363/P1363/testvector.txt - "ec { ansi-c2tnb191v1 }" sha - "0x5de37e756bd55d72e3768cb396ffeb962614dea4ce28a2e7, - 0x55c0e0e02f5fb132caf416ef85b229bbb8e1352003125ba1" - "abc" - 0x038e5a11fb55e4c65471dcd4998452b1e02d8af7099bb930 - 0x0c9a08c34468c244b4e5d6b21b3c68362807416020328b6e - 0; - - "ec { nist-p256 }" sha256 - "0xcc2aecbc5c5f6d72cd7b937279d72a732abcf880ea47e012ebec77ddbca6ed40, - 0x90f99cd799abc0ea571d0e02bad80f8323050b1adbdbff50060b6e1e6ebd8611" - "An example message" - 0xb30f954bfb624041e56f09ece884c17c74f866c24149bba0712303a9530142a6 - 0x1076bd32f298aaffa8c6242d881d928b1c4e0f5ad7e8ce3c4d815fe348a9666a - 0; - - # --- Test for over-long hash --- - - "ec { sect131r1 }" sha - "0x2218ba2b57a7821be97c0015b797d82fe, 0x666aed14fd7a2abf867c6fa222ab26fcc" - "An example message" - 0x1cba36e768c0247d537a744b7ea62e3b9 - 0x216e5d02a0b1fb11d6d2fc4b383dcb168 - 0; - - "ec { sect131r1 }" sha - "0x2218ba2b57a7821be97c0015b797d82fe, 0x666aed14fd7a2abf867c6fa222ab26fcc" - "An example messag" - 0x1cba36e768c0247d537a744b7ea62e3b9 - 0x216e5d02a0b1fb11d6d2fc4b383dcb168 - -1; - - "ec { nist-b163 }" sha512 - "0x385a32536d1cb46d10cf3034a3dd39eb25e4f5123, - 0x29ee1edfa37d0f306c4da17b8d883f01ce3be4d46" - "qpwmoeqpofaosdaspdpqoweopdoagnqornifnasd" - 0x0231b6a807f6af1aee0598768b3fabb863d14a7f8d - 0x01c2f638e9dffe03b562e48ca4e1a380cf8c3055f1 - 0; -} diff --git a/tests/gf b/tests/gf deleted file mode 100644 index 88d94cd..0000000 --- a/tests/gf +++ /dev/null @@ -1,91 +0,0 @@ -# $Id$ -# -# Test cases for higher-level binary poly arithmetic. - -add { - 0 0 0; - 1 1 0; - 1 2 3; - 4 5 1; - 0x7fb838a8a0a95046b9d9d9fb4440f7bb - 0xc1a7bd3b4e853fc92d4e1588719986aa - 0xbe1f8593ee2c6f8f9497cc7335d97111; - 0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b21 - 0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b22 3; -} - -mul { - 0 0 0; - 1 0 0; - 0 1 0; - 1 1 1; - 0x7fb838a8a0a95046b9d9d9fb4440f7bb - 0xc1a7bd3b4e853fc92d4e1588719986aa - 0x207ccad257b4ed64447158315bfb9aca5cbc5622cfb8fcbb1380eea1bc5c624e; - 0xc1a7bd3b4e853fc92d4e1588719986aa - 0x283ed59f1226dcefa7ff0ef87ceff5d5 - 0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b22; - 0xbe1f8593ee2c6f8f9497cc7335d97111 - 0x35a8e33503b3695be00528f8b82db931 - 0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b21; -} - -sqr { - 0 0; - 1 1; - 3 5; - 0x7fb838a8a0a95046b9d9d9fb4440f7bb - 0x1555454005404440440044411100101445415141514155451010100055154545; - 0x01f081e69f45d3254530766ab98d55fa612c7bb27ea31bc2621d894be9c0b196b3 - 0x0155004001541441551011510504111011050015141444454140511111554414010450154545041554440501455004140401514041104554415000450141144505; -} - -div { - 0 1 0 0; - 0x207ccad257b4ed64447158315bfb9aca5cbc5622cfb8fcbb1380eea1bc5c624e - 0x7fb838a8a0a95046b9d9d9fb4440f7bb - 0xc1a7bd3b4e853fc92d4e1588719986aa 0; - 0x6e0e2a282a5411ae76767ed1103deef069ef4ed3a14ff24b - 0x5385621c6661aaa35a24150d2c08332e - 0x01c2334cc957151dc7 - 0x398c4111da6d06cdf3d83704ee403101; -} - -exp { - 4 0 1; - 4 1 4; - 0x7 2 0x15; - 3 563 0xf000f000f000f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000f000f000f; -} - -irred { - 0 0; - 1 0; - 2 1; - 0xc1a7bd3b4e853fc92d4e1588719986aa 0; - 0x800000000000000000000000000000000000000c9 1; - 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001 1; -} - -gcd { - 0xc1a7bd3b4e853fc92d4e1588719986aa - 0xbe1f8593ee2c6f8f9497cc7335d97111 - 3 - 0x283ed59f1226dcefa7ff0ef87ceff5d5 - 0x35a8e33503b3695be00528f8b82db931; - 0xbe1f8593ee2c6f8f9497cc7335d97111 - 0xc1a7bd3b4e853fc92d4e1588719986aa - 3 - 0x35a8e33503b3695be00528f8b82db931 - 0x283ed59f1226dcefa7ff0ef87ceff5d5; - 0x800000000000000000000000000000000000000c9 - 4 - 1 - 1 - 0x20000000000000000000000000000000000000032; - 0x800000000000000000000000000000000000000c9 - 0x3f0eba16286a2d57ea0991168d4994637e8343e36 - 1 - 0xa17e704470d80cb5a78f295db0ce543dda16a169 - 0x3c8c172e24598e90b9542e6b8f6571f54be572b50; -} diff --git a/tests/gfn b/tests/gfn deleted file mode 100644 index 6586d50..0000000 --- a/tests/gfn +++ /dev/null @@ -1,34 +0,0 @@ -# $Id: gfn,v 1.2 2004/04/02 08:41:45 mdw Exp $ -# -# Normal basis conversions - -gfn { - 0x800000000000000000000000000000000000000c9 - 0x715169c109c612e390d347c748342bcd3b02a0bef - 0 0; - - 0x800000000000000000000000000000000000000c9 - 0x715169c109c612e390d347c748342bcd3b02a0bef - 1 - 0x7ffffffffffffffffffffffffffffffffffffffff; - - 0x800000000000000000000000000000000000000c9 - 0x715169c109c612e390d347c748342bcd3b02a0bef - 0x2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8 - 0x05679b353caa46825fea2d3713ba450da0c2a4541; - - 0x20000000000000000000000000000000000000004000000000000000001 - 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9 - 0x066647ede6c332c7f8c0923bb58213b333b20e9ce4281fe115f7d8f90ad - 0x1a003e0962d4f9a8e407c904a9538163adb825212600c7752ad52233279; - - 0x20000000000000000000000000000000000000004000000000000000001 - 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9 - 0x0fac9dfcbac8313bb2139f1bb755fef65bc391f8b36f8f8eb7371fd558b - 0x18b863524b3cdfefb94f2784e0b116faac54404bc9162a363bab84a14c5; - - 0x20000000000000000000000000000000000000004000000000000000001 - 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9 - 0x1006a08a41903350678e58528bebf8a0beff867a7ca36716f7e01f81052 - 0x04925df77bd8b8ff1a5ff519417822bfedf2bbd752644292c98c7af6e02; -} diff --git a/tests/gfreduce b/tests/gfreduce deleted file mode 100644 index c7c474a..0000000 --- a/tests/gfreduce +++ /dev/null @@ -1,81 +0,0 @@ -# $Id$ -# -# Test efficient polynomial reduction - -reduce { - 0x10000000 - 0x4509823098098435 - 0x8098435; - 0x100000000000000050002 - 0x4509823098098435 - 0x4509823098098435; - 0x100000000000000050002 - 0x450982309809843545609843098560803495 - 0x144f98a2f5cbc4773cfd; - 0xb2ca471b0867d5fae2e4f27a2d2706da - 0xf254423fef93d5d7a76ecf22c656c1352c53257875945d33 - 0x582f783fc210f72814780e69b0bd29ff; -} - -modexp { - 0x20000000000000000000000000000000000000000000000000000000000001001 - 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 0 - 1; - 0x20000000000000000000000000000000000000000000000000000000000001001 - 0x02 - 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 1; - 0x20000000000000000000000000000000000000000000000000000000000001001 - 0x435932098459080438094509845 - 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 1; - 0x10000000000000000000000000000000000000000003 - 0x02 - 0x0fffffffffffffffffffffffffffffffffffffffffff - 1; - 0x10000000000000000000000000000000000000000003 - 0x34235950984598345900983409845690805680985 - 0x0fffffffffffffffffffffffffffffffffffffffffff - 1; - - 0x800000000000000000000000000000000000000c9 - 0x3f0eba16286a2d57ea0991168d4994637e8343e36 - -1 - 0x3c8c172e24598e90b9542e6b8f6571f54be572b50; - 0x800000000000000000000000000000000000000c9 - 0x3c8c172e24598e90b9542e6b8f6571f54be572b50 - 342345 - 0x3521fe2666efe92ca4eb160a286e0fd9427b84a62; - 0x800000000000000000000000000000000000000c9 - 0x3f0eba16286a2d57ea0991168d4994637e8343e36 - -342345 - 0x3521fe2666efe92ca4eb160a286e0fd9427b84a62; -} - -sqrt { - 0x20000000000000000000000000000000000000000000000000000000000001001 - 0x1f081e69f45d3254530766ab98d55fa612c7bb27ea31bc2621d894be9c0b196b3 - 0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa; - 0x10000000000000000000000000000000000000000003 - 0x4594094509835690805698083560980459903450984 - 0x820291881a244a02840a2f8ece3f23f88f38bf0b3a; -} - -halftrace { - 0x20000000000000000000000000000000000000000000000000000000000001001 - 0x174e65c7d14a8ec286df8c7df17662f13f1d3563f13c8c63f23f5d0bd5d1b45cd - 0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9d; -} - -quadsolve { - 0x20000000000000000000000000000000000000000000000000000000000001001 - 0x174e65c7d14a8ec286df8c7df17662f13f1d3563f13c8c63f23f5d0bd5d1b45cd - 0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c; - 0x10000000000000000000000000000000000000000003 - 0x3b818b447e90713da04f13c3b07cb5e2681d08e4700 - 0x27aa17c97dfa80bbdef9f91b243c6e6ddba1a223cac; - 0x800000000000000000000000000000000000000c9 - 0x158fe327cc763a2fd7371ee80641ed1871a32aaa8 - 0x29ab0d7da05ffc3f1b3f97ac10e2092694aadbb7c; -} diff --git a/tests/gfx b/tests/gfx deleted file mode 100644 index b26433d..0000000 --- a/tests/gfx +++ /dev/null @@ -1,529 +0,0 @@ -# Test vectors for low-level GF functions -# -# $Id: gfx,v 1.2 2004/03/21 22:52:06 mdw Exp $ - -# --- Addition (and subtraction) --- - -add { - # --- Simple sanity tests --- - - 01 01 00; - 02 02 00; - 03 01 02; - - # --- Random data tests --- - - 7fb838a8a0a95046b9d9d9fb4440f7bb - c1a7bd3b4e853fc92d4e1588719986aa - be1f8593ee2c6f8f9497cc7335d97111; - 8d68905434b020ccb849e17a03a5c441 - d2a104aaf523699c1cc7a93174d21d9c - 5fc994fec1934950a48e484b7777d9dd; - 027aa17c97dfa80bbdef9f91b243c6e6 - ddba1a223cad8a39e9c986879ad21b75 - dfc0bb5eab722232542619162891dd93; - d668328b2594570198fd840b4783f5d9 - f474e9ef071c418acf1f71b9cccdd179 - 221cdb642288168b57e2f5b28b4e24a0; - 509e024b27fb8b3655da3938d0c04f92 - 3fa219832f73843c0ae8c4f4715f633c - 6f3c1bc808880f0a5f32fdcca19f2cae; - 13e8b9d83c66bc5fa56e2debbab3c9c2 - 6bb190b76e090abd7f6375a6921ad17e - 7859296f526fb6e2da0d584d28a918bc; - 3c98c1fd7d6e4ff9adae43a38ed0f2b3 - 101f88d732a51bbe40080cabd06002 - 3c88de75aa5ceae213ee4baf250092b1; - 2774d74b7453e63c2d314e0be52eaf79 - 54c0dc1a0bedbafcb0b707fe5e496a20 - 73b40b517fbe5cc09d8649f5bb67c559; - 75b9d1662c48f8c40ee4e9b3138a0b59 - 0ca3e9d4c75a6e2b493d7efb8554e9f8 - 791a38b2eb1296ef47d9974896dee2a1; - 501591c68468a7d8ecfcae3f419ecb52 - b0ad24cd246361f779e8317e94977c57 - e0b8b50ba00bc62f95149f41d509b705; - 6fa69209a292924f04fb5b3469a1068b - d9a06e9ac90f02ad095ff84f30a9addd - b606fc936b9d90e20da4a37b5908ab56; - ce596f2830ab988dfa7dc0add68214af - 860c30b9a27c7b2759666dd71ec578c3 - 48555f9192d7e3aaa31bad7ac8476c6c; - 862361325b5f7a6b506b948d55697ce3 - 95142973169fbae5410a22bb88ca63ee - 133748414dc0c08e1161b636dda31f0d; - 237495a82a6755689df073af2a56f88c - ab46613ddf7787fd1be42272fcb1be44 - 8832f495f510d295861451ddd6e746c8; - 6b2d8d2b513277cfb03d8a5731234a3d - 9cc41fbd7189a3b5b0ff2f3746eb9bc6 - f7e9929620bbd47a00c2a56077c8d1fb; - af7baf1a8ce5d42eca4353de181d085a - c59bde6136dda59a839605252d1dd390 - 6ae0717bba3871b449d556fb3500dbca; - 566a7c0f9adc5a021c1759e2c80708c0 - 28d1c20f2b8613b5e1ba8e3005aef30f - 7ebbbe00b15a49b7fdadd7d2cda9fbcf; - a7d716d198bf6bb3d32ba364f722de52 - 4c9a1fa66d2d0cf7935d45e83b9ce326 - eb4d0977f59267444076e68cccbe3d74; - 310d8bb131c4bed327529185c4d46db8 - 2742ea95019b5f186c3c848744743d4a - 164f6124305fe1cb4b6e150280a050f2; - 70f5bfbf5f18a3deef4230b875b3a0af - 93c9240145720297b96a404941792a21 - e33c9bbe1a6aa149562870f134ca8a8e; - 1ff7c9eaebd3b76791632b609a962992 - bc3aca2e99d965238d8433eafd717279 - a3cd03c4720ad2441ce7188a67e75beb; - 3d1693836d0964dea42c5e80a4307b6c - aed5dcd2e9e918e0ff9577f5ceb66256 - 93c34f5184e07c3e5bb929756a86193a; - 35706029aec609b55c48ab09df59744e - 6d9b5b4dbeb1779580cba9bbc9fb8921 - 58eb3b6410777e20dc8302b216a2fd6f; - 7a166f842cc6c36c09508e2b23dbad97 - 01e3fc1cacc040e96217a7281a4273d2 - 7bf59398800683856b4729033999de45; - 510ce80a4ab0f9eae5f6c3281e7506c5 - 06351138a1ecb6be56a84f1b28a26368 - 5739f932eb5c4f54b35e8c3336d765ad; - 31bfc6590de44898c40c31bb3aaddebc - 82b37993094c9ff6498c55ba1cced0f8 - b30cbfca04a8d76e8d80640126630e44; - d00d48a90eb9e89586cc3566b28fa5ea - 0f502f973c2f17ad79543b20a92f2905 - df5d673e3296ff38ff980e461ba08cef; - df63dead9d7aea0d3fca68123b0812ae - ae059fd909978bc6b8824b04e113fa2a - 7166417494ed61cb87482316da1be884; - 4c982bd2b93a027fd08ad69227a51506 - bdc1112c061be0756685473011c61067 - f1593afebf21e20ab60f91a236630561; - dc241c84816a1a50a7ad21519e6abd3a - f2c4d8d96bf32d999fdc7c37cfddac67 - 2ee0c45dea9937c938715d6651b7115d; - a466ee3984566e4947a28704ecd99d2f - 0a5e90153ae473c9bee43aafaec08446 - ae387e2cbeb21d80f946bdab42191969; - 8698e5d4eede21f8d4791d69fc4cfb22 - 7b4bb531b633dfcb80d9bd35e10d4f6b - fdd350e558edfe3354a0a05c1d41b449; - 4d2462e835a51ee5be30ea2bc6abbb1b - fb36217f8dd0fe234bb7dcb778130156 - b6124397b875e0c6f587369cbeb8ba4d; - abf5c76c26bf952d64667f5049bbe6b5 - 436fbd0ad52336b0c9d2987ac79d2909 - e89a7a66f39ca39dadb4e72a8e26cfbc; - 8943b34ab9bc6f6839c09a9852492238 - 38b2304265ac16c80f84be3d61a82628 - b1f18308dc1079a0364424a533e10410; - ae2730b3374140b33de67be248766cc7 - 1831ce84d756a4bda1c1ee22ed047d61 - b616fe37e017e40e9c2795c0a57211a6; - 4a87ef0f6bc691cab6d79253876ca89e - c0c2f4c479ffc90aeafe0598a4ac4d4b - 8a451bcb123958c05c2997cb23c0e5d5; - 63b2aad38a2d3b4cf681d892ed460110 - d707531874bbc8fa22a49fd26142c631 - b4b5f9cbfe96f3b6d42547408c04c721; - f44ef4d8cd19e4f6f6264c59360de94e - eb619a0c5fb3c490d382ff4a5d47a0f9 - 1f2f6ed492aa206625a4b3136b4a49b7; - 786fa5572011847269ba3f51db1226 - a1c8ac92fa365013326e0daac2dce7b9 - a1b0c337ad1641974007b7959307f59f; -} - -mul { - # --- Simple sanity tests --- - - 00 05 00; - 01 05 05; - 05 01 05; - 05 00 00; - - # --- Random data tests --- - - 7fb838a8a0a95046b9d9d9fb4440f7bb - c1a7bd3b4e853fc92d4e1588719986aa - 207ccad257b4ed64447158315bfb9aca5cbc5622cfb8fcbb1380eea1bc5c624e; - 8d68905434b020ccb849e17a03a5c441 - d2a104aaf523699c1cc7a93174d21d9c - 6c75a24ff82d63e8f9425d862be997fd7517511b2563189a6f0a238b33e60a9c; - 027aa17c97dfa80bbdef9f91b243c6e6 - ddba1a223cad8a39e9c986879ad21b75 - 019d5567c392730cf1fbc627f1de7ff20438e649e5ba7e7299fcea4ad4c7ac5e; - d668328b2594570198fd840b4783f5d9 - f474e9ef071c418acf1f71b9cccdd179 - 4a7d1a3b7b904b1b135cb89e6f37a38d7f20fcc9bd7b9ec9f0c38114d2a742e1; - 509e024b27fb8b3655da3938d0c04f92 - 3fa219832f73843c0ae8c4f4715f633c - 0c0ff0782f813600eda5b73c0d2deaf072ed8b9e98e94991bd2578b776063fb8; - 13e8b9d83c66bc5fa56e2debbab3c9c2 - 6bb190b76e090abd7f6375a6921ad17e - 0626e9a14f2ada51ad47ae2385248d361142636fed5f062be9fa0a0567f14c7c; - 3c98c1fd7d6e4ff9adae43a38ed0f2b3 - 101f88d732a51bbe40080cabd06002 - 03cb092534c593a9f834c21f1af0da8e604c416ec14e3fca1a72ba4c2b4566; - 2774d74b7453e63c2d314e0be52eaf79 - 54c0dc1a0bedbafcb0b707fe5e496a20 - 0b2dd510554c5442d5871586392f81d08322aa0cf052f64ee507d59ef730b520; - 75b9d1662c48f8c40ee4e9b3138a0b59 - 0ca3e9d4c75a6e2b493d7efb8554e9f8 - 024ff62a8d33d8c51560088e304cc9b13ccec97899ba476083b86f8c1dc28fb8; - 501591c68468a7d8ecfcae3f419ecb52 - b0ad24cd246361f779e8317e94977c57 - 2728b02f09e5cfc78d1b5e45d0b65d58aa353e8e5a928dc80a3fd523b464291e; - 6fa69209a292924f04fb5b3469a1068b - d9a06e9ac90f02ad095ff84f30a9addd - 29e8250c13db619580291b6d03317cf82d3f97c58aa1dc247c4d4ad25870b80f; - ce596f2830ab988dfa7dc0add68214af - 860c30b9a27c7b2759666dd71ec578c3 - 658c3e0257c6986e4d0b7fd1c2296182f48c395f7a01acdb623702a83c0be9b1; - 862361325b5f7a6b506b948d55697ce3 - 95142973169fbae5410a22bb88ca63ee - 49e7469f9f53f214425455d15b9b5cc6309617f18db3e02b98aabe1b134dbd72; - 237495a82a6755689df073af2a56f88c - ab46613ddf7787fd1be42272fcb1be44 - 14a2fbfb8b9621a60325ba6fc7c979b0caa46c7a5ffb865d01859f058621c930; - 6b2d8d2b513277cfb03d8a5731234a3d - 9cc41fbd7189a3b5b0ff2f3746eb9bc6 - 31ff31cfbb97615558ec4becb92036b6b8715ab6df7ed6dc18caff6e0641d24e; - af7baf1a8ce5d42eca4353de181d085a - c59bde6136dda59a839605252d1dd390 - 7e281956a0ae84282a4a600a9a434bcca6f89a9a661f03ac47dcd20ef2b066a0; - 566a7c0f9adc5a021c1759e2c80708c0 - 28d1c20f2b8613b5e1ba8e3005aef30f - 0845bd0d5a46401395876a7992ee9762842ea8d7202222e29b973a042a703c40; - a7d716d198bf6bb3d32ba364f722de52 - 4c9a1fa66d2d0cf7935d45e83b9ce326 - 2e09cac5254876c45a7dacddd71f13b394ca8ab95413ab681f554c50737839ac; - 310d8bb131c4bed327529185c4d46db8 - 2742ea95019b5f186c3c848744743d4a - 06baa3a8c8864b5ea1f998b6138db08924f3a49ddf1ecc22fa93110323aac0b0; - 70f5bfbf5f18a3deef4230b875b3a0af - 93c9240145720297b96a404941792a21 - 3fc325d1e5c637ab818172e3fdb51be97a28903ee232125797ead652b391734f; - 1ff7c9eaebd3b76791632b609a962992 - bc3aca2e99d965238d8433eafd717279 - 0d78c92f0d674c76fd9e71ace29b1ca58da8a67530a148bcf8815b395de46ee2; - 3d1693836d0964dea42c5e80a4307b6c - aed5dcd2e9e918e0ff9577f5ceb66256 - 185d9d9d173a78a2ea8a86cef12ac9a560f5c1fd96a3e40d47f2d34798d02ea8; - 35706029aec609b55c48ab09df59744e - 6d9b5b4dbeb1779580cba9bbc9fb8921 - 0aa132382fb96e788f85a52888a8ef7fa645e17dfaaf35444566c2a56584c38e; - 7a166f842cc6c36c09508e2b23dbad97 - 01e3fc1cacc040e96217a7281a4273d2 - 567d64a30f28d71578a9ced5624a950fe065d706cf3318c80c3883f126c51e; - 510ce80a4ab0f9eae5f6c3281e7506c5 - 06351138a1ecb6be56a84f1b28a26368 - 01e80b50adeebb3790d5249eb4170d093b88ab1d42d0737d3dad6825e181f0c8; - 31bfc6590de44898c40c31bb3aaddebc - 82b37993094c9ff6498c55ba1cced0f8 - 18a13563df977554b9d470e4c5009f7ec1c62f561a9cb2041a51e7af81e2f8a0; - d00d48a90eb9e89586cc3566b28fa5ea - 0f502f973c2f17ad79543b20a92f2905 - 048955ee72a928a69b16cc80502568ece68198c8947935283c725a2e6f00c842; - df63dead9d7aea0d3fca68123b0812ae - ae059fd909978bc6b8824b04e113fa2a - 706606ae02e140bbf3783da276f47110834defb48e89270797e86251e27369ec; - 4c982bd2b93a027fd08ad69227a51506 - bdc1112c061be0756685473011c61067 - 283989fcc502efa3d0006b67465f3ebe7950cac8d54daf45215e09bd6058ea52; - dc241c84816a1a50a7ad21519e6abd3a - f2c4d8d96bf32d999fdc7c37cfddac67 - 4ebfbaf107e1e74583f1a0c6de06f2a4c230c1a96329d8bac1d95d122ce8a266; - a466ee3984566e4947a28704ecd99d2f - 0a5e90153ae473c9bee43aafaec08446 - 044e0764b72ad37e86d87cca3b32c4d6797a7a9b2e8ab414e0c33617d2113922; - 8698e5d4eede21f8d4791d69fc4cfb22 - 7b4bb531b633dfcb80d9bd35e10d4f6b - 3c8785b738a800087fb26dc2562ebd676188a1f5e3b60d51463172a5ef5906b6; - 4d2462e835a51ee5be30ea2bc6abbb1b - fb36217f8dd0fe234bb7dcb778130156 - 3a1f7deaeed3275707c611b83b64b4514d9b8508ed4b0827a7001be9488af62a; - abf5c76c26bf952d64667f5049bbe6b5 - 436fbd0ad52336b0c9d2987ac79d2909 - 2b38ad58100db6e6bffc52c6e7622581cc5daf65c0b4f7b87dab8313af786e1d; - 8943b34ab9bc6f6839c09a9852492238 - 38b2304265ac16c80f84be3d61a82628 - 1daa464b09e5db4bef2c404c1be1fb6d6e0c5911ee10a1d7eba409e33b26c6c0; - ae2730b3374140b33de67be248766cc7 - 1831ce84d756a4bda1c1ee22ed047d61 - 0f8cb866e66f56fdfd530784d441c8b37d6e0b2a87e3ea6a0a2d6f4387e076e7; - 4a87ef0f6bc691cab6d79253876ca89e - c0c2f4c479ffc90aeafe0598a4ac4d4b - 37d54041b0e7d641ee3495897524f1ef4a4dad9671261e4aa03fba0bfadb0cd2; - 63b2aad38a2d3b4cf681d892ed460110 - d707531874bbc8fa22a49fd26142c631 - 2e25fc4f13fd3839c0698ca373d24ca2bfe572ad3ae46a50c1294237d30c5210; - f44ef4d8cd19e4f6f6264c59360de94e - eb619a0c5fb3c490d382ff4a5d47a0f9 - 5f20a07a81d4ed9f3d1fd9fef61318d01a58ea810b12ae3976dbe6c2406b2a9e; - 786fa5572011847269ba3f51db1226 - a1c8ac92fa365013326e0daac2dce7b9 - 336397c17a1fde4e90cbb9113a5fcd48239d39fee0807e66f8622d97b144b6; -} - -sqr { - # --- Simple sanity tests --- - - 00 00; - 01 01; - 03 05; - - # --- Random data tests --- - - 7fb838a8a0a95046b9d9d9fb4440f7bb - 1555454005404440440044411100101445415141514155451010100055154545; - c1a7bd3b4e853fc92d4e1588719986aa - 5001441545510545105440110555504104511054011140401501414140144444; - 8d68905434b020ccb849e17a03a5c441 - 4051144041001110051045000400505045401041540115440005441150101001; - d2a104aaf523699c1cc7a93174d21d9c - 5104440100104444551104051441415001505015444105011510510401514150; - 027aa17c97dfa80bbdef9f91b243c6e6 - 04154444011550411551554440004545515455415541014504100550145414; - ddba1a223cad8a39e9c986879ad21b75 - 5151454401440404055044514044054154415041401440154144510401451511; - d668328b2594570198fd840b4783f5d9 - 5114144005044045041141101115000141405551401000451015400555115141; - f474e9ef071c418acf1f71b9cccdd179 - 5510151054415455001501501001404450550155150145415050505151011541; - 509e024b27fb8b3655da3938d0c04f92 - 1100415400041045041555454045051411115144054105405100500010554104; - 3fa219832f73843c0ae8c4f4715f633c - 0555440401414005045515054010055000445440501055101501115514050550; - 13e8b9d83c66bc5fa56e2debbab3c9c2 - 0105544045415140055014144550115544111454045154454544450550415004; - 6bb190b76e090abd7f6375a6921ad17e - 1445450141004515145400410044455115551405151144144104014451011554; - 3c98c1fd7d6e4ff9adae43a38ed0f2b3 - 0550414050015551155114541055554144514454100544054054510055044505; - 101f88d732a51bbe40080cabd06002 - 010001554040511505044411014545541000004000504445510014000004; - 2774d74b7453e63c2d314e0be52eaf79 - 0415151051151045151011055414055004510501105400455411045444551541; - 54c0dc1a0bedbafcb0b707fe5e496a20 - 1110500051500144004554514544555045004515001555541154104114440400; - 75b9d1662c48f8c40ee4e9b3138a0b59 - 1511454151011414045010405540501000545410544145050105404400451141; - 0ca3e9d4c75a6e2b493d7efb8554e9f8 - 50440554415110501511441454044510410551155455454011111054415540; - 501591c68468a7d8ecfcae3f419ecb52 - 1100011141015014401014404415514054505550445405551001415450451104; - b0ad24cd246361f779e8317e94977c57 - 4500445104105051041014051401551515415440050115544110411515501115; - 6fa69209a292924f04fb5b3469a1068b - 1455441441040041440441044104105500105545114505101441440100144045; - d9a06e9ac90f02ad095ff84f30a9addd - 5141440014544144504100550004445100411155554010550500444144515151; - ce596f2830ab988dfa7dc0add68214af - 5054114114550440050044454140405155441551500044515114400401104455; - 860c30b9a27c7b2759666dd71ec578c3 - 4014005005004541440415501545041511411414145151150154501115405005; - 862361325b5f7a6b506b948d55697ce3 - 4014040514010504114511551544144511001445411040511111144115505405; - 95142973169fbae5410a22bb88ca63ee - 4111011004411505011441554544541110010044040445454040504414055454; - 237495a82a6755689df073af2a56f88c - 0405151041114440044414151111144041515500150544550444111455404050; - ab46613ddf7787fd1be42272fcb1be44 - 4445101414010551515515154015555101455410040415045550450145541010; - 6b2d8d2b513277cfb03d8a5731234a3d - 1445045140510445110105041515505545000551404411150501040510440551; - 9cc41fbd7189a3b5b0ff2f3746eb9bc6 - 4150501001554551150140414405451145005555045505151014544541455014; - af7baf1a8ce5d42eca4353de181d085a - 4455154544550144405054115110045450441005110551540140015100401144; - c59bde6136dda59a839605252d1dd390 - 5011414551541401051451514411414440054114001104110451015151054100; - 566a7c0f9adc5a021c1759e2c80708c0 - 1114144415500055414451501144000401500115114154045040001500405000; - 28d1c20f2b8613b5e1ba8e3005aef30f - 0440510150040055044540140105451154014544405405000011445455050055; - a7d716d198bf6bb3d32ba364f722de52 - 4415511501145101414045551445450551050445440514105515040451541104; - 4c9a1fa66d2d0cf7935d45e83b9ce326 - 1050414401554414145104510050551541051151101154400545415054050414; - 310d8bb131c4bed327529185c4d46db8 - 0501005140454501050150104554510504151104410140115010511014514540; - 2742ea95019b5f186c3c848744743d4a - 0415100454444111000141451155014014500550401040151010151005511044; - 70f5bfbf5f18a3deef4230b875b3a0af - 1500551145554555115501404405515454551004050045401511450544004455; - 93c9240145720297b96a404941792a21 - 4105504104100001101115040004411545411444100010411001154104440401; - - # --- Regression --- - - 01f081e69f45d3254530766ab98d55fa612c7bb27ea31bc2621d894be9c0b196b3 - 0155004001541441551011510504111011050015141444454140511111554414010450154545041554440501455004140401514041104554415000450141144505; -} - -div { - # --- Random data tests --- - - 6e0e2a282a5411ae76767ed1103deef069ef4ed3a14ff24b - 5385621c6661aaa35a24150d2c08332e - 01c2334cc957151dc7 - 398c4111da6d06cdf3d83704ee403101; - 785e80e9711074a8412abd48da670731ea - 4c5d348767009ea85f25f7ea02ef7be7 - 01c4 - 0b17de61cc808487285b72f14fa23336; - d921e3736edd0d111e56c51cf4e4c343cd690dbaeb34194592ca2b80cc7e - c205a3c1faecfa3a74f7838e20c5678f - 012492f38367090dbc739e8a15c414 - 34570d4431e79cc4d3ff2a583c3a56b2; - 06e7333745e54278092c9fee2cd95768e4e343013e48fe88660cbdce - 10f02ba313d1c57d8cf04fa2e760f19a - 6c1708dd11c7305e9d0a1974 - 0dd6757486f880c40590ed673c22ddc6; - bf4adc5bd775679384d763216edc12157afec6eb4d2435a2fc793183fafadc - 9ff35b5c87471da1e56600203f11ae65 - 014fd82ad3ab0ef9bda71f5d88ab3fe1 - 3b599b787383608d59ba518513d7d0d9; - 0377c80101957a0c0044ee9ae96e8a7cc785a629c1 - 7ca5d5ef2a981b83417db75f9616e0ff - 0b71080c88 - 2d21297ee7c68552c11b6199fa1d55b9; - 1c92d440eb73a2cc5891f1881dc9d366271416b21947d3a98eb4dc5692 - 7afdf70aa9d3f0a02b238d08d14fb1d9 - 4c61f24d2263168cc50b2d3126 - 2674528444adc656d5bfe3915849a064; - 0ae3f419ecb52b0ad24cd246361f779e8317e94977c576fa69209a292924f04f - b5b3469a1068bd9a06e9ac90f02ad095 - 13ecfde29e5a9f5ff20fae44744397d7 - 58be1a2775d5b0424b7e9ef4450e9e34; - 613cc2a6b7773965bca0c2ae6237e9f702b75a0852be1830c2e689f1ec9d6599 - b75c7b15e30e188d84c96d7de9ad41ae - e3c34ccd80ca28706fdcd10562bd60cd - 466ece9c2f57ebe70b744c210507d37f; - 3555a5f38e5450a5cc5a7eeb9504288aee23298fb8 - 8dd256a0a99d55a277c1cebca95be232 - 6fa74dc1f5 - 0fdf1eba1901a220dce11aff114ba7a2; - 23309eefbbc3fe8df211397e58df223596c695a8993be7d81ec52b - 9891a51ece620fdeb8c4d1dad87f979b - 4be153fb895358027814ae - 7d23cf0b5d1b872877af14ab1b35ea49; - 0175cde357bdd78d4672ea176521a9ef0c0e842d62cdef309b6ed2 - cd41cb0292968ee9c82b353e07cd6e2d - 037f62f06af153d6ad8c01 - 3d1533e7afd150b592fb196354585cff; - 8705d678b201c2300a347083cae184ed - 786ea38c016bbcc3e9f5c5b4662fdaec - 03 - 0fb632ecb1bd0774302a3e5f6091ebd9; - 0195d1b27b916f29264d0fd33696867bc9aea2f41dce71931886c5d898e25f69 - 93a948c2e26a36dc13a1754a80cdaf8c - 034aeb96693c049c2af77e1a7b277a5e - 3d9d04738de1dc0a7654b8115a7ee1e1; - 79090e88e87a94e1eb7f7ebe3147bdde846170 - eb67415f279248028ae4052f72d48092 - 9686d1 - 7100e616ea381ee5d0b2ffb7a67ee942; - f254423fef93d5d7a76ecf22c656c1352c53257875945d33 - b2ca471b0867d5fae2e4f27a2d2706da - 01bad680bd4a0132ee - 582f783fc210f72814780e69b0bd29ff; - c9bd4858bd014860f6d95dabb9a5d3d231 - c1ff2aefeb9d6cc4ac6ae0c0535d8c13 - 011f - 17949a58ebcb086a5350c3aceffbc4e0; - 0b8915613beb2e89cdb36b69b7d62ef2b0197537793f71 - 242f42cdf08598d86d812a11c5647b75 - 56ddd25003c7e7 - 1aa0da3ff44f29eb5db54ea6a970dd5a; - e03c7f839598081d2c42f4e503484e7a4a219d0149561f3d5cbed8 - 6503cea0d8a0c6a227143d96d7cad509 - 02c53788cff1530e65640225 - 078acf15737c0320afbac57f23098cd5; - 0165144c6d0637f8cb21bc8913188186376755bbd790566f32612993fec931 - 8ab74399da1f1a01a91521d73d12b0d9 - 02ed5b96b580b772606cb77ff49191 - 58d92bf9fb6f5fb9f0975b3e2f5ad1f8; - 02b35947d2f507a817cb9e178bd6bcaa1d9054979482efb1ef - 56cebd75069fe534091d8409575702cf - 08114f9866c8343218 - 2504e1784d51b5c26cad8df6357b0567; - 109978bc6b8824b04e113fa2a4c982bd2b93a027fd08ad69227a51506bdc11 - 12c061be0756685473011c61067dc241 - 012013fcb240a4d4f394c40f357c666b - 040d8ec7359c8fa7cb6864bb6fe2b6ba; - 0240b50d2853d690a8cf355e9d79626c6cb5f996cccfee3e1be7eed633 - d233771cc22b3724a3d14382766cce97 - 07b0d38444572f483317b557d4 - 7b499146cd46dab3812cf4691d3bbe5f; - 025e90153ae473c9bee43aafaec084468698e5d4eede21f8d4 - 791d69fc4cfb227b4bb531b633dfcb80 - 0d396769c6e551b981 - 0f0854faf0c35a4ffa142b21d0047354; - 0de9af086a7b5a69231741ad28f72df187515e355dd8dfd9b10bfc6e87f1 - 1a5dbee5bbc0980ab55fae3b6135fca9 - 89b00eb8894915d87ca6943ac6fd - 06fa712cefe56e4dddbccc3b389d7bc4; - 12333fa824ddf35aa1b7de856a919b5864e94c3d63ce94 - 84c4a1d9a55cde37b41ce04d4c292491 - 257b652b91361c - 6b6611dde69c73a3bdde7b6fd01d6748; - 038b2304265ac16c80f84be3d61a82628ae2 - 730b3374140b33de67be248766cc7183 - 0864 - 1519f8ad4b7430e93c72ce04104d044e; - 1d09aead497b4383dc45da08fac2950fde1e - d78d23956daf24a70ed9513d8185e988 - 2b5e - 227af9cc9eff71a25a89d3a5f95fc5ee; - 01ff9215d5fc0b3149589a96c76555a7145a7699ed03b125da8c0221ae0ea630 - e97791f445493fa4c2858c63e89de9b1 - 027c8467e27a018bbb903b85aeeff4c1 - 79ff4a78de0c7c1a9a87d63368ddcf41; - 033c9edec4c98b26c1bd29dd6c33418bf678921a705fe94ba8f4 - 1f200f0df4aae402308e4d3747ea3b62 - 2b085586f038a6997a7a - 095479470eacc695a289163c245933c0; - 01a8722b24be8d9404cc9b836ab0b739ee57ae60ed - 0ba579d54afea4a7386c2ae3664c3d93 - 3e54693717 - 0619d78694ac997bedf949a21bf9a024; - 112bf3440706f9935e8221356e908bdd1972bc0b7d4540a76c779d845f604fc2 - 2d27eaf11c8af56eab46d787c409293a - b779548b4b726be09029b5b6e414316b - 1498f6cd6bbed85fe55529a41188ce9c; - 5fbb399787dc1c088ae1b1a868a8fd68071662aebe6859d764d8c66d - 0ae272c16095b2e0b88f60f0bb2c77c1 - 09593fefe3ac800d34fa59a9d1 - 022c8aa8970653e5946394aaf55db47c; - 0ba36adf7f6695ffcaf3cb4f671fcf1167c79f - d24e71e6be0662a608ddaac25c3174b7 - 1836b1 - 5a783d61e236025be73de15c60fb1738; - 28b2a0867669dbc51f86661c3a1f6a1d5565284547a3f4f2f934 - 22bd5df7bc0c1e6a863a1a1c448733e7 - 01540ca5dc8900d40c3dd7 - 0eb263f6f9b698becce9b975cac485b1; - 15503e6802be9c85711f75250539c76426f91b77 - 91cc2ed96c4eee210ed0cb5251934085 - 2f2129de - 5430a3c98a336b14edef0d41d93dfad1; - 011816c74ce3765423825661feba199268be5453932b36d6 - a8a09df55f7606d260f79ad1825ec8ac - 02b46a057ab9b6d8 - 5d970c88da5e61edfcf5b0afb7112c76; - 0e58c4591e74eede082861a82117d4d41239247c - 22afdfd47592ee3f4e9777003ee9e7ad - 7437cb93 - 0faa41dc7710ab02ea755b778975ffdb; - 019717a6f636f25b0467f5ae365c2ba5b8 - 801bf58c5282787aec5c66702e80efd5 - 03 - 173bb862c174d38b531104a62faa95c7; - 1af0354e3dfc333b46c5efa3354f8a0cb6bb41 - 8d59fafe11fd9b7a2f687a13696d4315 - 375fa9 - 1993cbf7dfda1e1ce89c043dc306dbdc; -} diff --git a/tests/gkcdsa b/tests/gkcdsa deleted file mode 100644 index 314fe4a..0000000 --- a/tests/gkcdsa +++ /dev/null @@ -1,59 +0,0 @@ -# $Id: gkcdsa,v 1.1 2004/04/04 19:42:59 mdw Exp $ -# -# Tests for KCDSA - -sign { - "prime { - 0xd7b9afc104f4d53f737db88d6bf77e12cd7ec3d71cbe3cb74cd224bff348154afba6bfed797044dfc655dcc20c952c0ec43a97e1ad67e687d10729caf622845d162afca8f0248cc412b3596c4c5d3384f7e25ee644ba87bb09b164fb465477b87fdba5eaa400ffa0925714ae19464ffacead3a9750d121948ab2d8d65c82379f, - 0xc3ddd3717bf05b8f8dd725c162f0b9432c6f77fb, - 0x50e414c7a56892d1ad633e42d5cd8346f2c09808111c772cc30b0c544102c27e7b5f9bec57b9df2a153128919d795e46652b2a072e1f2517f2a3afff5815253aaefe35724cfa1af6afce3a6b41e3d0e13bed0eff54383c4665e69b47ba79bbc3339f86b9be2b58894a18b201afc41fe3a0d93d3125efda79bc50dbbb2c3ab639 - }" - has160 - 0x068c4ef355d8b6f53eff1df6f243f98563896c58 - "This is a test message for KCDSA usage!" - 0x4b037e4b573bb7e334cad0a70bed6b5881df9e8e - 8f996a98eda57cc8d88aa6ffdfaea22f39d7fa8a - 0x541f7dc4f92c65eb7f63b6b4f22177f1ee2cf339; - - "ec { nist-p256 }" sha256 - 0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa - "Testing elliptic curves with KCDSA" - 0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c - e3f05cea444ec44d508b3af5b8d2d8eb2bcbff680e83684e3e630ec5b07393c0 - 0x42e307f5fa0a4e01906b067965f6253f1a7919a566cf3d73ddd9a35a17b38617; -} - -verify { - "prime { - 0xd7b9afc104f4d53f737db88d6bf77e12cd7ec3d71cbe3cb74cd224bff348154afba6bfed797044dfc655dcc20c952c0ec43a97e1ad67e687d10729caf622845d162afca8f0248cc412b3596c4c5d3384f7e25ee644ba87bb09b164fb465477b87fdba5eaa400ffa0925714ae19464ffacead3a9750d121948ab2d8d65c82379f, - 0xc3ddd3717bf05b8f8dd725c162f0b9432c6f77fb, - 0x50e414c7a56892d1ad633e42d5cd8346f2c09808111c772cc30b0c544102c27e7b5f9bec57b9df2a153128919d795e46652b2a072e1f2517f2a3afff5815253aaefe35724cfa1af6afce3a6b41e3d0e13bed0eff54383c4665e69b47ba79bbc3339f86b9be2b58894a18b201afc41fe3a0d93d3125efda79bc50dbbb2c3ab639 - }" - has160 - 0x96dce0e7b2f170093d9b51d2ba78202733b62c406d3769758b3e0cbba1ff6c78727a35703cb6bc2476c3c293743dfee94aa4b9efa9a17fa6bf790ac25a82c61523f50abaac7b64647eb15c957b07f5ed7d467243089f74695cd58fbf57920cc0c05d45829c0a8161b943f18451845760ed096540e78aa9750b03d02448cbf8de - "This is a test message for KCDSA usage!" - 8f996a98eda57cc8d88aa6ffdfaea22f39d7fa8a - 0x541f7dc4f92c65eb7f63b6b4f22177f1ee2cf339 - 0; - - "prime { - 0xd7b9afc104f4d53f737db88d6bf77e12cd7ec3d71cbe3cb74cd224bff348154afba6bfed797044dfc655dcc20c952c0ec43a97e1ad67e687d10729caf622845d162afca8f0248cc412b3596c4c5d3384f7e25ee644ba87bb09b164fb465477b87fdba5eaa400ffa0925714ae19464ffacead3a9750d121948ab2d8d65c82379f, - 0xc3ddd3717bf05b8f8dd725c162f0b9432c6f77fb, - 0x50e414c7a56892d1ad633e42d5cd8346f2c09808111c772cc30b0c544102c27e7b5f9bec57b9df2a153128919d795e46652b2a072e1f2517f2a3afff5815253aaefe35724cfa1af6afce3a6b41e3d0e13bed0eff54383c4665e69b47ba79bbc3339f86b9be2b58894a18b201afc41fe3a0d93d3125efda79bc50dbbb2c3ab639 - }" - has160 - 0x96dce0e7b2f170093d9b51d2ba78202733b62c406d3769758b3e0cbba1ff6c78727a35703cb6bc2476c3c293743dfee94aa4b9efa9a17fa6bf790ac25a82c61523f50abaac7b64647eb15c957b07f5ed7d467243089f74695cd58fbf57920cc0c05d45829c0a8161b943f18451845760ed096540e78aa9750b03d02448cbf8de - "This is a test message for KCDSA usage?" - 8f996a98eda57cc8d88aa6ffdfaea22f39d7fa8a - 0x541f7dc4f92c65eb7f63b6b4f22177f1ee2cf339 - -1; - - "ec { nist-p256 }" sha256 - "0x5068f177ccebee933a27457707f6879eb5c4c59d58483766caf9aabcc367c0d1, - 0x4869c59dceadad93f1ed306b3ed544356c119996cc78708b9557c7ca5901da4a" - "Testing elliptic curves with KCDSA" - e3f05cea444ec44d508b3af5b8d2d8eb2bcbff680e83684e3e630ec5b07393c0 - 0x42e307f5fa0a4e01906b067965f6253f1a7919a566cf3d73ddd9a35a17b38617 - 0; -} - diff --git a/tests/group b/tests/group deleted file mode 100644 index dd09060..0000000 --- a/tests/group +++ /dev/null @@ -1,320 +0,0 @@ -# $Id$ -# -# Test group abstraction, and a bunch of other things. - -check { - "prime { 29, 7, 16 }" "ok"; - "prime { 29, 6, 5 }" "not a subgroup"; - "prime { 21, 2, 2 }" "p is not prime"; - "prime { 29, 14, 9 }" "group order not prime"; - - "ec { secp224r1 }" "ok"; - - "prime { catacomb-ll-160-1024 }" "ok"; - - "ec { - prime: - 0xdb7c2abf62e35e668076bead208b - primeproj: - 0xdb7c2abf62e35e668076bead2088, 0x659ef8ba043916eede8911702b22 - 0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500 - 0xdb7c2abf62e35e7628dfac6561c5 * 1 - }" "ok"; - - "ec { - prime: - 0xdb7c2abf62e35e668076bead208b - primeproj: - 0xdb7c2abf62e35e668076bead2088, 0x659ef8ba043916eede8911702b22 - 0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500 - 0xdb7c2abf62e35e7628dfac6561c5 * 2 - }" "incorrect or ambiguous cofactor"; - - # --- This one's oakley-155 --- - - "ec { - binpoly: 0x0800000000000000000000004000000000000001 - binproj: 0, 0x7338F - 0xaa089ae4666a422e714651ad9372213fa65a93, - 0x12d29c630dda76010397809a6816be6d2ffa815 - 0xaaaaaaaaaaaaaaaaaab1fcf1e206f421a3ea1b * 12 - }" "degree not prime"; - -} - -checkelt { - "prime { 29, 7, 16 }" 16 0; - "prime { 29, 7, 16 }" 2 -1; - - "ec { secp112r1 } " - "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500" - 0; - - "ec { - binpoly: 0x0800000000000000000000004000000000000001 - binproj: 0, 0x7338F - 0xaa089ae4666a422e714651ad9372213fa65a93, - 0x12d29c630dda76010397809a6816be6d2ffa815 - 0xaaaaaaaaaaaaaaaaaab1fcf1e206f421a3ea1b * 12 - }" - "0x7b, 0x1c8" - -1; - -} - -mul { - "prime { 29, 7, 16 }" 8 7 27; - - "prime { catacomb-ll-128-512 }" - 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 - 32459289443738057373904596685867555624839649360339363831766212033645755638497600605981483758068704145575847399920657057013890131443911836862688141735006 - 3947634573386515057215934636174241616115542585724861166389751782289048647501330677434616929656928819642658111077814577650964230037753641582364366136933940; - - "ec { nist-p192 }" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" - "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, - 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"; -} - -sqr { - "prime { 29, 7, 16 }" 8 6; - - "prime { catacomb-ll-128-512 }" - 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 - 1140714521254648115393410274780412972862841854751618635120376750594285456137894804866135103112174518443866054055338095672091997366768745026933347678925721; - - "ec { nist-p192 }" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; -} - -inv { - "prime { 29, 7, 16 }" 9 13; - - "prime { catacomb-ll-128-512 }" - 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 - 5876676858790113051879264634636727534122591023949326683791506203503263391580079717512212895466773363712551406785344528808275608153699681298608650332072384; - - "ec { nist-p192 }" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"; -} - -div { - "prime { 29, 7, 16 }" 9 5 25; - - "prime { catacomb-ll-128-512 }" - 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 - 1926426135381827210395257472845875618319108487720857260583372274154852182951667715700282388176779441854588992736540698662997833538400244234146123792411051 - 24069337702503046127918930405335466791703796668849861281722901639361967869381088162761943434867448224639537469251486209856612215080111132649928233405085; - - "ec { nist-p192 }" - "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da, - 0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888, - 0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"; -} - -exp { - "prime { 29, 7, 16 }" 3 12 16; - - "prime { 29, 7, 16 }" 3 -12 20; - - "prime { catacomb-ll-128-512 }" - 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 - 147362842169670001895012880214773009850 - 5743039465765061017258257285641279669186626264432710496849307123351095219091264933384359874588390730293795471675184250790999035405886273905917889887366080; - - "prime { catacomb-ll-128-512 }" - 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 - -147362842169670001895012880214773009850 - 3548613102603269389984811279864031309564549180885835723408511495891024326106890973751615845620404633717662823827170012116865930893524976817060348977482376; - - "ec { nist-p192 }" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 6277101735386680763835789423176059013767194773182842284081 - inf; - - "ec { nist-p192 }" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 3131675836296406071791252329528905062261497366991742517193 - "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71, - 0xc6e91094cb34131e539c3db25f7f32670ef8dfe03a88b6fb"; - - "ec { nist-p192 }" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 3131675836296406071791252329528905062261497366991742517193 - "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71, - 0xc6e91094cb34131e539c3db25f7f32670ef8dfe03a88b6fb"; - - "ec { nist-p192 }" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - -3131675836296406071791252329528905062261497366991742517193 - "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71, - 0x3916ef6b34cbece1ac63c24da080cd97f107201fc5774904"; -} - -mexp-1 { - "prime { 29, 7, 16 }" 3 12 16; - "prime { 29, 7, 16 }" 3 -12 20; - - "ec { nist-p192 }" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 3131675836296406071791252329528905062261497366991742517193 - "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71, - 0xc6e91094cb34131e539c3db25f7f32670ef8dfe03a88b6fb"; - - "ec { nist-p192 }" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - -3131675836296406071791252329528905062261497366991742517193 - "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71, - 0x3916ef6b34cbece1ac63c24da080cd97f107201fc5774904"; -} - -mexp-2 { - "prime { 29, 7, 16 }" 3 12 8 2 9; - "prime { 29, 7, 16 }" 3 -12 8 2 4; - - "prime { catacomb-ll-128-512 }" - 3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590 - -147362842169670001895012880214773009850 - 130340428707563070626027539288099297037336608388990593367322442443880297841210613523501678207607756678300142264348927299637006055881968995671289567513600 - 91626412351157168611316239052073981423 - 1022777063245982511046303002728993765008184164346724419524981660559588777350492245381260023136750231183070065817596986237402046431653662723677455952067221; - - "ec { nist-p192 }" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - -3131675836296406071791252329528905062261497366991742517193 - "0xea711858c23d92f9964655910bc90a197a915e90111cf11b, - 0x664189a1d8b2bb24f2b2ac64b19e2178118842e6ba9f4ad5" - 1110875761630725856340142297645383444629395595869672555585 - "0xaa25bb0bf38b06821e8641c1afb8bc078dbe11c3cf9bc97, - 0xf1a4c09d621fb52736f6010ae90e9bc9771ac017a62098f9"; -} - -toint { - "prime { 29, 7, 16 }" 15 0 15; - "prime { 29, 7, 16 }" 0 0 0; - - "ec { nist-p192 }" inf -1 0; - - "ec { nist-p192 }" - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - 0 602046282375688656758213480587526111916698976636884684818; -} - -fromint { - "prime { 29, 7, 16 }" 15 0 15; - "prime { 29, 7, 16 }" 0 0 0; - "prime { 29, 7, 16 }" 39527306161272833161358334459 0 19; - - "ec { nist-p192 }" 1 -1 inf; - "ec { nist-p192 }" 0 - 0 "0, 0x7b685605ee600cb363db5ea912f2bb5e3a0a2e0e60360f12"; -} - -toec { - "prime { 29, 7, 16 }" 0 -1 inf; - "ec { nist-p192 }" inf 0 inf; - "ec { secp112r1 }" - "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500" - 0 - "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"; -} - -fromec { - "prime { 29, 7, 16 }" inf -1 0; - "prime { 29, 7, 16 }" "39527306161272833161358334459, 9" 0 19; - - "ec { secp112r1 }" inf 0 inf; - "ec { nist-p192 }" "1, 5" -1 inf; - - "ec { secp112r1 }" - "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500" - 0 - "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"; -} - -tobuf { - "prime { 29, 7, 16 }" 22 -1 "00"; - "prime { 29, 7, 16 }" 22 0 "000116"; - "prime { 29, 7, 16 }" 0 -1 "0000"; - "prime { 29, 7, 16 }" 0 0 "000100"; - - "ec { secp112r1 }" inf 0 "0000"; - "ec { secp112r1 }" - "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500" - 0 "000e09487239995a5ee76b55f9c2f098000ea89ce5af8724c0a23e0e0ff77500"; - "ec { nist-p192 }" - "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed" - 0 "00010000188497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed"; -} - -frombuf { - "prime { 29, 7, 16 }" "00" -1 0; - "prime { 29, 7, 16 }" "000116" 3 22; - "prime { 29, 7, 16 }" "00000e" 2 0; - "prime { 29, 7, 16 }" "000100ff" 3 0; - - "ec { secp112r1 }" "0000" 2 inf; - "ec { secp112r1 }" - "000e09487239995a5ee76b55f9c2f098000ea89ce5af8724c0a23e0e0ff77500f00d" - 32 "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"; - "ec { secp112r1 }" "0001000001001ee7" -1 inf; - "ec { nist-p192 }" - "00010000188497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0eddead" - 29, "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed"; -} - -toraw { - "prime { 29, 7, 16 }" 22 -1 ""; - "prime { 29, 7, 16 }" 22 0 "16"; - "prime { 29, 7, 16 }" 0 -1 ""; - "prime { 29, 7, 16 }" 0 0 "00"; - "prime { 4294967311, 364289, 18767 }" 4285559121 0 "00ff707151"; - "prime { 4294967311, 364289, 18767 }" 4285559121 -1 "ff707151"; - - "ec { secp112r1 }" inf 0 "00"; - "ec { secp112r1 }" - "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500" - 0 "0409487239995a5ee76b55f9c2f098a89ce5af8724c0a23e0e0ff77500"; - "ec { nist-p192 }" - "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed" - 0 "040000000000000000000000000000000000000000000000008497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed"; -} - -fromraw { - "prime { 29, 7, 16 }" "" -1 0; - "prime { 29, 7, 16 }" "160bad" 1 22; - "prime { 29, 7, 16 }" "00" 1 0; - "prime { 4294967311, 364289, 18767 }" "00ff707151e7c0" 5 4285559121; - "prime { 4294967311, 364289, 18767 }" "ff707151" -1 0; - - "ec { secp112r1 }" "" -1 inf; - "ec { secp112r1 }" "00" 1 inf; - "ec { secp112r1 }" - "0409487239995a5ee76b55f9c2f098a89ce5af8724c0a23e0e0ff775" -1 inf; - "ec { secp112r1 }" - "0409487239995a5ee76b55f9c2f098a89ce5af8724c0a23e0e0ff77500" - 29 "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"; - "ec { nist-p192 }" - "070000000000000000000000000000000000000000000000008497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed00deadbeef" - 49 "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed"; -} diff --git a/tests/has160 b/tests/has160 deleted file mode 100644 index ba3db65..0000000 --- a/tests/has160 +++ /dev/null @@ -1,53 +0,0 @@ -# Test vectors for HAS160 hash function -# -# $Id: has160,v 1.1 2004/04/04 19:42:59 mdw Exp $ - -# --- Basic hash function --- -# -# Test vectors from `The Revised Version of KCDSA' by Chae Hoon Lim. - -has160 { - "" 307964ef34151d37c8047adec7ab50f4ff89762d; - "a" 4872bcbc4cd0f0a9dc7c2f7045e5b43b6c830db8; - "abc" 975e810488cf2a3d49838478124afce4b1c78804; - "message digest" 2338dbc8638d31225f73086246ba529f96710bc6; - "abcdefghijklmnopqrstuvwxyz" 596185c9ab6703d0d0dbb98702bc0f5729cd1d3c; -} - -has160-rep { - "a" 1000000 d6ad6f0608b878da9b87999c2525cc84f4c9f18d; -} - -# --- HMAC mode --- -# -# Regression catching only. - -has160-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - f5b44115a53f716b6f488de1098ee7c251418623; - - "what do ya want for nothing?" - 4a656665 - a74547c1ef0aa147c7428ab7e71664549be2a412; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - e4c91bc71782fa44a56be1a34aae167e8ffc9734; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - 14d1055da875222053bf1180bbef8892eba3ac30; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - 124131a293f1fdf3d6b11e2b7f7a1f5b12e42d58; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 63750d67af40e3fde33526545d300972a1527053; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 1bdb821e399e208352c64f0655f6601e2a8a087c; -} diff --git a/tests/idea b/tests/idea deleted file mode 100644 index ce947d3..0000000 --- a/tests/idea +++ /dev/null @@ -1,28 +0,0 @@ -# Test vectors for IDEA -# -# $Id: idea,v 1.2 2000/07/15 17:48:15 mdw Exp $ - -# --- Thin on the ground, these are --- - -idea { - 00010002000300040005000600070008 0000000100020003 11fbed2b01986de5; - 00000000000000000000000000000000 0000000000000000 0001000100000000; - 000027ed8f5c3e8baf16560d14c90b43 0000abbf94ff8b5f cbbb2e6c05ee8c89; - 000027ed8f5c3e8baf16560d14c90b43 6889f5647ab23d59 61d5397046f99637; - 000027ed8f5c3e8baf16560d14c90b43 6c2e3617da2bac35 b2229067630f7045; - 000027ed8f5c3e8baf16560d14c90b43 819440ca2065d112 c88600093b348575; - 000027ed8f5c3e8baf16560d14c90b43 848f836780938169 4821b99f61acebb7; - 000027ed8f5c3e8baf16560d14c90b43 ac4856242b121589 85c6b232294c2f27; - 000027ed8f5c3e8baf16560d14c90b43 cbe465f232f9d85c b67ac767c0c06a55; - 000027ed8f5c3e8baf16560d14c90b43 d53fabbf94ff8b5f 1320f99bfe052804; - 000027ed8f5c3e8baf16560d14c90b43 df8c6fc637e3dad1 ef4899b48de5907c; - 729a27ed8f5c3e8baf16560d14c90b43 0000abbf94ff8b5f 65861be574e1eab6; - 729a27ed8f5c3e8baf16560d14c90b43 6889f5647ab23d59 f963468b52f45d4d; - 729a27ed8f5c3e8baf16560d14c90b43 6c2e3617da2bac35 1569e0627007b12e; - 729a27ed8f5c3e8baf16560d14c90b43 819440ca2065d112 264a8bba66959075; - 729a27ed8f5c3e8baf16560d14c90b43 848f836780938169 d7e0468226d0fc56; - 729a27ed8f5c3e8baf16560d14c90b43 ac4856242b121589 95cd92f44bacb72d; - 729a27ed8f5c3e8baf16560d14c90b43 cbe465f232f9d85c bce24dc8d0961c44; - 729a27ed8f5c3e8baf16560d14c90b43 d53fabbf94ff8b5f 1d0cb2af1654820a; - 729a27ed8f5c3e8baf16560d14c90b43 df8c6fc637e3dad1 29358cc6c83828ae; -} diff --git a/tests/lcrand b/tests/lcrand deleted file mode 100644 index 8ffd7ed..0000000 --- a/tests/lcrand +++ /dev/null @@ -1,34 +0,0 @@ -# Test vectors for linear congruential generator -# -# $Id: lcrand,v 1.3 2000/07/15 10:03:13 mdw Exp $ - -lcrand { - # --- Standard stuff --- - - 0 271828183; - 271828183 996300340; - 996300340 228306184; - 228306184 1171467301; - 1171467301 3265426054; - 3265426054 2636049353; - 2636049353 3799512036; - 3799512036 2414373801; - 2414373801 1059474234; - 1059474234 2734911993; - 2734911993 239668818; - 239668818 1752802481; - 1752802481 34386946; - 34386946 1344553049; - 1344553049 1121833700; - 1121833700 636134543; - - # --- Particular outputs --- - - 2282233179 4294967290; - 2624567577 0; - 2966901975 1; - - # --- Fixed point --- - - 3223959250 3223959250; -} diff --git a/tests/md2 b/tests/md2 deleted file mode 100644 index 8930253..0000000 --- a/tests/md2 +++ /dev/null @@ -1,79 +0,0 @@ -# Test vectors for MD2 hash function -# -# $Id: md2,v 1.1 2001/02/21 20:03:23 mdw Exp $ - -# --- Basic hash function --- -# -# Test vectors from RFC1319. The last was generated using OpenSSL. - -md2 { - "" 8350e5a3e24c153df2275c9f80692773; - "a" 32ec01ec4a6dac72c0ab96fb34c0b5d1; - "abc" da853b0d3f88d99b30283a69e6ded6bb; - "message digest" ab4f496bfb2a530b219ff33031fe06b0; - "abcdefghijklmnopqrstuvwxyz" - 4e8ddff3650292ab5a4108c3aa47940b; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - da33def2a42df13975352846c30338cd; - "12345678901234567890123456789012345678901234567890123456789012345678901234567890" - d5976f79d83d3a0dc9806c3c66f3efd8; - - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -" 9bc05c2f44930f59882bb885a75b4c95; -} - -# --- HMAC mode --- -# -# These are just regression tests, generated internally. - -md2-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - b524be0196e491ed44823746cd8923af; - - "what do ya want for nothing?" - 4a656665 - 292f9d34f9e311846de86c495d7adfa2; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - ff09238e4bded84b5490bc42cfd5c265; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - ea3181bf1cc387f12ed0637105fb219d; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - 7177f2b3e5583078ee122f94fe3c784a; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 615b1c392f5aaeeeab7e82572e6395d5; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - df0b12810892f0c7559802d5c0ce1157; -} diff --git a/tests/md4 b/tests/md4 deleted file mode 100644 index 1439c35..0000000 --- a/tests/md4 +++ /dev/null @@ -1,59 +0,0 @@ -# Test vectors for MD4 hash function -# -# $Id: md4,v 1.2 2000/07/15 10:03:13 mdw Exp $ - -# --- Basic hash function --- -# -# Test vectors from RFC1186 and some others I generated using the reference -# implementation. - -md4 { - "" 31d6cfe0d16ae931b73c59d7e0c089c0; - "a" bde52cb31de33e46245e05fbdbd6fb24; - "abc" a448017aaf21d8525fc10ae87aa6729d; - "message digest" d9130a8164549fe818874806e1c7014b; - "abcdefghijklmnopqrstuvwxyz" - d79e1c308aa5bbcdeea8ed63df412da9; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - 043f8582f241db351ce627e153e7f0e4; -} - -# --- HMAC mode --- -# -# No test vectors available. The HMAC implementation has not been tested -# against an external reference. However, MD4 isn't strong enough to make -# a realistic MAC anyway, and use of md4-mac is thoroughly deprecated. The -# HMAC code is autogenerated anyway, and ought to be reliable and correct. -# -# These test vectors are here to spot changes in behaviour rather than ensure -# interoperability. - -md4-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - 90a79458f58f437e21f169cdba283da6; - - "what do ya want for nothing?" - 4a656665 - be192c588a8e914d8a59b474a828128f; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 75e5fb6e71ca6dcdd9fca269a9a3cd9c; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - fb14cddf9efe11ad24033fc70f37bb9e; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - 6306262f9ba0e83f9ce3f15aafc23be8; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 545b8f2577657042df628fbb98430d5f; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 0192f3442ad5d1ea5268306ab0d4962e; -} diff --git a/tests/md5 b/tests/md5 deleted file mode 100644 index d34918d..0000000 --- a/tests/md5 +++ /dev/null @@ -1,80 +0,0 @@ -# Test vectors for MD5 hash function -# -# $Id: md5,v 1.3 2000/07/15 10:03:13 mdw Exp $ - -# --- Basic hash function --- -# -# Test vectors from RFC1321 and some others I generated using the reference -# implementation. - -md5 { - "" d41d8cd98f00b204e9800998ecf8427e; - "a" 0cc175b9c0f1b6a831c399e269772661; - "abc" 900150983cd24fb0d6963f7d28e17f72; - "message digest" f96b697d7cb7938d525a2f31aaf161d0; - "abcdefghijklmnopqrstuvwxyz" - c3fcd3d76192e4007dfb496cca67e13b; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - d174ab98d277d9f5a5611c2c9f419d9f; - "12345678901234567890123456789012345678901234567890123456789012345678901234567890" - 57edf4a22be3c955ac49da2e2107b67a; - - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -" 2b65a7ba4acd105ef2cb9adebd9f0bfa; -} - -# --- HMAC mode --- -# -# Test vectors from RFC2104 and RFC2202. - -md5-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - 9294727a3638bb1c13f48ef8158bfc9d; - - "what do ya want for nothing?" - 4a656665 - 750c783e6ab0b503eaa86e310a5db738; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 56be34521d144c88dbb8c733f0e8b3f6; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - 697eaf0aca3a3aea3a75164746ffaa79; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - 56461ef2342edc00f9bab995690efd4c; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 6f630fad67cda0ee1fb1f562db3aa53e; -} diff --git a/tests/mp b/tests/mp deleted file mode 100644 index 0fbaf06..0000000 --- a/tests/mp +++ /dev/null @@ -1,328 +0,0 @@ -# Test vectors for MP functions -# -# $Id$ - -add { - 5 4 9; 5 -4 1; -5 4 -1; -5 -4 -9; - 0xffffffff 1 0x100000000; -} - -sub { - 5 4 1; 5 -4 9; -5 4 -9; -5 -4 -1; - 4 5 -1; 4 -5 9; -4 5 -9; -4 -5 1; -} - -mul { - 5 4 20; -5 4 -20; 5 -4 -20; -5 -4 20; - 0x10000 0x10000 0x100000000; -} - -div { - 9 4 2 1; -9 4 -3 3; 9 -4 -3 -3; -9 -4 2 -1; - -3 6277101735386680763835789423207666416083908700390324961279 - -1 6277101735386680763835789423207666416083908700390324961276; - 3131675836296406071791252329528905062261497366991742517193 - 1110875761630725856340142297645383444629395595869672555585 - 2 909924313034954359110967734238138173002706175252397406023; - 3131675836296406071791252329528905062261497366991742517193 - 53 - 59088223326347284373419855274130284193613157867768726739 26; - 1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919 - 776259046150354467565459065629240877815667024717257156601175597451483119974551053629334726938295821221455003840144432114575401859459023171316363806515641491872190410445098144254585345658296587683734775881559921685818610503605288959 - 2 1; -} - -exp { - 4 0 1; - 4 1 4; - 7 2 49; - 3 564 124849745640593184256214502788000232711984346194239284918599169775251467106591187580476305077269760425019686159071753053924227569816588462643229463821875763427430576080998505780547826368760514503807579784278708008217584939464444237989070811887584423210788916656247499281; -} - -bin2c { - and 5 3 1; - or 5 3 7; - xor 5 3 6; - 1111 0 0 -1; - or 45 -7 -3; - xor 0x343cd5 -0x6a49c -0x32984f; -} - -lsr2c { - -1 5 -1; - 1 5 0; - -6 2 -2; - 5 0 5; - -4 0 -4; - 7 2 1; - -7 2 -2; - -7 20 -1; -} - -lsl2c { - -1 5 -32; - 5 0 5; - -4 0 -4; - 7 2 28; - -7 2 -28; - 0xc0000000 1 0x180000000; - -0xc0000000 1 -0x180000000; - -1 32 -0x100000000; -} - -setbit { - 0 40 0x10000000000; - 0x87348 40 0x10000087348; - 5 1 7; - 7 1 7; - -3 1 -1; -} - -clrbit { - 0x10000000000 40 0; - 0x87348 40 0x87348; - 5 1 5; - 7 1 5; - -1 1 -3; -} - -neg { - 0 0; - 15 -15; - -15 15; -} - -odd { - 1 0 1; - 2 1 1; - 4 2 1; - 12 2 3; - 0x10000000000000 52 1; - 0x10000000400000 22 0x40000001; -} - -sqrt { - 0 0; - 1 1; - 4 2; - 9 3; - 16 4; - 99 9; -100 10; -101 10; -120 10; -121 11; - -10106623487257186586 3179091613; -14565040310136678240 3816417208; -} - -gcd { - # --- Simple tests --- - - 16 12 4 -11 15; - 12 16 4 -1 1; - 693 609 21 -7 8; - 4398082908043 90980984098081324 1 -32483863573352089 1570292150447; - - # --- Negative argument tests --- - - 16 -12 4 -11 -15; - -16 12 4 11 15; - -12 -16 4 1 -1; - -12 16 4 1 1; - -693 609 21 7 8; - 693 -609 21 -7 -8; - - # --- Zero argument tests --- - - 15 0 15 1 0; - 0 15 15 0 1; - -5 0 5 -1 0; - 0 -5 5 0 -1; - 0 0 0 0 0; - - # --- Random number tests --- - - 829561629303257626084392170900075 32498098450983560651904114638965 - 5 -29340810037249902802634060204608 748967211613630574419802053172497; - - 5509672937670943767152343650729669537671508 - 398326674296699796695672966992514673531 - 17 - -4158709420138833210339208344965073815 - 57523460582278135926717203882531035926727; - - 324098408098290809832490802984098208098324 - 23430980840982340982098409823089098443 - 1 - -4158709420138833210339208344965073815 - 57523460582278135926717203882531035926727; - - # --- RSA test --- - # - # The first number is (p - 1)(q - 1) from `mpmont'. The second is a - # random number (it's actually prime, but that doesn't matter) which I - # can use as an RSA encryption exponent. The last is the partner - # decryption exponent, produced using the extended GCD algorithm. - - 665251164384574309450646977867043764321191240895546832784045453360 - 5945908509680983480596809586040589085680968709809890671 - 1 - -4601007896041464028712478963832994007038251361995647370 - 514778499400157641662814932021958856708417966520837469125919104431; - - # --- Misery --- - # - # Some bugs discovered during RSA testing. - - 100000423751500546004561515884626739136961367515520675987004088469753859696407139054406989735113827981148062449057870561788973142250811838720214530386151198455545176591384352343648452329042764530196327665219224050630680827543991306749402959935685172017409062967157813233001567797128414009962262840951763040181 - 44895767034162990997987303986882660674722497505237491649296190658571471979065889234144353811843706629535512848235473808330181517421970135930320187227697512315919757806204341545022714991717913006031724818461724742069401359454784533576615919680949125073761586043027941204059690093447093117249681641020785611986 - 1 - -44146175664861261172356293340716833133750232401287328189797639296698679436925232375473973898100363205157703913050824405116878299310008848005045714833814493992539429428295945643439440068026313232881493081836812480325977761600303456915493177366981470223898994906470419007730670657168179659899713837827764669213 - 98330790743257232930640417364963717704786040860302439189781385170246412183980882564239377268174203679366339563908361674571088519452885615348465535190260914996055274486493192655677181637142116473172979503236297658204730543049175626205461452256333155750566288282331419748434569978343545573401114593095927172889; - - 44895767034162990997987303986882660674722497505237491649296190658571471979065889234144353811843706629535512848235473808330181517421970135930320187227697512315919757806204341545022714991717913006031724818461724742069401359454784533576615919680949125073761586043027941204059690093447093117249681641020785611986 - 100000423751500546004561515884626739136961367515520675987004088469753859696407139054406989735113827981148062449057870561788973142250811838720214530386151198455545176591384352343648452329042764530196327665219224050630680827543991306749402959935685172017409062967157813233001567797128414009962262840951763040181 - 1 - -1669633008243313073921098519663021432175326655218236797222703299507447512426256490167612466939624301781722885149508887217884622797926223371748995195890283459489902104891159687971270691900648057023348161982926392425950284494815680543941507679352016266842774684826393484566997818784868436561148247855835867292 - 749591369301729825631010646165827540972265103950163459498551361872792542140656858670379913743343424377808935184649403213303218111961287925274472393883018323380328377908395901583274923691599773150231736624912261743423597854481076661122742313967654849862591136557522196329019436278913457349967803193020942773; - - # --- Some other bugs --- - - 19504439280113284806725522136967618725661733412699408177537810327183285842670 - 1 - 1 - 0 - 1; -} - -modinv { - 5 9 2; - 15 64 47; - 564566436 546457643 408896426; -} - -jacobi { - 4 5 1; - 6 7 -1; - 15 27 0; - 2132498039840981 98729378979237498798347932749951 1; - 98729378979237498798347932749951 2132498039840981 1; - - # --- Kronecker extension --- - - 0 0 0; - 1 0 1; - -1 0 -1; - 2 0 0; - - 2132498039840981 197458757958474997596695865499902 -1; - 98729378979237498798347932749951 4264996079681962 1; - 98729378979237498798347932749951 -4264996079681962 1; - -98729378979237498798347932749951 -4264996079681962 -1; - - # --- Random tests made by PARI/gp --- - - 22 -19 -1; - 48 -37 1; - -13 29 1; - -19 2 -1; - -43 31 1; - -12 -7 -1; - -14 -34 0; - -30 -29 -1; - 25 26 1; - -27 20 -1; - -5 -45 0; - 9 -42 0; - -51 -3 0; - -39 35 -1; - 37 30 1; - 13 18 -1; - -28 6 0; - -49 -15 1; - -1 1 1; - -9 13 1; - -47 44 -1; - -14 -30 0; - 37 -36 1; - 45 9 0; - -29 30 -1; - 49 49 0; - -27 -10 -1; - -35 -25 0; - 17 14 -1; - -35 29 1; - -1 33 1; - 38 -11 1; - 3 -24 0; - 5 -25 0; - -31 22 -1; - 40 30 0; - -43 26 -1; - -22 10 0; - 11 -29 -1; - 40 -18 0; -} - -modsqrt { - 1 3 1; - 4 5 2; - 9775592058107450692 13391974640168007623 3264570455655810730; - 8155671698868891620 10189552848261357803 2073812183305821596; - 3248339460720824413 8976233780911635437 1220523478429582717; - 3447751741648956439 10155704720805654949 2812971608818169892; - 1453601744816463433 3095659104519735473 1260511572497628526; - 3366261317119810224 3756232416311497601 610261287187759737; - 3869491397135339653 5762828162167967567 2788500156455085147; - 660864223630638896 1729533840094059799 671335997718840076; -} - -modexp { - - # --- Montgomery exponentiation --- - - 435365332435654643667 8745435676786567758678547 - 4325987397987458979875737589783 - 2439674515119108242643169132064; - 0xfffffffdfffffffffffffffffffffffe 0 0xfffffffdffffffffffffffffffffffff 1; - 1804289383 -8939035539979879765 8939489893434234331 6139425926295484741; - - # --- Barrett exponentiation --- - - 435365332435654643667 8745435676786567758678547 - 4325987397987458979875737589782 - 2425191520487853884024972777945; -} - -factorial { - 0 1; - 1 1; - 2 2; - 3 6; - 4 24; - 5 120; - 30 265252859812191058636308480000000; - 100 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000; - 500 - 1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; -} - -fibonacci { - -20 -6765; - -19 4181; - -10 -55; - -9 34; - -2 -1; - -1 1; - 0 0; - 1 1; - 2 1; - 5 5; - 10 55; - 19 4181; - 20 6765; - 100 354224848179261915075; - 1000 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875; -} diff --git a/tests/mpbarrett b/tests/mpbarrett deleted file mode 100644 index 801b091..0000000 --- a/tests/mpbarrett +++ /dev/null @@ -1,135 +0,0 @@ -# Test vectors for Barrett modular reduction -# -# $Id$ - -mpbarrett-reduce { - 17 11 6; - -17 11 5; - - 0x8ab316d0d1a2e88535cf77c1172881ead70d592c59e9c5fbc16e4b0c4dc49481 - 0x18ca3bf7ee3c6d7bab3f144b015ccc6c25472843d346b461 - 0x02c1815029b766b96ad4507dc1af8151307961c6d161d065; - - 0x8117d1663ee63341eb8faeff304549f0f8b32d587acc2fd5597ea6a31625881d - 0xdc85df77dfb61876805623bcbed325b99d00c2cd65c252c879 - 0x395da02e8a6c66476467c4e04f328d8208cc411e3d1e96e14c; - - 0x63791966f2ad44a6df11bcc87c6b7c2400c74e69f7e3ca02fcac12b3bf56238b - 0xa49e473b8f7539d89cdb002d73182558773eec10db93cc6049d8c5533e - 0x65caf6833baa118b53c7bdc44a831605ca382b5993beead59f3971d13f; - - 0x9ca438db3e0f79305987292e8ec6174e6c313f7904ebb35a349a700e3ae63a37 - 0xb24c93d499c7073b8f7aac718c1f12da1a8fc8bccdd47b49 - 0x46393cb15e38cbbc8a85698151a113f28081b4c8f6ed232e; - - 0x8214fd17858a4a913015412b5331eb9654faeb5156a674b1e5f6550a68957146 - 0xc4f0ebaad6c0ee0111c57667ea8e0a254f3068f212949e20ededa89a7da6 - 0x3fde916ba21d19414d4316041420ca59d8b01aa2acf3f3ef106245c1915c; - - 0x367aa8f5ba9ac4e8e2ea198b8af2c3b3081deab392ffc05715783b245a62a6fa - 0x72e2c37447f8bca34c4a39b130ea8e5c9a7d8b54564aa88ea773 - 0x08e8c03ebf398c63d71d8fd7ca4ece12367a8dde180ca650afb6; - - 0xae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c - 0xc33c890f030644d88cc65f8ccf99c625c9b9fa21d4eb153e52ef89df54130855 - 0xae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c; - - 0x65901dcdad8dd0625d4d158f99b666fee10480d1df15e3bdac640584b9b746bc - 0xd8a1d326fee87d55f39f15b5b2cfe71f5146083928 - 0x859c41164983547c03134b99530e25a0f874315964; - - -0x65901dcdad8dd0625d4d158f99b666fee10480d1df15e3bdac640584b9b746bc - 0xd8a1d326fee87d55f39f15b5b2cfe71f5146083928 - 0x53059210b56528d9f08bca1c5fc1c17e58d1d6dfc4; -} - -mpbarrett-exp { - 4325987397987458979875737589783 - 435365332435654643667 - 8745435676786567758678547 - 2439674515119108242643169132064; - - 8939489893434234331 1804289383 454353454354565 6139425926295484741; - 8939489893434234331 1804289383 8939489893434234330 1; - - # --- Negative exponents --- - - 0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1; - 8939489893434234331 1804289383 -8939035539979879765 6139425926295484741; - - # --- DSA public key derivation --- - - 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5 - 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e - 0x1234 - 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47; - - 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7 - 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 - 0x23a252f60bae4907a8ed5b6203e2b1da32848cd9 - 0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074; - - # --- Quick RSA test --- - - 905609324890967090294090970600361 # This is p - 3 - 905609324890967090294090970600360 # This is (p - 1) - 1; # Fermat test: p is prime - - 734589569806680985408670989082927 # This is q - 5 - 734589569806680985408670989082926 # And this is (q - 1) - 1; # Fermat again: q is prime - - # --- Encrypt a message --- - # - # The public and private exponents are from the GCD test. The message - # is just obvious. The modulus is the product of the two primes above. - - 665251164384574309450646977867045404520085938543622535546005136647 - 123456789012345678901234567890123456789012345678901234567890 - 5945908509680983480596809586040589085680968709809890671 - 25906467774034212974484417859588980567136610347807401817990462701; - - # --- And decrypt it again --- - - 665251164384574309450646977867045404520085938543622535546005136647 - 25906467774034212974484417859588980567136610347807401817990462701 - 514778499400157641662814932021958856708417966520837469125919104431 - 123456789012345678901234567890123456789012345678901234567890; - - # --- Strange bug --- - # - # Strange memory corruption bug causing mpbarrett_reduce to hang. - # Seems to have vanished on a clean rebuild so maybe this was just build - # fluff or something. Leave it here to pick up regression. - - 30916300184138066757562815127455898754391418637651479989257882011612153138316483396290143656363307389355307404813205623380378799585065876990874918745873480056891738964426752 - 2 44329 - 10975270953088118598390528358454369816072092233138947812823085741431681835772475760228604878294514156761050649439713085882651077696501584961485141097470430535290622475239424; -} - -# --- Simultaneous exponentiation --- - -mexp-1 { - 4325987397987458979875737589783 - 435365332435654643667 - 8745435676786567758678547 - 2439674515119108242643169132064; -} - -mexp-2 { - 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 - 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 - 0xbf655bd046f0b35ec791b004804afcbb8ef7d69d - 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 - 0x821a926312e97adeabcc8d082b5278978a2df4b0 - 0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e; - - 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 - 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 - 0xbf655bd046f0b35ec791b004804afcbb8ef7d69d - 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 - -0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adabb090e849367fc31d4c6a97bac0b4be56a79a0de0 - 0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e; -} diff --git a/tests/mpcrt b/tests/mpcrt deleted file mode 100644 index 65a3c3d..0000000 --- a/tests/mpcrt +++ /dev/null @@ -1,21 +0,0 @@ -# Test vectors for Chinese Remainder Theorem solution (Gauss's algorithm) -# -# $Id: mpcrt,v 1.2 2000/07/09 21:33:54 mdw Exp $ - -crt-1 { - 1 5 1; - 3498243289823 4534543545463431 3498243289823; -} - -crt-2 { - 3 7 7 13 59; - 39845 435435221 43534545 32423423467 13736097689153284731; - - 2200541929485233317342398 498459898455435345676576793 - 13046769915260439091721075347560767438958354488807168684311588308214063361125238823412234206191582332588 40831929843180254171317254073271577309351168965431122042755102715326515941762786951037109689522493526197 - 14756532044160797319048143986538019326281096778844833416304858521742332925502855547148214406728673769162624068049034315018936294558; -} - -crt-4 { - 2 5 1 7 3 11 8 13 2192; -} diff --git a/tests/mpint b/tests/mpint deleted file mode 100644 index 49157ba..0000000 --- a/tests/mpint +++ /dev/null @@ -1,52 +0,0 @@ -# Test vectors for conversion between MP ints and C ints -# -# $Id: mpint,v 1.4 2002/01/13 19:51:34 mdw Exp $ - -# The tests look messy because I'm fighting with atoi here as well as the -# integer conversion routines I'm trying to test. - -fromuint { - 0 0; - 1 1; - -5 0xfffffffb; - 0x7ffff 0x7ffff; - 0x80000 0x80000; - 0xfffff 0xfffff; - 0x7fffffff 0x7fffffff; - 0x80000000 0x80000000; # Bastard torture test - 0xffffffff 0xffffffff; -} - -fromint { - 0 0; - 1 1; - -5 -5; - 0x7ffff 0x7ffff; - 0x80000 0x80000; - 0xfffff 0xfffff; - 0x7fffffff 0x7fffffff; - -0x80000000 -0x80000000; # Bastard torture test -} - -touint { - 0 0; - 1 1; - -5 -5; - 0x7ffff 0x7ffff; - 0x80000 0x80000; - 0xfffff 0xfffff; - 0x7fffffff 0x7fffffff; - 0x80000000 -0x80000000; # Bastard torture test - 0xffffffff 0xffffffff; -} - -toint { - 0 0; - 1 1; - -5 -5; - 0x7ffff 0x7ffff; - 0x80000 0x80000; - 0xfffff 0xfffff; - 0x7fffffff 0x7fffffff; - -0x80000000 -0x80000000; # Bastard torture test -} diff --git a/tests/mpmont b/tests/mpmont deleted file mode 100644 index a541508..0000000 --- a/tests/mpmont +++ /dev/null @@ -1,115 +0,0 @@ -# Test vectors for Montgomery reduction -# -# $Id$ - -create { - 340809809850981098423498794792349 # m - 266454859 # -m^{-1} mod b - 130655606683780235388773757767708 # R mod m - 237786678640282040194246459306177; # R^2 mod m -} - -mul { - 43289823545 - 234324324 - 6456542564 - 10807149256; - - 51518627314818829164222247085233898246715229794943812733936714788310185005015428803253311691709787911812368198649776769324928993075889524373913555618270874746833913595051625422038974326537979654635530320271853851973343513053953211672797425464186157719021174955241645388345195723368057041032310152242301620397 - 7041548659011846562361842096561083537784928869240554198760844555642215260669458833049231069318370838770180094409088437631986867239713464317243824963669990014087444248250948204574690463940534304651099653802302150197753463246181762684347288736386534346725039618007392334267637262008343417972878515511486456037 - 21451817224897484023627307128311082613304580637202546848860538836010530320943159719981586919811151828606838777812233053319458755053306547823820900602281867134174742586071226220962576712633552196944784360512851517812225731562588375896089193406088239903885470354101095713609394462435076126493339021945199401247 - 48192532305912989641372170084506981675917951543147719789775743631071830656350879578731578070582102149232280305157616093002880139716311910835926678896882798493523792373475521651115163420137602661060123597773253524671874189844988793471524978853764238038494563159505836018994860909028653670132922744758133798212; -} - -exp { - 4325987397987458979875737589783 - 435365332435654643667 - 8745435676786567758678547 - 2439674515119108242643169132064; - - # --- Bizarre bug --- - # - # This was caused by omission of the test-and-subtract step in the - # Montgomery reduction. - - 8939489893434234331 1804289383 454353454354565 6139425926295484741; - 8939489893434234331 1804289383 8939489893434234330 1; - - # --- Negative and zero exponents --- - - 0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1; - 8939489893434234331 1804289383 -8939035539979879765 6139425926295484741; - - # --- DSA public key derivation --- - - 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5 - 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e - 0x1234 - 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47; - - 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7 - 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 - 0x23a252f60bae4907a8ed5b6203e2b1da32848cd9 - 0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074; - - # --- Quick RSA test --- - - 905609324890967090294090970600361 # This is p - 3 - 905609324890967090294090970600360 # This is (p - 1) - 1; # Fermat test: p is prime - - 734589569806680985408670989082927 # This is q - 5 - 734589569806680985408670989082926 # And this is (q - 1) - 1; # Fermat again: q is prime - - # --- Encrypt a message --- - # - # The public and private exponents are from the GCD test. The message - # is just obvious. The modulus is the product of the two primes above. - - 665251164384574309450646977867045404520085938543622535546005136647 - 123456789012345678901234567890123456789012345678901234567890 - 5945908509680983480596809586040589085680968709809890671 - 25906467774034212974484417859588980567136610347807401817990462701; - - # --- And decrypt it again --- - - 665251164384574309450646977867045404520085938543622535546005136647 - 25906467774034212974484417859588980567136610347807401817990462701 - 514778499400157641662814932021958856708417966520837469125919104431 - 123456789012345678901234567890123456789012345678901234567890; - - # --- Regression --- - - 3986624077014487421577005607434178981611827907415414229383186257799185035259267946499319317546248903815958429965343062841026732183070884484415037389112766124480881891335541864933360040451772640848433986354946570483859801429553601029855169093153120649968457991955067742589996787220443833463413655161718521778024152687493646856649224308444934694934177848997119462792993163729623894124424825605063456003809024630116233635811919734143467917391222413748618664640084816819791040047135721631646389562380726980090637225607902904093720467390446340147754975063914238763877962986901317873962501987398883284691263121949707967483 - 2169501609694605731113683435915932024263931111070470928071742781553833481227229665038394569450673541955381439893533586899516369125587996614390351130855433932967123352056637148142399218614659226596196082977912512097782590337133839376057748669786776861900003976657975002808400242688631641605350346310303557783077961976578644612942618488786721156576047036803063809499458142391930097492829437793780428298460587910313123127299017105180518995858168981798364124607742910479678852164938149352363613709839015911625193499208078080300810729238501127706236236987807659841302058153641198634312186169690290317377895433013774581020 - 51190650099377934681679689372059155651634030541122059023228371179527051284414 - 2182336244564627050476203952083643687109210844491929333865487949231032236266424033053219865356293652087346833773990958617081657598928894294027838097457060132084513275728637155311686562443969707442331856969523833049082440569661820589637161378175422424940183890787723213162895088451684485064228413121825045190532424942855250521728705814032313019282814300698512615465322506857392325469773301168485302267577566759375501214494771698910873834970265937979350795050000891405548412798945017578510891723221844676960980502437259841806090144299798005080365645221451715661064400809603224286845878809241930399832108000526121054958; -} - -# --- Simultaneous exponentiation --- - -mexp-1 { - 4325987397987458979875737589783 - 435365332435654643667 - 8745435676786567758678547 - 2439674515119108242643169132064; -} - -mexp-2 { - 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 - 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 - 0xbf655bd046f0b35ec791b004804afcbb8ef7d69d - 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 - 0x821a926312e97adeabcc8d082b5278978a2df4b0 - 0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e; - - 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291 - 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 - 0xbf655bd046f0b35ec791b004804afcbb8ef7d69d - 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 - -0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adabb090e849367fc31d4c6a97bac0b4be56a79a0de0 - 0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e; -} diff --git a/tests/mpreduce b/tests/mpreduce deleted file mode 100644 index 16cd81f..0000000 --- a/tests/mpreduce +++ /dev/null @@ -1,33 +0,0 @@ -# $Id$ -# -# Tests for efficient reduction - -reduce { - 0xc000 0x16cb3 0xacb3; - 0x8000 0x345545 0x5545; - - 0xfffef 0x100000 0x11; - - 0x1ffffffe 0x26fc6567 0x6fc6569; - 0x3ffffffe 0x45445dc0 0x5445dc2; - 0x7ffffffe 0xd4827a70 0x54827a72; - - 0x72e2c37447f8bca34c4a39b130ea8e5c9a7d8b54564aa88ea773 - 0x367aa8f5ba9ac4e8e2ea198b8af2c3b3081deab392ffc05715783b245a62a6fa - 0x08e8c03ebf398c63d71d8fd7ca4ece12367a8dde180ca650afb6; - - 0xfffffffdffffffffffffffffffffffff - 0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b - 0xa019c198b9d9d9fb4440f7bc415ff5e4; -} - -modexp { - 0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1; - 0xfffffffdffffffffffffffffffffffff 2 - 0xfffffffdfffffffffffffffffffffffe 1; - 0xfffffffdffffffffffffffffffffffff 2 - 0xfffffffdfffffffffffffffffffffffd - 0x7fffffff000000000000000000000000; - 8939489893434234331 1804289383 - -8939035539979879765 6139425926295484741; -} diff --git a/tests/mptext b/tests/mptext deleted file mode 100644 index ed9fb6a..0000000 --- a/tests/mptext +++ /dev/null @@ -1,90 +0,0 @@ -# Test vectors for MP textual I/O -# -# $Id: mptext,v 1.12 2002/10/19 11:59:04 mdw Exp $ - -mptext-ascii { - # --- Perfectly valid things --- - - 10 0 10 0 ""; - 0 0 10 0 ""; - 10 52 10 52 ""; - 10 654365464655464577673765769678 10 654365464655464577673765769678 ""; - 10 654365464655464577673765769678 16 8425e6d06f272b9a2d73ed1ce ""; - 10 596569802840985608098409867 8 366570443501403714657464766613 ""; - 16 8425E6D06F272B9A2D73ED1CE 10 654365464655464577673765769678 ""; - 0 654365464655464577673765769678 16 8425e6d06f272b9a2d73ed1ce ""; - 0 16_8425E6D06F272B9A2D73ED1CE 10 654365464655464577673765769678 ""; - 0 -0x8425E6D06F272B9A2D73ED1CE 10 -654365464655464577673765769678 ""; - 0 -8_366570443501403714657464766613 10 -596569802840985608098409867 ""; - 8 -366570443501403714657464766613 10 -596569802840985608098409867 ""; - 0 0366570443501403714657464766613 10 596569802840985608098409867 ""; - - # --- Bogus things --- - - 10 "" 0 0 ""; # Empty string fails - 10 foo 0 0 "foo"; # Non-numeric character - 10 134f 10 134 "f"; # Stop parsing when reaching `f' - 4 12345 10 27 "45"; # Stop parsing when reaching `4' - 0 63_ 10 63 "_"; # 37 is an invalid base, so stop at `_' - 0 36_ 0 0 ""; # 36 is a valid base, so restart and fail - - # --- Big bases --- - - 62 0 10 0 ""; - 10 0 62 0 ""; - 36 A 10 10 ""; - 36 Z 10 35 ""; - 37 A 10 36 ""; - 10 36 37 A ""; - 62 Z 10 61 ""; - - 0 36_a 10 10 ""; - 0 36_A 10 10 ""; - 0 37_A 10 36 ""; - - 0 0x10 10 16 ""; - 0 0o10 10 8 ""; - 0 0b10 10 2 ""; - 0 010 10 8 ""; - - # --- Word-boundary tests for binary-radix translation --- - - 0 0 16 0 ""; - 8 1234567012 8 1234567012 ""; - 8 12345670123 8 12345670123 ""; - 8 123456701234 8 123456701234 ""; - - 16 1234567 16 1234567 ""; - 16 12345678 16 12345678 ""; - 16 123456789 16 123456789 ""; - - 10 -4009356060 16 -eef9eb1c ""; - - # --- Cussidness --- - - 0 -0 10 0 ""; - - # --- Bugs --- - - 16 84d192cd06ae59691897fa409da6198d5269325d - 16 84d192cd06ae59691897fa409da6198d5269325d ""; - - 16 -9802d5c5d5a73f9d4e694a8920f95231b4017f3ec6a4654ace3fa3d85879e5964dade0e051d57f13c275dab1df3da5331f39271efb2792d1dad4460fd5eb5c21fbf355456f523e5631e623074ff9b3e85cf5e0a9336c8d8b8621b24c4e625800ee0152d12c8e22658a66ade38cb4453ab6e4958114717355186649a6cc20d9f5ae2207f99814965035072a9f2121c8f9dd22ab134181378906291aae97287b62a2f592bbceb4198c9cd78e1968bf1e16865c3c6ce9c777232f186b5da240a24523a07faca9de44eba510c91917e099372e67a6a66e93fe7aaefcb9c5485e1a889eae721ab6407586880a95575a968b43bdf50323627aa0fcddfa4e198b0008 - 10 -74959454570640520505374182178324326240748657042677990093617716411759477136824854815262670168473667077524864904515489090301434501507378472350618141578200289566815110468728966378289347050752371322168328511598641143081017162500179880923097593329564317427467179672704707842937085621549781627579801356509572397210965270406925309382945647493757499822518272539171346319468210919037390479279679328187057939609889863122790083219768061816093131875491575840052493376341193028052061557296969558099473333023971577236615940525630787016398581105441977909848659239970133974969366933817929047771871736452423855320657946133173829640 ""; - - 10 687036505685680036980563991304827689190226068191165515873309582371531653761560838357887565473014960851061079052387145199258972778940173525017542879674305252823453991900595437468144352005006881129612951699750949026636206282574720840178116341517038998609517724307448384647380133273761360084019113505091720961437658149042479826982973196933684563380877276612883608481996579884762706391098995123384485837872544276099219443948234067623442105312332114374763392077663374681230289067615025968182722516808457505932863951619224171887832194148545132638772027329666389477813640620737624951105503846166715576529533580414958055708947608220960395455545922617914622611716584821091744228076205865701038484061060900340103461251087987631583104425599437283952841086221737575051158322973751353914369450945591184550003693808660890173148206999627057352641910478408389852121815588924208719373851205997267929487223022997903565246821511833717944887785333763131071163649350968541111796906733695518487580626938892775883629672280655177072837819344983336811201072380418330154409415723975489649421805372088286721361996667976678161505679350285875598457893785891475462099191282531966080162136450154198672623485698300307676277037616099696441730508788295411634665370788798384809584417102543248560317224205079917990766513568040641690632751952309869792602319263342525778046078743231821682847703178976601855555261436480615639995150308874740741630953255447186244703692652027199198662385455033073594432232250325046519267763604243367272471024553800469955272676941568451192546782745963075159357666087761637705388608592656535848292947073782242206595438203903079185128849386496430347274188109070907185471363018498891836986716946253163675821471661778024303689714601286352436391739170368727508436484115845640636653283093361670039386061546795520151041150800979484160765783927564359393959237330742523328888527872599693558141880251962681735003114604660394550415472363991770499647732372855076408144546777820449665557724138072899691283182780416000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - 10 687036505685680036980563991304827689190226068191165515873309582371531653761560838357887565473014960851061079052387145199258972778940173525017542879674305252823453991900595437468144352005006881129612951699750949026636206282574720840178116341517038998609517724307448384647380133273761360084019113505091720961437658149042479826982973196933684563380877276612883608481996579884762706391098995123384485837872544276099219443948234067623442105312332114374763392077663374681230289067615025968182722516808457505932863951619224171887832194148545132638772027329666389477813640620737624951105503846166715576529533580414958055708947608220960395455545922617914622611716584821091744228076205865701038484061060900340103461251087987631583104425599437283952841086221737575051158322973751353914369450945591184550003693808660890173148206999627057352641910478408389852121815588924208719373851205997267929487223022997903565246821511833717944887785333763131071163649350968541111796906733695518487580626938892775883629672280655177072837819344983336811201072380418330154409415723975489649421805372088286721361996667976678161505679350285875598457893785891475462099191282531966080162136450154198672623485698300307676277037616099696441730508788295411634665370788798384809584417102543248560317224205079917990766513568040641690632751952309869792602319263342525778046078743231821682847703178976601855555261436480615639995150308874740741630953255447186244703692652027199198662385455033073594432232250325046519267763604243367272471024553800469955272676941568451192546782745963075159357666087761637705388608592656535848292947073782242206595438203903079185128849386496430347274188109070907185471363018498891836986716946253163675821471661778024303689714601286352436391739170368727508436484115845640636653283093361670039386061546795520151041150800979484160765783927564359393959237330742523328888527872599693558141880251962681735003114604660394550415472363991770499647732372855076408144546777820449665557724138072899691283182780416000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ""; -} - -mptext-bin-in { - -10 010203040506070809 10 123456789 ""; - -100 01172d4359 10 123456789 ""; - -90 09124709 10 6713199 ""; -} - -mptext-bin-out { - 10 123456789 -10 010203040506070809 ""; - 10 123456789 -100 01172d4359 ""; - 10 6713199 -90 09124709 ""; - 10 0 -10 00 ""; -} diff --git a/tests/mpx b/tests/mpx deleted file mode 100644 index e30e91a..0000000 --- a/tests/mpx +++ /dev/null @@ -1,890 +0,0 @@ -# Test vectors for low-level MP functions -# -# $Id: mpx,v 1.12 2004/04/01 12:50:41 mdw Exp $ - -# --- Load-store tests --- -# -# The test loads each number, as both big- and little-endian, and compares it -# against the original octet version using a different method. It then -# stores the value to another octet array and compares. This is done for -# various sizes of MP, to ensure that truncation works correctly. - -load-store { - ""; - 00; - 0123; - 0123456789abcdef0123456789abcdef0123456789ab; - 00000123456789abcdef01234789abcdef0123456789ab; - 0123456789abcdef23456789abcdef0123456789ab0000; - 80f8c5606bff51bac932859a4fb6331c4023b32b65cd95f4edc1d1c919fcc078; - 522f8b1de257972a25ec49c9ff56340e2684e847ef2fa4d5714d7c8d454e90f6; -} - -# --- Two's complement tests --- - -2cb { - "" ""; - 00 00; - 000000 00000000000000000000; - 01 ff; - 0123456789abcdef fedcba9876543211; - 0123456789abcdef fffffffedcba9876543211; - 0100000000 ffffff00000000; - 00000000c1a4bc4b ffffffff3e5b43b5; - ffffffff3e5b43b5 00000000c1a4bc4b; -} - -2cl { - "" ""; - 00 00; - 000000 00000000000000000000; - 01 ff; - efcdab8967452301 1132547698badcfe; - efcdab8967452301 1132547698badcfeffffffff; - 0000000001 00000000ffffffff; - 4bbca4c100000000 b5435b3effffffff; - b5435b3effffffff 4bbca4c100000000; -} - -# --- Shift tests --- - -lsl { - # --- Simple sanity checks --- - - 01 2 04; - 01 4 10; - - 7 -1 0; - - # --- Copy shifts --- - - 01 0 01; - 0123456789abcdef0123456789abcdef 0 0123456789abcdef0123456789abcdef; - - # --- Single bit shifts --- - - 01 1 02; - ff000000 1 01fe000000; - - # --- Word-size shifts (assumes 32-bit words) --- - - 0123456789abcdef0123456789abcdef 32 - 0123456789abcdef0123456789abcdef00000000; - - # --- Random tests --- - - 13bbec3a734e0b8b5155600b0826b913 90 - 4eefb0e9cd382e2d4555802c209ae44c0000000000000000000000; - - d6ca6a99fe49b256f80e9643e2bd4f3e 80 - d6ca6a99fe49b256f80e9643e2bd4f3e00000000000000000000; - - c94784b40d54de614084915915531ddc 59 - 064a3c25a06aa6f30a04248ac8aa98eee000000000000000; - - a63c314a39cc37f950b3d530c95ead00 84 - 0a63c314a39cc37f950b3d530c95ead00000000000000000000000; - - 842d03a339f5004cfd311e2bb23216ac 62 - 210b40e8ce7d40133f4c478aec8c85ab0000000000000000; - - 9a8e659739bf9ee7aa908b7c058c5e7e 123 - 04d4732cb9cdfcf73d54845be02c62f3f0000000000000000000000000000000; - - 287f5774f212db87bcd83a1bbb7b1ad5 6 - 0a1fd5dd3c84b6e1ef360e86eedec6b540; - - ec1739174d9d4438d3093cf378605a5c 63 - 760b9c8ba6cea21c69849e79bc302d2e0000000000000000; - - 3dfa8ad6a60a783639d05aa5fbfd993d 46 - 0f7ea2b5a9829e0d8e7416a97eff664f400000000000; - - e4e93a80b6d25b34c23aca3a0d06d76c 63 - 72749d405b692d9a611d651d06836bb60000000000000000; - - 5a4cf5becb4b64a1a31637c91b6415fd 102 - 16933d6fb2d2d92868c58df246d9057f40000000000000000000000000; - - d92f60928b67416c1e20bd9e09026115 69 - 1b25ec12516ce82d83c417b3c1204c22a00000000000000000; - - eae78f56200d7734f7eb68479fe09d51 18 - 03ab9e3d588035dcd3dfada11e7f8275440000; - - 4c9c215ead951513d969d66614016f6e 28 - 04c9c215ead951513d969d66614016f6e0000000; - - 5cb1e4d625eac0393644fe6a7e3ff788 33 - b963c9ac4bd580726c89fcd4fc7fef1000000000; - - 68b23795968766c77b1897c88a5d6ba8 78 - 1a2c8de565a1d9b1dec625f222975aea00000000000000000000; - - 3d96cd168c74f9015afb691d629f3f6d 72 - 3d96cd168c74f9015afb691d629f3f6d000000000000000000; - - 38fa8f63dc426399e0f9b5c01231e02c 95 - 1c7d47b1ee2131ccf07cdae00918f016000000000000000000000000; - - 90176b493061899ec95677ccc58b8cdf 78 - 2405dad24c186267b2559df33162e337c0000000000000000000; - - 0706e95da68f32a4231ab184d16cbff7 33 - 0e0dd2bb4d1e654846356309a2d97fee00000000; -} - -lslc { - # --- Simple sanity checks --- - - 01 2 07; - 01 4 1f; - - 7 -1 0; - - # --- Copy shifts --- - - 01 0 01; - 0123456789abcdef0123456789abcdef 0 0123456789abcdef0123456789abcdef; - - # --- Single bit shifts --- - - 01 1 03; - ff000000 1 01fe000001; - - # --- Word-size shifts (assumes 32-bit words) --- - - 0123456789abcdef0123456789abcdef 32 - 0123456789abcdef0123456789abcdefffffffff; - - # --- Random tests --- - - 13bbec3a734e0b8b5155600b0826b913 90 - 4eefb0e9cd382e2d4555802c209ae44fffffffffffffffffffffff; - - d6ca6a99fe49b256f80e9643e2bd4f3e 80 - d6ca6a99fe49b256f80e9643e2bd4f3effffffffffffffffffff; - - c94784b40d54de614084915915531ddc 59 - 064a3c25a06aa6f30a04248ac8aa98eee7ffffffffffffff; - - a63c314a39cc37f950b3d530c95ead00 84 - 0a63c314a39cc37f950b3d530c95ead00fffffffffffffffffffff; - - 842d03a339f5004cfd311e2bb23216ac 62 - 210b40e8ce7d40133f4c478aec8c85ab3fffffffffffffff; - - 9a8e659739bf9ee7aa908b7c058c5e7e 123 - 04d4732cb9cdfcf73d54845be02c62f3f7ffffffffffffffffffffffffffffff; - - 287f5774f212db87bcd83a1bbb7b1ad5 6 - 0a1fd5dd3c84b6e1ef360e86eedec6b57f; - - ec1739174d9d4438d3093cf378605a5c 63 - 760b9c8ba6cea21c69849e79bc302d2e7fffffffffffffff; - - 3dfa8ad6a60a783639d05aa5fbfd993d 46 - 0f7ea2b5a9829e0d8e7416a97eff664f7fffffffffff; - - e4e93a80b6d25b34c23aca3a0d06d76c 63 - 72749d405b692d9a611d651d06836bb67fffffffffffffff; - - 5a4cf5becb4b64a1a31637c91b6415fd 102 - 16933d6fb2d2d92868c58df246d9057f7fffffffffffffffffffffffff; - - d92f60928b67416c1e20bd9e09026115 69 - 1b25ec12516ce82d83c417b3c1204c22bfffffffffffffffff; - - eae78f56200d7734f7eb68479fe09d51 18 - 03ab9e3d588035dcd3dfada11e7f827547ffff; - - 4c9c215ead951513d969d66614016f6e 28 - 04c9c215ead951513d969d66614016f6efffffff; - - 5cb1e4d625eac0393644fe6a7e3ff788 33 - b963c9ac4bd580726c89fcd4fc7fef11ffffffff; - - 68b23795968766c77b1897c88a5d6ba8 78 - 1a2c8de565a1d9b1dec625f222975aea3fffffffffffffffffff; - - 3d96cd168c74f9015afb691d629f3f6d 72 - 3d96cd168c74f9015afb691d629f3f6dffffffffffffffffff; - - 38fa8f63dc426399e0f9b5c01231e02c 95 - 1c7d47b1ee2131ccf07cdae00918f0167fffffffffffffffffffffff; - - 90176b493061899ec95677ccc58b8cdf 78 - 2405dad24c186267b2559df33162e337ffffffffffffffffffff; - - 0706e95da68f32a4231ab184d16cbff7 33 - 0e0dd2bb4d1e654846356309a2d97fefffffffff; -} - -lsr { - # --- Simple sanity checks --- - - 04 2 01; - 10 4 01; - 7 -1 0; - 7 32 0; - - # --- Copy shifts --- - - 01 0 01; - 0123456789abcdef0123456789abcdef 0 0123456789abcdef0123456789abcdef; - - # --- Single bit shifts --- - - 02 1 01; - 01fe000000 1 ff000000; - - # --- Word-size shifts (assumes 32-bit words) --- - - 0123456789abcdef0123456789abcdef 32 - 0123456789abcdef01234567; - - # --- Random tests --- - - eb4f57af83f78c0d67b3a6ad84e62378 120 - eb; - - c6a207d80522139f1fe168028d6afa8c 45 - 0635103ec029109cf8ff0b; - - 6027a129cf726a80445bf42a310ecd30 51 - 0c04f42539ee4d50088b; - - fb0cc20512774733c783bfea0ea3b503 36 - 0fb0cc20512774733c783bfe; - - 4f9884d0ec9fc9e3be6ac15382803eaa 107 - 09f310; - - e47895de118466ac7b16188284b35fb9 55 - 01c8f12bbc2308cd58f6; - - 22dfd1386bd2a5c4b6da0d619485e735 10 - 08b7f44e1af4a9712db68358652179; - - 489fab826eb8ce9f41084c2b4ea3bb25 117 - 0244; - - f6f7735e7d89edfa05482a6b19b1d7b6 53 - 07b7bb9af3ec4f6fd02a; - - bd4eda78b316190a28840f382a90bc63 80 - bd4eda78b316; - - af9f01ddcecf1d21b0af4c318df98e4f 39 - 015f3e03bb9d9e3a43615e98; - - 64d53464e8524ef2529389b14f2b9940 19 - 0c9aa68c9d0a49de4a52713629e5; - - ce49d3be79896131d044f41274ff13ee 99 - 19c93a77; - - 25a05fcae2ed3d9e2486cd633bd51070 18 - 096817f2b8bb4f678921b358cef5; - - 8a29be64acc97626d097231c4f3df4aa 82 - 228a6f992b32; - - ac27fc4590675fb16ecfbf774dc8e591 14 - 02b09ff116419d7ec5bb3efddd3723; - - b72f02eb26b965133db98adcedfe1e37 44 - 0b72f02eb26b965133db98; - - afc634103a039f37b8f9f98b1d94ac85 52 - 0afc634103a039f37b8f; - - f670a78a3801b81e0a00e5b5deb81a47 57 - 7b3853c51c00dc0f05; - - 3a1d23d0d00fa4e165ba2b54eccd8f8d 92 - 03a1d23d0d; -} - -# --- Arithmetic tests --- -# -# For each of the fundamental operations, there's a sequence of simple tests -# which ensure that the functions are working even slightly correctly. Then -# there are some tests aimed at limit conditions in the algorithm. Finally, -# some random tests dreamed up by the Perl script `mpx-gen.pl' are given. - -uadd { - - # --- Simple sanity checks --- - - 00 00 00; - 00 01 01; - 01 00 01; - - # --- Carry propagation tests --- - - ffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 01 - 0100000000000000000000000000000000000000000000000000000000; - - 01 - ffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 0100000000000000000000000000000000000000000000000000000000; - - 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f80 - 80808080808080808080808080808080 - 0100000000000000000000000000000000; - - # --- Random data tests --- - - 272724be3cc4179a4b387bcd1acf24e1107be9bbb4dbd68408303df3537c83e0 - c80ff7173b00d75c83bb38948118fecd9c16ec3bc2d5d051057a1ad8dbfa3349 - ef371bd577c4eef6cef3b4619be823aeac92d5f777b1a6d50daa58cc2f76b729; - - 257099bff6868847d89969cfc691e1f5e0af7516360493a8dae919704eea7385 - b4408b380c648d50175dfa8b9c1d8aa68f71f67b540045ed3f92f2aa19145cb2 - d9b124f802eb1597eff7645b62af6c9c70216b918a04d9961a7c0c1a67fed037; - - 11978446632ed887ce26aeabf9997a9ae9600da7cb6d431e6ab5dc932b427eec - 652931ca2eb81d3113453615d16e60de08b3777a6060d7f1775c916253b1e666 - 76c0b61091e6f5b8e16be4c1cb07db78f21385222bce1b0fe2126df57ef46552; - - 73d3697b4f886a8b242c21cb39151055937f36a6000849d0d1e526ce666a7d52 - 209e8d770ab7352e5441f74af428a2e9b791dabb655fd78d8a722055e896d7fe - 9471f6f25a3f9fb9786e19162d3db33f4b1111616568215e5c5747244f015550; - - 3e47ae33e633861903e0960b1ef8c8c8900a659cb3e03a1cf1ba04eed5e3f93d - b844b1b685b21fce078e0db2b960e22dd1e81aac33062b6d9ed1ab68b8cbbd67 - f68c5fea6be5a5e70b6ea3bdd859aaf661f28048e6e6658a908bb0578eafb6a4; - - 23156b15f2b9a6598b6703cda3177d7432016bb388989d5e33a5cb8778aca38f - 77197a3167c282ed511bf0eb865be89624e4b5e1e9dd4b7d44acd59d41287639 - 9a2ee5475a7c2946dc82f4b92973660a56e621957275e8db7852a124b9d519c8; - - ed61746de1ab76f33cf25878088b24a389d79ecd65df792954a5788a887982a7 - b673af9ad91712c6d64f05cc14fbd503b04345aca5695ef26cad9ca1f1460496 - 01a3d52408bac289ba13415e441d86f9a73a1ae47a0b48d81bc153152c79bf873d; - - 46a147c2b345b5ba782b600d1811975cd6a75b9bb6fa6db6bd8c594ecead30b3 - 3dff366370a27aef1ec46b32c4946f90ef75c7263f71703be87074ba18705391 - 84a07e2623e830a996efcb3fdca606edc61d22c1f66bddf2a5fcce08e71d8444; - - a1756514e2f8c5805538ad1b85bafebeb1d4ba9c61d19fbf2f286518eeac08fe - 4646f60744b71c5d7e2a5f66250e0295fc6ddf5acae1f2397ad37403a6881e24 - e7bc5b1c27afe1ddd3630c81aac90154ae4299f72cb391f8a9fbd91c95342722; - - cf5f959a7c1d3d0027f62303d4a517bd5acadde74db6f18bee67aed2ee1bbb23 - 76e38874ce5c3b7fe616b20f2ace6cf550190d9bad4b2fd80bf6deaff8a329c5 - 0146431e0f4a7978800e0cd512ff7384b2aae3eb82fb022163fa5e8d82e6bee4e8; - - 1dee3d9ad0cc6212e5843a57d736fad4675c422efbbac6d625a0f45ee90b7d73 - d6df29c49292fe633ec60e597d0c5688eb0ba6c134b7c041689fed3e72535c55 - f4cd675f635f6076244a48b15443515d5267e8f0307287178e40e19d5b5ed9c8; - - 3ba228e4e40cb50141845ae8b7318b43c6643765ace7ce83a069f1787ece6058 - 06b3792dbbde4db5f47be20035524962224fdaa18be7dd9eda23f1671e6ad33d - 4255a2129feb02b736003ce8ec83d4a5e8b4120738cfac227a8de2df9d393395; - - e7ff758bb68a5a6106962113f72f9705dc0641ad029741f7c57a5320d030ad32 - 7fd185b393c432dba9892a0b67aa12a85be6e1643cdfe8404963fe92f4f668bb - 0167d0fb3f4a4e8d3cb01f4b1f5ed9a9ae37ed23113f772a380ede51b3c52715ed; - - a5bb634cb6ffda70661189874605f802cc34a8960a137130f238638d9a9e72c1 - ddccdab554733987e04a5aa8674b5eba27f594f37cdec51b3b5745dfa159aab7 - 0183883e020b7313f8465be42fad5156bcf42a3d8986f2364c2d8fa96d3bf81d78; - - 76888f3fc82690a4681e30b5f94efd08d03b7eb1c814ed01cde866847e3c75a4 - 78d0869abb1b1fafc582ccd8bb0c27d7ba51de9832d3b0cd8ca366d27d268788 - ef5915da8341b0542da0fd8eb45b24e08a8d5d49fae89dcf5a8bcd56fb62fd2c; - - 24fbb9214449c926753d15573ca07552ff219c97c43824182a6dbabed6872610 - be3795a426052f168129345d33c6dded8ae8de0e0cbdbcc7c2b3f3386031b548 - e3334ec56a4ef83cf66649b4706753408a0a7aa5d0f5e0dfed21adf736b8db58; - - 97b74ea8ef087496a84b73ee7d8713a13a511f40cc9a19f613a10891774fbc9a - fe8dd31272be1f79ee524d736c7fbd3a2c1718b918b072025612a1f2176cf53b - 01964521bb61c69410969dc161ea06d0db666837f9e54a8bf869b3aa838ebcb1d5; - - 66a6b572a25f6f97ec5b7e7e393bfd686b69c083cd673feab076b9923133a46a - e7b501c43dafc08bc521b15be8a1ca9dffe174c282111ea9eb0bac34fd0584b7 - 014e5bb736e00f3023b17d2fda21ddc8066b4b35464f785e949b8265c72e392921; - - 59a803f729f14d54c35de20cdf9ce5b8e2f430016448c80e9d3e2ec608f8bd67 - 7a5a9cf43d1d70e200c5bc7baf4dad57e5892866bb3ced09eb0ed096214509b3 - d402a0eb670ebe36c4239e888eea9310c87d58681f85b518884cff5c2a3dc71a; - - d26914575527153ca24945f0e83df5b0480c8840e1e6807b71d008068b082c7d - 281c235d8f8773649c75baba0c302f99f3c526c971cf3daf976deba0bdb3f38f - fa8537b4e4ae88a13ebf00aaf46e254a3bd1af0a53b5be2b093df3a748bc200c; -} - -usub { - - # --- Simple sanity tests --- - - 01 00 01; - 02 01 01; - 05 03 02; - - # --- Carry propagation tests --- - - 0100000000 01 ffffffff; - 010000000000000000 01 ffffffffffffffff; - - # --- Random data tests --- - - a024729f63161b8fbb711008eb863b9e2044a77ccc7bccf19437471e51a4beec - 9239ec16929055e3a156768fa1432c56d997ba51c1efbed4c791f062d95641a5 - 0dea8688d085c5ac1a1a99794a430f4746aced2b0a8c0e1ccca556bb784e7d47; - - 8ab8ea06c7afbdfe6636590f748fdd376a2dd9c708e7923541e134687fbfd526 - 8896da6b7c98b78a0ea2c9cae23d7065a94daea56d1c919a7db2583da936bd8d - 02220f9b4b17067457938f4492526cd1c0e02b219bcb009ac42edc2ad6891799; - - fedfecaf26399ad6eda68c7c5cada4aed095e82182e3df696cae47e521c382a4 - 7510069be2896480db0beedc6c5497e79bd7ac5e9fc14bf9ca460c7f99aa6834 - 89cfe61343b03656129a9d9ff0590cc734be3bc2e322936fa2683b6588191a70; - - ffb81ed18909fda98730e146735c21d3914122faf84882dc688237371825739b - d7eb8f85d95888d2c4dc7b9fbbe689e2ce529f8870b2487ce28d192ef3ac2317 - 27cc8f4bafb174d6c25465a6b77597f0c2ee837287963a5f85f51e0824795084; - - c3c2c77bc0867d30c58c1eb786ab7feed60f9e0e2dcfd6ed97725fff364c7b5b - a936ff836dd8dd063ab05e4fc7176e8c05a45ddaa7f701e4184b4fd371ce968a - 1a8bc7f852ada02a8adbc067bf941162d06b403385d8d5097f27102bc47de4d1; - - ef76a6e2dc6ba3317dcec6e338a20cf12eb852388204efe290a3b1536f6b198b - 3eb8d18b7903d682d713859f258ddbc13aae32392a4267b0cd1481c036ab5baf - b0bdd5576367ccaea6bb41441314312ff40a1fff57c28831c38f2f9338bfbddc; - - 5cf09a0f0488a077e2983b4a854c28fc7a11f7befc196824f7990fadacfc26db - 0f46fbc396b81c512b7a0ec003759de05a967101a3ec50b7cbf84f42708f396c - 4da99e4b6dd08426b71e2c8a81d68b1c1f7b86bd582d176d2ba0c06b3c6ced6f; - - ea9b202602ad3219e3d3a8fbaf042c3cec8a3d7f16923855b0ae67b8ebf57b50 - 850568cdebe8fe9f91c3d8bb4bc525158bd8590b235f46d6d556bf969e2f24f4 - 6595b75816c4337a520fd040633f072760b1e473f332f17edb57a8224dc6565c; - - fab03a9f849f408b4af55746316f8e3a81c6359b3c3ba1ebd1d8b9e7a983a03b - a60ecaf59c0c7d0ce3ef4d6d9006880efc9c6e0edcafbf7291b009e7b3cb03e4 - 54a16fa9e892c37e670609d8a169062b8529c78c5f8be2794028affff5b89c57; - - ef7de9bf497c4c47d323a379a42789925606f700e786622b280aec1ee6e13901 - 8a4197e881f1d2f6a09296e6d826ea628aec658b4bf7e9c436ab7e70746c4c87 - 653c51d6c78a795132910c92cc009f2fcb1a91759b8e7866f15f6dae7274ec7a; - - 9cf0d943545ee18ca59af6f547cfb45de41b1d52c996f482728fe68993d3a966 - 58ad4b10fc09cf4f4f4a1488e36ed3beb0a2a9e8c8ec042aba113b2144ff1939 - 44438e325855123d5650e26c6460e09f3378736a00aaf057b87eab684ed4902d; - - 3e0e637d1f4ff5b6d58549f8011ae0a885bbdcb5c478777417e6293c108c7c0c - 09e06b0b986110817123a2a5aad0c178bac3005315628424d849216a43b71ac4 - 342df87186eee5356461a752564a1f2fcaf8dc62af15f34f3f9d07d1ccd56148; - - c3b4cb636f76027a876150753e266774af9350d3e68713adcc39cff5e389e285 - a4abec0b5d38bc91310f3b9e3e12d0c4af2984ba710a6309544340ac3c94e121 - 1f08df58123d45e9565214d7001396b00069cc19757cb0a477f68f49a6f50164; - - 175402d43706fcdb3caf41cd8de6822447e39f3a0ed2f00d4d315a1cc03b5bfa - 0ffd7d0692776dbce6e112902472edba5ec4c1500412d9bcd24472da90889b7e - 075685cda48f8f1e55ce2f3d69739469e91eddea0ac016507aece7422fb2c07c; - - f6060bfae1e558606d44496967e0eafe805e6f60d1c4a8f886574c9d6c6989da - e933391716ffc61eda9c547e7bdd41799ecc56e05178ebd7e2068d32467aace6 - 0cd2d2e3cae5924192a7f4eaec03a984e1921880804bbd20a450bf6b25eedcf4; - - cfd8ba6b7173b72451f370c7a7dad7754ea2323e52f622c1490ff2d3ccf5753e - b4e23f1700a3fe1d5f0465cf3666235f1c7460ffebce87c8b8d551ceab09ed1b - 1af67b5470cfb906f2ef0af87174b416322dd13e67279af8903aa10521eb8823; - - ebf9500e9cda50607204618fa6cf2f29f2e0af023237034f1a3e72787364370d - 0e826c97712e73f32d850d4cf63925fe8c8ed86396350432b9971900a4068cbe - dd76e3772babdc6d447f5442b096092b6651d69e9c01ff1c60a75977cf5daa4f; - - c4f9d29310ea767aa8dd0af418447dd3dc2c220c48591f99b6dbf0521f7a5640 - 6d72f5441ca9dbafcbf4db9701d6c667c1d5376251de09468e3efbf1fb04cd95 - 5786dd4ef4409acadce82f5d166db76c1a56eaa9f67b1653289cf460247588ab; - - 91af1ae9122ba385deae3f9b478c8270a2d2221396fb3639b44e06e3a1ae9817 - 08966b342d42332d2155fe03fef2d3f84b415d1fda1168a5c63d0f9b86b77cce - 8918afb4e4e97058bd5841974899ae785790c4f3bce9cd93ee10f7481af71b49; - - 976e1fa5146093d794691c63d1aff7ceb5851bb6196909eb51fbe4640829b208 - 1e8a3a0a9050c307cd94a65793371f88eebe42ae8893b1ff984357d597c884d1 - 78e3e59a840fd0cfc6d4760c3e78d845c6c6d90790d557ebb9b88c8e70612d37; -} - -umul { - - # --- Simple sanity tests --- - - 01 00 00; - 00 01 00; - 01 45 45; - 45 01 45; - - # --- Random tests --- - - 4162c300b3e157e9cd1301d499c20121 - 10549901fc6dcb85882440087bd398ff - 042bc7ac8fe08ceefb098f286cdd84fd037906ead144324e361c488a221db7df; - - f4c0a35591d6567a3ead2846f4350141 - 58bb07247f8a7591b7acfa727118ad8d - 54d507b0e32175976a30766da14de0726a8ffbdc7ef0291a7389759422229dcd; - - 5d0965f58c9d794ca477ca2349900193 - 2cbff5f50dbae1965e3aec1108c36d17 - 104360ec53eef2e669285143dc0d01c9ccf31a77dc302bf8d45356feb794bb35; - - 1a438b12e1babb4c68ae4606694fd1be - 5bac6d40fdea39c2f1f6ce285f028d36 - 0967b3069413a0fac34c03fdf67e2f5187232be344bbc6011849688052d7e414; - - 59e648d1f656407efc7c9b622de6bc6f - 0dd07d6e4dc035816236aa0cd512e424 - 04d9e8da01ea1a42b1b9670a4a14694cd104406f346a0598b65e0ae58f135b9c; - - 55c69d7a662a945e6a535911e7abdfc4 - 9883a7ea2c89f5a873b5bae63cf5ac73 - 331a0a66497eb713fb09b260f8774aa97765c13bb040d7917a4b7cb9a321350c; - - bb15812991a5a01c6e803475d5f2f1c8 - 66782adade0952e8ab51a2fda6a5f611 - 4ae262dc95488914177d07869caf42dd008ecfc3c092df3007fca8702f603e48; - - b06a37683348e8e46ccd954ff0348a82 - e158b834e442cf83aa863dde751525b7 - 9b4a7e266b977f83598e6288efafd0f517d9658a2bda86adec7e1835143dccee; - - b7f66a5ca27d276bdbad5995aac0f676 - 8f05519b9acbe85369aad7a865a0bc5e - 66c677de9ba98e4c527c86b80ad1485c41782c3e0be53dba2f547fa0ff992754; - - b7f43225f41056548b095f359b6a3b83 - 966a8ba6772991700ead0e01bde39120 - 6c15a4d835ec2367ec41c566ce63a098c496aec8a5b041fc7c91e6601525a360; - - 87277faca81e1bb28e0e24e4bbf5e8c3 - 5f126e08716855110489045453e69dcc - 3231633f7a7eb05793df2c7761d793a634faeb021fda1a404f05b2edefe71264; - - 3358074e192e79ba42c186ead80404a9 - dc1df51ac8c3328107638e83b17f777a - 2c25a8688faf32cb8b1d4b454cd4a2ad1130df69188cd2ec44cc8806f8ebc78a; - - 7ad1d7a04f7588af0ff7bf29c13533c9 - 0785d4d4d5f1d25aa6dcf744662ab2d6 - 039bf2064b716e3befa638d510131596518b1d91833200ba19ae6aff15750c06; - - 8b8a4c2ef785abd1607b663b3088e37c - fcc67dfa767e06d97cfd5341ded07e42 - 89c854a034d2cc29ebb34f379d6a74a9996d261774b1e7ba965e98204001adf8; - - 1c9ea6a1b9aba96124dd8abfd3dd78b1 - 93ecdfc3f4c188819e777f082b77e4c6 - 108994f4961164206f1a97cc0f39edc29faf2bad99d164fc60c06ccff20ffce6; - - c6d9a8a4760fffb11ac2d38b62f62a89 - c0989f4e8aabd21f7a2b38ec27afb783 - 9599cb75abf86c37db000858bd671992ecde9d440cc765855287391f8f06b31b; - - 5d48ba3dba86c0e9d3922cab8d88c5b7 - 5186010a8c3fc4e3499534669a13f219 - 1db4d7602500cc34de718d5892f79db44096a6c6705cf6e9ca8b438cdfd74cdf; - - d009f15fd77915f113e471884e464462 - cad68bffeb24842cc083f5496b10e36a - a4d6328ac530f0615ca3b0aebeaf104960e120609c58710eee206cc3f3db3694; - - 343f0033e5648741936c20439bf044c3 - 9b26545821fb1270515566d970e566bb - 1fa9f7b01c40607bdc8f554e57555de879784cdb1eebfcc3a75918d27656ec71; - - 08d95fc1d6dd6b9423c7bb033598df0c - 6c03f5958677efd383509141bf257375 - 03bbd76f19ba19e3f255c24063f6384d4ac913d9e582392589a525195bcc547c; - - # --- Karatsuba regression --- - # - # This bug was caused by kmul (a) choosing the split point too low on - # odd-sized inputs and (b) not allocating enough workspace. - - 21a9269d7b8b63cf18faa933b3c868ba1e8cb3f00b57e197709abf96eeb9bf12e8fe22b3 - 0144c992b68e3ca712678215d5bc968702ccfea17717737ba501a38d26fa5091ba - 2ab495f91afd7c36f85ece6fd58577f995de88d62a98a07c6d9e3500ae67b0f100bc709d1f30894662774d0cadfba091788c427cc6f4bacb26e42cf92f6e4494e03c990e; - - # --- Larger number tests for Karatsuba --- - - 416e63549e2cf08fb225058b3545cb4a47cbf9 - de38c473c27f7bdef02a084192b3e17f435cf7 - 38cc3c7f360737411df7b52a222a3672c6e0d39f0a868479176a6143e1129d44d5aa61be493f; - - aa20b1355073f21c57530d2f90bc40e47ac463 - 8315dfa60e97ff3dab7a6f61fcec2cd5b6f127 - 571d43fda6ce14a78534ac72c50b58738d62630766a59a7cec1a63433e499b1b5eac5ef71e15; - - f641594177c8c364d922c659a8f7ae0460c7d74b266c8cc258ad5f - 5948dd29fc5172c37c31da6957779a1bebe452d8deba26c5d3d390 - 55e2cf27aa49f938584dca4044d944077e226206c6f8c7688e8760f3b5c106413fd0ef4b63a97991da86fd113ff4822a41f76913d270; - - a4170f55dfa135c4bdd3a921a8c1567eebc6b799fb62b0dd27b089 - 7b7d619e07a5d01427348c05605f67196b2923b074787c375977ac - 4f277232c75290f0c5fed384dba2aaa23fe4a360ea63ee45fb6c0134b36a09a9163f3c767d498b8dcd31e5deaef386d4a9b7d85b4b0c; - - 250e7a0c7035df81429572d3f772720e723b710d54b9eb5f16814117980f0559bf12b82e00c5b3904e - 1be3c88b01ce53a70c12f74dcc247823846ac6c06a9cb41b86794900006045f05e29da23b81523aa9f - 04097fbcf75616fef7b6b91680963f7e0cf1bf72bc5f453e46136fc92b20ae8a30d7ae7965f8271de854442b93562ebaa9ee09fba4a7b79ef8b26718b12424419dc301496dc0d6cfb04e4f7a3a3729046c72; - - af3148a72dcf1340f6b5a3b2fc1cacd7e6f9e60a13de5c91c37bb850f0e930683c2dc96882a9f62b76 - 48603cc656908b34c70ed826da8c3414d5845100f53cb6f9f370a4c7708a9b8ffd787537048f89493a - 3187b8818bf644805c880d189bbf606ca23e01431cf5b3b633db48a1202aa346f6a0e3958c7264fa1de2d92660345e820f4f3659cf0040a28fb9b725f7ab83610c9c056062326f776ce871696eede0507ebc; - - 0b1cc934a2f6244b93c8ac10881de20349d133642ac19fa0be3acacbf4429d0ec7bbad2f41534a693647b7c02e683cde249e36f008fb68e96de65c8a268eb1ea - 12444899c13f0ee85a4f47024f06d8a5746f0d9fec02e57c6d87a7bba17c1454fe6387bff5b96e38ce6142b9eebe249865c52b617b8966e6f93b16f612a91155 - cafcf1ea9f16a56f9ac4635d58992a789c51b6d7e53b5e1d8b59d5c1850c5c6ac2297839af44b29d5cf440772f98fd9d090ccec2d56adeb113bd3459d620b0b02679b72f3170ea8e2bd4486eebf2496d8be01cfe86923e5bbeb6f91582dfb95c6ef0a52cbc068081dc363b31dbd2ed80e3267d973ea39f82e276002eab9cb2; - - 3ba5a9c550b8cf6c3b87cc106b6551221a0dc90ac193ebcc526e4e5f53cf012fa6e05b155dcb3c4c0e1a90a01062a67ec434f6744195349194770711ea836a8b - 54f04f121d22db842523e9bf75727d5b0e9ef17e6d727918894927fade87ceeb2106684c4af7c49653425e29f7a91abf8adec4de2ca499df2534644397e454ac - 13ca59703f4c087c16a9a7bc7022904a37a469c1d0fd9fa7ffabe8f7d887fe1572c0bf5c75fde6913b565f8106bba9c26c9bbce190a9b8967112d74c0ac3d4ff9d2a385b96833e3c456d5601c74d8d2c9fff35abc60e7cc15d7c680f20757c13a415f1b8fbe3c6c32434aa36c528473dd20ea39f0e5ee22d1cd23040900d3164; - - # --- More Karatsuba bugs --- - - 3fef06998b0ddd140e01527426ea409b2b9e640f223dfd652229fd17eb99d44f6be6d4935505df676f48c8fcbfe2d5096345d6509267aa40c54d427f0cce45cd0f8fa7e4a22492d7ed4ffa45e3c0e5e3c25c841943fb2cecd6ee9275ae93c4e15e2d9f8f317c44c541ed52a6338b0fb9f7f7f4dea78cf7ef5201837c00a6d4d2 - 0260acc6378341b2b894dacab3a44b914f19292bb32898b155584a406161bb04ad9c14db20888dfcdab613b368b5c699305c4e9b226d90f9523fbcb6293407bd2bb18bf7bdba8539fb577f19b72124c2d83a2bc31f44366e917ddc705085b79fe9e0df0e98e4f6ae3df63d9b321382c18b95de1dc4d1db93b3092c9c6f8c9764 - 9802d5c5d5a73f9d4e694a8920f951ce4bfe80c13a35cd5332a556136b83495a2e9b4d2ed53aae1218d2e1c41349311f86b1ee1f2ad5cd3c5b264e8e68906ca45bd7d0fc8e8a5a9648f458cecba41fd0848a04f506bb11ddb378f3214085cf865ba5533cfd73b28b1e12784f447b156f59a3b68e6ec68303ddfce59ce33ca386ff3316e6a5e6f9b4201682aa9e59a6d7cb9315a492457640acca19fc7dc3a25a316fea9a0f1d32838b7f911650647f996551263c2d001fa1c720753afca316c7137300ff93f2ddd2846ce14c55d0ead626f681bd11707f9674905396a9bc9a889eae721ab6407586880a95575a968b43bdf50323627aa0fcddfa4e198b0008; -} - -usqr { - - # --- Sanity check tests --- - - 00 00; - 01 01; - 02 04; - ff fe01; - - # --- Random tests --- - - d573446554727d0f05ad3ccd03665c2f - b1f903b723d65fefeb935ef5c50ab18da09777b28b8a093adab73a5cb0a5d0a1; - - 27ed6604397ef6acdb3f1906e5c0be25 - 063a313b55fe82206c4e69624c2afd726dcf52c1efc9d0f81c948907f6baf159; - - 869593eda5bbb87109593218d3c99f86 - 46c0ee42519e3a8ce80f19b6bd60332254e1e144350898d77e803ce2c7d3ba24; - - 94edc3ffcbd975677c95b44e7f4a8164 - 56a3c77441629088100fea8b3e510352c9904877e9705b9e150e7b004735ef10; - - 4a3b7b546f9f15a09bd35d6de3b33f82 - 1586711ee4ddaaf121f7e4311d3e182948ed5569def0257e099be8d66b8d3e04; - - adf038609b8f95940806994831db9409 - 762e8d9c53ce25e6641019bd974169acd1aa3e95968b13e80c97d2120f006851; - - 337e87847e2ddf24444fac6f64c6cc66 - 0a5ba888786f7db6d9c28a7482545e31ce687996024edfdc05ae3a8480fab8a4; - - 0b2c882b8a7dcad93cffc77be4436e62 - 7cdb72d54cb539de9fc55d68b9ca4731ad6b1bef79fd0dd12c9c8d86e45d84; - - 298a1b9f23f7e77dc288c177a492843c - 06bd875ac41323efd9b958064f96e74d84faf58a2c43f4bec525750ff8bdee10; - - f58345742a51bd04c80b3791a688871e - eb74864080bb96f90ac10021b82af6ea9acd21af8b8c103739a14c06bf30a784; - - 0c720ed1384848bc57e6f92cd98541cd - 9ae434d07874574a5702724fcaf6d27f5686744f03aa444afe9762f9ebbe29; - - 37e91e1c9a3f237a08dda2e6919dbfa8 - 0c35ff381de29f85eb03c278ca9623be8603ac9f744c826d08e91630f38c1e40; - - 8b270d9328ea8561db59a8ac4e651d05 - 4ba36eb2f1fd6b0cbd6f71ac36aabe1be53e21ae9afd4c9ce1715456f53c2219; - - 5e64af22a077e8832538dc9ff235bea0 - 22ce1836b8b5c880ea1e00f95f339ee776d8edda0563e498c98f726efc31e400; - - 8e6d67cd33ac976b183475e54afdb715 - 4f3d8de934283d046ebdb7263c73978e60c2e68179cb3edf79c266dd867107b9; - - 27f566956e3fa7141088402630e929e8 - 063cb07f0ab7d5d22828664724da2dd261c14526d80f7760aa04b4f44f2c2240; - - e26c74de93a02296693ee98e552d5524 - c843ac4bcdcdc37c3ef17997e8d013d1d4ecff5a58a22e2be50d1e80f2f8ed10; - - ca53baed02dd4ba78cf7a3963b438395 - 9fe83e60c6b25a7b58d1f84a5905081769b4c5b5c9b1d63a5bec2110d19fd4b9; - - d6e517000ade8ef62963e890a472d530 - b463cf763a508b234fbf75a75781c97b5a9963b8f8456d23d05a2aa81048e900; - - c4245e0ce04fe1151ca17eb8aeb6e3e3 - 9647b52e4da6dc80171bd5495ab519835e871bf915ee7e59f1fe2ac165a05b49; - - # --- Large tests for Karatsuba --- - - 8390d2dfc9770526e8c4820e1cccca0e8e19d2 - 439d89bef1a65f537e59e74590df3ef10b7e78066ac2af7b5c910e1929de102b491b9f92b044; - - 26c4cb564d57970bc3dd00c0c1690c7f1a2e9a - 05df03a59c9e6ab7bfed79ff8f32811303e46f94c2e8d9abcab5bdac1040e7fdaf5a4bc3b4a4; - - 599b3cceca39690c06425127a95b84310cddef - 1f5d4e6a797662648e4b09abeee439415b76cae52e7cf9db1a54b7f99afb9c00b6130cce8521; - - 485b65b3d5edb34810402943ccfbe37a137f8f - 147389d69e9730f86b04a1782fd15611e6f8dc2e99abc812be0cb82efb2a1ad538aa7ac931e1; - - 5a243e54da1f87a8fe23c8b0988b3574aa77c1fe620a5d25b8e03295aebe6c6e135a17 - 1fbd80f54068ba081e793c1aad443094416a75e2e708337618e4ff02ca9dd26bad87cdc0f758342df39a56625c956c971b1f7f18f7d3cb6a1880a574bb7b06a6ca4a431e2e11; - - f5c57a7610feec56586de369136ee25aaf5d3861ad80033410c410658332ca856e4cce - ebf394bbb0d2d75ba78b75ae018c77f417cc1c67f0aa587d070980386e14f2b59d9a580d8d483b4df7f6a8d4a44ec8786a87d1da031bb5c288c3afc65d931471786c2412f5c4; - - 5bc4457e00bcacf257200a96eadf90359cbd9f6a2c2c69b5ea2e4c5d3939f0ce100c06 - 20e51fe210546e478bfb9d2b0418df921974417799951533f317498439caed52a75c4c66db81910b3fc4f4fb3711cc25f2b4ef151a2023b6e52e64e1d5b7dffb0b9b29509024; - - 4b51f1e0a9206173d39a0f1f4eea558dbd9d1ca2d41671b2d27b1b77391e76504e14c0 - 16291df497ccc32ee92a9037b78ff10828c2645dfbf91541f3a0d963892d59c5cd966ffe1e1ebb2dfe6f434fae44da11ae2d2357876b711feba596612c102b8905c8a6ae9000; - - 10f63541b2bc5a7d241f887d0b3d182dc473a06c4fb275259112b2fecc9455d7b1eb5b2e9b5c3646c35121d05f1ae99f1ad990c7f0e48b002bd5fdd253c68b56 - 011fb3729baf522bcaed9a966645754804b2cc80168de9f93544e17d5b6d6b81c516f68b72580257f15e3f95bc6eec22608c3055de04051598bf4a76975d111a59d6b02a2fc42de65926cee5d5b97b6c7fc85e00dd59bfdac2c95bc80b7657582b2853244e55b507594a83d5bd87b7a83016dbbc104ce596bdaaed6d98de80e4; - - 9e40b3c041505a5e266109f752d85ae3abcbdd28bfc70bbb2c7228bc1564ea893cdda0350689610b74babfe45b14da9708f28c22e3999c841fc70075dd0535cb - 61d3ee3baef64371ce0416d3f5a6e687903413ad06e85ebbffb9ea0ae9e8cc290fe9dc1cec429e0a294b18121ee29755baf4306861e092e5c1f1def03953f559766787a222368b64594b7be2eeea0698d1fc630446714e681210b5a66e0433b6c43038c0ff213cd14fc0a1fb71789d57b097ab44d859f8bc912f2a89a33baef9; - - d35af50f523d29f53bf0126ccddf4f3052ddb44eeaead360b5f36aad902ba105a921880cefb12caf5e1b3719a40596732d265e996e491f82ca2edf08adca131e - ae7f10487aecfa7f91217020f96a1cb00d81545deaf9730daa2c7113e84e76c7e54a1b14971d26750816a696d55622ae1dbd56befdc12a656e66e1d10e87c3bc209e0903635784af6d48a4d7ec84634efb91b7efbfff724bb50ace7d4684d2e72eb7eef84ed5cfd14a7602ceded675da541646febcaa285396b23338b8c57784; - - 3df659f884c6a31c5b332efc44fbd70fea46b81adb241fc651af038380f8c476a471f06382ebe55eba339d84edb33a03002ac505d93c61a42ba20e36a691c287 - 0eff53f178849510a118db72c5620423c2991365b06e8caa76300f3df554cf8830c9833f6ec1d33c850b1bb380e33a486a9963b63b5228229fd7e9bdd308bc810aa5e74ccc0e65a2af40c9a287c67e69e841495b0221110f35ed6319bda0dcb0b02174b666df4766eea05481f6a80fe4b93a06fe475d58ae3002303904bee331; -} - -udiv { - - # --- Simple tests --- - - 09 04 02 01; - ffe3 01 ffe3 00; - cdef fedc 00 cdef; - - # --- Random tests --- - - 8ab316d0d1a2e88535cf77c1172881ead70d592c59e9c5fbc16e4b0c4dc49481 - 18ca3bf7ee3c6d7bab3f144b015ccc6c25472843d346b461 - 059850f995ddeb799c - 02c1815029b766b96ad4507dc1af8151307961c6d161d065; - - 8117d1663ee63341eb8faeff304549f0f8b32d587acc2fd5597ea6a31625881d - dc85df77dfb61876805623bcbed325b99d00c2cd65c252c879 - 95dc734282eb19 - 395da02e8a6c66476467c4e04f328d8208cc411e3d1e96e14c; - - 63791966f2ad44a6df11bcc87c6b7c2400c74e69f7e3ca02fcac12b3bf56238b - a49e473b8f7539d89cdb002d73182558773eec10db93cc6049d8c5533e - 9ab11a - 65caf6833baa118b53c7bdc44a831605ca382b5993beead59f3971d13f; - - 9ca438db3e0f79305987292e8ec6174e6c313f7904ebb35a349a700e3ae63a37 - b24c93d499c7073b8f7aac718c1f12da1a8fc8bccdd47b49 - e0e779304869fdc1 - 46393cb15e38cbbc8a85698151a113f28081b4c8f6ed232e; - - 8214fd17858a4a913015412b5331eb9654faeb5156a674b1e5f6550a68957146 - c4f0ebaad6c0ee0111c57667ea8e0a254f3068f212949e20ededa89a7da6 - a917 - 3fde916ba21d19414d4316041420ca59d8b01aa2acf3f3ef106245c1915c; - - 55a487a70935360158bd55542eb46271f90f7312e77344c4ca6a580a80810612 - 8996dd0613f846 - 9f58fe011d73a8750454d9bffb55906e9bcf563e0c48b5b608 - 4cfd95e3e17fe2; - - 6a13e1be50ecdd7011f9ced42269615efb38fcd3e5477bc57377138cf1ff9519 - fda103ff99ff21 - 6b11bf2670bf080ef7c5aa0fa5989324e88e3e581c0e7507ba - 717db69e0d501f; - - 367aa8f5ba9ac4e8e2ea198b8af2c3b3081deab392ffc05715783b245a62a6fa - 72e2c37447f8bca34c4a39b130ea8e5c9a7d8b54564aa88ea773 - 7965572732ac - 08e8c03ebf398c63d71d8fd7ca4ece12367a8dde180ca650afb6; - - 6da07a0a1f9a7dd93e1f82be23fd5e7814b84fc74d4566dd83914adf368c1689 - 3cc71e64 - 01cdc15d7d825955c50ccca72fc5a16f9a7dd04363b12d8354d3088e51 - 299000e5; - - 001f5d985f594315d8c58f2d654304c8417f683b65d6d3246b89960e5f6c133c - 5bbc034d956a17998a30a3 - 5787e7e94449592b493486bd9a323f939ad9bfde - 1298fecf49a80ad72148e2; - - ae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c - c33c890f030644d88cc65f8ccf99c625c9b9fa21d4eb153e52ef89df54130855 - 00 - ae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c; - - 65901dcdad8dd0625d4d158f99b666fee10480d1df15e3bdac640584b9b746bc - d8a1d326fee87d55f39f15b5b2cfe71f5146083928 - 7805090edf620d22dac08f - 859c41164983547c03134b99530e25a0f874315964; - - 5d9e7037d70e822c2ce4b3d93f3e20d437a047aa94103296cc041e1b7ea0d9ae - d2b14235853f6bac6fdba208897d - 71c036bc8940293745e65c49f9b0bc1a8aa3 - 700473d994c1cd61ab24f661ed17; - - 3a826450bde36cf03de1d6829f7e21af52beb2655e2c902ed634f84e135b241c - 3023b54e1deda493ad0b4558 - 01372549e716f70dd3c6bb31f193682b7a9355a7fc - 04359aabd8bfdf8dd3ce797c; - - bdcfd9593348eb1567377e0d4f4bfe8a26acac14b56f7dfd82beddb4f11c2373 - 1f0356b60ad66f4fd7dda57cfc6d1aa374108bd4841127c8 - 061ed1e07aff1c094d - 0e313b6052859863725786d1459434762ccad8540bad244b; - - 293be875d1251920e18102446ceec021da8d8d24aabe49c5911d19ddc3db516d - b66e4ce3aa7390a9d888c5d22176bea5c36ae962ae8f252cdf3642556641271c - 00 - 293be875d1251920e18102446ceec021da8d8d24aabe49c5911d19ddc3db516d; - - 5f1085256c5fb856ceab16f2372b6b7024c7d1fcfa7039a0555bb1496c0bc92b - c46c1fcd4a8a9cb91775f901af0ab42e39015e09fc737ae2011899b34322cd - 7b - b091ddc98f1f09e065684e681146ddef6429ce2e24bd95bed4df704aca10ac; - - 82ea5bd086409cf3681e55e6133626ce9579db9eb01a0411db9c8521c3c66c2c - 605a13a7d4b75f1094260227cd4cab - 015bd5405d6bfd4571e54bc47a1b089abfd7 - 3074a3c84ec3bfa32e0db1b349738f; - - 3b68662228026ec9e9be8206d3226edd265552a3dbe15a7aa399eba05a69a6c3 - a0f4265e8f59474132846bfb15 - 5e7d40f138e2a107a52f85a0eb6f92a1c3ec97 - 1508f62d27e7fad09e3d423160; - - 82a5058150e570c9eef1f4e5d55d3cf261de28a17f4735caec8bb38e1813978a - 620d87bb63872a40fc2092b0ed7d3ec4b648be41 - 0155177e99a8a5113226ff8270 - 2ea2205327e66d75990cc999fc2380883ee4591a; - - # --- Bugs --- - - 1a923b3406cbe81b093ce418f6a73107f504502b2e3d1b200762fcf6062723de405cab0aea00000000000000000000000000000000 - 184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000 - 0117d3db34ad005954459be9abedd0e5deb4ea0000000000000000 - 00; - - ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff - 7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31d1b107fffffffffffffff - 02 01; - - 26737e 0ffffc 02 067386; -} diff --git a/tests/mpx-gen b/tests/mpx-gen deleted file mode 100755 index e53b1d6..0000000 --- a/tests/mpx-gen +++ /dev/null @@ -1,120 +0,0 @@ -#! /usr/bin/awk -f -# -# $Id: mpx-gen,v 1.2 1999/12/10 23:26:51 mdw Exp $ -# -# Generate test vectors for MPX testing - -# --- Generate an `l'-byte hex number --- - -function r(l, i, s, x) -{ - if (!l) l = len; - s = ""; - for (i = 0; i < l; i++) { - x = int(rand() * 256); - s = s sprintf("%02X", x); - } - return (s); -} - -# --- Main code --- - -BEGIN { - - # --- Initialization --- - - i = 1; - if (i in ARGV) len = ARGV[i++]; else len = 32; - if (i in ARGV) op = ARGV[i++]; else op = "+"; - if (i in ARGV) rep = ARGV[i++]; else rep = 1; - - # --- Output filters --- - # - # This is complicated. `bc' emits numbers split over multiple lines with - # backslashes. It also doesn't pad to an even number of digits, which the - # test rig is expecting, or use lower-case, which looks nicer. - # - # The first bit matches a line ending with a backslash. If it finds one, - # it appends the next line, removes the backslash/newline pair, and loops - # around to the top. - # - # The next substitution translates the whole kaboodle into lower-case. - # - # The next one looks for an off number of hex digits and prepends a zero if - # it finds one. - # - # The one after that just indents by two spaces. The final one sticks a - # semicolon on the end. - - bc = "bc | sed '\ -:top\n\ -/\\\\$/ {\n\ - N\n\ - s/\\\\\\\n\ -//;\n\ - b top;\n\ -}\n\ -y/ABCDEF/abcdef/\n\ -s/^[0-9a-f]\\([0-9a-f][0-9a-f]\\)*$/0&/\n\ -s/^/ /\n\ -$ s/$/;/'"; - out = "sed 'y/ABCDEF/abcdef/; s/^/ /'" - - # --- Main code --- - - srand(); - - while (rep--) { - x = r(); - - print "obase = 16" | bc; - print "ibase = 16" | bc; - - # --- Shifting operations --- - - if (op == "<<" || op == ">>") { - y = int(rand() * len * 4) + int(rand() * len * 4); - rop = (op == "<<" ? "*" : "/"); - z = sprintf("%X", y); - print x, y | out; - print x, rop, "(2 ^ " z ")" | bc; - } - - # --- Division --- - - else if (op == "/") { - ylen = int(rand() * len) + 1; - y = r(ylen); - print x | out; - print y | out; - print x, "/", y | bc; - print x, "%", y | bc; - } - - # --- Squaring --- - - else if (op == "2") { - print x | out; - print x, "*", x | bc; - } - - # --- Other operations --- - - else { - y = r(); - if (op == "-" && x < y) { - t = x; x = y; y = t; - } - print x | out; - print y | out; - print x, op, y | bc; - } - - close(out); - close(bc); - if (rep) - print; - } - - exit 0; -} diff --git a/tests/noekeon b/tests/noekeon deleted file mode 100644 index c9ae935..0000000 --- a/tests/noekeon +++ /dev/null @@ -1,12 +0,0 @@ -# $Id: noekeon,v 1.1 2001/05/08 22:17:42 mdw Exp $ -# -# Test vectors for Noekeon - -noekeon { - 00000000000000000000000000000000 - 00000000000000000000000000000000 ba6933819299c71699a99f08f678178b; - ffffffffffffffffffffffffffffffff - ffffffffffffffffffffffffffffffff 52f88a7b283c1f7bdf7b6faa5011c7d8; - ba6933819299c71699a99f08f678178b - 52f88a7b283c1f7bdf7b6faa5011c7d8 5096f2bfc82ae6e2d9495515c277fa70; -} diff --git a/tests/pgen b/tests/pgen deleted file mode 100644 index 6e78dee..0000000 --- a/tests/pgen +++ /dev/null @@ -1,40 +0,0 @@ -# Test vectors for prime number finder -# -# $Id: pgen,v 1.2 2001/06/16 13:20:46 mdw Exp $ - -pgen { - 2 2; - 3 3; - 245 251; - - 4294967295 4294967311; - - # --- These can take a little while --- - - 498459898455435345676576789 498459898455435345676576793; - 40831929843180254171317254073271577309351168965431122042755102715326515941762786951037109689522493525769 40831929843180254171317254073271577309351168965431122042755102715326515941762786951037109689522493526197; - 166359567317705838255275971708060308423814413741683015010175247351623188739655446196925981468626681882384215574706593049022467680136399439302347043107836749816290369600677730213469006507173065402294688841278559283358390567733443050775707749725690534182003442070447739085348456478911335969765393755383551520173 166359567317705838255275971708060308423814413741683015010175247351623188739655446196925981468626681882384215574706593049022467680136399439302347043107836749816290369600677730213469006507173065402294688841278559283358390567733443050775707749725690534182003442070447739085348456478911335969765393755383551520257; -} - -primep { - -5 0; - -1 0; - 0 0; - 1 0; - 2 1; - 3 1; - 4 0; - 40301809 1; - 40301811 0; -} - -primeiter { - 0 2 3 5 7 11; - 2 2 3 5 7 11; - 3 3 5 7 11 13; - 4 5 7 11 13 17; - - 2309 2309 2311 2333 2339 2341; - 7878 7879 7883 7901 7907 7919; - 7879 7879 7883 7901 7907 7919; -} diff --git a/tests/rc2 b/tests/rc2 deleted file mode 100644 index d6f9e74..0000000 --- a/tests/rc2 +++ /dev/null @@ -1,15 +0,0 @@ -# Test vectors for RC2 -# -# $Id: rc2,v 1.1 2000/06/17 12:11:49 mdw Exp $ - -rc2 { - 0000000000000000 63 0000000000000000 ebb773f993278eff; - ffffffffffffffff 64 ffffffffffffffff 278b27e42e2f0d49; - 3000000000000000 64 1000000000000001 30649edf9be7d2c2; - 88 64 0000000000000000 61a8a244adacccf0; - 88bca90e90875a 64 0000000000000000 6ccf4308974c267f; - 88bca90e90875a7f0f79c384627bafb2 64 0000000000000000 1a807d272bbe5db1; - 88bca90e90875a7f0f79c384627bafb2 128 0000000000000000 2269552ab0f85ca6; - 88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e 129 - 0000000000000000 5b78d3a43dfff1f1; -} diff --git a/tests/rc4 b/tests/rc4 deleted file mode 100644 index 374430d..0000000 --- a/tests/rc4 +++ /dev/null @@ -1,28 +0,0 @@ -# Test vectors for RC4 -# -# $Id: rc4,v 1.1 1999/09/03 08:41:14 mdw Exp $ - -# --- Note about these test vectors --- -# -# These test vectors come from two places: the Usenet article confirming that -# the alleged RC4 source is interoperable with the BSAFE version, and some -# tests I performed with the RC4-in-a-signature Perl version. Some testing -# with the SSLeay version shows that for an all-zero key I'm compatible, but -# with any other I'm not. Since I pass the Usenet test vectors (which I -# found in the SSLeay sources!), and I'm compatible with at least one other -# implementation, I'm happy that I'm in the right here. - -rc4-encrypt { - 0123456789abcdef 0123456789abcdef 75b7878099e0c596; - 0123456789abcdef - 010101010101010101010101010101010101010101 - 7595c3e6114a09780c4ad452338e1ffd9a1be9498f; -} - -rc4-generate { - 00 0 de188941a3375d3a8a061e67576e926d; - 01fe23dc45ba6798 0 643ded26ae29c15cda4f2b96d66baf2c; - 08192a3b4c5d6e7f 1024 abb3a32a2ba4d409752923aa4032be16; - 0123456789abcdef 0 7494c2e7104b0879; - ef012345 0 d6a141a7ec3c38dfbd61; -} diff --git a/tests/rc5 b/tests/rc5 deleted file mode 100644 index 340354f..0000000 --- a/tests/rc5 +++ /dev/null @@ -1,17 +0,0 @@ -# Test vectors for RC5-32/12 -# -# $Id: rc5,v 1.1 1999/09/03 08:41:14 mdw Exp $ - -# --- Main cipher test vectors --- -# -# Taken from `The RC5 Encryption Algorithm' by Rivest. Important: the -# test vectors given in the paper are given as 32-bit words, not bytes, so -# since RC5 is little-endian they need to be swapped here. - -rc5 { - 00000000000000000000000000000000 0000000000000000 21a5dbee154b8f6d; - 915f4619be41b2516355a50110a9ce91 21a5dbee154b8f6d f7c013ac5b2b8952; - 783348e75aeb0f2fd7b169bb8dc16787 f7c013ac5b2b8952 2f42b3b70369fc92; - dc49db1375a5584f6485b413b5f12baf 2f42b3b70369fc92 65c178b284d197cc; - 5269f149d41ba0152497574d7f153125 65c178b284d197cc eb44e415da319824; -} diff --git a/tests/rijndael192 b/tests/rijndael192 deleted file mode 100644 index 49898cb..0000000 --- a/tests/rijndael192 +++ /dev/null @@ -1,2886 +0,0 @@ -# $Id: rijndael192,v 1.2 2001/06/16 13:23:19 mdw Exp $ -# -# Test vectors for Rijndael - -rijndael192 { - 01000000000000000000000000000000 - 023a67f4591abd1dc00c5abebebe0397a3b347451ad3112d - 7ff75c2eeefa7f368c8a8b4520696533bff5aba750f61004; - 02000000000000000000000000000000 - 506a186359362e62a58444f018f882194d728766ca6ff976 - 6288af2dd607059b760ec2ae99287ff4f5f135350c6533b3; - 04000000000000000000000000000000 - ca5c42150025d70706f9df66c6a149878f99b02d80d24af6 - 2740c22885fa7f6979eed72c31254719f75097913d55d089; - 08000000000000000000000000000000 - 03ebd2ad4e4c4b8767eef082e0671b8a40aa83205dd2cd7d - 50d067dfe60008dcff6c8f6011a56b04297a0886b818fdb3; - 10000000000000000000000000000000 - c8b526b380f2b8ddf60ad4527b585b36bc886f915906f34a - ee2550dd5a911da2bb85424687b6d06e18607d9800822a8b; - 20000000000000000000000000000000 - b5fe0634f8cc42cad26dd7448ed44288ff054435747606ac - fabc0ae4d9eb26ed89375f1e24215540b37d106c3f4429b3; - 40000000000000000000000000000000 - 2a8b55370b58585cd5c545065c1236876c25f7227043f697 - 9a2efe9a23f99898519dfc86bd82ac51311356e96a744e4c; - 80000000000000000000000000000000 - 225d2952c570bd85c57b60bdf0d7813cee77f88eb94b9fe0 - 66391730c52594f80fdf06e5da751aad9613767c8a7dbc12; - 00010000000000000000000000000000 - 4ebb41c4aeee673f8a24dca03806b456d7f0371f59ad215d - e20e4d661c9411afca8208e71c2245954316b17d355cc87f; - 00020000000000000000000000000000 - 1ece0d84de9d85f599c043e81ed0d0788b0300dc720806f1 - 8b58730dc35a5b8b679a38662163bbf61f4bcb963d67c0c9; - 00040000000000000000000000000000 - 0acbe6c5eb0b944562a37976acdeaaa343d28c1023805af2 - 77ab5a554203d92b600fe57510c081be22d9a0474158fa0c; - 00080000000000000000000000000000 - 41be3904653a1575e5b06c44aea5d2136df8f9ccd7f42897 - 84ddaa529a9e0c24bb4437fd7c59d126e9f3a2fd144747a8; - 00100000000000000000000000000000 - 1f64e3968eecb4f75248981ee4afe469df2506d85373244e - c0e3387b78dc708656ce32cb56ba8f3a7481db57b2e2f31c; - 00200000000000000000000000000000 - 4aa4faa759d8ae50e22eb0c8d9a35a5ac45d8c321e7945a8 - f912da323759360ab2a17b8903a3995ba1fd286b4f5c0428; - 00400000000000000000000000000000 - ef444349c97db6ced680f42fb6c5be12b6093315d9735c99 - a8e88259daf069ab83caf0827dd8a70aec60763343f1d5e8; - 00800000000000000000000000000000 - 52d311d50f4b8dadb35e14061d24b77128f5fd8f1a4408cc - 830b1649d46496e4e3379c6af09ef3a2db387234e20e0f8a; - 00000100000000000000000000000000 - e7bcd07378c8fa7412cdca4747b825586c1d1db42cb9e3f5 - f646e68c39285ce45d564195ab947cef8f842e83a0039311; - 00000200000000000000000000000000 - 2d6f4c9d74fa658286d89ac21a293b0dbfa23a8b5509d22f - ecab2eb6d811c3c5cbb7ca9697039c0183deba100bd857ef; - 00000400000000000000000000000000 - 553847fabc37d17234bd17f7d9306530bf778143642aaf86 - 6b4c872d23f5e2055dd7b7dfb5e4b7e9e2ca030a4248d033; - 00000800000000000000000000000000 - 940ab6a034bee50736899c4d635156aca5417be2643202a6 - 7518c4af96fa52e3c0b00b874d394c4aa633d0cba04ef54c; - 00001000000000000000000000000000 - fac2d9c5408abd20b4cb620b4e9ae56f94d5c4a1d5875dd1 - cb766e2a037a343083229141d004ba100c4f33de8e064961; - 00002000000000000000000000000000 - b4e037145cfe062329702825eef3c0187602e7c81b196d01 - f307dab2d4b0c4e95024e95bf869da3759038799142e7a4e; - 00004000000000000000000000000000 - faf4093cecf9b49b79ac867cb8eb254f4e6b1cdc0fa8d2e1 - c5a7383e7e51e02872407a34099bffbd43e2369e5b3c4bfb; - 00008000000000000000000000000000 - 13226b07eb7e44d65c4eac727e788fc246c71b7877150716 - 74cd36201eb1e07da6d7f7a922fb4cc9bb76e13b1f770fbe; - 00000001000000000000000000000000 - a4d115e01be2e296dc61104749f5cf13e1b0660b619901da - 6cd992b789f2e6bcae1fc4c54e31983a91cfe80221065d45; - 00000002000000000000000000000000 - c177c0361498f3b8162b8a1e4791d393c90f9be62af73a0d - 8fea60d9cc0b31580e42a55bf633d926458eab2269e284c3; - 00000004000000000000000000000000 - b3fa237d5af3b8b030559f59b22394b94d8b71fe7c499896 - 090181d182605dc6d04734312631193af9ba97a41e36cd6d; - 00000008000000000000000000000000 - d43a7d6e1c6e6bd70ddf057df51171968f135cc628c87aee - a83d729f48beaad53c4703edf669cc3b8172b1f3815826ea; - 00000010000000000000000000000000 - d4a801587858558d74174ec9bf5af46357cb6b509c1cd3c6 - 3c8d553aad2e9e9b57012b8b624864282605a202e770988b; - 00000020000000000000000000000000 - a244142ed94451165b1b284659dd09bf19522d8ede74fa50 - 56a4918a03a03e7522287f2697058a5a4568ee1044abb7a5; - 00000040000000000000000000000000 - 256c7215a7a1f6277efd963ac44f273a67331722a35733a6 - 772bad0f5ba9b17a70db868fa6c94e894332da2be4188990; - 00000080000000000000000000000000 - 0180a9b501ffa92c8d82f9a6841762c0a999f075374ba5ed - b2866da4615cd4dc433537c2946f8892b44f3bd0b2c4dd72; - 00000000010000000000000000000000 - 74094fb2efc7ad295a4e59e6f3cc4bca98f9ca9426f1dc7d - 66e1d8c5b64590a10887d4f30d593e21a988ccc2cb0c56f3; - 00000000020000000000000000000000 - e0f2350c0bc86af716d0e3a4a43f7226642e41247cc365a8 - 47a078702ce531d10d0ee151761fbba5e8b62354fa78b6f2; - 00000000040000000000000000000000 - 422af1fef9c1b8c8a0ef3b62abb1318556ed6fc1f66a9d87 - b334db883014ca79f7822e91203840185153bb845171cf62; - 00000000080000000000000000000000 - 94112b3e064fbe4658252cd678a689e30989d9801f8026bc - 9960c684f52a14396a807b1457b55a6e8805adbd2cad3ea7; - 00000000100000000000000000000000 - 9cdaf684882ddd6dc44fa74b080f6a3b63fa4ddf2a8708f2 - 9640e06263fcdc7f42e8364b6832202026b715b1d604802b; - 00000000200000000000000000000000 - c138345c90c2823c192bb0a347baa310068951f512554d95 - f0b31139a5e0d808349a5897341ceab6d1c92ad0db7efa56; - 00000000400000000000000000000000 - 8ea80f74f49292759317b0b4a1bd488edc883616c04c8920 - 3e2a07a682bf608ec4f94faaac7049323435e17bdf8ce8bf; - 00000000800000000000000000000000 - d170aa41a6e50b8b2738de41f189cf9991eaade3dbd5dec5 - 4b0901022f4449e5fca714fb4a08524c0b33632a704ed726; - 00000000000100000000000000000000 - 9a308261c52d829caacc1b70eb47049a598a4702e22aad0a - 0bcd79778982f5797fb92d16d7e772e624a65e15dde0dcee; - 00000000000200000000000000000000 - 40cff4c8c86429193aa94de96b2719a99f60cbca577980f5 - 47ed4c47df14c5a14290faf23855088bb0fd75d8f209f276; - 00000000000400000000000000000000 - ba4d0f077f721f3939f1389d44a86fcd7f2591b94c9e9080 - adf066342c154cf5c2fb2609be3126b1bfa8098d8be8f1c4; - 00000000000800000000000000000000 - 4c635236910df9d5d1a6ed65c7252a72fb20a716bb64d9b8 - ee98a1c2c6a9c9590f626f4b7f685c8575da477a356d557b; - 00000000001000000000000000000000 - fd3fb55926f16ac3c458669f23a4647fb771ccaa49cafb4b - c3757d955b8944c8dfb62e77cf643f6d8b58261916aec7b6; - 00000000002000000000000000000000 - ab5289cafd68c2bd7facced12251962f7be2b30a99945c9f - 92f2d77a9f0dd409bf737cda459d7d3dce6e407dba592858; - 00000000004000000000000000000000 - 050c239f2157e5355525ffe4557e54b2c8838a68899707cf - c3317fdb7edf02d7b43ff293346977da2a22108748574302; - 00000000008000000000000000000000 - 287c55a9636fd7123dd9851cf5c27c73f3f3a165a4b5ab31 - ef8d185840b9f6f057792cecc2880366dbee7e5b56a38fd5; - 00000000000001000000000000000000 - cc76fb5b7e8316d4c74e1df3f913139e739d9f30e0e320b9 - 9dd58b054a33098f0228bc6b05712e9c7a50add7868a2f96; - 00000000000002000000000000000000 - aa21dae2afdb95ad368f9c1babf2769407cb6d7975d41257 - 3591625006cb3c2bda175be3f715a6ed63d59261a3182f5d; - 00000000000004000000000000000000 - 8cc0d35698def74ded8c1d8222b67e543af62f9627978c80 - 4829e5802b83b5614b58d68305aa94f06aaf37a0c0c4ed5e; - 00000000000008000000000000000000 - da702b5e9b3c7ce13681b3e1a38ae1babd06a0ba46612f63 - 9d162f4850b8b4e4b1a01213138c1f22c863e32c12539a87; - 00000000000010000000000000000000 - 486599f86813923735d14c4308f142eb8a57086a8507255b - 40b857e962dfe1f9d1dd46b69ab4f5ff7faf34b407623c3c; - 00000000000020000000000000000000 - 82f7da5f0379e2cb4e3b58a03ca3de256b282dce73285090 - 1bf3d369ccd413ad0f95a1928715fb8ed55aeb2e9d93f2cc; - 00000000000040000000000000000000 - 3a2ccdf7ca733ef507a485ab20c62cf6fb13cd1281008b49 - 335d30e28232b4bc1dff9de3a4a9faebd4b5accc3cd2eac6; - 00000000000080000000000000000000 - 5129bfb136556242d24c0a69d1b471e39bef4502dcc6ab63 - 0e7f709d8e65ecdeccf0f8f51e1eadd4deb33218ca96133d; - 00000000000000010000000000000000 - bb55b9b172f5102a71d27564fb441ad75ef525e3c7b95569 - 2fe4ac5360626eff86d72d472cff3428f0891f2e708c1fc0; - 00000000000000020000000000000000 - 29e121d9d060b4cb1a8b985514642d2ae657d1bee74622af - 330a0002c3bb7bdd1141085283a2390d50b992667e9c7a2e; - 00000000000000040000000000000000 - 1eab5cf16eaed7787fdca7a4a13f02e89e838e28fee07574 - f351daecc945e7f4fb609f83b30f4a5f96d8d453770235a1; - 00000000000000080000000000000000 - 1d1c207423b291e4faa33ba5511d99fa0a1d6217dfb01503 - f8d4232565a6ec23973b2814fe0d4b0d795df4afb24646bc; - 00000000000000100000000000000000 - 428cd893c5c48447e67a5a78ced4e75b9424d26162396397 - df261879c0edbb80b244a8f95c319bd2f09db2fd24e46664; - 00000000000000200000000000000000 - d559589331a70000a25b0bdcc69edfadacca1a42e26858c8 - 408b5610b79984e6b95c48b6b370c670b054a7f4218bf388; - 00000000000000400000000000000000 - 4b3ae76b7fd6acc18a44eb946daa6bb70d58086904f61243 - 926965c763cbb68699d3e77aa76acebff7be816b27cdae87; - 00000000000000800000000000000000 - c5fb0e875cc5f0d3b8e3056be3c1fef7cb653c2d357de33f - acad4ba4b859549071b491f07e7f90d50ff1e9aaf9d4c566; - 00000000000000000100000000000000 - 50f32b167426251526e8f63bab0d615e016e03058902fe4f - e899b8984e8f6e7203c364181d89439c3bac8e60914d5644; - 00000000000000000200000000000000 - 54418fd49d84a2e725f99459c10454af6e408b945e108275 - cbda143f3ee4dab705f1a91bc941054ffd0ad144d50368b7; - 00000000000000000400000000000000 - 6117166e773302a1b3d21e869407c18a13655033d5ca007b - bbb97e4178dbe65c25ec8002b53ef7932c4ae1cfb947918c; - 00000000000000000800000000000000 - f89ddf74283be908896c62bc18feaa8d305e9ae4278233ce - 2089a78434cf69651c06cf00dbe89bb6b446e4f3db6ce8e5; - 00000000000000001000000000000000 - 03af049da485a4b4ddb468bf3261c38aad2a71c96f990a22 - 46146187446746bbf8dcc71cb5c583506244c1468a015144; - 00000000000000002000000000000000 - aa70df415bd87335969b4fb3c363529061a3da319ef2d890 - a63e67308c4b7f2b33f279bee222a9869446c8c0c250cf06; - 00000000000000004000000000000000 - dad7d93b5a7bff63476de8b3d20190a29f28eecc88495d3d - 9839a4942c8f69283e91eca22ffd198a4a79e68ec07e578f; - 00000000000000008000000000000000 - 59d603166b649e9be642bd3ccbc03f7d9abb3e89aaf0f1c6 - 8686e6909dcd9f787f9fa180a46d1d433bf2721a238faab1; - 00000000000000000001000000000000 - 7bb6311899138ae33f095f79487a8c1ff8efc0a1ba1c0844 - 69e02af433d3d1234a315658f80f6dbad8339e77b894a3bf; - 00000000000000000002000000000000 - 27112725333fed86f93b09ac882e54cc2c625de0970a56c0 - d840315b675f117468782d16dd143961e972a62733ab5b12; - 00000000000000000004000000000000 - 798b2230146a75a46854e26ed0cb07419e79ac176059f223 - f543a2dffe039126eacbb3c5253d3e0656df5886aa7dc934; - 00000000000000000008000000000000 - fdf295ab966e035dc8d9c6a7d378aa1fed50f85e09afc9fd - 1e353b843bfdfb8e04196ebc2a2fba0e6ac7651aec3034a8; - 00000000000000000010000000000000 - 4b9bb076f6e3b227ff27210398252df65e9e2fe255b13992 - e42c1d4b04422a38c1dc7a4bc241ee1f4b9aa5a2aa42047e; - 00000000000000000020000000000000 - f45fa1b841562f0d20769390f1dafd13324bf86216565f5e - 7e96c285bffe97be47ea277140b179e92daa6a13647905b4; - 00000000000000000040000000000000 - de745e5baa6ac8a095898d562c187de0064d23c9b748a115 - 10cf435b1841a119ef753a471f57261af2d137b2eef59c81; - 00000000000000000080000000000000 - ca3c51b2670418b4ec09ffce8f626bbe891b266446f89853 - fb5c6a49a40e79c468ae275331230e37f5e47c3a10159d58; - 00000000000000000000010000000000 - 0a9529d7ca30fca5081c364376c766fa5cb0a488bff9f638 - 149db4dddd0c11aef1e7ffe76286351b2212a17771bb3bba; - 00000000000000000000020000000000 - ac80ed034867425e0482cd34ee6666ff8ed09cad5901c0c9 - 3a4cc4d2888134ad2d77ef262a222c79b66d93226209e6ec; - 00000000000000000000040000000000 - c01846df500d6d9da7755fee30847e2b6e5ef2af29fb768d - 234eee5672c9964bfaeff3d7612ad7796d52630dc86bca96; - 00000000000000000000080000000000 - c15f53accfc0d88ab029139dd65019fa6003b7afe2bd4e54 - a0d7bfcdeb22254d8ea42219368656569742324922a9ee6d; - 00000000000000000000100000000000 - ff213f49aee42eac2aa72d7a29e7ab41aa7f586012e9f97f - f17c2e5990d08495dc94764f8e85c51851a4f413b581584c; - 00000000000000000000200000000000 - 25cae6c9325a23f04d3f14e8c2c2d2e7cf47f4245a813568 - e2f0783438ad7bd9a4f84b1b3a895c05714c514dac819bb1; - 00000000000000000000400000000000 - 22870931c60c3752f5eb3408f4f4f311ecc94d45746334b3 - 6b62d15ad6d4d9a0bcf4f718fa02fcd154922ae0eabb53ba; - 00000000000000000000800000000000 - c08edd588aefb0162ed5a83866b4125c4763187fa2c3a0ec - 06c5641d79eb161bac7db67e4563298fb255ba9d19795081; - 00000000000000000000000100000000 - a27d1bf8dd539451b9c1be660a658551358e0d5e24afc3b9 - 7676d1200c042937af0775b682b8a079e537e09ed0aa4683; - 00000000000000000000000200000000 - 985703a552bf2ef0f0b13cdfdcea1b5f0e8aa26dd0a2df73 - 7c2f3cd5a37195e38378625ba3dcc0331b5f541a8ab99782; - 00000000000000000000000400000000 - 6ec0cf3e2eebe473928c8816aacafa30697d2f1886216355 - 74cd8be145dae8057f60216a73c5facedb9f4e82e0bd65cb; - 00000000000000000000000800000000 - 616f098bebcbf2ed4b706c97bf2515c3b0816deb15de4059 - d15e35c97769885b1a3d35e8e1fe85b693ec2c8744417bfa; - 00000000000000000000001000000000 - e8dd7dbcf07d102c7eaaade8d9024829251e934d0da9d7aa - e3999556264744496ad4d86d445457888419bbe8871d7b4d; - 00000000000000000000002000000000 - 1fa50547af8d9f2d55028008536f066753c17fc8e2d44057 - 4acb79c912d344fae3419ef5700aa6a3d883184f34e5d59e; - 00000000000000000000004000000000 - 92eeebbe20902b4c0a5f890399c32c243e89d8ed91332e3e - e46625fbad57eb9c626e2125cf248e269332527015dcd3e3; - 00000000000000000000008000000000 - cdbf15c739d3fc86f9420eedf6a0956502a4a733217102f4 - 81c056e8176355317af92ba38e40fd5c26f907b285f840ea; - 00000000000000000000000001000000 - 2d349f3bd80ff88f4eee644682b62fd1eb719b9c81b816f6 - 9d44dd091630b3772cb94b8c652a15df0474881371f0b04e; - 00000000000000000000000002000000 - 6c53dac01503d4ea8e2da6e54403fd20c1f5a1f967732cde - 4c17e967bb54e474f3e323d4f0e18ce40e44ea61c2338cd4; - 00000000000000000000000004000000 - 1991e580e4801fc43a1aaef646626306f5b86f93bc114393 - 7237846ab5e292d29a7f115d0b10530720a1d5ea7c5aedf2; - 00000000000000000000000008000000 - 89c2a0916aaf1f36b54c0ac5f74a2cf7ae2d151e9ba39b22 - fdb640c3275ac44815c50f2d872e28060501598e7e9947ea; - 00000000000000000000000010000000 - 5c052c84dea984ffd5703103883523da2208e3bfa1e06649 - 5e97c772783c94a50d288284afa25295f877e5c29d174529; - 00000000000000000000000020000000 - 89dd0a9f15abb0e943d4bd0eb37e9280cb046c88999a5f14 - b8979c6cd28d05d20e4b3ea5ef472ae7d62a2470014f6e7c; - 00000000000000000000000040000000 - fe7ded8a12dcd5bae797cc30cd0596052ef5a56c0924f199 - 30272a00835e69223739d31e66a87ee9810c3181cafa4c5a; - 00000000000000000000000080000000 - 5a856f3220f42525eb711f1895eb09403fddbebfff60851a - ac07c9e6190701a516d89034e9af0229a2ea8bd42ec699aa; - 00000000000000000000000000010000 - ae67448d9fc57e487a4bab448208035dc06ffae8b5e9e8f4 - 693ce9e015e6f445bab0613cf858e152baf438c76bea9239; - 00000000000000000000000000020000 - 349b4b3daff60002fead10f7f11f1ba69a7142c2256214a3 - b24cef9c0a98b607339f148be6af519555fdb8d59237e06f; - 00000000000000000000000000040000 - 0d3724d48fbd0b053b9594042107bd4b91bdcd98a6fa14f9 - ac041956dca2caab9d5e40d344a5ff2e02e48cc638be7058; - 00000000000000000000000000080000 - 29bb7572498bf205d1939c754ba87e3a4f1a2c866bff4377 - c2b627375f0020f1e01df599ccd0c9afef8f72f2fc8c432c; - 00000000000000000000000000100000 - 79898e51f8e2ff9303d2eaf1c113d4be2d7fd73c4f29c1d4 - 02ff562fdf5ba2e325a7daa8e77485d261bf798a70562492; - 00000000000000000000000000200000 - 91ab2704db9e0cb20236885aa1812677767f29887a3825f9 - 945703d5a2ed4c7fbc46641a86b1c4ae52e2b6ae86370b7e; - 00000000000000000000000000400000 - d15999107c2747d3df7e21240b729cafaf32e45ff2e2eb94 - 0621fbacd6f9e17748a251d9ce0f6279c0b4f76de76ca07a; - 00000000000000000000000000800000 - 3022e256e1700e1b38860e08860de7ee7011a471744c4a28 - 5d0cea63850c605346b1bbde1277bd04e9a7ea67dcb95a0c; - 00000000000000000000000000000100 - c41bad6d44d9b3ddb77289d0bc75728ea32d21174989429d - daf7d221677be4c01c524941b43a6583b736f59485c37f9e; - 00000000000000000000000000000200 - c244e345c8771efc91cf85737fbbe0e7f9fe1ad53727bda8 - 0e45be68828f5dbe2cec1eb6631dd455f9f742ec1c6d5734; - 00000000000000000000000000000400 - ea91f3b274796e1a463d3263acf96d8192c927d1fa66b022 - 53a6eb98500423e77e4a17fe1e936500a3411d9d194ee941; - 00000000000000000000000000000800 - b955548cb651e31e94102068eccd141d55333cbb3e34946d - 07af2dbc8c097871dd3ceabb8645a164f445226eac474927; - 00000000000000000000000000001000 - 7f7864177e868e5e4a07a99252eadd43b0529bf5b9b05013 - 2746566baca5f019ff0eea70d3eb82278398c9e9926c3883; - 00000000000000000000000000002000 - 55cafc87e6ce1e903805d23153711dc8c7e8d269e19be3eb - 7946dffc2d8ab6a40a397f81eedb2568c6df9f0b06391d82; - 00000000000000000000000000004000 - 95bd56e986ab583193786c37328d4dde20e62b0d39c19b9c - 1f261cbca6aa0875c3b610990236178251d2865b5033ea5f; - 00000000000000000000000000008000 - 21b185e2c61a750a4dbc47d1af6cf3b47f56ceb362d785b5 - ce8b0dd60ba2d9b6e2582aa6b262cdc674d96848a67641fe; - 00000000000000000000000000000001 - e7d5e316da3127f89538a3b2d24e5f7e8006557dcb03b5e5 - d41ee11b4115c2e2155c0bc35b31d8c38e2282d17ef5ab4b; - 00000000000000000000000000000002 - dc4a61888202b8e52a97af475726e545372aa67912ca8cb1 - c4c595fbf14bd2e4f55acff059c17c243ebbb6e979713bd0; - 00000000000000000000000000000004 - c4306af68bbe3af8b223151aa99c94488c8107fbfdd3b680 - d15a72460ab5a62385c5db730fce1ddd02ca531d250b114d; - 00000000000000000000000000000008 - 5c33a8ad6ca05fc247427b898126e4ab9fd05ed334e14c68 - 8f887594d5f3a14aba879167d605d2ca84abd2aa60ca85dc; - 00000000000000000000000000000010 - d8abe4455e58859d84b0594f2804f77f15ad38887e29d705 - 407f2f3751880efd85de8ba315f222712df2674f20c9baa4; - 00000000000000000000000000000020 - 20b5cc79b89b41aaef175caf0975d6d8f2be320075b8cfbc - 6b366acae30d75bf715a67703cf61e349229015e3587ec05; - 00000000000000000000000000000040 - 3cb706cb93bc33a1fe6b1a68c9c902d187b6c57abee350dc - a1d213280eb276238acf137f2ef7b15216b571f42c9dce58; - 00000000000000000000000000000080 - 7654351a040718ddd3d7fb2cd9af802c17e7db0e7a6cfaf5 - ee3058937fc02624cc4ec6d19a7c8d3a655c6e8fc8c12622; - 0100000000000000000000000000000000000000 - d0b1960db19a85a7a77e46229b9f985139829c3aa120c3ae - c642be9d84e9f449586f6329a6d0783aafc5b9a71d5fdfcf; - 0200000000000000000000000000000000000000 - fbed0648eebac5ad6af9c89f04c759f5b3caaaf2fc77b33a - e2f666ffea4b816c59587f2cc5c4007a6e797c66c20d454d; - 0400000000000000000000000000000000000000 - c5310bb95af7c9a72af7fe845bcfc5944f98606f21d7d414 - 91ddc7e0d5626d0929262a339e488e7b80b59c748b99d96d; - 0800000000000000000000000000000000000000 - 2c22bb4931178c38b575e8a697e774f4b6cc49163b4fc863 - a29c3dfc98b1061718a8b858b582badd3565354c7dfa11e4; - 1000000000000000000000000000000000000000 - 004b667ecd93b6cf8120b4d13f63cc8676f25669cfd54198 - e61ac997edc61a530e21d3fa92597765bf8088eeb044378b; - 2000000000000000000000000000000000000000 - cac87cd9c6a8336a855d7fa479a41348615befe661bccd5f - 3c4de80c174170a85b453b0245b40090c62d7c733e691cd3; - 4000000000000000000000000000000000000000 - 271170c80822719aa7abc308af71bff47220c9c0e1d0af10 - 6adc1a35f39600a3ded1dfa8db6f54d06975f3df17410963; - 8000000000000000000000000000000000000000 - c799a3e1f803ebf7674e82af4e130a1edb80fff06b36913e - 5255a39bc0b3903213e8af99c129481a1a91546435a0b9f4; - 0001000000000000000000000000000000000000 - 7f5dd7178fc11e33e75039cd3b31c3ba715669a2d97fd67d - ea9f8cfdfbf79ffc004244db67a186188761b94dcb680ede; - 0002000000000000000000000000000000000000 - 890342e3bab9d5c12af0eb1147adf72ced3c858a36666765 - fb317078fc5a6f72cd05ed99754244c1d832bce05b495ce9; - 0004000000000000000000000000000000000000 - 4dc89624333568e75ad013d4777641293110c8293a4564eb - 5c215202bce7ac289462ee973b208517a100effc3f045037; - 0008000000000000000000000000000000000000 - eb39a4f0a41388595563ca25220d2ba33e8827e6886dee50 - 6c3cbd45e11b03f217232c6e8f412b2d45626fcbecbbd046; - 0010000000000000000000000000000000000000 - c3768a3a08cde5986f31f19adeb5637c2517e4b793e75c8e - e16c0fd6a2460933f758b736979efb34a9c35df0b58c290c; - 0020000000000000000000000000000000000000 - c4ad863e851697c80ed0607192c54debcf7c66fa38c4a4af - 7907d69fb955ab18bf7c198454c6d8d15e4226b08e322ad6; - 0040000000000000000000000000000000000000 - d2090fd250ba63f3a708140e11ef64f8afcff45dc70cef3f - dd4c891a83c86dd31eb4973dd3948a94d1fbbe6f03fc26c6; - 0080000000000000000000000000000000000000 - 110a9f65db98d165f6d71f8350ab602f4b2039e162744741 - 54d10329bfcb29cd51fbcabda51e28a5d2009694353a43f6; - 0000010000000000000000000000000000000000 - a8c1ba8a548e6f3ed996445f62845dcc078495a6cf9739cc - 6a2fe74b53328830ba707a56c80935b74dec32a312c5f6f2; - 0000020000000000000000000000000000000000 - 94c0028f97319ac431e83414b6c660939b11047f310854b7 - 46a1a901558c6bbb0f8be8662095454d9decbcfa416557da; - 0000040000000000000000000000000000000000 - cb4c1feaab04ab5a6bd70259afafd3bee103ec9f90a5150a - 270e073e9de7d0f5c887b62093e705b6457d0eb070b3c68b; - 0000080000000000000000000000000000000000 - b9d1993a3ea9b0f635d37edcb4c5ce7bdaccf5be5cb7bf02 - 8400b07b3cb30c941e468274b10c77ba3d853c418c2efa15; - 0000100000000000000000000000000000000000 - b4ab6fb85ee6b43cf76adc45644eecee472abcdad771604d - 97133160d397d761ded692085318c15285392e4887563703; - 0000200000000000000000000000000000000000 - 7367a4de601e0bf5244fb989a03fc80ed93d3141424b9477 - c3085f4757b45152825ea9197538a5797bb15b374231992b; - 0000400000000000000000000000000000000000 - 8e97f0e67b27ace30dc30a4ae45670c1378dc2b5bbe12400 - c9a494ceb0d7e51eefc737a9ca0e8af490be4e6a5ed1ce6b; - 0000800000000000000000000000000000000000 - 2713deee079aabbabc432a62e260b8d9291e98595dc86623 - e6ef22a2af39e8cc4415dcf216b7a998b98a7d240e2c3e07; - 0000000100000000000000000000000000000000 - 3dfd7ba2b48e4ffd7c0885552dbab3133c2757683fd817a9 - 7e98b7592893cf2253c1b393e5dacbb233dc803589421eaf; - 0000000200000000000000000000000000000000 - 2ea177197993e7c293ce7a59bd3deef17485c206dd19195d - f1758101cddd487e37c8e5b179cc2d90f15adaa047c61a90; - 0000000400000000000000000000000000000000 - 8fb6036b6580c04c433fb07d0760fef91bba85272739c0c0 - 11c2bc53cfc7fde6fdccefe4f20dba513c465b092194a3a4; - 0000000800000000000000000000000000000000 - 703784863ff9e7e3c09fa9bf128ea31dbd2b8b4f5cb99e36 - 936d221d1f0c14b6f01cb3028873895e5b24d16f0031ab8f; - 0000001000000000000000000000000000000000 - 5a69ea7cc7fa7302fcbd1ac2d07dc7c6621ee0aff1d018a4 - 41c2343b468dcccc3ccfda966cc9ba78d8d57083ae27f29a; - 0000002000000000000000000000000000000000 - c89944b86c5edf216c8a8f8e58eb307bd311e11e66ee4ebe - b38dc49125243cc11781df4559f9d84640a7338403236c85; - 0000004000000000000000000000000000000000 - 3c669450967f16dda82835eaa8cd3877fa8de68ddd5c59b1 - 278e188e35f3c26eb8bff5c03a5b266f0f51aaa4a603081d; - 0000008000000000000000000000000000000000 - 9823a5e5bdb3ca2edc47618be7ba9ca742d5f0d2198047d3 - 21a333410512108c86dc7950ab1abe701a9e3d856e6d9269; - 0000000001000000000000000000000000000000 - 981fa376decb5e95a92b842e2dee03c562d8ebde0c8d6cc6 - 370eb81d50ef15a799ca481521a24966d033da29486007cd; - 0000000002000000000000000000000000000000 - 44b698fa4f4f6bf89fc66a23abb6145d9713908bb03705d5 - fe70a9986d13fbf73500352f742708a29eba0f80d324843d; - 0000000004000000000000000000000000000000 - fee1b9fad13700816390e29880a83233e7b90cf183cd3527 - 0c8ab7fceeeb439397c095de04ae56eb867499360c6033ab; - 0000000008000000000000000000000000000000 - 31defe3570475738ce89f436ab737800c6a59fce561372b7 - d78ea1624b5ed5cce49a46ead9237bbb48b90327db11c74f; - 0000000010000000000000000000000000000000 - 652a17e6b330a95d8237cfa2356e47c295585ba7666fd7f4 - f85f595cc857f48461b889a0ca7f6245866e45946f5c8522; - 0000000020000000000000000000000000000000 - a658d408b3856df66df0e5026173ae70627a649b836c5011 - 38ccb2e915fdfa02fdc9b19a8fa446b538559c6d74af7f97; - 0000000040000000000000000000000000000000 - 84ce7b3fab5d81b85e00681ed7b2ea130c53e405233408f6 - 92d8342bebfc338cec2bb424174d7951ce2ad5407211a53a; - 0000000080000000000000000000000000000000 - 17a24739d92ed5f4f09f886a435af20a3f786bceeb86293c - f51ef9e9d4841d25699f1199bf1b66d3f54e1e1b91e91482; - 0000000000010000000000000000000000000000 - eaa616b384519b85852137c3f4ee61b6b48a2eba21d566d9 - 9e58a0b7cb6d0872f9882cb52abf91ccd7978367ff6228e9; - 0000000000020000000000000000000000000000 - ebd576de80da794a234a8be925c69e88bede65f64d7225bb - aede5cc115eff89d20b3ecde8d4e03a7935d368c20c837c4; - 0000000000040000000000000000000000000000 - 4090b3588edef6e689399495eea36b33fb23104527e353ed - 5295d7a3f7ec90d084282a1a0eb82d6cff90ac2a25f6d3db; - 0000000000080000000000000000000000000000 - 947b834b466d2f3d92ef9512c3e450f0b578e9ac3be212e7 - eff671d27f5e2af474962fa0f66b63276b24e484c66be17b; - 0000000000100000000000000000000000000000 - e611b6a6801fdb802ba7499c39a966bbd8b8410f79ddfada - 357c82dda476be8ad41b40e2269ad52baa9d806c2143f84c; - 0000000000200000000000000000000000000000 - 86e67d84b15f9f40a0fff739679044f91b0ed0376a1095ad - d72da9a06dc17ce4fcb24d51b804262513573c799a57b130; - 0000000000400000000000000000000000000000 - c19000056d359565e51b7a3de313c57ff2bb35d76393acc4 - e5bd4cbffd461144135051d8555128786a9e106d063a6993; - 0000000000800000000000000000000000000000 - 2570f1f193ad3a0d2314158dd137347dd99690a6b886bc5c - 0146f5cc2c6b14652e8aa52d1c4733ba5e367a57109c5bf4; - 0000000000000100000000000000000000000000 - 7526b9f746fbf4396e5663ba52f5bfa682b0501fbd36b5bc - 107ae0fa5444fec8cc7d0f01eafa3eb0fffd7c34ac6869bd; - 0000000000000200000000000000000000000000 - abbd3dbd4a1864fc20f7226f563a7f5098ff273cc8bf6576 - fd12b3b1749e8469a8ec879560b583e2dd88784db4c25879; - 0000000000000400000000000000000000000000 - e281a5fd1b6a7aaeef32e40482d6291aa697cffa21dc27a9 - 0cef0579d12fdce29f96f135be671012502db1f95a55f8f0; - 0000000000000800000000000000000000000000 - abff457652774b07fdc99738bac8ec162a01b73f8a71b126 - 970ff7ab84f483c9f1e73567d7f38163363b14850fad8834; - 0000000000001000000000000000000000000000 - 1d75fbd8451f22a0b0a4a9c62ac6a5716511600bc76e8378 - 6be81dfd6a58e989c4a7d5f1f8fa22f36b079894564434e8; - 0000000000002000000000000000000000000000 - 362b88b73e2cd980d5d78d3b7c591fa0b1e70a9ed5eba7a5 - 7f3c71fecac4105cee4c489c01f975a232402c4635b515fa; - 0000000000004000000000000000000000000000 - a76d84d4eeb86444c3a948c0a798b9dd2778a96e30e61aba - 992557baa0a7dd9a06007681153f98f02c19d6de76d898fd; - 0000000000008000000000000000000000000000 - 667c962b1ba89807b086fa168e80aeee355e825176e212eb - 785d4ed06bcdb3f0fd2cb716ee9a1a3c462fc9b51e305082; - 0000000000000001000000000000000000000000 - c0ce233a95f06506ecc20c9d94ec5c6c757b4c5b0727d492 - 157a5a7d1e8e91495bba18085d26338a3b1463d4e9db858e; - 0000000000000002000000000000000000000000 - 85b69eb5d5b732a8bb0b1a9b3693116f983675785aedff22 - c6fea81b9347c9e7567fbad82d5b8912bbb76dba8f4a29d8; - 0000000000000004000000000000000000000000 - 2795aa156ddfa00c39642ab05e286c964ed00633bd60c5f6 - b7aedfef19724e4782a10536428547040ff7f59c8767f2d3; - 0000000000000008000000000000000000000000 - 86a2b6fb19ca72c2958a6569aaabc0d7d1f2d7dcd2b5b61e - 39130045632a3ee79eca91f2f29056c887192ce4436614ad; - 0000000000000010000000000000000000000000 - 38a0281fc43a1c8719f255c575a9b1dea32a4c81e2d4a934 - 24a434c2d65df7b788bf3bf0664a22928ce07df667017502; - 0000000000000020000000000000000000000000 - 8c8bd4434261667e10c6e5527640e4be2fd50112c27604a4 - 95c7dc7d90348e480db9cef4b640dbc62f4bd76714cbdca5; - 0000000000000040000000000000000000000000 - 7a20a0e0bdc0ce07559e7e247fe27b2e57a3a2bfd1ac0964 - ce680c2c69f4951a45434e164644c36dec6abb246bd4f1b9; - 0000000000000080000000000000000000000000 - cbf7402991a61ead1dfa657b8688ec6b1d3755f1c12d975c - 5bc02ef2adf14ec62187882da764fb4bcd8837eaa3f8014c; - 0000000000000000010000000000000000000000 - e4218125dc4a288d9bcb43710ec3029f0a5d631dfe401b47 - ae21a4b216e530a6ab6c14c8d1c728db79109ec58cf93a0f; - 0000000000000000020000000000000000000000 - 1c7038534568125aac9c0b8f3cf3df6b5c409f47d6cf7a36 - 5b87e5ab0f97669d705271c435c4e070712bd16f2c5d2e68; - 0000000000000000040000000000000000000000 - 10d92270537442d4b847b42107047bc05239ef1ca981e89a - 931bc9341a445caea1a5088b2b4121e8f8ef085a86075715; - 0000000000000000080000000000000000000000 - cb5438433b829ea6a99da8216785cf60b99ceb0923b9571f - f239aad41f8d994e8019211e64520780dea454282a625568; - 0000000000000000100000000000000000000000 - 720dd5511ad848d9c25861488223d168fe72bcb22918fda2 - c39891cba3b1e61e71101f3dfb2e72b1bed9866050dcc11a; - 0000000000000000200000000000000000000000 - f0b450e144ae3ca96a39f8ec440bd9cd20bb77deda9307e6 - 0da749458faef5ceb6192c90857a7aa5bd010fdc57799dfb; - 0000000000000000400000000000000000000000 - 01e54bdceb03d02c43f7a24495c462287bdc2bd34ea16e0c - 89cba811c829d32dc1bd8e3302c13415dc9676975cb8ea60; - 0000000000000000800000000000000000000000 - 47207ea139f08fc11911585ac7b449116552db41f111c437 - 798c17318213280bdc778c2e761913983673079ef8d74230; - 0000000000000000000100000000000000000000 - bddc51901a7f6556334147d54051bb50ddfc42b4ea97d1d0 - 07c366e28a2cca1cf218b56e12277e18c7ddc698f2ac48ec; - 0000000000000000000200000000000000000000 - c2e65edfbb87317b24d411449ed48f323b12ccc1d5a5b7ff - fd99a7ce5d3e82b466e1b5396a0fac675678d17237b6d52b; - 0000000000000000000400000000000000000000 - 30a8d0ef4c28908b2f18b2bb9848eae86269ac525798ae76 - c36b40691fb3860ed243d7c4ca22dbe6300b84dfc91f541a; - 0000000000000000000800000000000000000000 - d2bfc99db253d16a9b3da4c77b4d8ae6ce5a82388ad113c2 - 5a005838a2a9713b8384cbb052ff742664f69a24260a03d4; - 0000000000000000001000000000000000000000 - 2a916a4edd73e4dca0a529a08b8f9d29e437edaa9ea50bb0 - bc202d61c79a55eed0cc2489c4ba4c7b5bdaccf3e6404dba; - 0000000000000000002000000000000000000000 - bf7879a48b750f7b9392746617c768581f3b21b231ce81e3 - 67560a5ac0f6d75e0b9e0c81e006d685923d80bdfc75c064; - 0000000000000000004000000000000000000000 - fd436ed32f95d1682008a0faff041f4793f67fadbef3645d - ad24e531f725780b4e2a33c01e1cab0c278bcb6f40edc186; - 0000000000000000008000000000000000000000 - 524a9d2ffc5a0261bb2db2158632b886966ac2935c05c0d8 - e9615c9cede6feaf6877611d633c2454d3acdde2ae2ceb4c; - 0000000000000000000001000000000000000000 - a6a9f7b07ba8db6b135bddcebf9f137b46c21366c742b3c8 - 2f54bbdf8a289de06c20837df3752765970d582f7cfbb5ed; - 0000000000000000000002000000000000000000 - af9c61ac592907f8526a96bb7b6fb146c5a069aee0775b07 - c79a6ccbc8d009fc3358646fee5236fe6b739f02f2bb5a86; - 0000000000000000000004000000000000000000 - 0ac8672af776f5e1ca0fe859501d3676b5358f9b22f856e8 - f113bbcafb23ccc325b906522b4058e6cb26fcf24abf6658; - 0000000000000000000008000000000000000000 - 498b0116b3767b651da3b7d4ec2d513305d1260826d3c166 - 862fd18cd2fa16ae249b66066db3cb871fb1571678bfc82b; - 0000000000000000000010000000000000000000 - bdc25d6e937f2e889fd774cab71fc86b2898652c44406193 - e48d25b9e80fe5bee1fa7e6480c9f4502fd0d5e1534f7748; - 0000000000000000000020000000000000000000 - 978a52ba33b411f1dd33ccb5f9fa7978014ff0877a8ae115 - 9710fffcc51af2e428f5a4da72ab1fd721be7ad3aaeef40a; - 0000000000000000000040000000000000000000 - a79c6dc139e5d91b27102f5fa0f1b8e6482fa96fecb021dd - 15605d2943c8c9d182208e4db05075e132e451086a9b609a; - 0000000000000000000080000000000000000000 - 321eac9f621e2ac12cbe8b5d5d1a75fc03f6c16371374934 - 548803f109cf611d2e7ec0e87098e27b2c149194ed832352; - 0000000000000000000000010000000000000000 - 50117692ce6e19e23d553a4266cc3458f8b05e02c7dec8c9 - 6c83e70eebb0018f4d6e229404e39688bd07666f6733b560; - 0000000000000000000000020000000000000000 - ff480a631e43dfdab88f31f20699a113d7a6ff04d8f33bab - a1485a58f6d8c01604dadfda7d03d7717a8dd2c2d20a074e; - 0000000000000000000000040000000000000000 - 23e5ca641b9b76fee53eb3f8783a24030dccfdacefc8ef29 - d4a1f481e845a6025b3bc9901a003e2a3b4a6ea49e8ebdbf; - 0000000000000000000000080000000000000000 - e06841bfb58278e02eef5c29cf5d05c00274e18bb34d967b - 70097b468635250585a96b9d81f1d54cab338095c33b954a; - 0000000000000000000000100000000000000000 - 853d124cdc7b138c9b17798a4f1aaa343bc179c7aebfbaa9 - 59b5ca04ffb3d7277c0e0505e8be581641f233e7824d5e11; - 0000000000000000000000200000000000000000 - 5998176bd90c122ed78911aa5948a5ad2a07df42cc41e967 - bf577dc495b1f12096a3c1503d1c3a1263895dfc9669a2dd; - 0000000000000000000000400000000000000000 - d11f16da1b85b6b7f91fd0c4e24122c9169b45fcc0f630f2 - 03d6401fd083a0700a06a243c8cee99c0966e61230c70901; - 0000000000000000000000800000000000000000 - 24d65de955a156e8253055f73589da884636a0c5058bf6b4 - e89aa9e074432b437f15b56f6d38a7fcb24cbb208337dd01; - 0000000000000000000000000100000000000000 - 4b93290373c2747ab475d7f4992477727b21391f0cb42739 - 959d181d009c0d0898a694b8d850647d76961f611682ea7c; - 0000000000000000000000000200000000000000 - 93fff47d6977a99536ab313546ba940048841fba7a5fd9eb - f8769c05212e6d6d4093fbd80ea4559513b3d18f62ed698c; - 0000000000000000000000000400000000000000 - c8070ba52cb08c0f814b025d10071efaa91babd0a3a8a1bd - fa1c2ca6ecc071ecb923ccadc0f69acb701daef5f56f1936; - 0000000000000000000000000800000000000000 - 0a3ce83ede05ef4dc7095fa9234e419fc31acf8696e9cb1a - b6fdefc344f34cfff5b2e2e4afa00f426607f4ec1f727eff; - 0000000000000000000000001000000000000000 - 4dc5c361823d632dcc5813096d9e0ec1e0f797d303d75e7a - f156ae67015b18cb6ecda9e03c6558a67b89834a175e5e77; - 0000000000000000000000002000000000000000 - ab85aa11008c58f59b58019794a2b480cf51aade35a2d269 - 9c2821ffb2e3dc84b9608d607133e4b34e35643de130442e; - 0000000000000000000000004000000000000000 - 87dc8d3de6852d06a9712bd570873c1620800ffd01e35b17 - 0fbe6f80f9306e00330a42a9d7e57cc68c0d992b70d9e982; - 0000000000000000000000008000000000000000 - 606855c5e2af7d73a759c740552e82ccb6cebe5509d6b8e7 - 78e8ab0a55e16027dacacf1de95a31f9cfe73bbb17aeacd9; - 0000000000000000000000000001000000000000 - a739b8e8bd92be110edb4378a58e0ccd15d564093f303750 - 124ef1013fa8a440375625eb3d056d78bbeab4f5e808783a; - 0000000000000000000000000002000000000000 - 58ec509a6c549d855602a8ebe8cd3e81be9125f7df70a84c - fd3f5db70bb2eba772ec550e30b2b3e5d51aea15ec0f2e3d; - 0000000000000000000000000004000000000000 - 447c79e0983fb296711c2fff964122ed7ed11292c018d2e2 - 83e12d4da49d463333fe370cd180c683ba65f9145a76aa18; - 0000000000000000000000000008000000000000 - be55d4ffe6d7cca90032c0808f58bb3b1713e19b1151ac0b - 9514f1e6c4e615dc11d0e4f9a25646f2d3361fd038bd8cad; - 0000000000000000000000000010000000000000 - b2288fec987471fff2d3625f55630630c6344b720e2f9d17 - f7eb7d549d9279701f73b30ac5747fb2caadf10af6967bc2; - 0000000000000000000000000020000000000000 - f4092ee2b5f070731b2d68a0acf2dfd5caff8b7302f00eea - 181be1b17f1bb5df53c76582bc5f460fd90eca3f273f004f; - 0000000000000000000000000040000000000000 - 7421b7fae0482f6cf39682fcf32a7c23377f46d15e5d2fab - bebc8fdcaae6d0891571abba31fd6b5525e3825689951ff4; - 0000000000000000000000000080000000000000 - 6a0271edebc4ee46a837798b8a11e11fc9dd37f5eac9cea5 - f88c774103bfd9656cad11ad4b2ff3246a79271f9bd319e3; - 0000000000000000000000000000010000000000 - 7e7790676f13b58bff48031105e4b0e0ddea47e227cab1b6 - 95e30e5b38892f17c26315287bb12011906932ef6888c307; - 0000000000000000000000000000020000000000 - e1f369e67be60abe334c75c254bd5f819d15397e52ce1991 - 5e08e9923dcac610c4f228b1feac23bc6e0ee8f2880625d3; - 0000000000000000000000000000040000000000 - 5da337bd8a553d4a311d9cd0d00cd8c1292a248704f08e67 - be4b68b824170d0a635b10c1dadb2a69146f5a9ff9c45d7a; - 0000000000000000000000000000080000000000 - f36268dc83dad1fb42ac11a70d2b04c3074caf05f0d28e4b - 93e3bdb8ae0c1283991383131f42785aa6c13efac96a4ac2; - 0000000000000000000000000000100000000000 - f509a4aaa4dd6d33c58f09517fd61b0a3e173981cee23328 - 0d3acc8d01a95faa7bae199eadb1b7f0a6799cc193a36b87; - 0000000000000000000000000000200000000000 - f06206eb3ca9d5b3a97ce33c86ab3ec88e025396414965f4 - 06c48b3173b95040a1b30b80892f28205bc3073c06af9690; - 0000000000000000000000000000400000000000 - d94cd93f0aa42e7aadc3fe5134a75e22901a277a9a8b8914 - d040857811c9e9ba2b1d13842e74a2aa3242e8b92106d648; - 0000000000000000000000000000800000000000 - de0fcacadfd215ef8ad575bdaa2fc3530d913a03801a7e93 - 142c97486e896f09f6694b3fb82fc7e6da00fe9882351ad4; - 0000000000000000000000000000000100000000 - 416e67c9024af80ce9084c854109b4d78fca84cffd481f3c - b9a534a054aa28ae408d293652388f7dc8782441dae29783; - 0000000000000000000000000000000200000000 - 1967362294f80c18835408ec52e69b4863a0e463f759a6f0 - 95e7f20d718ffc48412abc598fad1826697b7545c8e3e0af; - 0000000000000000000000000000000400000000 - 1ce4ad11f24cf2785769f676ecfd2cd5479766bb09236f8c - ae02eac15efa0b102722ec4b393323c3f9b4299ec8d62ed6; - 0000000000000000000000000000000800000000 - e3c9df7ae6d132da795747f26daf2a538776ed4694636419 - 9c6012e67ff701322397ad7a374116289b3b1e35277812ac; - 0000000000000000000000000000001000000000 - f4faf834e3aa92af4178e31d770e7ebf70bebcab1752c561 - f6fe6c69c4227663ce35b7abb77b78df395f2ebf8523cf28; - 0000000000000000000000000000002000000000 - d667bdd9f5967cc525310fefc616998b4705ed09714a55df - efb98baf6fe8946fe39778606ae2fa874502918c0885ff8e; - 0000000000000000000000000000004000000000 - 830e96038280527632cbc228474953ec407956662ecd1e7f - bc1b15c2f9951c77111f6aca5fc75222615e4a12287edc86; - 0000000000000000000000000000008000000000 - 6afe6de17fbd8260c7dce898f26d002a6359800bb5789c23 - f3c39e7caa6be7d346d62eccf9e1d20a4df2f2c52f0c4c2e; - 0000000000000000000000000000000001000000 - 6eb5d0fab61828d24ae3323d3018f65400c8c3c0ded66ded - 5a585a0bf790d36ca04f6e3db2a8240bde8674bf26d0bcc5; - 0000000000000000000000000000000002000000 - 279323d7c326dfe129bab246202e23158e24abf280e04a5e - 721cf1d8e73cad3c3ab65d34cd83fc131acb73161d33ee18; - 0000000000000000000000000000000004000000 - 6e74528189d18b5d8de86975b2272b708dc62f912bb1f90e - 8e2431350408e2394201afeed37957886df2ec97eb5a872e; - 0000000000000000000000000000000008000000 - 0e4780dbee0c09822f67da8b98aced5440e3641fc8c80d4b - 5049f512c2cb135fb8842351a8cb5502bfb9895914494497; - 0000000000000000000000000000000010000000 - b40751d42e542a27240b1c25d17d088fdf35357a8e606b65 - 0e9feaceb106eafffd46da59acfd588c91510fdb60f6c101; - 0000000000000000000000000000000020000000 - ccdf33f8a14357509960e96ffd707d34d6e125593c470b22 - da36d09446c89b49417909efc8ab9b8884a82676d0083b27; - 0000000000000000000000000000000040000000 - 7b51094cfa2d2972b921feb7bc4910af27329e6417eab51e - 4af16a9cd82694f045f72a419bac4b36c8f4d1ba7b6d7853; - 0000000000000000000000000000000080000000 - 8912b55eabcae2fd33cc24d48c77e9ea91ad17637fcc4e9a - ecdedb7cb770eb34f181e7f4e168d3cb97a62eda8a93a71d; - 0000000000000000000000000000000000010000 - 4da00b91551750c9e42920ca30cb60c6800614cdd94478f8 - a1fb6aac2ba91f1db16292fba881ec25ec5139a05bef8360; - 0000000000000000000000000000000000020000 - 1ac4f21d876b643c6a4e7dbde96f5b46871988c089075722 - 957f88bb33b20c12a264f47f483a7319275351c5beae257c; - 0000000000000000000000000000000000040000 - cf0e9847cf96d79d483634b86b9d946163fc7f75ad200380 - 090dcf1b1e3d1614b9a81368ae7494eaebafa78f7c8ee545; - 0000000000000000000000000000000000080000 - 8776c8edab400e4e107458c529119fb645ed0232c13ef316 - c190562aa4f0e4a8a0b142d3842e16a1e4145a865533f820; - 0000000000000000000000000000000000100000 - 5364915ad601a7b24e7fa93224e0f890c1b19976ef727604 - 8fb3df4ab244c50af5acdd8273bbdd5ee22433978a1eb577; - 0000000000000000000000000000000000200000 - ac3f6c09935979c1c7ed97fb57b6b4effc7ae93007905959 - 65d4b7f38a928a43be02d8c01e6de2709e2eafe4cbdf00d3; - 0000000000000000000000000000000000400000 - 6531fb35b522582fd8e344b4967d4fd96f3f028df9b8a0f0 - 433d474f5759f5a6268d21ff330185eefd7581fb417824ad; - 0000000000000000000000000000000000800000 - cddb346f0a62dab089d9d08e5728c390528341a65207762a - 15a50b1d5b86af3bbc2d769639d1863187e6abf155550d85; - 0000000000000000000000000000000000000100 - 76a743ed49c15a6ae22baed339d3b3de0538d9dd9a5fad03 - 2f81d127787c8b56417ec1b0eeed0bedf24dfaaa5fc101a9; - 0000000000000000000000000000000000000200 - 959c1be8dc4a8d23c065d0af24ac881204f64c6ac6f39649 - e5535e583d915bcc451d04d40f88d00d531eab1e74a85936; - 0000000000000000000000000000000000000400 - 60f09275f915ecd4753a88c14f310627a68c85b0059cc7cd - f2eb6f33261a6f1521acf10950689cf8300ea1f7dd02c455; - 0000000000000000000000000000000000000800 - a582a3a84d722b1888eef5459d744f4c9bf0f254393eade3 - 5171c29052d8aa3d3bed54ed6013e5bf27f0ca0c256e5df0; - 0000000000000000000000000000000000001000 - 5075b276fc0c1b44b34c2d7103a321119dfd5ca9858f5ebd - c3e543ed7b34b725a060380f5f351859b5cd34c3655c1bb8; - 0000000000000000000000000000000000002000 - 76ecbfce581f71b255f56aa7118900ca55482a1402d508ac - 16f238cab43a3e15aa8bdb6546bf4907171d6062faf6d51e; - 0000000000000000000000000000000000004000 - 48c37ef151bd87c3c8af4b33d2cce7007aeb511e4c9eea95 - b78ed418a8749a58fd1fa8eccd28ed1ce220682caae446b4; - 0000000000000000000000000000000000008000 - efbc6f0100835c8051fa95f338915f80004763efd684f982 - e88cad94409c47ee2fb48fea7996afd75780fdc66f55e145; - 0000000000000000000000000000000000000001 - 8f537350f5a94603ac84b105dad1ce2b27e775b251ffcaf1 - ccf28017b1b6d8e853094535b78c0c533ca88d3119f88130; - 0000000000000000000000000000000000000002 - 73bf403e90243af00ae3573bf26cbbfaf22bfc64c25042ba - 842c8b6edfd5470e1261b53cf3f495c03e7ffbf747917b03; - 0000000000000000000000000000000000000004 - b2e7d8fb0bb71f3543285e36b768726cdbad667cd415fedc - cae46b71316c769290340cdfc99c9751fcdf53a911e75700; - 0000000000000000000000000000000000000008 - 391c06d7329a903e22f310c602d86877dd921f82e15173be - e2b1e5114f1648ba3449d564fb1ee26d7c325630777a6ae5; - 0000000000000000000000000000000000000010 - b54aa87e67f0e182a88660fe8df6a34dc2fb021fc80e372a - 30d3fcde749a306eb9d5aad0527c7e187449beb5a0b4e2a1; - 0000000000000000000000000000000000000020 - 003bc47785839c9c0d915eddb61b2eefb3e474c86cccd321 - 388746b96cc6ccadf4f86e0a98baa5dcf6d2c777195a8b07; - 0000000000000000000000000000000000000040 - c737e23e4813ee5321ac10198e108ad3cb59dc35a46aa4e2 - 987655569a6d6c797b7c432b8711c1c4a29c95c8849fbb6f; - 0000000000000000000000000000000000000080 - 2ea5c63608597b7da53a2ceed973943951552fffd89c0101 - 1d6673cdb23e07fd73fb0f325b98a9d7640a118e170b20ae; - 010000000000000000000000000000000000000000000000 - 950227a0e0af4be87ad9923642ae064a989f7bd41783a808 - 9d1b35004e09dc8a26c67a60c358a299cfd493a5825d2bfc; - 020000000000000000000000000000000000000000000000 - e06478bdbb64dfc81293d20b3babe451119c00a57abc32d5 - 5cba681dc30a6350b640f6ff5d82b9a59ef4724cceacd6a8; - 040000000000000000000000000000000000000000000000 - 9e2a31deb5c28e271d69790d7dde1fc96b5e2f727ba863d7 - 383972aa8b8a05beacfd3cca26b84ea7e658f0a161c44307; - 080000000000000000000000000000000000000000000000 - e7248873cbe00a5eb07d18a36dd1551e1de656f175795b68 - 72c76c4142011ef65b3ee4d1d92845dec5d24c09b8e15ea6; - 100000000000000000000000000000000000000000000000 - bc6a56d706b865d0d0bb17f6f56a946b19b6463823b50705 - 5856456857fe3829df5ae6ce9c1559e2ec272e2023bed389; - 200000000000000000000000000000000000000000000000 - fc9f70464be8294b04c3092a09815ca7cbd9e4007e35a6e7 - 1873b51c4e65ef63ea2ad3ab7bbe2933c53607c2f4f822ad; - 400000000000000000000000000000000000000000000000 - 9252b21b6ee8ad2618bbbb0624fc077c593422d73c205172 - 3fa2ea516e55274a6eeffc125729b4f323395a9375fabe20; - 800000000000000000000000000000000000000000000000 - 23ff2420dc5bfa41b4c1e02c9724c8356973ee4c29900941 - eb5c441b2c65f801f3781c59bcfba202ccca06a5a0daace2; - 000100000000000000000000000000000000000000000000 - 21bb39d0e07a104683fcabcbf086ae38505f21119eb69eb5 - 317efbc320dc245436f65995b9555a70567061f15b882765; - 000200000000000000000000000000000000000000000000 - 5faa02f914a0d07a3ef66ad9b85dd7292cfca0e96b41b18f - ac6668e2d5bc13abf89ab4ef5ba02e4893c63453fe6cdfd1; - 000400000000000000000000000000000000000000000000 - fd2edab89c53584e62d29154ae3eb025eda061a2094d1c55 - 074cae6a1865c11c8a740c06500f972946ef3f7cfca6c784; - 000800000000000000000000000000000000000000000000 - 1200e02bfb0d2994eee80495fe6f8db63f480f23b06943ae - 665960dec953660aa472689e099663ea2e9281bc0ec42b70; - 001000000000000000000000000000000000000000000000 - d7680b371b3db05b0fd319e98c4fb48faa5147c24fb8dc98 - f0faf1fe00730c1795fbc5865cf67def50d494e9b0e40085; - 002000000000000000000000000000000000000000000000 - 0ba73097866cf7add6a87d76db9512a2965f43a59842dc9c - 867abf83d19cda8d1c980c008be09eb6d3fd4c2a3aefe157; - 004000000000000000000000000000000000000000000000 - 0efdd7ae03dd5d0586093ce70bb56933d277cf262a708e53 - 15828719856c5b9f77c12dace0afd8bf79de06c99b18ca32; - 008000000000000000000000000000000000000000000000 - f8aa22bf8e9b805311ea0cfeb6633a4d333c25df26a44086 - d24bebb6a79cf48786be0aa33e3f0d904f4c1c256ce5284e; - 000001000000000000000000000000000000000000000000 - bd4971c056be4d3e3a7a7f727700ab237838abe0cb8006c7 - ab9a06b02608dc9824147e4fae22347564145cc72acf6d63; - 000002000000000000000000000000000000000000000000 - 47dd63c99f11d04f002c78b4a9f7e87e6a95103f6b952088 - ad3844299f2996c7124618b420a5d20476f8724a1a2a554f; - 000004000000000000000000000000000000000000000000 - c23a8c3c1c99c1094e0e33ea48a795e457124f219a7ca076 - 1756e14debebb81278d38a6e1e030c41ab3ad10db3723956; - 000008000000000000000000000000000000000000000000 - 4e51df50080c1c5ead84794c7f8c0b6af24eb44940230a54 - 6ffad11649a0460c565e360be1d922b3882760bf6f6cdb0a; - 000010000000000000000000000000000000000000000000 - 94544aa77e6f2e88130f6d882ce6d41b92805e8a33bbf758 - afbfa3504fa60b0c174dc726c32e36cf044730b03de81da9; - 000020000000000000000000000000000000000000000000 - 4fcde9e30ebe03a1f724f6b00d806273582e1cdfc15ff147 - 80558bc2b6f44c7ba7d6640d99278f274b2290e3d574e93f; - 000040000000000000000000000000000000000000000000 - 2fc3569fa2e00eef7c411f2b469869e37982de1d4a6e6a6d - 6adb474171dac11f836848dc4753239335b91b1f5e1392fc; - 000080000000000000000000000000000000000000000000 - fc5b0abf6a26469cbc8b64bd73322994717393eef4fcfb9d - 3c2acabbf67983924899ccfc1d003cd931f4808fd2aba192; - 000000010000000000000000000000000000000000000000 - 4c72a0fc014cb5ca4e85b0871f3fce111bfeb1ee212bc3f3 - ef0ba0a4ccfef260c42884b03ca09c7bbd022b3c69d2efaf; - 000000020000000000000000000000000000000000000000 - 723a6062b95c8e17cd63441dc3542103ef5b62b2ee67f696 - 0a0c19d7009f4984767aac9284ee75784b632ff2b8b0165e; - 000000040000000000000000000000000000000000000000 - 00f433db06d51a81037b312e1687b90668b14b5c87019e79 - 2769bcb9e372babe64498035c9ca6d385e713f2c62da9830; - 000000080000000000000000000000000000000000000000 - c00a26a106c43e944d8012181e873d57658bd3efbef46926 - beb3b2eeb0e4cf7af92ab9eedab0afaceda36a4d158fc060; - 000000100000000000000000000000000000000000000000 - 2b6af19499046a72002bb08321899ea1196e43a3445dc66a - 53355ad208629b72a6b63955ea29d96f8625ef065d7bfbfb; - 000000200000000000000000000000000000000000000000 - b8bd2b3ca21a4e9c46f3a6ee8283c629e51ad868be5da5eb - 099fb4ee85dd16e2adb3a8392721eddef3284ebe72a629fc; - 000000400000000000000000000000000000000000000000 - e7a823381ecefd169648af7cdebe27bdd33575997b16c9ea - 2087cb8faf6e0f87bfd483bef04ae0aa84b7faf1d66c3067; - 000000800000000000000000000000000000000000000000 - 10bf2538f02d13d5d6df68708a1a875152c8253a189c44a6 - d7c45cd1b7df5ee240c9e19d9a875c99d06bffd5b58249e0; - 000000000100000000000000000000000000000000000000 - d60033a9a4020d3be5214edc136c993f05a04a3e8ea5c8a4 - 25b00716396a5cc3c54215e42da5c2642073d967fc26dbee; - 000000000200000000000000000000000000000000000000 - c69e4ed75ca48419d526e5997f9634d1cc230c49158907d5 - b8eedcc2227f3593df72a78ed1100394eb65f9098b5eb4f1; - 000000000400000000000000000000000000000000000000 - 9dd47ff28851b4da258c41aedadb4d407e39dcf8421fe2fe - 913ceb307bd491e5a5e7c6945c7b3ccf2b30571beeab889e; - 000000000800000000000000000000000000000000000000 - 245dadd57e5ea520d0319892ecb964fc7d7d75ac259196e5 - 06ed9325638f5f233cc3c6687e966d18d13a2376a7d0d2e3; - 000000001000000000000000000000000000000000000000 - 4b88b385ae2ce90610c3de9942359182b23cf96617b01a50 - 1789bd30c366f57f606c139d7dc7c00bd6999994bc225eba; - 000000002000000000000000000000000000000000000000 - ced8575125b759ba6fb81c4cf51b309f1199038471b1034f - 4d3bb5964432e95176d2438ae186c9ecd0aba9b71899b85b; - 000000004000000000000000000000000000000000000000 - 2d74c25a841900a8b9a663b0ef0dbb1e24a4950eb06445e3 - e766ee906e42ad9fbde3aeb74fdc464fc3eb72c87bef45cb; - 000000008000000000000000000000000000000000000000 - 20f7f88a12d40f3cb6b592008dec36ee508387a7870e8ba0 - 68f515a58c25941d27fc209666df7caac05c6ac143a883dd; - 000000000001000000000000000000000000000000000000 - 9c95399291b0d3202663fd9f6ee972975c862cedbf2461e3 - cd0987b7da9744e475b9a457e34330216858240559c3758c; - 000000000002000000000000000000000000000000000000 - 877cf0278449adf691b20d5b453d891951a1d1e8eb03c47c - 5b16a43b032ca092aaa101ce8d0daf61894d53075fe02768; - 000000000004000000000000000000000000000000000000 - bae2c00d2a033ad2acd8719acfb01332aaf91987a84b046d - b9f4306305a262b7a8341f8bd9a30722b18479e8a722c030; - 000000000008000000000000000000000000000000000000 - 3a8b7c986f313adf30c17005fc8f4e4783cc7efbabb45b0e - 80c005616ccd2e26d65e3b9d6b3284218a90448b59d6a4c1; - 000000000010000000000000000000000000000000000000 - fd95f34a972382c5c78e702b777c873040970ec04477a9b7 - 0f8ef6fab119411fcac25d7794514f6879ccadfbbdcf1737; - 000000000020000000000000000000000000000000000000 - 0e76cd58cca1993794ee6fd9537271c337844d69317a3064 - 0187210213980e21d629cf30ce5702e6c3a78fbec1847c30; - 000000000040000000000000000000000000000000000000 - 7cc71eda22e83901a5e7d5d0fc5a2dd1a9a74c25146406ed - 040739cf452779ac78d307c96dc0298e34f9ed95b4bddce2; - 000000000080000000000000000000000000000000000000 - 34a0f031a22247f0583237ab3084581ea0cd8df336723285 - 3a9ec82043173a791c04b9b8be7ffb35118bf09e3d2ee0ff; - 000000000000010000000000000000000000000000000000 - 0b6cf14a5abe2dd979c268d5145083b48889d69df0d37708 - 991b6be8eee496149a181200b1fd081e437a9b5fc0cac4e0; - 000000000000020000000000000000000000000000000000 - 08cc9b13e27d4cd3e3d7563eef1dbba235abec2a418f1852 - ae9edb5746fdacfa76de58675cbbd24a4a7e77d96fbe7b6c; - 000000000000040000000000000000000000000000000000 - 824c0dec5d6a4df429da24bb8e2fc8a4372bb92074a2727a - 8f0715b035222ee533b0981f01550e8e5a9e24412d9ddfb4; - 000000000000080000000000000000000000000000000000 - 68c15e06234437eeb45d5108e8259a70e13258dbab25b697 - 8d177379a2039c1a7843ad87fc6ee1393a4cee80a2751141; - 000000000000100000000000000000000000000000000000 - 1001198aada4c22c4dc1d84fa1e010cd54835e132f22dfeb - b8cd530fe6ca419cfd7bb8081845fcde53b2adedbd801018; - 000000000000200000000000000000000000000000000000 - 9ee54d6bc7e24d0c738ddfb263e5b63fa26811b76b578409 - 7f7446709375b8e32d8f0fc000eac04f0b1b82a3125cdf96; - 000000000000400000000000000000000000000000000000 - 85c19ef941156968fe05f7fb61bbec5122012fa0fd4bc828 - 7168634d5b191ffacd2f8e4928119d68627bd4b027db18c5; - 000000000000800000000000000000000000000000000000 - 2e644758b3e889cdaf5c845e4ed308be6a3eea514f893e6f - d077d2ee5cc8d36b632d4e983578d6bc894ed2006b57b466; - 000000000000000100000000000000000000000000000000 - d86c637f816b37de534d296fe76092971f47418fe1250959 - b15790c9ab783aac93d8944f77eb9d0d3ef9fecac04a2918; - 000000000000000200000000000000000000000000000000 - 864954a4c173fcf64b26cd5f046a1c7a05d1c947e054f155 - 4fb4609c1b2739d513358c7bcf38385f1d90431c60437b6f; - 000000000000000400000000000000000000000000000000 - 7429d917ca0f35eedf754a3dfc87fa86efb1c7d67297343b - 7c66f4fc42a427a5175cbb09feac1aea770471a8566ea04f; - 000000000000000800000000000000000000000000000000 - 3782aa7d7eb154ed5d96a1cba095ddab7d2446cfc02928bc - 1e6d44ca07547ad0916761154378d997b27c06f4162dcf9a; - 000000000000001000000000000000000000000000000000 - a668c27906252b42c57223bf1041b4474a265e456e2b2ecd - 3560a2b61ac784e7a96ef52262e6dc91e50518c9fac3b4b0; - 000000000000002000000000000000000000000000000000 - c84f1667f91ee7bdfc4354dc978f0d7cb7bdbf8851a26120 - c7e80fbe3e6f54d7b6e5d8b678c95da1836ee1f51d9433ae; - 000000000000004000000000000000000000000000000000 - 29292efb39b4bcf42c932f53d49b14c97594be6e0b3433f1 - 37073c3c11ddb32e01fdfd49f6eb19b2b651fa9243a77376; - 000000000000008000000000000000000000000000000000 - 55fada32dbb1f89e56aa524e1fd89d54b43c4df2bc223e4b - d6d58bfc7a97a059494c17ef3affdf7d3e1702e78ca36062; - 000000000000000001000000000000000000000000000000 - ccd662881392daf3ff1ed0021b38e19d8ab8d01a2bf58700 - 336934b6f95645d246b72d600bd366a77d312065ff9ecfe8; - 000000000000000002000000000000000000000000000000 - 922bf0e21bef2411ae54cd3cc6d5eb7a9ecfadb1db60fc5e - 88d77b89f6936f6249cd1128bbd9ca6625fcb1fc3a08a251; - 000000000000000004000000000000000000000000000000 - f687602ca24ca63d2a29a2767278dc6548520317451902e5 - 55d57692a413659d964e04914e6256bf92155c60c99bb55e; - 000000000000000008000000000000000000000000000000 - b5f8969d59419a804c80468b2a9de9c79516a0799abac18c - c1057e3f43e1ebaf15d380a7e0e6de243f7f2fa3950e4c99; - 000000000000000010000000000000000000000000000000 - e04bc9f8b61a4f9de92ae6244c7b2a4e08f6c3e3f1448f33 - 0f8fde70f9e667cf2e9ceaffbac28d2e209ea2abcbbb8a77; - 000000000000000020000000000000000000000000000000 - e971da1f557584cf07135aca681908701acdaf839e3712d4 - 09acbfeb972d8a06fbf34de6c82365c23d999cd74647abff; - 000000000000000040000000000000000000000000000000 - bda162e322c262b9d35b36e0e46a23676014fe48429f5cdc - aa5b0598386fb110a46a87c8fbcaeb516de28ea2ed7f8d20; - 000000000000000080000000000000000000000000000000 - fd9ed1383cec0c64be074a4d57ddf0afe49e5ad2c009fe66 - fa16f08eef73e9de97deb09eb19f332ea42193d110bd8404; - 000000000000000000010000000000000000000000000000 - 27f427404340f50680538b37b52c848743366495fc402563 - abaa5141060bf1bf3134136e0b0b141ab248d2ddb9ff063d; - 000000000000000000020000000000000000000000000000 - ae41da022c6449e1e8a428ec9b889ffdb8a437d6480a0c81 - 15abc9a52c7469e98ce02e534753cc84f76cae07acddc082; - 000000000000000000040000000000000000000000000000 - f0b9b3502228b1f620038dad3f8851b141a294c1248d68ab - b76b98012d904ebba304ae707227df9950522a6d5d4461a8; - 000000000000000000080000000000000000000000000000 - 60ffd6930e94706f169e7067ae595c5e8e0ddf0b77db2829 - 3e8e2ac1f42519bdf5bec90400c716fae98a1be517fd4792; - 000000000000000000100000000000000000000000000000 - de5aea72327f9a7b74a5f80fda52e2157b22ea92e14adca2 - 55d09602919f23cdab77f5c03bc381a6bb318b8468f21c8d; - 000000000000000000200000000000000000000000000000 - 0b5ab5730b4974b1eb97cf228b330248a095259668378c80 - 268cf5bc198bc91b6644663d29ba29f90916737b513b54a2; - 000000000000000000400000000000000000000000000000 - c7fda4b796b2152eee8141d57bad874253c307c6458ba9bd - 0211fccf6da981c4e1de0f8b8fe3e1dc12e57d0ba2c4bd45; - 000000000000000000800000000000000000000000000000 - 0ccf6e36230d2a3fcf1c3166362811bcebbf84ab4c6266dd - d185d6a587f704393c58c0808b9054aba16b27c46129afdd; - 000000000000000000000100000000000000000000000000 - d0eb3bac789ca548310b28febf4ebe3a8730edc80788e322 - 72d5147984e036a42b7b803b1ab7e8de83a5bfaaed63eb93; - 000000000000000000000200000000000000000000000000 - f1f9a72096a0d35a3bde4203b234d6fd8fe7cee52c73d3b2 - 45b9e1ac776727e325b3d07cdcb8c7950586be2ba64a7e20; - 000000000000000000000400000000000000000000000000 - a0f475abb02d86fca05f4ee38a4b96f1671edc37e4921789 - 92e568e95bb7da1bd9c413d3c506edd480ca5a2022145e18; - 000000000000000000000800000000000000000000000000 - c2cb82eb6202462faffbe17860caf958127837bb56679d26 - 84a77a9c5053d7b382937ae4058a0c2c8e0cae806750047b; - 000000000000000000001000000000000000000000000000 - f69a70aaa3145b6648b244b0cfe95e258de12960733fef39 - 8e1d6e60c18153a420586a9525a8a35a0e01c33d445d394c; - 000000000000000000002000000000000000000000000000 - ce821767e1c5200f6e949eac5d032365a021002376f286ba - 66c57c2559bff8bb523acf8308a6e87d48507287f78d5fb2; - 000000000000000000004000000000000000000000000000 - 25a78a2f37beea632aba391e99c8ee0cbd895861704b0508 - 7837958ca54303afcf6497fbfc3feab75fa8dacbb2da0271; - 000000000000000000008000000000000000000000000000 - 424443625ccf703366b5006c2a06a5844107afeaca134291 - 67d5149bf0ef07975a81fbb90367b0c388c71706a71b57de; - 000000000000000000000001000000000000000000000000 - 0c4b5edc7c9af09602270ecfcb227a08c3eb41e8e743c46f - 38451d3e127ced080e76deac3a2608e4ba9c6f64858986f9; - 000000000000000000000002000000000000000000000000 - 3806f72a054c5cae45b69837bf2ed1cf3d95f548ceb6ab8c - bf3a0b3586be379283cc846f0e2f7a726667f22b4bd8073d; - 000000000000000000000004000000000000000000000000 - 53acb46560bcc190fae42c7a64bf9dc3523d6e039a6a2362 - 1662cc1720996bb8a3af6255e767b3197904d036ffc66bf6; - 000000000000000000000008000000000000000000000000 - 02f3e87b459d0f8b9efc00443a035552f21f114b7b85f451 - a9b157c5bfa6119d89b2c205b7a1f9742865b4c1e7f64501; - 000000000000000000000010000000000000000000000000 - 8c5505d686afcdecb2260e057ac8f325657df05bf9b05966 - 5ec81b79d35ba3280ea12e5b043b3e31e268829e3d563eff; - 000000000000000000000020000000000000000000000000 - 55cb50e1caf5c71429c98f03714b692ea31b1c43cae13b34 - c889fdec89a6a1495614efaf5af9ba6defb5a56452ddf97a; - 000000000000000000000040000000000000000000000000 - a738befdbe5ca885c080949c0c6d20ae12673cc7d20f8f83 - b6a93ddc7d3c794fc40483401e90d67841b9f5354e14c5ee; - 000000000000000000000080000000000000000000000000 - ad437b56deab48e58dbac0415241c21f1e58f9697810c86e - 5f39077bf328fac90226b173cd437ef53ecb7a98e0cd4439; - 000000000000000000000000010000000000000000000000 - bea057a143e4fca512bc0a7905a92efde0403dfc766633d0 - e22ff885888f579985075b711375ab522d0f44def0571561; - 000000000000000000000000020000000000000000000000 - 52ae9040cda27f5ee7fe1414b48401560faa8141518dc3d8 - ca197b53ddce530fdd18c70d16cfb3ebcfabaf86f28a3593; - 000000000000000000000000040000000000000000000000 - 6bb619e1ad95c1cae465758158d3eb2f49eeb6fdf72f46b6 - 87c5624f8f1cd1ebef2de00f71c5747bd1b62abdba15326d; - 000000000000000000000000080000000000000000000000 - 6420252af652e672b66ba8b28241d159e9ba6359c5c9b917 - 090a8bc5603faff86b116c11c4934bf8f5c1aaa119fd4b04; - 000000000000000000000000100000000000000000000000 - 1761ffce62135461d02a5426b1c31ba1e693ab9a12aa68e6 - 82d92d00ab3f980a7b07e7fa4edd44dcda5b0f57cf6911ad; - 000000000000000000000000200000000000000000000000 - 8f05ebc8491092d047674a6c6b984e95076dbcbc476ee825 - 66a587a3f6a816a6fc8c5ae7945b26f5386a156fd886e8a3; - 000000000000000000000000400000000000000000000000 - b5b04bb84c64d7d82a9a6627b45e2d730e619261ccaf8612 - 0b258b61b0732a06f0b3b1e6128461525f14b93edcf6e65b; - 000000000000000000000000800000000000000000000000 - 94efc3bae8b030363dc12b9d98f462a53e669bab96a04bd6 - d19b3eee10c9305677102f713cc0e44dd94b38b586e66c85; - 000000000000000000000000000100000000000000000000 - 44f615f33c33876b0a7f5eaf4e5194228138486b7bb661d8 - 324dd74ce8e0b2353f6b0956d90db45d0ba174348fbe8009; - 000000000000000000000000000200000000000000000000 - ab1ee468f066b46ee35ff4cf3b061e0b032c11316e829294 - 0b9fe8ce0e6ec4775aba86a76e6f15b01139c55952356e45; - 000000000000000000000000000400000000000000000000 - ff5f9a1310f1972c3e2ff648f5c7a3c253910b6f4c9cec98 - ce4364ba24319ee0e1d7b47207ed8fd704d41284f857aafd; - 000000000000000000000000000800000000000000000000 - 67547ca22ec3022cd81a011d8a36f081e6e6665d53d59615 - 3eab5b8d3cb573b7cd71dfd69f8865da04e88bed2c22fcc4; - 000000000000000000000000001000000000000000000000 - 43a0b4632e7b5746206f24fcc0cc5c02abedccf93209a90c - 86f8af1e716badbcc467b179e06f84c4a0b7050b3d381646; - 000000000000000000000000002000000000000000000000 - 84e3a90828dc4d3a965e6a2ab5d0aa532aab68bd6dc61171 - 780e5dae9e9d1f276da173517a11d0b70daafbafef4ec191; - 000000000000000000000000004000000000000000000000 - a59916e1e69488af5c2315227ae07a1fd29c7e88316de33d - dd0a3a126707ea8a9b19b2bca7d6c6f91e4288707da624b3; - 000000000000000000000000008000000000000000000000 - 5bb210f3f571f79c7b6020cd4076feecebce67313fd4e92c - 5dd34c33bd75b5cc2712c284f06ebd0771f03bbe6a0933ef; - 000000000000000000000000000001000000000000000000 - 16377666962332f0d015c24a8a64c8fba0a6b0026448df2d - 4dc232f7602f414acd74682fc955cd7a39e965277ab13f73; - 000000000000000000000000000002000000000000000000 - 88a0800a751e61a4cf3556fc09a5e2267f012c48125f9b6f - 0fae8ad675be20c5cf2811f31e013754e20600d789d0d366; - 000000000000000000000000000004000000000000000000 - 536255493cd9b75e93b7b3d8a22b9a5250f5715da602c2a8 - eb03a459e1ecfcf80d8c869a0800d10d9bf0eb16deb0feb0; - 000000000000000000000000000008000000000000000000 - d23dab5d3651b9b3d90315939175223e6e3dd8f06c87b2f4 - bc59d143168febd05f77d5edc352db18040573e5e90c1b97; - 000000000000000000000000000010000000000000000000 - a991cf922b451c1eeb6052888c28b5c51371101c15ac05e6 - 10467d595653eca2298f0fb16b0260e79c2f6bfc1fe0b9bd; - 000000000000000000000000000020000000000000000000 - a54de96886108612191972a6c17cc10f2fe3b218433cb6e9 - 19ade54eb641c24ef2cf34831b80002993d1f584f5126112; - 000000000000000000000000000040000000000000000000 - 4df1ea44dc58b80b0d4ffb6440a023175f0de0ca13e5b20f - 3b73e209e5db273ea076697eb09a23d75a06763c95ddfa52; - 000000000000000000000000000080000000000000000000 - f8266b0377535bdeb855801f5815c1c51e6de75d9372c249 - 8f3b81b9b8daa6b9134c358fd69df65d682a2bb1e3897653; - 000000000000000000000000000000010000000000000000 - 96712bf387a2bd8915be3400cfe50c9edba2a03e24e9da7e - bdcee44e3c128f80ab846ceebd787775d7d12a8c0c4b1b7f; - 000000000000000000000000000000020000000000000000 - 86e7bd89620da09a32041eed8dc60f4df1708c674baf7d9f - 7ac5acbe1e3549204cd4940e4189424dc800a37e3bf49645; - 000000000000000000000000000000040000000000000000 - cb943d6a0c33f4d6fc0856026a2e0f8b8b15572789cc156b - 3e16f341f83c585e427dee9184d650a00206454148fe2c47; - 000000000000000000000000000000080000000000000000 - 15abf241bbb3e72ffc263366ccfe5c42b8afa0e615246fa2 - 1bbc37453d729fa3f560cdcefafa5bec04097b34f04e69e0; - 000000000000000000000000000000100000000000000000 - e3a2fbaf70c336c960076e25901b08ea70f00cfbdb678c99 - 6199c398d7970a32a506c58e7deaef154b08bd660cda65dd; - 000000000000000000000000000000200000000000000000 - 4ba54ce0040ef1780a0286d10ac5cf13f563d688c214080a - e2d23bc27ecd4508c2b934c201410ec11ccf581738f9deb6; - 000000000000000000000000000000400000000000000000 - 81953955d6a216c4be8a3dc461783a0af5edc5f4291f4edf - 858b1e9cd5c1b34c7df03a68aa618a046e9870f3edd2be08; - 000000000000000000000000000000800000000000000000 - 46be627870c3f043209d65725bf2a546aee9d2dc6d355f03 - 6d35d794d51108c1828114d73df644f5e537523567ba3866; - 000000000000000000000000000000000100000000000000 - 6081001224d8a1b4062908a261bab7dc4dcbadefb31c47fb - e62bd23c4597a7fa473c3fae0d3b499cdfbb81a3cf2ff46e; - 000000000000000000000000000000000200000000000000 - 9cd0184802fb4297083c8fe4289a50b0b54daf57ce7d3c7f - f08cf7cef963531dd323b2d85ee2e57956eefb463813e810; - 000000000000000000000000000000000400000000000000 - cd2a4132daaadd45eef34602ab287ab35da3216d7e0c2201 - 18bd53d544503fbbfe63fc730f9ea3f83a92a075b9c731b1; - 000000000000000000000000000000000800000000000000 - 7dd4dab1cceab233b8f440e7c798d926d6672fae111b97a6 - 0155e424ee93cbeb18f5de8353fac06917061248e64a1db0; - 000000000000000000000000000000001000000000000000 - 2bebc540b952ee15d29456eeb9754bbfd6d14dd4df9ee357 - 4a6e99f2277d6436c5f76ed6143a0a5e0871842134a67f9b; - 000000000000000000000000000000002000000000000000 - c599a8f74e66cc416087a2c232debb1b9ca96ef0eecf7692 - deb16181993fbe042307dea974ae92137f39a6107a6cd52c; - 000000000000000000000000000000004000000000000000 - 1ed3a61376f1e6730127787de72c37ba58d748acdad988b5 - 4b4d63ad13b6e936379710f9f1c9d5c01a3884713e2323c4; - 000000000000000000000000000000008000000000000000 - e976691853eee2c466e8d9ecac6f2be9dd4d119250e9687b - a9d8242d5171109459a60bf382bf5542278a0fafd6a31c33; - 000000000000000000000000000000000001000000000000 - 817d9313109eac3b60bc647e881f9fd77296b7fd5521a4fa - 083fe0e8e375636af03941ea797f9a5a7798cfab8b260e19; - 000000000000000000000000000000000002000000000000 - 3609713a1383562d139c62be8b46b22814c52d0498bd0743 - 31cac650c1affaeac478b5cc8145e5afff54f9c486803fb6; - 000000000000000000000000000000000004000000000000 - b6da3ad2f7b51786fb5a1e52cdeaccfbeddc948211e1fd6c - afb15f06a78e82084de6200f85b0f7ba6c9f80ee34fbff8b; - 000000000000000000000000000000000008000000000000 - 30e517ce758f7bfd6d50c44802880144b2f0b37052cc5efb - 3183baf097aa12da6830fb3781b803f32e8f89f01cd9d25e; - 000000000000000000000000000000000010000000000000 - c561eb0df785893728c7ab68541ee65b5de5f0def12f1570 - 92f0838b81ecc63bd92162455803a4865f3771af19d0cfd0; - 000000000000000000000000000000000020000000000000 - d5fd1003a7018381ade31fe9ce9a64126ee798d2a2ec8733 - 7336952580c0fd50af4df8939122ccb98963c88631f4e74e; - 000000000000000000000000000000000040000000000000 - 99d96e0cdccd1a71a29a6e15441a2d3a25a0718ea84c2726 - 04c80e68b0f9daeddbf4a243332a2a9c03684811420318dd; - 000000000000000000000000000000000080000000000000 - 5c123dbda2b026c444fc873e2884e7c733642451b8c58bea - e4a1520b9dbb0580eadd7e983e5f7ffca560a2aa69cb4acd; - 000000000000000000000000000000000000010000000000 - aa82a0f119dd67acec85d42d52866a18fc250f5b063bbc67 - e01b60199b085ecb412d68b2b4fc65b5ea827a6f5e2a7b85; - 000000000000000000000000000000000000020000000000 - e3d91efce207edf5a3f0c5412c517ca2caf860fb80c75a23 - 5b79bb6bd28b687eb07afe51566ea4b1a791aa9620734a22; - 000000000000000000000000000000000000040000000000 - 120d205dc675f1585fa3b9cf92627e7644be58785b0ab209 - 98f71325ccdd857d0eac2bcd8e6201ea042569d2b06dc82f; - 000000000000000000000000000000000000080000000000 - ecc047da556e6c5ea7c195ed3c5386f60dd3b95537e41aed - b21cb8440842e4bde27ee84bfcbf0ee0bc8b8b3ad88455e2; - 000000000000000000000000000000000000100000000000 - 9c595d82e523573893ef08454be25082e3e2dfdbe71f6634 - e040f8c529241507b3f450b48f1f05605c1566443dfae0e3; - 000000000000000000000000000000000000200000000000 - 35f4e989da7d064611287588d3566eb092c87405cbdc6873 - 913e8b1818b9f317ac16b02ff0226c0d7749d40612eb5a6b; - 000000000000000000000000000000000000400000000000 - 8efaff57d270546c21d4728e904409ebf9d19d86ba797a1b - 4423538d5d87cfb5c636b71801ed86751b722779545a73e0; - 000000000000000000000000000000000000800000000000 - 38f285b482c3d66af4e661a07a3e6069143cad4dc1e3e804 - 6f1184beb0f6f27e0e2389d84bc6df3d54a51bd1c6336b8b; - 000000000000000000000000000000000000000100000000 - 9ab7f76f277e7c5e9e437d44506feac61c20c40c50d4f4a6 - f5c357f4d66b8e96f8245c41324e8645cfa9953dcb2f4b70; - 000000000000000000000000000000000000000200000000 - 6077ee198eee87d2ab2bc968f4f594b7db9070b367409f9d - 8e3e4e0f06c954bf256d3ff91852e1b2b392665c4385d9e2; - 000000000000000000000000000000000000000400000000 - dd9d75908bbdc05e2cfb8df5d1db68ccce7bbe7f121eacc2 - 78082c854cd92adbc3c37daee124d4d9a7d97b9c6c7ff4d9; - 000000000000000000000000000000000000000800000000 - 41e7465edc8a9d8bc8f4eded1405c82d2fe9dd6232807b95 - 3a4701a2768128fdd2dbf43278039f36226d0f32401c2f46; - 000000000000000000000000000000000000001000000000 - c08c6119ee2a2197f963a599bd65b0590ef5a519e33c636e - 977467c483d31158e24a00e7057e9122d84b8c29df6a40bc; - 000000000000000000000000000000000000002000000000 - af0bc2d846a385793ff0719690346f88e8906d59d731b053 - 5961660b15037b718ca51d2162edbc423c42ff094c3a74c2; - 000000000000000000000000000000000000004000000000 - 00fb58016823ff21666d4834be7777977c39dc524831f78d - 16f43859a26050bab89f24747aa2f159f7f952a4f7d0b423; - 000000000000000000000000000000000000008000000000 - 8888994bacf06498d6c65514458e0dcd5c47a89096431c97 - 84d3b8542bce25195af4c2c2db5278afb5c090980e978d84; - 000000000000000000000000000000000000000001000000 - 5c09111b5f1d7071f9ff25551b298c3ce446aa3413097e62 - 583739a94482dd2d485b26f9eb11466298b1ad5c1acb1204; - 000000000000000000000000000000000000000002000000 - 04aec49c4fb80d6561c745f51784f4f3d31547bd4de5a94c - e7f83b28e61a9eb7929382f435c7113a3110a08c7cb69634; - 000000000000000000000000000000000000000004000000 - 8391493f0cff3eedcb9fe1bdd422793ee5e124d343b375f0 - 2d9e4938f6c4c337b943809490c1b6ff3c843bb0bff1dded; - 000000000000000000000000000000000000000008000000 - 6d1246c48d1683a7fd7329c85ba193d285192c8831176913 - 32f271fc06af76ab98807731b3a47eeac2a107c02cf30196; - 000000000000000000000000000000000000000010000000 - 3cd9d97a17d77d3f3e9edb8d72032b5f655f948b32f59e00 - 5d7c293fa62a9a1f91b0baef7efd96f8e35188f75cd8a331; - 000000000000000000000000000000000000000020000000 - cfcc2990da7be7df288d8be5f9be1deff14637612107ab29 - e381e161b0b8bf30d3b28575c72f5605a83d5ea4d23a34b5; - 000000000000000000000000000000000000000040000000 - ac740d1ff0eacc8d57f042f7835ad95a80edcd3fdf28371b - 7ccb5ead7d391d393d19ce552040dd00ee411901f82f53ed; - 000000000000000000000000000000000000000080000000 - 177a0fcbbe76481f473a27bf63aaf2ab9d127e399a3c73c2 - e21338988039b5aebe5cb3d5b632250b9801271a117440cc; - 000000000000000000000000000000000000000000010000 - 96ca2977c2f58083155573e55b681ac307b40e601652836b - 678a557c88b2e1df13ac012a7104d40d33349b981db71476; - 000000000000000000000000000000000000000000020000 - 0e7ba2f3476c82f01ab7fdc7203ad2cfca591ecc829d8409 - daab2f21fd15fdc90a7cb7a6a56a0d0c6942ae2b86113373; - 000000000000000000000000000000000000000000040000 - b309f8daf59f74bac80f710fe07350f899bb1492f24e1425 - aadd706e551425657e4e8d5138a8d13337d53346885b2ecc; - 000000000000000000000000000000000000000000080000 - 2d392f58a4b220211b884f4287ad76c9f9515ec47c284290 - 9aa9a624109b06d5722df543b3b0e105052ad578b54e47d1; - 000000000000000000000000000000000000000000100000 - cccb9eb8fc84365765163c40bd24b6bb51a45e7345bd7a14 - 6d9e8097f75b13cb808d2c44efaa556a56aa7c9ab8106563; - 000000000000000000000000000000000000000000200000 - 78a5d8d79b63dc0324761e93b76a7c79d6455539ffa6f088 - 8b6df918ec48a084ee472612bf14b3611a9a9c10660f31a7; - 000000000000000000000000000000000000000000400000 - c8240b82b4e438074aac4a34be3d0b01b3b7a5c1746f5dd0 - 5c4650702bfc551e85a269d7f97fd98d49db0f45f40ea608; - 000000000000000000000000000000000000000000800000 - e6880f3681fdc188ceab24c0c1cb3f90357fd05130687b07 - f53ef53b6216d61118877eee6f9406f076a9b8bf4b31ad9b; - 000000000000000000000000000000000000000000000100 - c734620cda2c3f3b71d8195949898c8740acb8444fa9e1e3 - 2083e8448b090301f991ac6687179d6773c128dee6aff608; - 000000000000000000000000000000000000000000000200 - 2f67eb665331c85869ce51b067c6e6e94cc8ab45fc71407c - b61d957135c33783e803e9e535702f2818c21ff62be94c51; - 000000000000000000000000000000000000000000000400 - d590b7a848006f402461a88874eb9b5d9add7ec80c81b154 - febf425ef71bc535730788b70bcc2833e08accaeae7e9ee6; - 000000000000000000000000000000000000000000000800 - b02090c689481635b33f992e13b59eea15aaf9f25b778979 - 417ed646b20cbab90952020eee8069dbe00f18d2572f8d72; - 000000000000000000000000000000000000000000001000 - ff1e358c8bd643176d87f75c2175c4b66ab1ffaf0079c012 - b06d3d892f6d85bf268276d7102d7471eaca99b16260a39c; - 000000000000000000000000000000000000000000002000 - 57d86ced26040b7dc14c2f47cbce1f5c70398ec902d6d484 - d8ea3cdcc2566d14f6d996971796161e493677cbad536027; - 000000000000000000000000000000000000000000004000 - 1cbd6500cb1061ae856e10557c84f085d340b5ac6394de48 - 0fdb3c9f37cd7b03b4ad10a5a090afaabc9eb6e623721af1; - 000000000000000000000000000000000000000000008000 - 18975b942cfdbe8391c4e2a96e03df6cc3d44d1be1fdb697 - 86f3a467cd9b71208dd75efb91fc77a1dcc25dd45a6002f6; - 000000000000000000000000000000000000000000000001 - 806011240d6c13fab000555504cc68fa756d5c0cd85d2933 - 7793edb94f67a425483b90cc7b869880143272ee85ca2ad3; - 000000000000000000000000000000000000000000000002 - 3d04d556fbf1d4dd76fa97215fe58c170d0198c19d5a0b8e - 850321dd6927deef53ce43fcdd07df6a3aa1fbe0d26026d6; - 000000000000000000000000000000000000000000000004 - b1a243ffdbccf642800db3cd11beb064a2674f49ae9c6550 - 850c7c28e1d1dd64373ddb8388755325671fd7cdf34fdd2d; - 000000000000000000000000000000000000000000000008 - 3705ff7df146cebda207c1fc2348252f28156b752e9cd167 - 418592dcaf9178228f66511810bfed87e7ac9d2a138d741e; - 000000000000000000000000000000000000000000000010 - a4597f7b0bc5b5cd53bbc04d644901b385d2c5d03aa0e363 - f1f007c32f306ef45e0f78c24bbdf7507a62e44861c1d579; - 000000000000000000000000000000000000000000000020 - 3f2e6b8d77db0bb0f4dc09f8b3f5ef841b65f389194865ae - d50dcc3d890fac6c458ffe6334a2ecfe329f9ccac8bcd609; - 000000000000000000000000000000000000000000000040 - db05a0aed5d55023dee7dd6671cbcf71cfbb29c10c4babd2 - 8925fce6cf19f3b2f34d61b894b213a8c59e69a3993cfdb4; - 000000000000000000000000000000000000000000000080 - 4c73cdb5851ef5a107ae0acc485cfe49f23051ada2cfba2b - dc81803c4aba313b5bf42236e208b8bf66d62810ec0a8fc8; - 01000000000000000000000000000000000000000000000000000000 - e466a171f30130c5886045ab035a744b80a63cf10ad50670 - 7d0a3d9a3ad5af4590a18eab995623914ab2377cfe35d3be; - 02000000000000000000000000000000000000000000000000000000 - 3979486436134c0b0d1cbf612b6745e7a43038c176e50759 - dc0c555a7b1425e8d83ae80934676ece2a2f8a654196dbe7; - 04000000000000000000000000000000000000000000000000000000 - 517b1b4b00e143a73e315298830e0fd8f0692549b4efa53f - b47ae72ce84e68257377022abb9cbb566e58c501e1ae8956; - 08000000000000000000000000000000000000000000000000000000 - 197c1cc090ee4f199c5573cfa65f6bc84ab8957fc8c2be23 - a56f67e2313fcd2fdf621da945eef4e31a8fd9d0445b1b66; - 10000000000000000000000000000000000000000000000000000000 - d59e9e6be1cefd6881df7772eeb46295e7c6ef787264ea73 - 9c9bbcab22f66a437538d795d041399093f694c669b2f559; - 20000000000000000000000000000000000000000000000000000000 - de47466a965a4d5d92eed3b856591fbb787ce6863da4d8f6 - 94a4c31a6e8418b46529e547d7a9aa0e1d2962a63eee5654; - 40000000000000000000000000000000000000000000000000000000 - 36dbd72833a532f365e6be111aafe17c2fd49f21f4eaad76 - 6327e174d21ea698cf34bffe36672e7ffa931abb615148aa; - 80000000000000000000000000000000000000000000000000000000 - c10d857d362ebe177aa6b240bb27340b0ad2b283cbaaa84f - 184d05e1651645e67d0d42eea84f4a8c56972014aeab4602; - 00010000000000000000000000000000000000000000000000000000 - b23943ae799651f7219dad8ead93d03c4eed373f6389b117 - ff33f2564db3a027b45f2652ac244eff9d5641212fe33a33; - 00020000000000000000000000000000000000000000000000000000 - 9126da9f43bbdbd9216f40c2414236438b5520304f21b2fd - f7c8bc04d48f4b18f44044f6a5175b67e5a0369475e38840; - 00040000000000000000000000000000000000000000000000000000 - d73e01f210826c0205aaad28db4cb341804a696f1b683a14 - 47632f2712f7d9a63c7fb8c1462279e3c5d824ecfe35d3d3; - 00080000000000000000000000000000000000000000000000000000 - 3a8a518775a687bcd6245cd6e8504765275b7c9df76817b7 - 884f7908451106aa852323dee7b353a4b1686cc7f74b738f; - 00100000000000000000000000000000000000000000000000000000 - c054a470e6d41003d3b20ba165d391cdc934138b55ad957d - 2ff8dd62427119acf5427b73db572167f953f778b5536a3b; - 00200000000000000000000000000000000000000000000000000000 - ac86f7a300e3f4b248c17113ab2a5ff0ec5aa11c26f7e9cf - f391deaba561f263728c3810c4246bb850a38c22c3d0ff22; - 00400000000000000000000000000000000000000000000000000000 - ed1cc342bb9b9f0463f8254343f79ef3ff75359bf78c6a06 - e657015d282084ec74214fb5926eacebe91b2b0818cd96c2; - 00800000000000000000000000000000000000000000000000000000 - 275083f0158e81bbdb5bddd8471d4346d2dc2dfdeda59d17 - 85405f2ff391329b38a6bcbaec9890fd5f6c27c43c4d42ae; - 00000100000000000000000000000000000000000000000000000000 - 5d875aebf5496ef91d1fb5fd6b7c10ca3472ac04190fb5a5 - 30f8d4f4e34ded31074ab7bdd98cdee6995f363361dfb67a; - 00000200000000000000000000000000000000000000000000000000 - ea05609c5f54d16590cbf9bee2fa008f60aac96ed40148ae - 0356240ac83e1f2874e37d5577009d79cea8ab677d05d35e; - 00000400000000000000000000000000000000000000000000000000 - 241a143eb59063bcf573483f0453cd3b7c20613e976e1677 - 584f0cef868af6aae2474278099ecf8d9af01d1b540c1853; - 00000800000000000000000000000000000000000000000000000000 - 8d642d6c2ddeb938e63fe0da1f84700ae21c35317652dcf8 - e692d249d7c24d32555f7a69d88980e56b33e95659ea5182; - 00001000000000000000000000000000000000000000000000000000 - abe335a44913c306c289a66bdc6551dfaf69febea41c73f1 - 669f21ff2d1979cf255d0f357d477f62a2c376e2f7e49ee4; - 00002000000000000000000000000000000000000000000000000000 - 88ace268351b45c9ad63579ad01f5631fc6ac91d5de6ef19 - 065b1d6414049be6fd09ae8f4cf9101e625ac3781f146a3e; - 00004000000000000000000000000000000000000000000000000000 - a6d8ec0b3de91563f75df992e97a5f8565333056dbeb5495 - c56801660652b4d8973edeec960f6c606f553af746e7fb36; - 00008000000000000000000000000000000000000000000000000000 - a159457dde64aa20ffb81591e52a684c4f01f224d77de994 - 2ce28f10c61918f29a4ced6d5969aad3e26397d68b273e3a; - 00000001000000000000000000000000000000000000000000000000 - 0658da014d05ae4231fb93096483492482ee0ce8495a482d - 945a27517e687cd2fd0d03c57dbdea162b4fe10d05081869; - 00000002000000000000000000000000000000000000000000000000 - 85ca27e90b91de2e400a59c00ed82116302cd2a1367c3411 - fb1858e39f2cf75d36fc308270510d9710fc6bab72fb3162; - 00000004000000000000000000000000000000000000000000000000 - fc60f7ea828f3813eba9d5136a34ce868510a6f5c9d61124 - 74fa96b782f8e68a9b93c82ff428feaaa66a75331df5e98d; - 00000008000000000000000000000000000000000000000000000000 - 49a4c0b759451a9047440e8ba0670a750a69f92aab520c26 - 4e1631c860ed0a4a9917983f15f889383860921298bf76f6; - 00000010000000000000000000000000000000000000000000000000 - 090c2326593b51e1dc6d59542c8ec15d2f60302371489e36 - 8f961912ca14f7208c5608eea98208eea9d45255e5f4c900; - 00000020000000000000000000000000000000000000000000000000 - 04f1eb6340739f6c37e3b0571b1d41553adfb376053ce64d - 242c48e139838ae26843e54dc149b154bf3e8c490fe0f1e8; - 00000040000000000000000000000000000000000000000000000000 - ad61378d9b886d236a585a35749caf40552a018246cd8203 - ea01b68642d2988df8d124f74dafa6abf853b017d4cb5496; - 00000080000000000000000000000000000000000000000000000000 - 5291f7145b376f42de91b492a803c3da552d1bf3cae38f74 - 1bbcbcd28382cb960e12663fa17ce99d8fd996480afdacc8; - 00000000010000000000000000000000000000000000000000000000 - 3283a8ad59723b954c26d32641e1aca7ecc37cad79757fb1 - 331cd49fd0def48a4c449efbcb35b3ee20552fc441300884; - 00000000020000000000000000000000000000000000000000000000 - 1e9b00edfb67ee5e7e72d5bde45c69dda0f0b9f145ba376a - b11264164e9e70271ea379123bba996844d8224b2c4a5792; - 00000000040000000000000000000000000000000000000000000000 - 891d65411edc72bfad04c2b32dc4f3daa46fdbcdf2295b7e - 7019b3daf1d8d054ced0c9b41903c328cef85eb8b30490ed; - 00000000080000000000000000000000000000000000000000000000 - a692a308739c497d2fbc905d2c1212d9ba02b5c896330480 - 87747a33be359d180b13c7c2da559adae20d7e3fa677d80a; - 00000000100000000000000000000000000000000000000000000000 - a646d48b3a7570c884b7d20b3ec1910062742ea29f9b87db - 6dba393a5c0c22f991052587f2d03cbd6fa1b97032ce8d70; - 00000000200000000000000000000000000000000000000000000000 - b9980daa0335682e0d5f943db1d63f76a5afba294b00c894 - 6dcff8118dbd4938d98327457b611b78bc6fc3858308d44e; - 00000000400000000000000000000000000000000000000000000000 - 5a6d143a6bbe108a8e865d262700c5e3d681a864c9bf2889 - bb00e78a312810a37d218fe1e898e34ba684df92d5df8a80; - 00000000800000000000000000000000000000000000000000000000 - 27b44c0f87ac23ff95a31e1b328d928a1c08104a3d67a9a2 - 2d2fc5dacb8cc5cb49812ff3fb4c4dc710b27126aca8af6d; - 00000000000100000000000000000000000000000000000000000000 - 52a8962f43e282225863b45fcbdca1c7970d05cdee3661ae - 0138f4025e6f693f784e26c368f3e99bfc912da83619df70; - 00000000000200000000000000000000000000000000000000000000 - 9d778e66c779bab53e8bd4cba07121af23a00a64f2d69033 - 74818f00faeb596041c9f60ecf7fd36ce6ca568bea39cc20; - 00000000000400000000000000000000000000000000000000000000 - 541065c87d92ba58c18ae8220da27a8d54ad7741989ad6c8 - 4c5ed522130b99c5d54d6c9d500e04646deafd63003904ef; - 00000000000800000000000000000000000000000000000000000000 - 2f20f79d4c2b14d94977d1079c3c94c781df42adf3d6901f - ff0efe5eeb85df42c23a1c7cb86b3ef67a423f7dfe4a8ebd; - 00000000001000000000000000000000000000000000000000000000 - 2e5c45b439d98cde7dd553cc7f6d55867792f2b97d4096fa - 432b23888d0e8efa3ca6e7770a9b70add2d31113d187cd15; - 00000000002000000000000000000000000000000000000000000000 - dc84f5bf78bed0ec4011a808b3ccba862ffe18c6bd0af093 - 8a7df628ccdb8d0d9527d0ac6a2a37cc3496ce920a6549af; - 00000000004000000000000000000000000000000000000000000000 - a8950cd163f3bcef61d2fd66c2c84a7069498f1a4480fa9b - a52e41655dcb9f4419b3aafdeb1b388fdea9ede2eb71d55e; - 00000000008000000000000000000000000000000000000000000000 - 48ec823bb0601d23644fecaf15522422ebfc773c6741921d - a9f9ecb94e7a4a0f6196d9f585f981529aadf5b1ee13c5aa; - 00000000000001000000000000000000000000000000000000000000 - 4a360f8b6fb99125be62dda9f47fc5568119ab2e76dcb2da - a2bb0963d479e76d1f32a7e724ca64982093d519649a2676; - 00000000000002000000000000000000000000000000000000000000 - 5628f1141e35d240bcf5ec4bfadb44376b82edc1c1821181 - 00fe7d461f3b521fe1d76fdfcfaee8b2f95be74121660550; - 00000000000004000000000000000000000000000000000000000000 - 6b7e5c402de45b783cbf0bc2a922f034d93d41dd69a02d98 - 4e64fb1db55e3b0c622002306567bd38068dff297b8caddf; - 00000000000008000000000000000000000000000000000000000000 - 2a0a0ac9f03ce1be0f6a913cca6f12dafb4ee79af1173aea - da2b5561384eedd083365dbfdbac266556f306779654a946; - 00000000000010000000000000000000000000000000000000000000 - 1c1b4df7b4f126620df92c52fbcc07d7b8a5aa44f3e5f1ab - 46626e5971070b4cd57d5b49f3b3e228e2dbd1b9798e79ed; - 00000000000020000000000000000000000000000000000000000000 - 5682d5056b30cd7b84911adaf1af2af99fb16fe82beed222 - a62abeb1341cb2cc15a3947ce8b571d2b48ebc7365072e2b; - 00000000000040000000000000000000000000000000000000000000 - f20e8c97b521ed21e72686e503b30412060626094e2569ae - caa011296fd4dc935074560a2608c9e1db2848ae25f4395d; - 00000000000080000000000000000000000000000000000000000000 - 461dcc25da2c567f2c330d1ba39172451f8b0c1e4575623b - e4a8929a202cd9cf07a3a914d900eda1a1aa79dfe332fef6; - 00000000000000010000000000000000000000000000000000000000 - 179913568dd00f3c3e6638fff80b19078f605d2989b40f4e - 98901d6c7f82903c81fb45e93a8d70b2126a40465cc82536; - 00000000000000020000000000000000000000000000000000000000 - 01d0dd28e61252d14ec58b782dc7c777f3e88a652014bb84 - 71802a1c775ec9574b443f5ff43868d8df47620e291aa4be; - 00000000000000040000000000000000000000000000000000000000 - 0f6ebfa8809b841679990649948d76b1d79ec12ece1f4751 - 69f01483dd242bf68434e66b66fb25ee6115664ce75850ba; - 00000000000000080000000000000000000000000000000000000000 - 089df5d6f5a4f9967693d8872da3808eccabe037cae99337 - 95ce5e283ee609b6d62bbeb996d3c99bc11e66250f2884d0; - 00000000000000100000000000000000000000000000000000000000 - da907941cc5d4349988756b71b3d625ffa68f36ddb5b76d1 - ab0b6cfc89a17453f0a7e76216d4c134d8385732e8b7ea9a; - 00000000000000200000000000000000000000000000000000000000 - 61ff06d4942fd9296587bdfba1e8e27d42d7701ac7efb31c - 69f0acaa8622c8d71497ed99f646d033d81b943cf2da78f4; - 00000000000000400000000000000000000000000000000000000000 - 6bd9b77d87473a6501421f565884cc9bca0ff6cdbd8608cf - c25e725bddaead2ac2c854d645565cff9d13a49325318470; - 00000000000000800000000000000000000000000000000000000000 - 779ee5f0fe88dc65da96ffda43e5bbd77fc34efa0eea92d3 - 1d32b8d6e4ca8735ff8489f3316e5dde7eae25346199436d; - 00000000000000000100000000000000000000000000000000000000 - dfe0750917dfced0bfdce54668950a91b3697636a7f622da - 785410a4bd7246c3f351ec3c17dd4fbea179d282bd3edd35; - 00000000000000000200000000000000000000000000000000000000 - d88b50720ac2b514d8e32766e4c10f52099b7c9dbdfa4639 - ee78f304793920cd1996322df67166ccce319c7b79aedbca; - 00000000000000000400000000000000000000000000000000000000 - 40297cfb793bc7411ac6a38c2f5e35f13e076c96e3ba8cd7 - 8b19a2d7268324413e76dbef51d544522afcfdb234a80b79; - 00000000000000000800000000000000000000000000000000000000 - bf474a47de1427ffc76f22f85fdcb322eceb654b82ae1476 - c1107b5c9aea17142905e7423c03ada55b4de08d68551412; - 00000000000000001000000000000000000000000000000000000000 - 5430fc20a9a834d033b1931d41c692682a389b6bd68abfb2 - d5007648b6b5c9b3ce44fe8c8261af3509f2854bf12bca03; - 00000000000000002000000000000000000000000000000000000000 - dc814d7cafd842955d624394a5885e9900fb48302c02079d - a8507e6a2969200463221a3d8baa430a65dff06e495d54f7; - 00000000000000004000000000000000000000000000000000000000 - eec73ecf6bda3f4dda70ddac567649e3acae53c79973d91a - 43eb2159dde1ef21d0fdfe7d0313f5d608b12ae157c0175c; - 00000000000000008000000000000000000000000000000000000000 - b31185b8c7a09b6c8431604c9d73a92cb0e368af1e109593 - 1621f258ac6562bf15900e46ee38ce54d17fa998a6718126; - 00000000000000000001000000000000000000000000000000000000 - 861599547a7005f367bcf4bb2d7e77d23ae864dc0a97f3a4 - e81d4a8675c7805ae2ddfc663db35f050decd5bfd14f89dd; - 00000000000000000002000000000000000000000000000000000000 - 4fa5147d9ec4057b649f7cff1202fc99cae58e1aefccdab9 - 064b3918cd10ce4f246d3f79ff52e3fb20f770f07e942b01; - 00000000000000000004000000000000000000000000000000000000 - 35eaeba3a19c8fcbe86181577734db4cc2ae23a0035fe2be - 6338c7f38226401f0a4c72c5c4a43a14ffcf0724f7cc579e; - 00000000000000000008000000000000000000000000000000000000 - 843eb5da5349484b83b951550554fbcffca7c80861860b84 - 1d127da43d43487a2221c36ee63ba71f75e6e7254307037d; - 00000000000000000010000000000000000000000000000000000000 - 39864279e3c8580727d48936a1620cf01667f76e3c300498 - 137a5254e5815de51641a5d15b2691b31e08512537427e3d; - 00000000000000000020000000000000000000000000000000000000 - c6d896c129ea56b02c159cade2a6cbbc974ec04ffb4f538b - e546edaf391396e7c5cfacf94cf37ff79ca56a0418872860; - 00000000000000000040000000000000000000000000000000000000 - f35dfbaa8f13910ba7f3a9de5a9fd6f36d8dd8a444fd3144 - b3882f070df1375e3e84e933de4e4372ccd8dd84923d228f; - 00000000000000000080000000000000000000000000000000000000 - ea26fbac4c2c5e46100785a99008d4ae890ad258918aa18b - 768ec538c5f61bad6e7b49ae664ccd4ad481c8c37f317b31; - 00000000000000000000010000000000000000000000000000000000 - 477c6bc073748fc4c0511b0d1e180315530037ef71cb4026 - 7d8bdebdcf35e2c38c6d9d19bf97f6fa76e75a3f9ae22e9a; - 00000000000000000000020000000000000000000000000000000000 - 655699d22c61a253572cd6d4df64d4fab06874c340e95783 - 7cd5f30366d96ce31338f5438263c887d4698a2d1f826509; - 00000000000000000000040000000000000000000000000000000000 - accdb0fada298f97c199b0b75ebec0f8eda6c819a322cc84 - 839916db991581426da7dad428a2ce1f1fdfe0e94551e45c; - 00000000000000000000080000000000000000000000000000000000 - 710b2db656a99904896580bc97453f7af6d40326f8ccfa0f - a02c312babab962db4503415f05d52b2f30bfcc35869f08b; - 00000000000000000000100000000000000000000000000000000000 - b09a7b21b66ea4e6409b36515c849ab0c89cd4793b86aad7 - 25d64c7e387e9f7fb9bcae80fcb95e60ee764b4b91f5a623; - 00000000000000000000200000000000000000000000000000000000 - 961df75dd24a7f370750a17c2025867442411790e604c7d5 - 762b027acee1b991b90b83f9d918f2f74e84383f425c64a9; - 00000000000000000000400000000000000000000000000000000000 - d9a3a55ac9d2517b149b2a6981a1123c0d9b4abe03982e03 - cd43bb557f2674593b8692472f225fb4c7f5f207ea1ebcf6; - 00000000000000000000800000000000000000000000000000000000 - 3d42aaf1230930786e7febf219ff6c90759295547a2c0e9f - 3a00b929fe7dd2f848d9078fe862bdc1abfb0b242f2709a7; - 00000000000000000000000100000000000000000000000000000000 - 4dc0cb0a3d1ab6fffab767a4ef3d47f029d9f035192d7dc8 - a10e7b96eda011b4b927bce0d98b6822540b9b7521a22b57; - 00000000000000000000000200000000000000000000000000000000 - 5b23eaf61681e3574a8a097d763a3cd828626b749851ce7c - fb624ad9a049613c27011972f01dc669560322040aa7c4af; - 00000000000000000000000400000000000000000000000000000000 - f6db6f3ddbab5d3228812a70fba910ed17ef493b8cec3ca9 - dc3c24735d9fa10c848f9b09a9fd8514ea4c1a576f8ef4d8; - 00000000000000000000000800000000000000000000000000000000 - 07f9b15343927460366de4a9ac3f819566e670f4b58a00d3 - bb6bfb31664ac99f9af977589ada9831b121ad90466375dc; - 00000000000000000000001000000000000000000000000000000000 - a305415baba5afdae40a6f9a1b6e8e3232e143a7f1138c6e - 5d4109fa28245a22bd6c812016617e1aaa21c9e5b5cdf87e; - 00000000000000000000002000000000000000000000000000000000 - 74cd6460d4ac168edb0e544890907cd954c24c468ed87848 - 0ce59ed2694fe93103eafe67f702b32dd5545e5fa53b261c; - 00000000000000000000004000000000000000000000000000000000 - 4cf6e84f95eda559ec34c93a2e4ad35325e0885642d4dab5 - 6e8d542ff0d468d44331de0482b9f483ef1e81afce8556c9; - 00000000000000000000008000000000000000000000000000000000 - 223fbd1515d17968e6365920d08afefc8dcc1b7aa1a48a94 - 846cd8e79252fddc2bd9dc79047d55c96158dd9834e79e43; - 00000000000000000000000001000000000000000000000000000000 - 3d42cf134f2ce3f69168b13b9104bf20e720aa1ca5db3abb - 076f0dc3b495de14b6626ef3986cf70fcc62c73101b3c00b; - 00000000000000000000000002000000000000000000000000000000 - 62964b3de5a5f29fb46af05e22e604adc0ddd469023572a3 - b53b2d9fddfd2e9ea18258fcc56afdefacb68000766cb625; - 00000000000000000000000004000000000000000000000000000000 - ce9999154c2cb7cac5bff38080d9cb5bf7e25e48469907a7 - 126fb43d45542ca289681f8a96f1eca1f78065dc3d563476; - 00000000000000000000000008000000000000000000000000000000 - c316c04b5351c4a9ab217b997403bdcd4b6b0cdbeeb61020 - 8359e9725a86108c9e9df165c8db8dfd97ef0c0d5ecf8700; - 00000000000000000000000010000000000000000000000000000000 - 037524620d481439f805bd9b97f564fc54fad6d68ebf6d37 - 1a3ce3addd3aa06fe3c0851bb36d6484d00b71e2f7f24f93; - 00000000000000000000000020000000000000000000000000000000 - 678374857cc068a2a29348279f2a9ec8edfecc0cd658defc - b22c3aaefa728e55ac29d4b624eae74248f3f983029b4b30; - 00000000000000000000000040000000000000000000000000000000 - dc8f9708feef6e43a07c93abff90668180ab88838767164f - d3afd33038af52da8546589a263cc81dad1d99d156b321a5; - 00000000000000000000000080000000000000000000000000000000 - 6eac02f84c3e0ac288f692dcbef8ae12cab31fbd53d97397 - 2ad2aaafe7a7ac392fad7a0287fa2f2d2681dab726bf44a6; - 00000000000000000000000000010000000000000000000000000000 - efe7d7c2bf9e3822761cdac372165820b9ab2ec899424e8a - cb3757944a16a71ec99813133ed5745459defd3bbce8bc73; - 00000000000000000000000000020000000000000000000000000000 - 48b83fc1b61f1f635033c366f9ada4d79966f82a68764c7b - 0844cda500c0ddeaeed7b63f2223877838f379aa7504661f; - 00000000000000000000000000040000000000000000000000000000 - 842e81ad0e1d515d7cab6f58288c30357dbc621387091fae - 9afa55ddff3b59ff3a6d3b52d011ea090cbd32b56f25ecd8; - 00000000000000000000000000080000000000000000000000000000 - de27653b243a814cfeeb90eef9d612ab98224704e328923f - 093aab7b15166c45d7381decbdb00d3fcc62e59d6d3fbc59; - 00000000000000000000000000100000000000000000000000000000 - 80199c47a849f02460357ba7c920b4f91007ccc3572f8a95 - 975554126ac6b55767e57be44de8141f83d2c6e88371c207; - 00000000000000000000000000200000000000000000000000000000 - 18214d1c20eb598db7ef9e19f66b41be9a3c6a28a2a06c09 - 36d76057e43f8033756217742d563bd811e1130b9273a3ab; - 00000000000000000000000000400000000000000000000000000000 - b02556b90f7846ed7ef080a17b6131cc6e34de764fedf66f - c5a1433480f37105516a2903fbf4a2cadf94061dad71dc47; - 00000000000000000000000000800000000000000000000000000000 - 67f22905a1db5aa9dbc49b92986a0e6a76f555b26fa844cb - 9197f321a515351baf650e1375ccf1d0964653e35e4f2f3c; - 00000000000000000000000000000100000000000000000000000000 - e684a0b52b370cb0d1a56313d388a136108c642d3b39bc9d - 62943cc6636002312b13fa373109f4291ccfaa872da2ee77; - 00000000000000000000000000000200000000000000000000000000 - 5a4dda4fc12d0c760398b47169e470f74446acb791559bc6 - 0bcd3206810ee183fee9b0bb838efa857d695ca3e7ed1253; - 00000000000000000000000000000400000000000000000000000000 - 9fc13edf3cd388716e9f4e1494d8a0a96281dc961d4548a3 - a26ac7726848e147e7ced7cca7e4503ee20f42705fcfc755; - 00000000000000000000000000000800000000000000000000000000 - 86f93d79f1f26b011541ae929aa31b9a4c84e8c4d880d5f9 - c967183176facd949e28f687f2086f29a6b6c955d64b6178; - 00000000000000000000000000001000000000000000000000000000 - 2dda65d35ba60b691738ab14de4aa36c4ab68618547f1b4f - 0db07d9558e660576689ff6572d2af9edd01452072c50fb6; - 00000000000000000000000000002000000000000000000000000000 - 90a296d7040d9ee0fd061caddf8e617c536560e397e9725c - 69a73a1e466811b91368ca4791ac75045174f24c389aca14; - 00000000000000000000000000004000000000000000000000000000 - 466cf4d9755f99cfe79a8d73f0e9274e266e6acae13155f7 - 83b4f7458050bfe285c60e56424314fd6b01a6194fba4960; - 00000000000000000000000000008000000000000000000000000000 - 93d678400420bd1d482812485d96fdb170b4f055e1bf98a4 - 400aefb2a3dcdda2e48195eca5b600eed2a4c6c70db3a20f; - 00000000000000000000000000000001000000000000000000000000 - 61a2973e5424ba1c6d3e276569114d4ebdfadf198bdeb004 - 12957492fc5e51fb9f87b5f263486bd6e9030ca493e40b1a; - 00000000000000000000000000000002000000000000000000000000 - 38e6ce3158f5b500a01c1920345e2680695993ac084b84a9 - 1e11bdc8bc76b33ce64300760fc35e8bca2b8f7f8f708287; - 00000000000000000000000000000004000000000000000000000000 - b8d2cf2220f5ab4797feab4ac9bd35cbd2564dcfb099b5e6 - 3f66306393714717cc65e6a61242cc809c1a7c56f03ca87b; - 00000000000000000000000000000008000000000000000000000000 - 2b402e5af6ef5af420416bf1f5a2ac86576443db7e33974d - 61313e285d7928b69426ac7310ee16c80138c71adb9acf2e; - 00000000000000000000000000000010000000000000000000000000 - 002baae76bcd86eda5bc78d008ba23b0d2e772ff31004297 - ac9e2599d3b76610df2a492191e54ae52f2d1fd0583eb4b5; - 00000000000000000000000000000020000000000000000000000000 - bc03714729c9d4d276860ca7654dc3ff0956f84e1bbb9efe - 90ea6fccf1b49e1dcde379e04fdc02ffe00e30e07d5fed1b; - 00000000000000000000000000000040000000000000000000000000 - aa901e454ded6dd58dfeb8204b59bad80b570ccf24cbb23d - 22b08dc3430cb5ceca63a8a9b39ae41d6fd3dfcf95a1c88c; - 00000000000000000000000000000080000000000000000000000000 - b5e0906965a567b3784924265066b5a1756bf0cebd39518c - bb18608dc7c7fe6f59d011573234a4208a227f341bdd786f; - 00000000000000000000000000000000010000000000000000000000 - ae8b977065e3abf413f592cdefa3d2da660649f0e2f5a94c - 82899bc15e3efebe9338ac27ee29ea69dccfecd7e649af51; - 00000000000000000000000000000000020000000000000000000000 - a0b0a11f8461d83fa6fa785cba312b64367555de2759d4e5 - 0daffded48564ebbe98f69964b4959ea0aebe5a28a3d5a58; - 00000000000000000000000000000000040000000000000000000000 - fa55efcb4c907fcef36a43f6c2608639b56ce2effad4f6d2 - fb02f2826bf087101311832eb00d57a1d771d705ef70e337; - 00000000000000000000000000000000080000000000000000000000 - 1cc3544ae7b7c2737b6bd7e2ac832d681434326a556df8fc - 083d876d584412e85543eeee4512f059636c21f7bde4d3f9; - 00000000000000000000000000000000100000000000000000000000 - 1d4fa6dc25e6fd24a5ff13a30f63e783860c6c671ef428c4 - 90863553710ecfbec99e8b2b415b4e4f71dd88f6ebce7e38; - 00000000000000000000000000000000200000000000000000000000 - 45beef6f77bfaa83e25df7fd33806a7dc63175fc25c8a29e - 39fe2f8bfcc92b89431b08d5d9e3788f92fd10b9d5e18e70; - 00000000000000000000000000000000400000000000000000000000 - 28043c18a7e18389d6d73860977e2cb0c9cd282a267c5b72 - 17cb6c2df1e9b9fa149d0f0785f8f2f263da16ecf1935d89; - 00000000000000000000000000000000800000000000000000000000 - 4765dfba04c731becb1085f02d4f5eda72689f4bae916ea3 - 5d3068aebac8cb3cf5516b77384dc3416e2b5e8c982bbdd6; - 00000000000000000000000000000000000100000000000000000000 - 46f68d6acada331052225f714a5729c8116d19076f00ce44 - e7d20a3ca6208e5f407aa0f94f79bdcf82ad79592a079ff6; - 00000000000000000000000000000000000200000000000000000000 - 82b3c9ade76a91b3672754877beb7f1a2c87daec16b8667b - 13edc9289453530b65339df5c6c82c0a31d9e0b90e3ac873; - 00000000000000000000000000000000000400000000000000000000 - f36b6f67f121d8bb7f5de602902a9110abc7ff403913f3e6 - 4407a45e633e76537036fece0a3c71c0f15b88027b3303e1; - 00000000000000000000000000000000000800000000000000000000 - 03deea8338479826f1687012b30423234a36163e4aad49e6 - 9f7f6b5f8dd376aa0716651283ae9f0908f0cb4b34b771bb; - 00000000000000000000000000000000001000000000000000000000 - e853a06b951d48565445889b4e320bfe1c6b9084720cd142 - aae2e8c15f771e0ed58f8a92ef4da29759c38de9565ea06e; - 00000000000000000000000000000000002000000000000000000000 - 9d1546729f32d2188be60529b218bd703736f74e9f432d35 - 201f67b0162aced8172d99e73ab0a182154f3615f2e28f4f; - 00000000000000000000000000000000004000000000000000000000 - 07e669da1d9c8e593fda3ced0eb617708f2ac422d43c45ac - 1cd97e6d08da27f0daa041282df010e0f43908d8dd36b9c0; - 00000000000000000000000000000000008000000000000000000000 - 6bf530e97b29ece372e7ba9a7831dfbf56d66936e773ff19 - fa8388bd4a8c495383efebcc1416fd38a139db06a1729f4b; - 00000000000000000000000000000000000001000000000000000000 - 5d83bb98570d03ed7b6e5288911100680abe75d88c9ec453 - 51b426c7cfa0c0b178ed9def654b7e777164c7c1d945d394; - 00000000000000000000000000000000000002000000000000000000 - 4747797b044c2fc06cc39bdc2ed894585aad485e039b4988 - 79a1b62a586d5a72bbb16ed12d7b6692fd5526872388ce8e; - 00000000000000000000000000000000000004000000000000000000 - 9f79507a0960c45fa87e8f83cc6699a4932ba4c15791bcdb - 4a055efe90785b26b43cba08efbffd9de944028147f471f9; - 00000000000000000000000000000000000008000000000000000000 - cb56d08085757939b6542b8a6b80caac7508683cae4752e4 - 73a4795fa9184b465d6a6c3fbb3afee1d77daf4a9b4617af; - 00000000000000000000000000000000000010000000000000000000 - 765cbda6115109ee35dd5132d1467963c8d01c98c45c3453 - 02c719a0f74edba7975927b1854d3508b8f3ac1208c197ba; - 00000000000000000000000000000000000020000000000000000000 - 0209e8466c40204db5fdd3359b27e40920c79c1c63c6f030 - 9ffb260428629704470a539de1daa6f7afd55bd0aa2ba9ed; - 00000000000000000000000000000000000040000000000000000000 - 5738c3f833379616dc030b4000f32d672d30fe2246aac454 - 5b92b0ac5fd6fc2fa16f09c3b561300423f6d85e30e3cb26; - 00000000000000000000000000000000000080000000000000000000 - f7675f3bba2be50634a853bba205f33616eba5716513e28c - 5da69b1cb28398302f5896aefe2013ca82d0435550770288; - 00000000000000000000000000000000000000010000000000000000 - d3589f775c28ad54dbc5b3f5fac58c7f714b02a76c724212 - 570c32b8036aea0148294b6e3a7f7645716f4a34a7d391b9; - 00000000000000000000000000000000000000020000000000000000 - b3cbc1dcf7bafd4831b3008d60d90bb94ce50ad0cd633bf4 - d12cfaf58ebb31eb52c15279b6dc2288d403c5095801bf96; - 00000000000000000000000000000000000000040000000000000000 - a4fbc80a9d9e447197727034ebe3b15160cbc7cd9f269fc2 - 199b46bf2f636e5cf1ec0f1941a82d8b6d64e1b663894942; - 00000000000000000000000000000000000000080000000000000000 - 0c6ebfc561c10d994fd1475a2a3675341f7593f9f66cad31 - 6a8e9c8aa02e39174dbbde841585d9e874730a52d61649ba; - 00000000000000000000000000000000000000100000000000000000 - 25bdd9705ce78a156f3776455ddc4581aa1aec50684936c9 - ccbe10b3b46d201f199b58c3d19d1f9638d2886e7ce0478c; - 00000000000000000000000000000000000000200000000000000000 - 613f897e927225132429762e4dda85c607abba9a858c8996 - f76e01e51cea715d0dff5d54736c93bdfbf019c78a0bdd1b; - 00000000000000000000000000000000000000400000000000000000 - 65e343dc8bb79912567a55f71e99b3feaf3ee50c427c6143 - f0d0a8cb38b9d35d3b6aa98d14c323458dcd13e1ce4a7772; - 00000000000000000000000000000000000000800000000000000000 - be901e27296d7b03a1a7b96f1cd04fe3082ceae9efc53a5e - 359b7c239f049c9643aae5cf2d928dbcd5b05a4cee9ac27c; - 00000000000000000000000000000000000000000100000000000000 - c4707ac4f4b93bcf32243d79dd30ec29ab7f36fabc2febce - c70cff93a2465945e80ff266fa22d2680caa09f4d3679f65; - 00000000000000000000000000000000000000000200000000000000 - d30d652d01d6935233b1c345293f0936146cfd487a2601a6 - 0b752affdb6fb51a9e4811e71bcd057d0c586feb5f992e9d; - 00000000000000000000000000000000000000000400000000000000 - c5ecb03f48abf44cfa91c989948e4a211a0a8843a74154f5 - 3fc154fc54f79ecdbdfeea0e394341f4f0b9947eacf35ef1; - 00000000000000000000000000000000000000000800000000000000 - eac3e4e82fd8888c86cd00b70624420bc40a329308291941 - 643b0abd39245647ecd9b49028267e84a3fa5f4c1528e9a0; - 00000000000000000000000000000000000000001000000000000000 - ba153e4e10b7e393efcac79f73f7a6a78717e866110a6c18 - 98e9a632cb6e6ce3b28f461d51d2f95fcb476f25259338a7; - 00000000000000000000000000000000000000002000000000000000 - 2f5e5111f2c6689c1b7922f13b77bc21d1dcfa0548a365e3 - 7381da06831dad907c647f476b6b7acaa1c4f8bf39f906b2; - 00000000000000000000000000000000000000004000000000000000 - 29289bc290af03cb098c53e68749b16d5622d3db2f3011eb - 8844a8e6f3c043c0a6e1ad0c7f2aeea959e314cc794d7481; - 00000000000000000000000000000000000000008000000000000000 - 2a2993ed185b84670e2bb7aba5ccb4144bff86ca3c3e37ef - 76d2ab7bf99472ca115b666c932e90d21df5cb555e2d7985; - 00000000000000000000000000000000000000000001000000000000 - 44a7149685be83061a8141f9f86fb598a2d2489af958237c - 12d9cd9df6be396ecf0dcb2eea70261db337379379a56b41; - 00000000000000000000000000000000000000000002000000000000 - 2a54c1eb6658e329179fa565fe8e70dcd325148c764f3278 - 6da20c81af891dc85b8b42aaa370c490e2342d401ed8b36b; - 00000000000000000000000000000000000000000004000000000000 - d002d417bb650e197d87823051824f0060127a5d9a80cde2 - b6858026aee1cefb44780100c66666a157ef41771be03d5f; - 00000000000000000000000000000000000000000008000000000000 - c87daae7c988751a47c8b2defef5662711bffcda2b04c68d - b9f0df2039ed2a5645162dda2143829d5c4d6e6a3ce2bd66; - 00000000000000000000000000000000000000000010000000000000 - 82c21873ca16ff6e831d9a630dc8edeef5c0e45233d9e653 - 10115819eb20be42ca003cf7b313446ffb522e1fd1e3878c; - 00000000000000000000000000000000000000000020000000000000 - d9209dc4bc41a359f42281e85ae7a815a372ee810992f297 - 38a198719939dd10ff3f978a6ccd182f8a2a7ce6c79f6d45; - 00000000000000000000000000000000000000000040000000000000 - 7772821616ba97f2cd390075d0d207742eed03e4ef9ae8fa - 4ba5d91e1ce3f521d1365157de2adc666222c222ec2d3227; - 00000000000000000000000000000000000000000080000000000000 - 4c49fbe58fa73f8f6984924ee2feb30c11af06b6127c23e8 - 4a5c4b2cf401cdc8a8d42fa2c04065aa52f351b20b60df20; - 00000000000000000000000000000000000000000000010000000000 - af551b0b91cc045e718974bdb030e0f2c70c512aa2ea1032 - a1649d4e580003a845693e8b25388a7b9789126e672548c8; - 00000000000000000000000000000000000000000000020000000000 - 877e0d6ba70f8642e068805a01abc9f66f6ca53371ee07e0 - 9bad4b2043b8ca9d9045dcad8d3b85c1e7c312f54c93d465; - 00000000000000000000000000000000000000000000040000000000 - 737a994ba01e24ff5a87cfc942c7e398b9fe8f5c36480f7f - 206781c03a35312079afa8630dfef2597c886e9a8d6668d7; - 00000000000000000000000000000000000000000000080000000000 - f3699997c4c0df71ca34541d9326d4439ea2b6dd194ede4a - c9b558da91f88f4fb0f1ae1c462102cef0a0f03b5e001cfc; - 00000000000000000000000000000000000000000000100000000000 - 258e1e16d13ce49d113eed5aa036400fa1967e8f9e3f2a52 - 8b3e40554cc38790919fbac7dc1ad86334e4df9c2a50078a; - 00000000000000000000000000000000000000000000200000000000 - edec557cf03cf9bfa8694c02a366ec44d552bd9034eba4fa - 905b8240be31313ead25d8380c55f6d1a0df89179884b494; - 00000000000000000000000000000000000000000000400000000000 - a655d39d3d8b773c9fdde7c9ad2fe5f8967800a621b91aa7 - 23f9a1388e522b6b7eec35c9f1c027385f2f74aa8d9feaf1; - 00000000000000000000000000000000000000000000800000000000 - 11ba6f9a3cdb2a23aa1b923c797b5ec61b8f67aecc8218bd - f2994709f5fdf5edca503eb14a1b237c272cd7a16c4bb072; - 00000000000000000000000000000000000000000000000100000000 - 9f6c02ee484726800d87ee458e3c69fd4b44f3a93714a791 - e489a54780e1d8facf73b69d02dbe550ba970997f292993f; - 00000000000000000000000000000000000000000000000200000000 - d11f7985dc2c25d01e3a830c612875b27459321fee2de1e2 - cb5311c276aa3b8092c9a63b569d6b2c6f5738ed264029fa; - 00000000000000000000000000000000000000000000000400000000 - f3fa791265d231b06bf42f5d120edc44c080ae541f58043e - 0dd8b041c1a3dcd2e9f79fa6b027ebf3aedfed442c4139e4; - 00000000000000000000000000000000000000000000000800000000 - 21ac1c566d8473defc012313319fc2d8da50af71121186be - b39f67818cf2269e439ccf386aa13dd404ff5233b9345e61; - 00000000000000000000000000000000000000000000001000000000 - 316273fc4a0b6ddd90574335fb8a0a20ed0a0104e70e9a1f - 832163f88a2b62a4aaf619fea36cfa56d8979011bbb8fda6; - 00000000000000000000000000000000000000000000002000000000 - 00b5c352659ab100326d110075c041f8217976ed3821547f - fb48516c09d9593945e71a141fccaa663e8df96a44eb9327; - 00000000000000000000000000000000000000000000004000000000 - 6bc65cafae23e4394e970f4679861a2aafeaefe19633bb51 - 875173998a5e5ea76517c0b0a229219e0a5f3700d1fb75ac; - 00000000000000000000000000000000000000000000008000000000 - 71d385beb370fc18c1d7173cb75b3b1f15d30d8e3ccc7cbf - 1902091418ff8923ae4d4ea42fe9ce406a2cc5a394def524; - 00000000000000000000000000000000000000000000000001000000 - 960d8a3ececaae6e42d47d39fea65aa3ecf2d5ab7140944a - a981274234e998b241ef58d3424055faa7f701c312b7f958; - 00000000000000000000000000000000000000000000000002000000 - 5cefd34143969f72981162d8d10bf719973e9fbe7e9492f2 - 0ddeebd6797292c2f539f8f0a82dc646f42cedbe163f89e9; - 00000000000000000000000000000000000000000000000004000000 - f70b2d5be4989f4e7711d02c0bc03a7e1a8f8cc605e3a853 - f7778358e0e77f7f7ef7ed5c41005f49ec91e4d45c3d8495; - 00000000000000000000000000000000000000000000000008000000 - 89957ec9016662bfedfcb4872c182e648edf00dc59012050 - b425631c3d6d683c8183590c99058c18c9c3d4cf56d10500; - 00000000000000000000000000000000000000000000000010000000 - 01edcc0af8796870f0cbc9ca12d1beeae0a693fcec632a3c - f848bbcb8b7710c805d884ce13c231f7d83ff63444065406; - 00000000000000000000000000000000000000000000000020000000 - 960fe2a9d448e5b2ab8dd99ec58a6c07c40b5af464631c34 - 55ae3aa987bdd74c63fd3b0cb5818557dc4f2b886a73d880; - 00000000000000000000000000000000000000000000000040000000 - ab20af3c5b1df2a2d9eea9a2c524bbc83fd1195103f76856 - 1826890675b9f2cd2b2af4b1fa67fea727f2b036bbd82d66; - 00000000000000000000000000000000000000000000000080000000 - c2261c4fa3ab84dd38c7ec512ac972a05e29b6ed65852e29 - f941c28063eba8408762134ca5c6132a2854c545d7a64377; - 00000000000000000000000000000000000000000000000000010000 - 3d9da2d2eaeb97d162cd86f1bb343deda244a304ed9232c0 - 77aaa14ed3e383a2e6c4455797ce6d683a20e280d5ec9ab8; - 00000000000000000000000000000000000000000000000000020000 - 9a121137759cfcfe9167b57727df46bf5b8d35e54e813ab7 - 2536cd77c22795c50384c0ffb3c667b13ec99de25b8cc659; - 00000000000000000000000000000000000000000000000000040000 - 8c308d1e799e8e4e483c0ed00a4468d06932c66c7fa66b4e - db1b00bb64b9011494de6a0605dd496d5ff97a89f7928490; - 00000000000000000000000000000000000000000000000000080000 - ef3da9e874c3c3abe1b6ce46bc78107e5bd6e5d4223c07d8 - 6c942783ad9307f21b698970e99be812ce10bec7282a809f; - 00000000000000000000000000000000000000000000000000100000 - e3465e5da4ac75dd663bbe7f59cea84db1d4cd987b659a1d - ebd3d5e7fd0495a999cce1d056b0e694cfd1167d277e41f3; - 00000000000000000000000000000000000000000000000000200000 - 9e115d1a939d05b6a970dcbb27a1d29182117ae6f90a6b8f - 7a0a4b5b59c7594fac6801ddc6b20ff56e6842ca0ff395d0; - 00000000000000000000000000000000000000000000000000400000 - eae903ee25f7c95a7384f4516e88d89ec8423789b8abeffd - 1442520d0cd4a9342da833f247446e08e200369637db11fc; - 00000000000000000000000000000000000000000000000000800000 - 134cb0fcb97808665bb77439cc40fcc189067eb89f8965dd - b101aa60872909d82906bc746f64d174b8eb2ad70ecf1abc; - 00000000000000000000000000000000000000000000000000000100 - 2fdf734b5a69c30be8214ad46a0327487d97fa2f694b6f6b - 87340c26b15fecebe01b98b3b86d3b0d434855c0d747c85a; - 00000000000000000000000000000000000000000000000000000200 - 17c9d9be32dfb06cfbd47e8467d7464d85366a42fa7b1121 - 71065364320dc8ebf10abc71915b9a37fe13fbe8012be9cf; - 00000000000000000000000000000000000000000000000000000400 - b242f3fc2bbfbe89a3f0ca2605244b692ee7d96fca5ec3e5 - ba5c15f7e1dea1c4c02d81b446b6b97e91d3f27acc3ece9c; - 00000000000000000000000000000000000000000000000000000800 - 1389f6dbb847264179557e2a635c3f0cd843f5b82a457cf6 - 064d9fb5d2409e24bbeba7e45c4c57156c4fb11f373e76ca; - 00000000000000000000000000000000000000000000000000001000 - 42f828955b36c547dfbad0c56d6b4d2f623ef52ef7fa2738 - 3e80ab94606fef79fec3d3bfcb8707d9726cbe27233cb419; - 00000000000000000000000000000000000000000000000000002000 - e23e23434169161071da977b4620dbe5beb6fa04b47b432d - 9c1963564bf7a6473027442cb42cef4ef2e248090be98c2b; - 00000000000000000000000000000000000000000000000000004000 - e30e30336add2c54af49b3f2d172c5c151eb7dccd049f423 - b8d3c3935a0470147bff00344d0a9ca5ebd06ea22bfd2d6c; - 00000000000000000000000000000000000000000000000000008000 - 299e23a4828145c8c2bb7db4819b175ffd57ed50af2db5ae - 791ff2f9a6f0dc8bee326d9eadd920da1edc5d2a17d327d8; - 00000000000000000000000000000000000000000000000000000001 - 37de5c10c2e92a137264787163cb8ae954d81933dcf9cecc - 29ecfaa7a976d0b3dc7edd2066cefe484ad12f9aead252f7; - 00000000000000000000000000000000000000000000000000000002 - 0442bd68ddf0523120c45e5b858520cc025719fd408d757c - 373a1aa3eac3bb1b5a96a20e8e65bc41c5894deb725e27c5; - 00000000000000000000000000000000000000000000000000000004 - 4a6cd629968c0b125350dc0ff1ab3a603c0b93e9a3e56c1d - 03779efb521048c170b78c8502b166d9fa5813527e504e13; - 00000000000000000000000000000000000000000000000000000008 - f4d8d2f1b211988847b5313b5fefb87ad44d824767c22cad - 647f58392ce955573d3f741ffb51ec3cffb6fdb662996ab6; - 00000000000000000000000000000000000000000000000000000010 - 980a235b4a173431de984f8210de069493a85242bf14f269 - 1b4e10e4fbba7103e91b9977a6e4f492f04318e3aaba2419; - 00000000000000000000000000000000000000000000000000000020 - 647f56d74ca28c355462bedce39dc1dd85dad8aa5b1307a1 - 534a6e7b84c5303539ad359bf6c0603f29106f6333df6bf7; - 00000000000000000000000000000000000000000000000000000040 - da74d3bc915e164c185021b9085367232a1e10b8d063186b - 86caf736c5ddc7b3e4c15644a19334fb805ac1d869a88866; - 00000000000000000000000000000000000000000000000000000080 - 7343f4e043fd65520bd2d84e8c3edb26e617a654f05bf05c - e31bf2ac0a70d475260de31778ed39005cec782018514932; - 0100000000000000000000000000000000000000000000000000000000000000 - 9f5070b134d17734e035f8382ad4c1f61f83a6a9a0667e1e - 6c64f62e4376d0e962ece7e1aae286ddb0deca287e90b156; - 0200000000000000000000000000000000000000000000000000000000000000 - 3749a578adb8406d74022aa37e419f6a1fc561da5d11f163 - c59fb6c711df8e2ab61e9acaf513da8f1c76b91c272a6726; - 0400000000000000000000000000000000000000000000000000000000000000 - c8c990a321ea2a6a87066981b4982e89accabb0cbae03efb - b7502857ce96c6e469bfedcd3dc8eeb3f0326358bc076618; - 0800000000000000000000000000000000000000000000000000000000000000 - 73e3d8ac9ed3560c15322b54e30ab8d2c2162f029663c79f - 260b56cace6aef56377acf544c6899c81eff1a27c5d36f82; - 1000000000000000000000000000000000000000000000000000000000000000 - 738f42325ef664ec8928bc526abec512b8ea953e33ed0006 - 2090089fd9fcc5aed2612744712dae81c09ff05e5e4d615e; - 2000000000000000000000000000000000000000000000000000000000000000 - e8f4aac282194e7e31743aa524f7d9b004d2e63e0a30511b - 3b6c4ff45cf657d73bfe0ff0725b594a97d75a4cd02eebc9; - 4000000000000000000000000000000000000000000000000000000000000000 - 6ca217b943cef2c7e222e163bfec73c9f2a5b5674a39955c - 359b596401604ba4f686b1f81dfbc33e6333a6ab054d9b5d; - 8000000000000000000000000000000000000000000000000000000000000000 - ac011f99d6766074346e8155ac4a132558775649391ef793 - 21a191c34b73b95fdec1b26477ba3711c668e7e03b9e72fd; - 0001000000000000000000000000000000000000000000000000000000000000 - 1bf0e285f67aff5b9e50c33f72819e4954345c81d4bf4d70 - 82e9cf04f361e790544077fded5dc925866c0f6598016e62; - 0002000000000000000000000000000000000000000000000000000000000000 - 7af6bdf52d8cb70ad56ba7ca466315e9431c9be251059915 - ab68dab956704aa49dc6938771e720d53afb6c001a9c45dc; - 0004000000000000000000000000000000000000000000000000000000000000 - 6b64c2b68c3a70c98a3a27d73fde094efc351355708bb8e5 - b3e7e648edbdce4024fe88afd65bcf79756146f37ba2b523; - 0008000000000000000000000000000000000000000000000000000000000000 - bafc3238aebf8a428a560cf351d235dbde917cc1743c94c4 - 2bd0b7ab6759ca6461974b402f77287d4047b6c580ed057e; - 0010000000000000000000000000000000000000000000000000000000000000 - e3c12e9c2d584133495b3ad8a93a18303809cae7ac8a5c35 - 01f1f0781ab946f016082703b7a5f0a8e2538e6399fb2a27; - 0020000000000000000000000000000000000000000000000000000000000000 - 15b55c96181a311f3f7f74f1eb85acd21405e577c99ce7e6 - 7be214ae039f75aff28c25e1693d9509b95e7702100136bd; - 0040000000000000000000000000000000000000000000000000000000000000 - ef286b5b57c90b082099f1ba63d66b831c2636dbf89284de - 405ff3ab609cad17a727f3a32a728176f60738ee93ea4ce3; - 0080000000000000000000000000000000000000000000000000000000000000 - 6a9f9a517d801e276faed59b37815a0543470f62ddcb36d0 - 6cfd80ee554662542fa45f8619fa8596a5b0fa90207c6e3a; - 0000010000000000000000000000000000000000000000000000000000000000 - 2c65e60021dce4ab35356c77e3a8d9d489b229961214d45c - 84fb478f9555f964aa1c963c796afc08249dfa483cea11a5; - 0000020000000000000000000000000000000000000000000000000000000000 - 6290778c236da149367eff1a881fb693e5fc1577b911bd50 - fed8ace2fa769e2e59191c11af5981610c7f1d1cd16a63c0; - 0000040000000000000000000000000000000000000000000000000000000000 - f3a53dab4a1b2ee51c925c64b80509168fe2c4a39f89eb9b - fb14272d3dd9a4a43c3c77edcb2ee13d1c0cf5736c100e3f; - 0000080000000000000000000000000000000000000000000000000000000000 - 37853db27afa67b912d92274f952fe6cffcea6749c9cf346 - 5c3738ff494ec6280aa714196e4285d78ad3efe97dcbd993; - 0000100000000000000000000000000000000000000000000000000000000000 - de4ee75f7a008440578d541a9e9beae7ae6f2ce540682a51 - aa01dc968b1c9c699098297c7a6230ed03e9d1f8930fba2e; - 0000200000000000000000000000000000000000000000000000000000000000 - ec682371507c5eacf5b1c6510338f9979c93480dfeb327a4 - 00a05844fa3d11d1ecfab19b2fed0d6eaebe4265a89c2214; - 0000400000000000000000000000000000000000000000000000000000000000 - e1e5590bbbd38ba2e79d7f674c1446517c0fb92ea29d4b08 - d3e5d1af3b1798d750976f6744baa274a9ecf75c44efe46e; - 0000800000000000000000000000000000000000000000000000000000000000 - 121dadba2540831650bab205a38ede0f515ffaee7788932b - 2ae7182cd02fda62b2fca3aa1459f88ba131f5037734d486; - 0000000100000000000000000000000000000000000000000000000000000000 - bfcf69c073a8f4110b4f2506e422d57ac27336ca35fc55b7 - 9b92c327f8d3a10f0294570ce6dbad15e63828cce97ff2e2; - 0000000200000000000000000000000000000000000000000000000000000000 - f9e64438a44d994229bfc83934b5900cd3742508d8c1e3f4 - a91cde6622ae50df47b3efb44188211a9cb855dd13f196e0; - 0000000400000000000000000000000000000000000000000000000000000000 - 02bc24f93a54d95614eb323e668dbb078db65376f8222669 - 12e0a8abaf64c61b674b1e7e80245c8486d0b8b958d23d63; - 0000000800000000000000000000000000000000000000000000000000000000 - 38fd0dd2508ccaaf72e404c3aa6197ecdebc6bccc2906e35 - e7178e54aba498545f12beab6f4566d0af8ddd737e1094f9; - 0000001000000000000000000000000000000000000000000000000000000000 - 6c2bdfe67c48ab3cb5e107ef3bad9aaaf4b7815775e31441 - 51dfedda78ac4f3bd74de1129075f40b6489e7dcef913c8f; - 0000002000000000000000000000000000000000000000000000000000000000 - 9996e38570d89d1e4c716d17d2d18cace32196b32b13dd4f - 4d69155a61196d98ba7d4c3760cb5b42ca7826433f767477; - 0000004000000000000000000000000000000000000000000000000000000000 - 2e5f7b788f621e6e00e568a5d6f6366a204be180a4150c1c - ef2f1ced4c859dc6abe9a7797f94474a8c5cc738524cb51c; - 0000008000000000000000000000000000000000000000000000000000000000 - 225d5651c62b76b58162ee3565c87920e73f8b26874b5834 - 51d5591d45055db3213c2037ea19d19e3f30c57930cb408c; - 0000000001000000000000000000000000000000000000000000000000000000 - 778f01b3f568dc1cc0190d8a9d45f046ad0d7bd0a2e83bd5 - a659640486d774d149cfa752fe07f16839ad0a4e0965023e; - 0000000002000000000000000000000000000000000000000000000000000000 - 07469341cf3d3fa4f1e4503d51b2147eecece66e55a4aacf - 0f4db2767bcdce2479987e1dee35bce57d3f0c1f064e8388; - 0000000004000000000000000000000000000000000000000000000000000000 - fbb5a12272515cb6cef56c3394497f17c295a8168ab7cf52 - 79e3d684921c85b2aee19fd542fd0e326d06db185ed4b2eb; - 0000000008000000000000000000000000000000000000000000000000000000 - 23b46f278eab2f8cdad836b7a0805cdb5705959dfad8a8f6 - 47e50febaeb4948f0f08b02d8f00ff84b1a4e28741b84be1; - 0000000010000000000000000000000000000000000000000000000000000000 - 755fc8fb5a4247070161365d075fdca9c315f7ecb9638c5b - c0a7a431c614f79e0efa949a89b0a1d3a44b726f75cca6df; - 0000000020000000000000000000000000000000000000000000000000000000 - d1777c337f61776201449d5dda39dd3acf48b521ea993028 - 10e87a928e0ef507398afe7f1d3de0cfe3be585831d6b8fa; - 0000000040000000000000000000000000000000000000000000000000000000 - ed33aa1685adb27dbc81bff9211d9199feb400b8084362b2 - c75e37d353c1cf37451eeb3739c92d3111e5e6a95c3f6a1f; - 0000000080000000000000000000000000000000000000000000000000000000 - bc37576aeb1bf24f50806c7b96cc3ebedf64f5d444238cfe - ee28dd6263ba7f0cdc8588aeb27563e83dd26a66c519a3ff; - 0000000000010000000000000000000000000000000000000000000000000000 - 18a038c2820a8f3e7df91219c8937a403fc5b04476b5b00d - 9e3908a1ed2c0d5b7d8ca231a0e9d965c5bedd70c2e91782; - 0000000000020000000000000000000000000000000000000000000000000000 - 266d38db2332f7b5aac71f5e9c4f201abb66e07d3e0f33c6 - aa256588a4aa4bee6595a18b9083ebd7b4e33adb2f7f3112; - 0000000000040000000000000000000000000000000000000000000000000000 - 4e456d28fdb91a55600a0f0a940ff6a23e99a7ace2302257 - 7faaa8ceac5fdb90aa67d0cbfc3ba885c19236ccede0267c; - 0000000000080000000000000000000000000000000000000000000000000000 - b7e154b0cef10b51c0c37d92d1ee18f87e9c034bef605109 - b953b77fc877b9877c566c04077eba7de5ce3712302f5bec; - 0000000000100000000000000000000000000000000000000000000000000000 - 23076ca9ba4b66fd5dad468e32b6aabd89157dd9484de084 - afe987cc7c00e457432b4343130c0efab5ab5bde088a8b09; - 0000000000200000000000000000000000000000000000000000000000000000 - ba9528c919d59237d542419e822ea53d44d7709ed8831393 - a46e0010238e90da8a824c99e48ddd516b53d1b58babfb67; - 0000000000400000000000000000000000000000000000000000000000000000 - a45c47b8b5d93ac468ce2698c4bb818d18cddd27d3c90ef1 - 05d4636e0dc06295cf47fbe08564a1a890d42be50da9a712; - 0000000000800000000000000000000000000000000000000000000000000000 - 009e53d4f953ad0a4e3a6f424958319f9b0ebcd4eb32e6b7 - b26f95360e1f006e78c56c7bdb60aa517c08b6b353ef3954; - 0000000000000100000000000000000000000000000000000000000000000000 - 60beab9429813d3bbc70a65f440af15b1bcec02ab53e3b17 - 25eb48a26dc3ec9d67440f4adfaeebf3c851cfb774f5d9fd; - 0000000000000200000000000000000000000000000000000000000000000000 - 8446b9d837207ac194d094bfa5768dad1bc7ac62b507d6f6 - b93872a3955bfcb3a085def48e48ad7468172a3ef1381296; - 0000000000000400000000000000000000000000000000000000000000000000 - b18d63b9b8f957da2cb1d8315958058f607ee9aa10803040 - f8fa5297afba5460f910507495a4aa3c03c08ccbe658173a; - 0000000000000800000000000000000000000000000000000000000000000000 - 8569811b5e86046299507b8f1ca054bbd291997c92120b1e - 56b1179f4e1abf339b12b0c9a05b428171dd207e2f90e9ee; - 0000000000001000000000000000000000000000000000000000000000000000 - b2641a18af6dd774a608b6b7a498b5962ea67f5b52807803 - 7a7e0f1cf78a9fa1421196d03455525341514b24dcbbccb8; - 0000000000002000000000000000000000000000000000000000000000000000 - 5ee40a1926ada020139789a195f1d7fcfd8339a5905d8c91 - bcf4d04a361be5738498700a057b6a767af995b1ae9cc990; - 0000000000004000000000000000000000000000000000000000000000000000 - 97fc38aa8fb864828a1f8ae469219da97ecc1d352fd8478b - fbb3e38a2e3ae33ce7cbd0d9ef4278ecbbca11e5571a21b3; - 0000000000008000000000000000000000000000000000000000000000000000 - ba1314e36083bcbb1f01a1b0dcee1c5167d95058d03cb298 - 9c1f480bafe7df16d6ee5d5e44296998acbed57fa981cc8d; - 0000000000000001000000000000000000000000000000000000000000000000 - d1c445fbbb6c11b248816ee124502e8d9a44750df0288c84 - bde77bc4f65398b2e4385be1e459925ab0b29fad2e2ec1c0; - 0000000000000002000000000000000000000000000000000000000000000000 - 91e1b29bac8b3004b7e0a3c4df1f49131b73cf7ee9daf237 - e6838a7e1686dedfb4f590be43684645a9b1b4d41178368c; - 0000000000000004000000000000000000000000000000000000000000000000 - a618c81acb2f8ffa633fae6f430d849213633f506ecfb4a9 - 4fb027cf52b913a04d493a225be16d06e8bdd2e335a59f11; - 0000000000000008000000000000000000000000000000000000000000000000 - 425ac642bdb172b0d8af9b5e8733b4138f9a8b73c53e78df - fafc2c7ef14412e28b3091420e524b7a617fcb79fd7a2333; - 0000000000000010000000000000000000000000000000000000000000000000 - bb83697c816b291cbeacef56116984f1bcac5d1185a96046 - 94ef1fed71ae8838ea5dcd1fd87df10aa5dfdaf7247b20f5; - 0000000000000020000000000000000000000000000000000000000000000000 - b9a35b83d2fc63f3a59889ed2464ad35fe2304bc8b243620 - c072779c8f7c58b5e54f87de26ff3e8c9bcbddcd843d0ec3; - 0000000000000040000000000000000000000000000000000000000000000000 - d5ea0b3466ac121ad1117536c22443eb6206c8f0cb129db8 - 2d3e46147b3d926b59e2d3d848a519ae9d0dab3002c7a447; - 0000000000000080000000000000000000000000000000000000000000000000 - efa22fd1dbb1fd3fe8b4713b358382a3ebfb7971d71c619b - db33941cff2f3ba57574a6babe30d3a2482fa5fabe541248; - 0000000000000000010000000000000000000000000000000000000000000000 - ec54918b940cca8540c84dfb4951115e41eea879f69226e7 - c3f4bbd94a5f8ab825e14d399d1d63b419b920a985eb537c; - 0000000000000000020000000000000000000000000000000000000000000000 - 882f20f80febf9a64f8513d9da4a84ed12230066759e0baf - 171124ee711829702478c993e0a69614a5fa6abe5693c757; - 0000000000000000040000000000000000000000000000000000000000000000 - 999b241ea0f1f9d8291458bc1706019f2a62597d2e08e808 - afaa8b4bed7aec429f62ef6bd157ea1b0cca67b539d35f8c; - 0000000000000000080000000000000000000000000000000000000000000000 - 9d1c95595d1c8b43b32dcbd7d157ed0cc500beceb9ad7dfb - cfbc5738f8c2d1fe1489aeb853e7afe75d3228e820e5d1f8; - 0000000000000000100000000000000000000000000000000000000000000000 - 939c98efb6a332bd0d106b0ad73c7bea3b27509089a9b3ed - f8ddedef92e523ba101a8cbc3f5910457b4c10f632ea8c1b; - 0000000000000000200000000000000000000000000000000000000000000000 - 62260cb25a9c5f13da85ba16c781315e00fcf91a14ecfe7d - 4a81f4764d73cff0c6c598bb14d03dbe7456d84480b3d97b; - 0000000000000000400000000000000000000000000000000000000000000000 - d13026196c4648cf6eb48ab504801dceb09c184da5d02206 - ffdd66bf5a8ef884b365ff79cb468a07483ce1af9c781ad6; - 0000000000000000800000000000000000000000000000000000000000000000 - 1950354058a14fa13adea19ad18be46eaeae9d314400ecc7 - 3911826bb13fb45bcee0680c2e2988d22c404120b67174a4; - 0000000000000000000100000000000000000000000000000000000000000000 - cab6747886cacbd533a4a28581622772ca4026b7735cfd62 - 1e03b32dbe480ae229b614d23e1d0ca3b4089d622b525960; - 0000000000000000000200000000000000000000000000000000000000000000 - c258d3ab881322905a693d6eb560b14c93c6e1f1ace6cba3 - ca58904c0affa64dc2fc1fd744de880eb86876a93c30c04e; - 0000000000000000000400000000000000000000000000000000000000000000 - d059b736116667cfd8f94e294252ccc57adfb59c7f2a5f39 - 2f3e359bb0ae9d420049351b1b256049f61ba52996f08036; - 0000000000000000000800000000000000000000000000000000000000000000 - 8b8c9610ae81e48055eec551f0d52cc552b12753c6bb7924 - fc2c7edfce13b888076c6b8932a76c00aed86dc34bcb04a9; - 0000000000000000001000000000000000000000000000000000000000000000 - 95f736d9848960fe82200410199208bc50bff3776e7d800a - 01da25ce699dad03299a6b2f02422deb0296463df7976a1a; - 0000000000000000002000000000000000000000000000000000000000000000 - 348e25a9a47f7371785c033e858054e8b84b4aca450330bf - 46e40e1b342b0197a6c9823810b563ab162a4afff3ef8d3c; - 0000000000000000004000000000000000000000000000000000000000000000 - 398d57d71fbbc564ba40316a04a78661be30188d8a00a9c2 - 1dc6b4d53c6cb47c518a07e6caf6aebb60879202c2902404; - 0000000000000000008000000000000000000000000000000000000000000000 - 8c2ce222b3845769ac1b5c6087a4a78767bb7b5b6db0b844 - 386089aa0f982dab5aec5ce3c0d6c22e57850ef5dad854d5; - 0000000000000000000001000000000000000000000000000000000000000000 - 367067c67a278f8da0b6d95e01e1300c4ce4dc4564643a1a - d9f7b526134055e0863b763367ef09c4999b3d3f7478f2fc; - 0000000000000000000002000000000000000000000000000000000000000000 - c4531ccef569e7ac3fe27aee4f9413a5ea932d077eafe749 - f8617cd036e260fcf3cfcfd7227ae8ec3823dc1806a5186c; - 0000000000000000000004000000000000000000000000000000000000000000 - b23ab66b0a48a91976906f145c49acf72cfa24a718e29d43 - db0602809ba65f935b2b761ac68698f44ab52e3073318480; - 0000000000000000000008000000000000000000000000000000000000000000 - 84e2f169348f9c12292bae0e4a411c04bbae0dae1010c6fe - abb60974909b46172f0ff9f8d3e0c1ac90e354ef5d8d4b96; - 0000000000000000000010000000000000000000000000000000000000000000 - 178f1df13876d9aabf1d7567a9ac8548033ab879cea6c62d - e8275ded5d48c972e53d5542d039c3c0643bc221ec7ba6af; - 0000000000000000000020000000000000000000000000000000000000000000 - df2371204f0d5fb0d345feacc299424b1f09c4fdfe740b29 - 1d7867481c4958a1e96b74d7564fab9081826baaef1c0bc1; - 0000000000000000000040000000000000000000000000000000000000000000 - 85f193b35e480c86febd733e3d73c5e533f5af5fa670464c - aa297d5e92606023fcd76ff39b447bd6f8b528d2eb8aa389; - 0000000000000000000080000000000000000000000000000000000000000000 - 3c7e3ef5b75bdd8c4ebf0ab567fa9dfab7b14f65465d5202 - 2d1d772ca4e8c4627d10252c17f8de9fe4eb5f2410036f8f; - 0000000000000000000000010000000000000000000000000000000000000000 - 7946c21f3ec9019663b088701ec2fe303a91473d66166c07 - e0781ca73a7ba4da909faabd4ac41a9d2a04aee40741a362; - 0000000000000000000000020000000000000000000000000000000000000000 - bdc80943ef24005d2b2b9cf4a622cdeee6052c94028be903 - c1a5cf266e621e1dc67f7d95e8d4a0352abbe6906e2509a3; - 0000000000000000000000040000000000000000000000000000000000000000 - a363dfe9c29405923502bb20f0ca9433d2bd2e935bd158c6 - 73ecbaa847e33990a348518355d24250d78ba4bfe0cc6ec5; - 0000000000000000000000080000000000000000000000000000000000000000 - 91a79788d280aa0f726e81b5e120fd0d175e9f835196013f - 417a49bc83ff1cae0de19f5469644fdcff16a19b0c48e2ca; - 0000000000000000000000100000000000000000000000000000000000000000 - 4899462607deead1c0bd532d7aca9b707ab2e7fe0e29b590 - a81d309f9faf421664ba046616b4dc07c918d857d3d84905; - 0000000000000000000000200000000000000000000000000000000000000000 - 0aaae126611efd36cfaabc703328ce88567f1e1ae8d98ab9 - 642e95674700002ad5aa27d465b538e764fe7bd9c14c73aa; - 0000000000000000000000400000000000000000000000000000000000000000 - 89518487c389f394664d1db1e9110d4f31ee5a30ab504538 - 9096525261c9c51132a575c2fa95ec45b126d1978b3c8f0f; - 0000000000000000000000800000000000000000000000000000000000000000 - 48a115999ac4106147c25c8af6490e3f864fe07a4aa0814b - 6034cf7c5049884a7251bfe1e908db7ae5a242bd7528cb80; - 0000000000000000000000000100000000000000000000000000000000000000 - f4a37d22f6ccc6807c77a2b00892c34f751e6af9d507b7f2 - f05a07fe2964989df5de5c5568f0cc2a4cc385a0046653a8; - 0000000000000000000000000200000000000000000000000000000000000000 - 504eb8d6d794ad17fb17701daa68a27909c10b07db35d59c - 04d1a5d0a25f37c358ad1544a61c35e3b27bb8e872a66657; - 0000000000000000000000000400000000000000000000000000000000000000 - df0ad9ae9ea8203f839254c51201e4badf59280ec5791f21 - 60d514f1dc0ae5f0041b7dc951c2b7878620178f6cdf40b5; - 0000000000000000000000000800000000000000000000000000000000000000 - f134b86ddc24cedefa5919802e2ee4a1b8b3dfdbd6d4707f - a2a6684093c8fc7fda6d78137007ed72ae90c2bdd5457351; - 0000000000000000000000001000000000000000000000000000000000000000 - c1227e56f680ff943c4a6eae53aa8c47603dc225a0770151 - 20a18398e209070d630fd66253f8198d838c133fb8b2877d; - 0000000000000000000000002000000000000000000000000000000000000000 - 618aed56a6e67024f44a5182f8b3a0429f1f816e40d36940 - f4a5ef442826ecf4f7b51af42c67ca6efa9eeb05c950d0e1; - 0000000000000000000000004000000000000000000000000000000000000000 - 993f917a093d0593ffef2ee61717769d0310a338971ad5c3 - 633c510c65b17337fa6600f7b8c587f06cdbce7eed021dcf; - 0000000000000000000000008000000000000000000000000000000000000000 - d08c7506bc96104784ffd62989f3e7f14b7941408aff19a9 - 4ef7c78afbe041881669a436f0b3a2c175bd1872d417f427; - 0000000000000000000000000001000000000000000000000000000000000000 - e4c926c1c6af627ff4aea8915cbddf2d51fea4f8efbc84f7 - 297dc1f8f2f34488496c0a7315c434545c2c356da2f2b8a8; - 0000000000000000000000000002000000000000000000000000000000000000 - a1d9f20b38fc8ff10284673b5401b340d3606374c0705387 - 538fac79ea64656d7b752ea715238b7168b7fc3e3c307e79; - 0000000000000000000000000004000000000000000000000000000000000000 - 48a83c0d5aaa75c08186e0c3b43c12359d64ef6c5b51178f - ae4c16dbfd40480fec24032f13ce1ce1ee236785754befa4; - 0000000000000000000000000008000000000000000000000000000000000000 - 98c9f42280dbba13cc6058bcb1fc101f535c17ceadb39384 - 97c2fcd700e5ba4010191d1a2bf39b94ef26c1f10eb5dea4; - 0000000000000000000000000010000000000000000000000000000000000000 - 6e5185272ea765f9c63e084aceb39635fc7064c5500933a4 - 789c9eef18191c6eb37ff8bc61737be04cdb38074cf16342; - 0000000000000000000000000020000000000000000000000000000000000000 - f1a2076d13ea103ec3bc2a7981628b6c46b7e05ea2b8cff0 - 1c960f47235aa3c2f7db928c79eef79c1abb58df32be0519; - 0000000000000000000000000040000000000000000000000000000000000000 - 2a25e1c3d40e114369c652f39101b149ad121e1e297568f0 - 39a862fc9c7501571eebb68fda325a20bfbc18b8d1dc06a2; - 0000000000000000000000000080000000000000000000000000000000000000 - 4c368f98b55ba57c8a9f50143c85ba209f46b19a287fe96d - 805862de2dbfb0b5fc8522fe1775db56cae5d782c5ed78fb; - 0000000000000000000000000000010000000000000000000000000000000000 - a0c97c9e66701e6478fb012dc563dcbb1f5c6da5ab22e1c7 - 7deb07741bae22c3a4e245df6f6f0ea157e8c2fe11277248; - 0000000000000000000000000000020000000000000000000000000000000000 - c1aff5f111b93662f2101a991dc73b3c6ae24a7305ffe5dc - 0c4cda55e6b291dff5fd90fa1b5fec0d74e2658a9fb8be12; - 0000000000000000000000000000040000000000000000000000000000000000 - 2f7e8a0ccc58df1c6241c31911d531e9990eb7849c9dd986 - 57a80345e95f8e8f0c235e56e34b0b92bb6c3f7d1da32f1d; - 0000000000000000000000000000080000000000000000000000000000000000 - 22bea653be4b485e68b8579537213762f44e42f6d810a498 - 7c4fb10db02107f924884cc1813fafc08800fd616c7463f3; - 0000000000000000000000000000100000000000000000000000000000000000 - d7542072c23ba5a53a81ef80fd2e18a4fa4e797ff6600040 - 2a7bf2b00a0e7248f754fa91239b22954286887269c33386; - 0000000000000000000000000000200000000000000000000000000000000000 - 67cdb364f19b764b08f2fbe24e0d8f5045cd24643068dbb5 - bdcb57ef947437c8607c456b12a0e35dee06a72ddc6b39bc; - 0000000000000000000000000000400000000000000000000000000000000000 - 4b69f9d96da82a8e111ba914616b8181351b6c7378c398ab - c3c93b51b1523b3d5cff783005bc32aebb490df5dffbf54e; - 0000000000000000000000000000800000000000000000000000000000000000 - 9cd63826b5c968a2b91637f08960fff1db80be3e5f4e1b10 - 37e40726553084bf60ccfa589cd5a7ad328a9d2731b07c22; - 0000000000000000000000000000000100000000000000000000000000000000 - 9e35e64ebdb49e1eee17085264da59b066e3bbe33369e668 - e700e349d9ba81dc389c9ea47ae3397d2021cbb0a1dc3f50; - 0000000000000000000000000000000200000000000000000000000000000000 - d01966c6c3c1743b53cd852ed40141a122f10191b1c31a86 - cbb249292e1f8720ed8bd068e08d00e58b5b6ded6db35967; - 0000000000000000000000000000000400000000000000000000000000000000 - 5d22197b1f31e555244767a519cf1612dcb1e0c389dc5e85 - 6c356e034f76f45d77eac2372b1b8d13fe37a9793267579f; - 0000000000000000000000000000000800000000000000000000000000000000 - 7a6346dd4b48c8e2578dc9e44cef59b355e745603ad70e56 - e0ad6bfb7dd04c50408813e9ffc253a786a79f322270e3c7; - 0000000000000000000000000000001000000000000000000000000000000000 - cd6744a38f58ff1565c63b618f6d4602f48424ef96cba9fe - 223ebbfcee0d2261dcac64d4457563e8662cead4f842f885; - 0000000000000000000000000000002000000000000000000000000000000000 - e7181dde8f2bb5257724386d775d816db6ba1788840b2ef3 - ce12f93c38f34c761b6290ab661bea7a94d7bedcce619c42; - 0000000000000000000000000000004000000000000000000000000000000000 - 35144d4cd483e6ff784cdaba5d8fe43457400002e50652b5 - c9d58b472c45d4a0bc60c5f068babd4761119b8411392863; - 0000000000000000000000000000008000000000000000000000000000000000 - 49e3852d9ebf4a20761f9e3cc5af7079f92434f3cc0498bc - b5111d55ae21a4dd1d94208eb1e2bddc2121792c0865ea1c; - 0000000000000000000000000000000001000000000000000000000000000000 - b5be1b964131cf4bcc472ff83c7175747c0a8142a1b592cf - 82bd1f73170e94ea2dd2533fcb2e10b86d223ab573b7acb5; - 0000000000000000000000000000000002000000000000000000000000000000 - 436643b8310b2f8012fff1718d811445febcb62174eeaf89 - 4d73981253903319bbf05beaf81b161b5eda9da17a6c465f; - 0000000000000000000000000000000004000000000000000000000000000000 - 26fe5bba90ad70222b6e0dfb3f910225dfd1d94e8a6eeeb1 - e50c6fed998ff52d18c1cfaef6486c7dda0353d609893ed2; - 0000000000000000000000000000000008000000000000000000000000000000 - 167ca811688841bbc017aef57f046c72c89cfb105675abd6 - 474b913d96b3065573859d90259e7170ed086c7e85e6f833; - 0000000000000000000000000000000010000000000000000000000000000000 - 2241fe3b5601c4f8691132f7fef47b2a705ee925419fb2b8 - e4f6a1a195420d5be230460d72cb10e0d5fa98e3473dcddb; - 0000000000000000000000000000000020000000000000000000000000000000 - f73edb64726d1038febe1182d24c9df9ac4c2e44d27350a1 - d023f50e6c5815af9f68c18fa011c72a0ac1de37ba50052d; - 0000000000000000000000000000000040000000000000000000000000000000 - 414f12c0bd23b6541fe25e485c99ce83c5d29d5284c6d635 - b9be932cebc3b0451aca78b190970be486bff89022dbdef8; - 0000000000000000000000000000000080000000000000000000000000000000 - 9cb48ce5c9bbf7cdf172e72b8ef47ee0b9954d4d83f64e85 - ddbad8bb1b68dbe0d1c2377a9f851cdd40941f1e8b17a72e; - 0000000000000000000000000000000000010000000000000000000000000000 - 9ad04eb679eb45041adb6e18229ab8ef134f96b9ec4efa8e - af91847fd9a9b0853b5adc3952ec93b729931bafac0960c5; - 0000000000000000000000000000000000020000000000000000000000000000 - 7fdf8d84ca1f1ef75921d13340a8613a4abce59f8e6719a0 - 048a8092055d9bc71038c2adc3fc74a9941b1bad6bb0d748; - 0000000000000000000000000000000000040000000000000000000000000000 - 3bb8a2eede247347d3293a7827b935696db66633154f6eb8 - 6da269df5b0af347a91ef471261dc6aae07939d7562dd17e; - 0000000000000000000000000000000000080000000000000000000000000000 - 76cdee34adbfe476b19f218ad192ff91cc764594ea84e9e9 - b89d091dbfdd454d3de741971939aa47c84b65e5601ed69e; - 0000000000000000000000000000000000100000000000000000000000000000 - a5be84ab2131cc15fe88214e692c2a1c93649c302935f68e - 74a065159a3a25b7beab96afda6cb4a15f0f0974650825d2; - 0000000000000000000000000000000000200000000000000000000000000000 - a1c10a2b8f9117b9c7d2bb4a4b8fb19ad5862a070afb8f34 - 11b10a5b03c2e735c20aa91c796a30e1e5012eea5d17a2fb; - 0000000000000000000000000000000000400000000000000000000000000000 - f30f479b09b7078984a91a14766ca5331ca54f237e832e00 - 2754d3cdeb587cacac85e5b9bc2a8df745b72ae84c83e30b; - 0000000000000000000000000000000000800000000000000000000000000000 - f15256ae559de534a46259c458ed699763917bb67c42caa5 - 998dda9353cad5811b4d26b418d2c36ac8241cf9162afcb2; - 0000000000000000000000000000000000000100000000000000000000000000 - e9dd34edf9072580a9e6bf92f517160410c41b28056a8acd - 0dbf466153aff0de4e09a06fac89bde833afca483a514c02; - 0000000000000000000000000000000000000200000000000000000000000000 - a3af6ddf33c781ddce6b0033eb3afe64149b1e22c3298b6d - 8d18a7ab3755354db7ce3336d2ad1870d83f84efbabf3f1e; - 0000000000000000000000000000000000000400000000000000000000000000 - 943acab0e9cf4ec9267798ec18e96ea9c4953d194d06572e - 2ce3b4bf975ef64655d8bf4e56016cb2889016c1884d649d; - 0000000000000000000000000000000000000800000000000000000000000000 - b150a772fa4e01a865d822ad9f08e192a2f09e10ba815686 - d4e5f4ca1ab70dd9ba5b5af2efaa89b3a273cc13dd63bc5b; - 0000000000000000000000000000000000001000000000000000000000000000 - 685d0a283480caadd55b2866fb4a0a41b6c7cd10a178c267 - 4e8943a076e33ac2517b897f25f5e1b946a421676d59866f; - 0000000000000000000000000000000000002000000000000000000000000000 - 6adb8fb9971688de77028f21a600d2ec2e7ea7469aa68f49 - d25f5e79e204a87897d24530d30e7fd55f852298fe41b993; - 0000000000000000000000000000000000004000000000000000000000000000 - 34e213c058fa256f43ce41f0a636f04d6de70d66fe58fd7b - b5a6056e1a9fe00af39fc4f6dcc737bfaaf953b94c3d7d62; - 0000000000000000000000000000000000008000000000000000000000000000 - acfa06bba285a64d49b3e40fa21a87807bab2e1b8be93dc5 - 9c607c350a79fcb9c3c08482a9899662911dd9d78241e5af; - 0000000000000000000000000000000000000001000000000000000000000000 - af8fe6e769d9a9de9103857c73cfc48caf07a0a162a9c84e - badb8bf3e3901514c364d5ab4fd71dbb4adafc33a57e0dbb; - 0000000000000000000000000000000000000002000000000000000000000000 - 03e0acc3efbcef91c181e6b725efe6d5988aa3fcf2d97918 - 3562afdb394cb6c829361868d3fe9e2a795dc73d6650c385; - 0000000000000000000000000000000000000004000000000000000000000000 - deefc043580767155330551bbb6aefbfeb83f2a53645534a - c8162770dbda0fc2e009cbc088d52b75e0c5b3d8c3aa935d; - 0000000000000000000000000000000000000008000000000000000000000000 - ee46ee36468537d3eb9a8712e6ac1658c502a2ee5f3b9dab - 9f7aa36fec8e73e4e31f29bae48a0484eae73f9b1afa9eb1; - 0000000000000000000000000000000000000010000000000000000000000000 - f724e6422f7b27fcb8f589d2c1303a57c1a029486a5049a9 - 04ba1444c6b13adef4ca56bfd9723f32813dd2e96f7fd03f; - 0000000000000000000000000000000000000020000000000000000000000000 - 3fa0e90f02790b3a69e7c89a13d6237f2673e06ee8350c6c - 68709de5c53ea86e2ddf950a5f9accf42013439e1528ffc2; - 0000000000000000000000000000000000000040000000000000000000000000 - dd0a534025a9e27706db2a670c60f0b02dfc511b1b96bfd3 - 195469451086eeeec709c9906f70dbb4b1f69bafbf3764b0; - 0000000000000000000000000000000000000080000000000000000000000000 - a4da0b9a38fef97bc79f467b2f3377e146dc3b15803892d8 - 1a60ea09b20c6f489204d8118b122c5867833c7ef3bfae13; - 0000000000000000000000000000000000000000010000000000000000000000 - 4ce7a4c772c8f9ef1e4fd4702305e22a16658796d594c785 - 2bc89b262839d2e7c5a4d6c6d54d2c12c3b6f393f74911c5; - 0000000000000000000000000000000000000000020000000000000000000000 - f8bbca32a6f4757c7f11f4135ab07d44abcf888c01104279 - 92f67af3b9e25a74c087616ff87b74940ef2e13bdee48a8f; - 0000000000000000000000000000000000000000040000000000000000000000 - d7a63b5010a345f136e5410666d62c0d0db6c72a14cb0e40 - 480a96adbe7e4e18fb726976e153421b959e118d53db9782; - 0000000000000000000000000000000000000000080000000000000000000000 - 1e73ce2be743ce28821a6f9fa91746ec106e6027ee10813d - 4c295b3a21cc9e8fcc591dde212cfd4813bc12add97b6c5d; - 0000000000000000000000000000000000000000100000000000000000000000 - 3eaf2b1202ae5b92708c0ebac3f190c3716ef8c42f7e3eb1 - 5cd7adf3e81c0d0362b0b2d6ff1ba5a8c2bd1adae8e3750d; - 0000000000000000000000000000000000000000200000000000000000000000 - 5fe4c2d04550aed6b268726c60e2a3bdaee377ce8dded8f0 - 3c1c3483e260bec348c8e0efde742b41d16f75054171b1ca; - 0000000000000000000000000000000000000000400000000000000000000000 - 4571854265e30e3b8f55932f432def3e8c817608c600871f - 290bbe7940b15a6f592caf95508152e4016adb9a5ad04a90; - 0000000000000000000000000000000000000000800000000000000000000000 - a1955f1a9e1c293f46422688b749ddaedac0de5392039212 - 2eadf68986a238b85ab9576d1fe2fb8dc0c166f574ba2019; - 0000000000000000000000000000000000000000000100000000000000000000 - c0382ec488cb6cd0ab2ed8079e57229ca27219138da9ca68 - ed3ebf43bc1b7b5f4ee91e71d07b2cb4eb3f661cfc31b8ab; - 0000000000000000000000000000000000000000000200000000000000000000 - 22eeabdba671f4cfe635b615c4cb4f759263bd01ee087152 - 8d38f4ef0fd7b17469f70779e40c45a58b862d81bcfbe619; - 0000000000000000000000000000000000000000000400000000000000000000 - 10da653a6533ea959ac42304fee9983a673ff5fa6e5fe9c3 - 9f253744a1337662c662f359128b5446ea5d9f24c0bd9ec1; - 0000000000000000000000000000000000000000000800000000000000000000 - ab7f47fcb791cfe0d6fe82904f63653e747b8930bed679d4 - 862e7a3bd1cad80aeeec6510428e173529e4fd5b1385b8f7; - 0000000000000000000000000000000000000000001000000000000000000000 - 2fcd824a19c499683a7c43edd5f5e930d5ada53282ab92b5 - ba1f9df708477b5e0ffafa8e17af2c78b45ea8dc9f960ce0; - 0000000000000000000000000000000000000000002000000000000000000000 - 8ac9cec56baa8ac099a09910199e1bd22b8a12b35b9825ad - 1ab5db73d52b33050688969f6048d74c1f39e1a019481850; - 0000000000000000000000000000000000000000004000000000000000000000 - a2970217cd733f9e3a2fba569b5c69549b1d85fa0762065e - ae252ce23450578857e504ec52b91a452a44ee6e284e2fd2; - 0000000000000000000000000000000000000000008000000000000000000000 - f13b417168c5175dc741d3abff665b90323806d25a7ffd1c - c95a2a90eec8869f2d9c3274fc5c23ada2d19576ff61ee70; - 0000000000000000000000000000000000000000000001000000000000000000 - 5fe138aee8e0a7ae229395928700fa9a37f51ae1ce8a7d9e - 16bc8db3599524e304c3b1315c953e244bf106019952f465; - 0000000000000000000000000000000000000000000002000000000000000000 - 072a6b141853fcd7c03087fb051ca86c2999e287a19acc06 - 6e39c731cafc7ab8cc4302937a6eb2f48d5b69f59a8ab6c9; - 0000000000000000000000000000000000000000000004000000000000000000 - 6e61abf961c86ab5d8ff5fdc86fd254077c50b20831af694 - db7d8555b0499464c07e8046d2424702977304ea2ed3dfdf; - 0000000000000000000000000000000000000000000008000000000000000000 - c554b1f1bb02a20c71ccc3a5844cbdaab6ac6065f1981773 - 3ab9f2337b4b69e8cc3074bed8ec371642f191e4a504238e; - 0000000000000000000000000000000000000000000010000000000000000000 - 51b3412d7e6cdfa87026451d611b398963ed0f7914be657e - 8b4c78acb1464f76d7217ec4420c84ed8914426b96e995f5; - 0000000000000000000000000000000000000000000020000000000000000000 - 4e2b6793fbcb06050191865e6cd61abdd7f3cb3cfa0a198a - 40587eccc2c8c15bd735fc22c776f16c18c019fb7b4b04d9; - 0000000000000000000000000000000000000000000040000000000000000000 - 9e32130b3039abe1c5e5b26c41e633218e7e17be20463769 - 52e3af3dd33eb613e5022c26a0e97b3a43d983db2dd3d8ed; - 0000000000000000000000000000000000000000000080000000000000000000 - c18d4991afb0f844fe4430eb4ceef9600f0707f526d50cb1 - 60f22bca3934262d0d4d8f8118df4325b2440a2cefec2c8a; - 0000000000000000000000000000000000000000000000010000000000000000 - ba1c2f2d4855d9bffc68849e061cb23af605aad9e1ca459d - 3f9c6666ca2497aba5f22dc6d49efdb97e63b7e05de5f3e6; - 0000000000000000000000000000000000000000000000020000000000000000 - a58dadf4b734ba815d34bb5fc543b46db3b427f2f4d89c3b - b0c10ef8e3a3ff48c57b8f1b60d0b10b5b4f2121167e8d1e; - 0000000000000000000000000000000000000000000000040000000000000000 - 34b7ba1db271bde528765d75773f5956464b714d9c994878 - a0e25defbe4b845460e20fdb066c63a1e4593c63e88b6b8c; - 0000000000000000000000000000000000000000000000080000000000000000 - cf5cc81f0e5924e5c7503f919f137c50a7f59c664a36f278 - 0e3b9fcea7afbbb9c756a53d04c8dc3930bdbbc219b92e0b; - 0000000000000000000000000000000000000000000000100000000000000000 - 809712627c15317a1ff6a5a53a9af3726209d3dc74f281af - 9e4ede48a23fa258a1c7550087bcbf7cbc1a0239b35900cf; - 0000000000000000000000000000000000000000000000200000000000000000 - 6dda715bb1227452f50923799bf245029bee7eb6a6203b41 - 4987a0919df53153f00e23d8eb5cc95b873c0ad9b40f3c46; - 0000000000000000000000000000000000000000000000400000000000000000 - baa6dffbedd6c9bd75b929d444800382a3fd330d43eefb50 - 06f07bfa7811fed5de8eb93a5c2b28ca90558c62e4821ebb; - 0000000000000000000000000000000000000000000000800000000000000000 - 9327fe772c60b53dfc5e11c56bad70b6321acdcd88beec99 - 86f5bbbd94e1ceb8cf9b07fecd13bcba73ae64951c37e637; - 0000000000000000000000000000000000000000000000000100000000000000 - 3395521584ec93e8579797d3a966bd1c2380a66f95982be7 - 4383715ed3d034f970662395f3d1f0c5d14a9cc926c5cd02; - 0000000000000000000000000000000000000000000000000200000000000000 - f9d37ca7294d832210c1e653e441007b56381b1af68ab0fa - e1cd78182664abe5ad64c6188a901ac00e8006ac7176d0fb; - 0000000000000000000000000000000000000000000000000400000000000000 - 25adde24141811ca576c77e10c61b07e9ba9fb023cd8bd9c - e04f17ea502b9ab5b0f1c7ac16affb150df42cccd56152e5; - 0000000000000000000000000000000000000000000000000800000000000000 - 8903e96a3fcb869b6ed8ebd05b41d15eeea0b1b8c175fd1a - aa89b098ff1dad397e3ac31c21cfdcaf1889a704e9ea946a; - 0000000000000000000000000000000000000000000000001000000000000000 - fcbd400b1a05a47c9ea7f1c4e52403a6bdaeae6c2a6048cc - 761b1b18c0637dfd6d55d87a4f113b68af688f81f8d4f5fe; - 0000000000000000000000000000000000000000000000002000000000000000 - 88c39912dd77f2510290e9b32fdff085e167a338862d6766 - 7bcd793c08afc09b27b95aceb0d9616d7fd66335020e55ef; - 0000000000000000000000000000000000000000000000004000000000000000 - 51208b60bc0f91bfe1054342a73ade654872554eed23c450 - 426a4e6f17ae2f29a35133cc6300736b32b5679c8780165e; - 0000000000000000000000000000000000000000000000008000000000000000 - 003625a0bb5f162b18bab7b498553bd1ee67b969a504f533 - ff852ceabb97d9928cbc671b3987a21d0622bf480f9857c9; - 0000000000000000000000000000000000000000000000000001000000000000 - 9a776d5d249c627fd74d868ca2e5f30f9578e7dc3c1b4e49 - 713cf88deca40e521d15324aca994976f1d970ed4f118906; - 0000000000000000000000000000000000000000000000000002000000000000 - 47b7a8e4643e9ba7917144b787496f6e08a7c03e17ae9c6b - 17f02b23ced0669a67d6fd22870f8f60937c956c7aed718b; - 0000000000000000000000000000000000000000000000000004000000000000 - 09702bdb907f135f8ac4564319bb91e0272c5f49f63d6c2c - 04cedb6f979d648ec677348f46b3b6d2e491b3c735791ec2; - 0000000000000000000000000000000000000000000000000008000000000000 - 859421e35f2789869f2bc401e802a7a2e5a3dd671d0dd761 - d4430b200d778d764b57e4abbd9b6f2a0bebd6d4ca76dfcc; - 0000000000000000000000000000000000000000000000000010000000000000 - ce6f45b33b4517f6de34eec218103ab52e2f7c9ee5c3d5a7 - 5aa67eb1b6382cc16467d12322af504d4a7c5c6883fe7551; - 0000000000000000000000000000000000000000000000000020000000000000 - 55e3dca7d6904f0bd898779f77eb57cb670777f8e5840821 - dc0b2bd616b31cc061911a30121130880221b4c3b49942dc; - 0000000000000000000000000000000000000000000000000040000000000000 - 29bcce433a0f89958c85cfe3d4acfcf9d2392c25c75e638d - 5cd8ef967295257dc0fc379f496f484961ee297633e64cec; - 0000000000000000000000000000000000000000000000000080000000000000 - 735d4826ff04c760e49504fae1a49ff1070648d3c7d0170c - 28961576dbd22448001631547726e7cb517df4fa6d9e486d; - 0000000000000000000000000000000000000000000000000000010000000000 - a4522ada107ea62be6bf5b5bf160b4c75e15f6ef0d16595e - b45177640fd710089c014d55a72101fc7f973bf462f6e0e2; - 0000000000000000000000000000000000000000000000000000020000000000 - 42298f9e5660dde82a88fd096bfadb44aa0ce8615f5e2ea1 - c24ccf0957f55d4b9390672e525622b9453092176e5feb6a; - 0000000000000000000000000000000000000000000000000000040000000000 - 371b0a87d047cad422619a1ab8bbf8d2421625c36eb54734 - 154be268071b1b7d6548bf3933ce23e892dd4ef599e3cd7c; - 0000000000000000000000000000000000000000000000000000080000000000 - 1b3a0995a3ea458e99eca6ce81d8d2943d3ce4036f280185 - 5e1eaae31384cca72fe15cb928e7247a289569759c92f347; - 0000000000000000000000000000000000000000000000000000100000000000 - 75bf29ac66c69352ae6cc00493f8e448e3d568327b9cf474 - 543795ab540b32b3248a0d6518e6c3b865eeaebb36e5802b; - 0000000000000000000000000000000000000000000000000000200000000000 - 5a0399a8cb30b225742bc5cdb7b19c2e090bb1e195a66791 - c76ef9568728d4ddd5520ee9876a73ca72123eaf9ed79751; - 0000000000000000000000000000000000000000000000000000400000000000 - d18c12e6527e6e0f607a6babc9848f54082c3bc3bae5828a - dc5d12790a1da64c1976d0b8d6d66d9874f0b887444ec537; - 0000000000000000000000000000000000000000000000000000800000000000 - 870a20d71492d99531323a86994e43af13c7519bd2527e6c - 02d19d7b5cc70a320bdcfdd41f9921ffe0d6742644399c52; - 0000000000000000000000000000000000000000000000000000000100000000 - 54b0a108605642493ce135710d562de7c32889b831abf8f2 - 654df69490c47dd5fff15effb5cb315585ae64cf6d8a69d2; - 0000000000000000000000000000000000000000000000000000000200000000 - a59695a3fa53bc16c5ca7fa67f939076ae5c60fe454556ec - 528c3c4bd121d39056898a0034b596a433c8e70a509274f8; - 0000000000000000000000000000000000000000000000000000000400000000 - b2035a4f13eed6a75ff080223dc8e342de3d213c294c9b2b - 823cf02821214fd46d9a8a8def8920b8fd02043a90915754; - 0000000000000000000000000000000000000000000000000000000800000000 - 7e6009fc5a9a4bcb932fba990f5b27279ddf357a71f4f8fb - a18b1ee4c68c9b9db4b9351c147bdbc901af12d956eef5c5; - 0000000000000000000000000000000000000000000000000000001000000000 - 2ea14149be04b3f717bd70eecd2c263da8bb87513c7a3a35 - 65f1bef465ed26b40bf1ffb916cbf111ce5d5549eb19a401; - 0000000000000000000000000000000000000000000000000000002000000000 - 82560beaf44f02d49699d4288779c46b26e1449b3d347e1f - ad005df53b419cd35042f844834157cad6ff20b9820c58ec; - 0000000000000000000000000000000000000000000000000000004000000000 - 4f16682c365b3b245e2ac0851460e935d293ee25ed63b926 - f155888b05d06adb3b212c988978b509c819ccffce05a3cb; - 0000000000000000000000000000000000000000000000000000008000000000 - 65130d454a144c68a45274fb5a34000e47bda215d7ef794e - 7dc0c4ad2951417bceb94b84224e2392ea24e878db411d70; - 0000000000000000000000000000000000000000000000000000000001000000 - b229d4e287009b3bfaadc07ef82c7dcb23aa3efd3ccad210 - 0d391fe98acba6abb8fed9caadddc59cc933b07eecf98879; - 0000000000000000000000000000000000000000000000000000000002000000 - e997bd8285b6ac3f3f14fbc98e8a6f2d7f310eb250a1d3ea - 374efdbadf8a357324705281c621abd460fa3bd5818898a7; - 0000000000000000000000000000000000000000000000000000000004000000 - e88323084406260258f70be1a98be9f175bd33dba86dc309 - f689401325a73fe8d162b13d808a4027360d85594700776e; - 0000000000000000000000000000000000000000000000000000000008000000 - 5c877129c311d257a8b929cdce288c8c41d29f48c7f09645 - 766bc49677fa50b1a9089308c82f973b16250d8ce85fb972; - 0000000000000000000000000000000000000000000000000000000010000000 - 3847656ab3097dbdb9f850b3eaede060015145dfebe081b0 - c824634dbe6bcc4e3c0e4814267577d0a8e88e6484956e47; - 0000000000000000000000000000000000000000000000000000000020000000 - d6722ced938f45256e6bfac3209d8afc3332bfc4b9728f6e - 510d68ab75eb49f7aa970e4c8d4458f26c76da52b97d9c2f; - 0000000000000000000000000000000000000000000000000000000040000000 - e46d2ddbc9e9cd7668f0345ecb38f4b9d033e6277c770339 - 754eaf9252e18b20b04528133b5513d0b45eb610332bbbee; - 0000000000000000000000000000000000000000000000000000000080000000 - 6b179b4be801c3c22c67820b4a0602da09b36a0b4003e19b - 594fbe016179a0c60e814192aa5acf26b8c7263288e5e6ef; - 0000000000000000000000000000000000000000000000000000000000010000 - d3b5ae53b5bbed9e11806475fb8e892abad4d0df57d37432 - 925c57438355e2ed191f44a62ef5d233e736d533c384b23b; - 0000000000000000000000000000000000000000000000000000000000020000 - 3c69bd1198742f571ba466d75f33e2f8875bca181e7c5060 - 2cbce555cb50bfbc7f03b5cae522dcc9e3a6f652d7f95ee7; - 0000000000000000000000000000000000000000000000000000000000040000 - faf5577aa967ce1b528cb3183d311a4a01fe0bcb8eff52eb - 359c1f635ba4aeea1496961d0acea82f8b287e6c333c631f; - 0000000000000000000000000000000000000000000000000000000000080000 - 17a59ff4260e682c5fd265c4c8cbb1f2394df520878d54e7 - bd62dc2010bb988cd034dc3471b8771c1e83cada3160a162; - 0000000000000000000000000000000000000000000000000000000000100000 - cb77f4cacf18f51a20b2b2a9424df516ca09da86df7e060c - 8f21087d1f761b40dc9fdc48591725f6c3ab8c996da2e69f; - 0000000000000000000000000000000000000000000000000000000000200000 - efbb6a40a6bb6a73f2b00fe2672d9d9c418be6077d05d6d0 - 11556df337561494f1a88048287e274b091fdc8c3248fdaf; - 0000000000000000000000000000000000000000000000000000000000400000 - 482e51026536799a4adde4ed551b5b37bd946806f72a1e84 - 5c83416d574c4d4fa9f844a8bbf2502a2e423e9333ba5c09; - 0000000000000000000000000000000000000000000000000000000000800000 - 3f2aba49c1d122f4fcb3fcaca344b48526426a3a11792420 - bc2446d092a3cb6c47d34d6b8dc6504e71faf9cab27d5af5; - 0000000000000000000000000000000000000000000000000000000000000100 - d64b82bf6776e07d16dad6b610bc5ccd1566a340d5439920 - 9f0ec7057d88a8b9a1d7f37e8ae54ddc286143aded0b727d; - 0000000000000000000000000000000000000000000000000000000000000200 - 10ac120667f6cc8fb3eb5e4fca09393e4d752378c1ff3aff - 84fffb34309cd0f900753a880af05503913925a676ccf8bb; - 0000000000000000000000000000000000000000000000000000000000000400 - 913aba9a2ee4d9cdbfd723b02acd5fdbcecdba6e5ee9fba5 - a6935a6a0f5be5e36a5ddd2489a849723bbf32193b352276; - 0000000000000000000000000000000000000000000000000000000000000800 - 2096ad29e264550d7f50f5225b174de08c4e33407e229ef8 - 322b672ed96a11c24452ab02e5bbfcbd8d2c055dd4ff1502; - 0000000000000000000000000000000000000000000000000000000000001000 - e2fa3c20c1c3697f0fbef257014f4a0851c7a424287f58b6 - 3dcf94cfeeec73127384a8dc89d1de1791c2bffa516848e3; - 0000000000000000000000000000000000000000000000000000000000002000 - 25d94a019001c3a4fd30bd51206497e094942ae9691215ec - c52be65c97df81a1cdf06760d79bdfa04a8a11024535c51a; - 0000000000000000000000000000000000000000000000000000000000004000 - 20acbb4cb8509b255bf293e116b32d01a284c10402387352 - f98ab11ac1e9fd49d644292f7e70d78bc8528c5c85afb7a9; - 0000000000000000000000000000000000000000000000000000000000008000 - b61f153afbed502f9e64d13a25107529e614e39b992d3d22 - f720e227475a727d1e3f9ee9bc7d3ba079ce32d076a2cbd9; - 0000000000000000000000000000000000000000000000000000000000000001 - 1621dca63b7555e070a05b5a265a0ab530a79e71542ed333 - 220384f259384d523e7b0328739f608d976b2498cf77c7cf; - 0000000000000000000000000000000000000000000000000000000000000002 - 35ed02357b26181864f5de07718913a33ed9fab93d845302 - c7f8b065f6bd6d800c8881040c68828189979be2c86abe64; - 0000000000000000000000000000000000000000000000000000000000000004 - e0cbbdcc0724419ab098dc25606c6277160215eb3a166b5b - 106d2fc9c5e5d2f8a7e6ba7db2a4e1927adc2ab6a26d20aa; - 0000000000000000000000000000000000000000000000000000000000000008 - 2879e25e570e536c936c8bcd66bd780047b73d53922933ea - c3cf14d55169ad5281175057db3a614351dd78ca57c9ada1; - 0000000000000000000000000000000000000000000000000000000000000010 - 45ed18e18449285fdf874b675784b18d412e504075c61fcd - bfb1f7d80745dd69a5fd479fe14c449ebd1ff19501c42ccf; - 0000000000000000000000000000000000000000000000000000000000000020 - 3ccc94e3f12a3e2e4321e397300aa6444ec21526098b0eaa - 0ac9c1ae854812f92615b3fc45e65c945f3e1ceb8efd4a9a; - 0000000000000000000000000000000000000000000000000000000000000040 - f300d3a47eb7d9bf3215140c894b4e8888040541424e4c11 - 74587eb6e7f9b2ecf7bcd8f63948ad0417f439f8596ad52e; - 0000000000000000000000000000000000000000000000000000000000000080 - df6e46c2dbf69f357bbe22bf604efca58a7352a18f41a7ad - 1d5fa8d85dc2428dabb69eb4c9cea7180f2fa554eadb9dc4; -} diff --git a/tests/rijndael256 b/tests/rijndael256 deleted file mode 100644 index dd93096..0000000 --- a/tests/rijndael256 +++ /dev/null @@ -1,2886 +0,0 @@ -# $Id: rijndael256,v 1.2 2001/06/16 13:23:19 mdw Exp $ -# -# Test vectors for Rijndael - -rijndael256 { - 01000000000000000000000000000000 - 0d166d15e764fb6bc005df25b169d93f1cc03580e9dd4a19c4bd7cd32e6ca03b - a8dcbf6ab9a5d693428c82d2de78a4fecd75573d00d25a1cd7723a3897521c4c; - 02000000000000000000000000000000 - ba36af55f2b81650aabe5f1496e0675bf42979ccbe66ce7e9dc42269c8a40378 - 710168005b92abf4e5fc36d9ae0aab11a872720aef853e37d7a929bf4ae023e1; - 04000000000000000000000000000000 - 79c77f01ae4a137b07fcc8be95693b7157b55aa02bfab77bc0ebbf7b383dfd9f - 1b82ae9934d5fd2ee151529c7cf17ee653ad859b80d1ab1a02b31f23e17c1526; - 08000000000000000000000000000000 - ce6c53e5ceb51d313d95c7831966807d25eac9fbadd3802f7bfbff4f9cf2dd51 - 1263853b8b7f61e02cc9568c6e925b79375a1d7212277bbb44e15aa5874842f3; - 10000000000000000000000000000000 - be529de8125596ed7ef7621e6fa1ea17343eb9b3c34181484e09af18dcc8343b - f91c5fd5f8fe1692a9cd403531ee7643ffd91de0a8238e3263f361c22b31bac2; - 20000000000000000000000000000000 - 62bcd58193cc12ed08ce4a5b51d3a679678a1561be6a805e69e1f1b2da45e7c8 - 9d1ee83ac951bece4f9535b1f4d461b99960b0021be3b8d4c8d20521ed3978c6; - 40000000000000000000000000000000 - ababd0ea311aea38cb364d367c27462d7c7c874cd8138dab3d8331d90c483e2a - e360e0bfc704c664550069c9c675304dd24121be987dd76b7e718f8a1aa2277b; - 80000000000000000000000000000000 - 93b811f0e3bf6c0b00d4f8002783ce01c24ac3671dc198805aba8846dfebb288 - 1726d2a0c6d4d7078322b48824071fc4c6226b8a10bdd8d09bd6b90d5cff9812; - 00010000000000000000000000000000 - 8b9328500908af71236b5ed841a9e177fac26c81034dffb99e89753de0aeb4d0 - 1ae78759e134dbeebbea45fe9a0a66174264a1efe55a87569fe1a1568a28544d; - 00020000000000000000000000000000 - c5c7c19175d9ab800bf358d066f0da2e86fd20ee6ba4e5cfec1e8b1932b42466 - 7b0069d82b61439e71a7cc911d3253f71efc8da14244dddaf323283c9c99c123; - 00040000000000000000000000000000 - a5a088b14f876b6291f5a92993540f972012b6e8a0eaf2ab0adaca3b3410c888 - ca33da2e73e8a8f62fb2b6c23f59a54363fff8bb3c806c6c71e1c22b6f90c81e; - 00080000000000000000000000000000 - 9c482dd8e9e514270d153a310d4179166391ccc10ff594133d2b023c307fc951 - 3e0d22a6e0dc4c5952b417ca6edcab1edf6438fece9e4d05a409d0adde7331b3; - 00100000000000000000000000000000 - cbb011e00200dc67a685963f6dd64373b87eee0e1db3c2c3b9f31a290682c7e4 - 4a71ca431d8e66467b67a5dda1c759f4e5a70eb6fa990d8621fc8c107ecc31ed; - 00200000000000000000000000000000 - c134cbc298d7fc2a3df295534c5b51a810999bc66c64ce5810086ac896af12aa - e21d816bd83eb2ccee4c12c0060a07b5a9b1f52639e957db1ba3c94b0d1ef5d9; - 00400000000000000000000000000000 - 00d96bf86467d8eecc800930d9ab0511252f62ddf77a2c6fcf560ec64a99992e - 8f8cb84f6ec8a751a2c52140d1aaccffd75be6f0750c0f4300d8a95be1497d13; - 00800000000000000000000000000000 - dfbc41532baf8d1ee9c00f40cb9dd9c9970949d182a651af9809ef097d9f95b5 - adeaba98648d76d63be914a169821e4b6b816965082a56c64a2600cd0b0ab1b3; - 00000100000000000000000000000000 - 3ec45f406e61c9c862add48b59e2193a9e044d8450dcf06ec9781ea54b25770d - 0cb3cb766c1b3af62594b5beb5f794c537fca3ef3a7aa34c19965d194d616590; - 00000200000000000000000000000000 - 5f63e9e91b5cf923dffa47b0430c9c5741e36bbbf2f7561e5e4522a9dd086f59 - c8d48dfaddd6db42fb88d5e5a774d796ca0ccbd2aea63ed8af958be542577c60; - 00000400000000000000000000000000 - aaa49691c18a878cae6d8ef28cea273d39a85d65ac6656efadba875d4de8dd7e - ab5274393cec473dda0b9b0d150c3119a6c7c7c5f546bbfd48be3fec8e0b5ceb; - 00000800000000000000000000000000 - a7a1884e2e0ff36211f92ececf5d10a026f0d7fca3ec36bb4fdb3dc39c8b0286 - ffdddaf16fce3a8ee9ffaefec4f86d0a12b153b1642147201fa93f0165d95786; - 00001000000000000000000000000000 - ca7d8e1fbc8de0b208ef96a731cde9e71447c7976a7b4b70f6c6670c3683825d - 373578f19f83d5af1ba61e156754fe0b8210d75b3b94e4ea7c94d51f2c6db580; - 00002000000000000000000000000000 - 82e91aea18e826867c8df83eb68d783f70792019c350859c4c6eddc40017aeb9 - 01ebc069581ee246b6f49707ea3d5e0f7b22665c40f111963d2e42f45c937f95; - 00004000000000000000000000000000 - 46acbcffb692d63566c52fd7f0ec13199b07b747c75d5edbf1a3f684b51f634c - 3c1563b0cc61be41ff454b2b1b4f7dd9b102efd860a6e60a245391629963440e; - 00008000000000000000000000000000 - 0ed05e750de5f56965775ce44dec375ab74d16c9537df755ec21402b3a10d0ce - 662e2d66cbc1a9018e142430e5fa0093dc5aa33d99e225944fc651d0234424de; - 00000001000000000000000000000000 - bba5a7e1d984cb9c1c37f664632649363524e1e2206ece1d998fcc2706545d7b - 889def781d00c866e878bec6965ff82def729be52611d0b805ebdc97541a63a9; - 00000002000000000000000000000000 - 99da531198516629a6c5625c483bd08ad864b54914efd29982737f6572076b55 - 40ea49fa08ecaf017df5e73f9ecca8c24bfddd40327add7407badeb51d551f21; - 00000004000000000000000000000000 - 9c7e2c74e8a14ef12e6a8106608bc3e70206ebd402457cca671e6804ad55648f - 5eef85026cd49329caa947624c88c91e27f817f8d01768b98d121a69d9cade76; - 00000008000000000000000000000000 - 53e1750bc3bf2cfd3ee05caff29cd98c56cb32ffb75548c8b3482a266b4a1067 - 6236cf6d9974e50472854642a529c86ef62599e4172e3bf5d12909721a6e606d; - 00000010000000000000000000000000 - 2cf3f5109eab2d3c501f70b3ae1fd8c744f1c1dfa41f34921f55a3547c76110f - 6b9f52bd5d1ab2d483a614f590f571b1f086aa63bfd0c197c02d514d03a7f695; - 00000020000000000000000000000000 - 81e041228896707809dec23dc43f023ad3a8b741fb097158de5abdd9e8e63e2a - bd80f493cba17cbfd79870c1fd0f7052ebcb07d19f3b7101e6ee9a64691b0e33; - 00000040000000000000000000000000 - df020d98627cda7f93bdda5f2544b46530b645ab1c619583a8d34ece8f0402e2 - d56f8c7d45ced4bd015c413b5076cd494ebf0ee3c6564b1c8980b6db9f8ef18d; - 00000080000000000000000000000000 - 3f2a2e2d05337597567e45ffff3644d1b78d446e54113961a282c63693137ddf - ed749629bc2a4d3a97a678bc810913458dc7f06d181e6c2ce232b01da705cc59; - 00000000010000000000000000000000 - 7276b5b02da780407cbe4a9feb17230e308d01d37c2d50b2f357d2c25342736e - da1d5b5238aa6516f1bc3982e6a22d18a404645edd961251d8242fbc639ef442; - 00000000020000000000000000000000 - 94df6723a4b7e8a3c548a794ae9dd2d44c2596e6a2b313f4caee48b2dab60d0c - 9b760a577ba48b855d2787253507b5405745ada1060c99ce476c3cd5863015b6; - 00000000040000000000000000000000 - b0942965db151da90df6354e57d78c3b0e6c31e624c610dc018d3e1411c13239 - 5c37701aa5d1d0b1681ec86eafbb59f8acca725816ec73edc7ff34a68b1414a1; - 00000000080000000000000000000000 - 4193eb057627735cfa1e3a6b1ff107898c1df42499bdbdb50999808a4443c616 - 2048e754d9481745d95a3e6b4d54cd7b3ca5c09fcc27f22a6bb3b411e4213ac9; - 00000000100000000000000000000000 - 6496cb3d2a6d1927a86aeb9a81838b7782554d67dd17da1eb55d86e680f18a67 - bf66014d7eb0b274ca931b913b1a792f9b303b6cb1581914f7d12ad92cfdfdb9; - 00000000200000000000000000000000 - 5f2e0aad9d2b66428bd14e92e04ba45c1b2c4d8a3626af7e14ba88ed30a939b0 - 53359f5e143fc6c5ed119106f09ed6020c07a840f37c881a19fbb664a2932912; - 00000000400000000000000000000000 - b7ac23c7ea16038b23ff99fd8471a66173c72992009d67c136ce635b6c9d9a0f - 9c1a45cf93c6c3eaa67f56c6fb0004ff9182d4c76cebb113a297a6786bc3a7e8; - 00000000800000000000000000000000 - 6af8fbcd1498dbaf169b3c6cbf99c0d954f0a6074a391b50ceb179a25b76a4d8 - 4f6042a77083581ff33c731111d3040fb551a9139bedf5266b83e0bdf5f4e9f8; - 00000000000100000000000000000000 - 66af8d706d38d51808409619ee4672ad39c45025094bff004dcab2d29057ae9f - 5866f66669833af9565097ab80f6b7ab00acc862e71767cf94e7c59dc0645ec4; - 00000000000200000000000000000000 - 6839cd0cbbd72732d67074d3573594cc7db1285aff8e8c2fbb8eac3d0e22b3f7 - d5df2fc8ccd2699e5af63b16538339487a94145dc1ed775fbb852b368106dc15; - 00000000000400000000000000000000 - 4a2afabea926caf55464e6508976960589b0681c0f0c42f6dabde37b3f2c2d7b - 8b17b2bdb951c39d359b5ffbfe5fd62fc5cf948652429c43b3a580a044fc2202; - 00000000000800000000000000000000 - 75ae68f8e02256da8395c00d1a79a398914aab74c1aeb6a1fd49ffa1e25115b5 - 182317ac645d381058cfb6582eed55afd1c41a01c1ae6984f475c1c9829b51fc; - 00000000001000000000000000000000 - 371cda9a5c73b8faf952ce65d226947fb69d22412669709a3759279e3b652b30 - 3d4b5768c554b31a48a8f2493aba5267e7ae2825a224e7fe296dfb2cd18826f4; - 00000000002000000000000000000000 - ee23c425adef80ebdde63fe7a6191d8065d719c3d24fc8939956225a3e4d9e57 - 67aa7cca219754c484451c80e76329984eacb8a664bd122ee7c81133f0448bb5; - 00000000004000000000000000000000 - 781a2bfdcf0f59ff6feb06131eaadec6b3f86febd94e875be5b88262d9a61e61 - 90e87594d441c52f3b940079b3144b16efbb7da652f85ded012e72df45c5f947; - 00000000008000000000000000000000 - 619835ea64b097c90af092514b6fdd58a5773f4492148463c98a2422e6d29ed8 - 94cff55bfec62839a98e2099bf70024bfa3f36ee382d79273da4cffd2af262c3; - 00000000000001000000000000000000 - 089af763aad8339e9a9019899dac708f9edd78d984d42105b218191e4547ef1b - 8f5400c80a1a6944e1494e72823013571bc53a7a0da4ca876a34aa3fc923e431; - 00000000000002000000000000000000 - e8da39299778df8feabfc548421775fc8ec1d473bc24397281c1b494fe35bd97 - ba3a2f4ad75c1a36d8ce2488d80d9a7c37886f0f25cefa6f906c1d3c97028c9c; - 00000000000004000000000000000000 - 1b6dea579c09a10ff8296c9d2fb29ffaef89169a901f48a1de8d1867e71bed1d - 306fc026f4f82433051bc469f6b4dbab3840332f6069a91df2cd5f8fa71779d5; - 00000000000008000000000000000000 - 84ccdeb939ed5ac41671c7c60404991c4411b5ece49d01401a10a3b906381777 - 5ac3702f5a3b7d54d5cd6f60fb5ba7f4eef23aac98c068f706042c91f7b9c8dc; - 00000000000010000000000000000000 - f05402b141f7578d2e7190d607ed24c60d169c798c36dbf510f57c106b4796a3 - d7853ee992f541e06ec1bfae4e0ce59cd02ec65130dd2c5b25164325ff72a89f; - 00000000000020000000000000000000 - c225cd7a41b66da52a753fd620c04655e1f5028857f5004617228d0a79677ccc - 44534e3a429b02d1280c784bc3d43d3f3f7d68a5c1e4bec773bba7fede5b539e; - 00000000000040000000000000000000 - 5b02c15dfeacdac4a847dbde35f251aaffc17704bf8727a5ad53f84d0315a405 - b9520766f0f67abb9e3a879239650cc41d90716560d83f6c2115e62c67ff9bd4; - 00000000000080000000000000000000 - 397b5b0ad0d8540d90b96a293e9e3ebffbb2ab2272c93f5c854a1316cc45fa00 - effc84efef486e591669f535d5cef87b0cbb224b7e33e0068b4d058a8a81b4d0; - 00000000000000010000000000000000 - 1e8942d564866774f20a8abe42694994b281278037f373b5c867115bfc8500ad - 052566319e8cfe1627f10d5ec55ec4eb50cd1b8e82c7bc9859f7b1ede1d2822f; - 00000000000000020000000000000000 - b71ca147cb496c3c65099a87e63026aa51d044ce55145adb861f1d473c1d856b - d08a2b0bc7ad08d1ff0a4b7f5c285ea9df8b7583536dd58f8d184f9c7a657909; - 00000000000000040000000000000000 - c048a83a291148835727a9792e7864550e71812eed389d97c8bace4246ea75dd - 0af26c6f1f02650ab2532756ae34d59d8580310cc4c3c26f147ff1197a6e09eb; - 00000000000000080000000000000000 - 4d425145fd1166ade64ccfd5e52734ebbdc31ad4512f74e4a7e5e3e0d24dc18d - 35855dfc6ae18052f682b171895f775aa94c293dee1512635f1ed5216fb96558; - 00000000000000100000000000000000 - 9ea4fddb10565fbcd92c352fc81fea49a755a3b64e98ace666f81f42678c33ee - e8e17030571a18fb74a91d93c8d2907a5befb7f0695770d203965b25984c9238; - 00000000000000200000000000000000 - 48059d5828c995e546f8bc6579a167c9ce53d6fde10cf3b7d923be137093aba3 - 4bb16948d4126f77882f10aa89876c55b80b390fd516eef2fb1db6c1527b28c8; - 00000000000000400000000000000000 - d3a5ff5dc944cd7944103104173b40aab097ffd6973f7cde14a001c522818872 - 247d0b74d7149225a6c05f832fd51e221730ee857b34671a4b9509cb2e2bd4da; - 00000000000000800000000000000000 - 2883cdec39ade0aefa06f3d046ceefb87df0dbaa79e978af5828c429d4fcdcfe - 7ad775fd0742338854dd747b5381637ca5260c90e3954774cb4a2ae8c5a0b92d; - 00000000000000000100000000000000 - 8d09a89b9bd6428d8461d17682b84cec190cd76a230fbaad63179ae678106aa1 - 11762fa2295143bccbb767f201dc866258bc600c7ba012fbe8caa8fcbf493790; - 00000000000000000200000000000000 - e57182f9cfe9d9d189e3d679c02e5102fbc6b7fa449357739bc7ad2c7b479214 - 2203765631ddd429485e18f78dfde1b869195f81d8366f352faf8d48dac3a7ad; - 00000000000000000400000000000000 - 29e7e527c65204a7a21ca5db7b9a4d9e3341a1af894ec0773de2f3dae3d3143e - b87c10b138e84a56de01841ed2f73b15d192500e89337e964025ebf6f6387297; - 00000000000000000800000000000000 - b6a6752bc5bee6d41ccc022092cc46b27145fe2902091c054363cfb472d48b81 - 43352f812f48951dc628216466304c09d1f03b19d807eef29a3f720378777241; - 00000000000000001000000000000000 - 278b6c69b23d755bda9eb003a50fe7a928a38d7c9b85eb71692c79d7e0f0800b - dcf964dfdd2ced07b2aa36622f1fd8b7d222d02f9acdf1c1acfbdff9a0199b59; - 00000000000000002000000000000000 - cc50d65a6a9184a5f14102010cb4600393da166d264a605150b1c0718f1e04a8 - c22ee130cb19ece6ba705757d6a416abb709c691898293d31eb66a72ebf81549; - 00000000000000004000000000000000 - c0ce6ea99eeb4674828fcd37fb65e7c2af9ea924a19d121a7f940a026fd2dc40 - 315be95dd9b189d192c5c9333a145d8897af5ad256ff8026fdde53f841b99756; - 00000000000000008000000000000000 - f5fc52f270dc27f07ad2780891d9995c914f8931dc45f6a1fe423fa5fcfd4a1a - f3d2d39afaae2eb6bb9cfc255ca09ed8c46152e75d13f6e2e9f818a94b9a729d; - 00000000000000000001000000000000 - c5e467ab0c5dadbacba076637d3ef4a54d1f086612b970b78f562980324e2d31 - 9f1e48b2dbd80ab69f76fc5e827653dbaef521afb5d6949351ebbc31f82c0a65; - 00000000000000000002000000000000 - 34abac049584a4d1e29bdb7c08ff7ca43dea973e6bbf196ff470d43712610a9d - 676e22e0c042aab946ee5d009cac02b91c104bf324526c39e6b3a8ce57734ff6; - 00000000000000000004000000000000 - 701c6d175096e7e8ad4187c1b592cf81db897a54fddbb542152c7d50b3f1b81a - 77119d05608366998aa3b08e473f4bfaf9e694bc15c15f73e8f33b3fadffbea9; - 00000000000000000008000000000000 - 4e98b3ace7c111c1e81f6f2b407a934877a1c08fd0dfa9eb80698d985d68fe23 - 83c58c3066f0c4feff1d4d5a098afd3521e30fd8a0ee221a80671ab1c17f40b5; - 00000000000000000010000000000000 - e1b4125ee35b0e69f1aac9556596147bc526647375781e1926732976a77f7550 - a341567706ab2a2cb79adcbccd39c81eea1e36e1e0eb8f118a9fbc502eeaf105; - 00000000000000000020000000000000 - e479c9546ebfad858cb2353808aaf1a51b1473f229f81e13e1b5dc7cc7fef349 - 572915a2eeb3dba77a3596075313d43709e01baff1e591bcbaa209703d3a0bff; - 00000000000000000040000000000000 - 6ca46d724403120fa8517f40a36eaa1759653b2d91cc9107c2328602d04ace40 - 4785180fd5f43b9941ba27ef0ef72eefddc77c9dd6ad7ea0f11211b8b55e3025; - 00000000000000000080000000000000 - 32b9348cbb3eebcafdb4716b69b73b0677e1e5e3e6e68758615809fd06a15368 - 22d90cef816242b9dcc7fb7fa644eaf9643da10bb1136cf6788178aac1e532a9; - 00000000000000000000010000000000 - c3ed54670a25cba194830476ffb2f5d765d5dcf476235a0e7df9f405a8679771 - caaf44da13d9a6a68c162810196a8de1facb747efee5d73d0916da3c4828382e; - 00000000000000000000020000000000 - 7e20b32d7ff48cd1be4108dcee7c9e61c99d3d23a79c770a3aa10853e04b0dd2 - 75779c17a8ef0d15cb1eb48decdf3d8c3823eea7c8e75b8b2393b898c4c0ca6e; - 00000000000000000000040000000000 - 43adf9131d705d4a66e300af90ce15d82574e71ca62988ccf4cd03a460518889 - fdbc8f6097b19e5ce90411f88acd3002d27270de234d79d8808b950f65e3921c; - 00000000000000000000080000000000 - 93f2c1b9a55a325d39e769b23da246865f66e15f25dd6f84f44e58ecdadd2091 - 06db50bf315c02892d1bbb304b63ad876b8123cb87a9d1c4b1681abac4a6230d; - 00000000000000000000100000000000 - 39bcb5eb623be3e37858c37e7ee77a56f7983b4ae246658264b760e77242437e - ce60286ff551c33f6a96510bbd33632721db632291c54543b641b0de5d0045a6; - 00000000000000000000200000000000 - b1e70576e01c1f029dd9b309670bc41161bb13888b1c93c6f8a0fd2f5a6e7fc3 - 45e345d2b2610909dc837aaaf07d58117189369c8e3bfc5b718457083a61346a; - 00000000000000000000400000000000 - dc8af5dde236c0d2a18ad310a21abab9549a54c4b3f16d6e3433578f35f04322 - 94580e73b2ecb615c73fced8aa1b14180068b8a1aebd3b677e1d37c21df4abc0; - 00000000000000000000800000000000 - 53823c917b2dade044551689d7f703fa83f31237af4f4687016c4ec13f435993 - 1bef0d32e4ee66c805f793553852ec7b803b300c5434215cceabd276fedea323; - 00000000000000000000000100000000 - 2c5d0e5a610cc3dafc0ea2340d8340667a7870ffeaa2b88056ce23c93131f9cc - 5e73c45a4318ac800e3459af74eb3fa7a2010b3bbd53c9bcd51613fc63cc79b2; - 00000000000000000000000200000000 - 118d26d3c0856588f39d2f654eff64ded5e93fd1900e85abbec0a2c25cfce7d0 - 20d1d578de49459eb928acf39f46dc28089dd3972e57818e0a49f46c6d0576d2; - 00000000000000000000000400000000 - c1253993f9b3f51578f16f5766161b3ff425cf569432121dad3eb9623b9ebcf7 - 9acbaa6aa62d50751f95583545dc3b83c235e18a2b868f4d866e86417c75a22a; - 00000000000000000000000800000000 - 538012f59baf81597c561b999827d7e177542fda70c9b8a20180042cf49f0511 - 088a9449af39cc0b2a88863fa939f31c8730e696ae260a286e8e5f725167e725; - 00000000000000000000001000000000 - 8e058aa747ad629433aef87fa710053792c9ecfd6f04f749aaf97bfe280707ae - 70add57b59bd76f07688c0d9753dc6576301471052885ca8bfce36a8ae17a7dc; - 00000000000000000000002000000000 - 54eea8fd10d61d8b8edd62f26c4bfc47a1b444210c1550c7860cf558de3f3e02 - d22c759d1cf0da43c9ad0cc3ab34fd4c0d24dd4f0a12050af976705422abae39; - 00000000000000000000004000000000 - b117f239922fa9d89f9a0d77d212f54a82c20b14d2031892a1215ab70dac40b6 - e9f9ec1886337f55d43ed990227687c796aaf978af708ca6ed2308e4b706a2a5; - 00000000000000000000008000000000 - bd17e0f86d1043e1f48b5e3bd2267bb9d1834d4c710207deb618b9786610c0e2 - e251c120f7141aa0942b275c26e487212849330a798f392229a2b4909b97e9de; - 00000000000000000000000001000000 - 62a328c617554b9382aac406ecaa84370fc28c0b600711ea2ec5d132231913d6 - 568c846b732c9ec98cf437fe67a223a7e7b63d42b20e57fe95572a2fc6cbda10; - 00000000000000000000000002000000 - 41242d5ab9cdf29b78ad952fe5a967918df393d64613df7145adc5f540ac163c - 87b5af373d78b9edc963cfa1f2b88a55143fe2996403cf6b12ba4d2a4de0dd95; - 00000000000000000000000004000000 - 8d075e35e0cb14e23310bb213e59c416d35bcdfa548b7e4a45ef159c10635532 - 57392072b104f59f65043656c14ddaf32ac366f0cdbedffa7c5482be297da5b3; - 00000000000000000000000008000000 - 01a45d81b5100e5d8971525bf21993c8d18d637b17d91b5d704c54cf081ddc60 - 73790c7237a1eecf35349452f60d4c934dec2a3f42f4bcc4939e63245bb97882; - 00000000000000000000000010000000 - 09843cdeef62a0420a74674575790d67934f88dcb8492a6f15aff243c8e15e4f - dc36416b1f0a13a0270816309d20507c6479f735acb3b35c0e5700c5349d07f0; - 00000000000000000000000020000000 - 31612d05a352c54e516e379767c096a79a1c4234bd17d4f46c73205980561b8f - 9370ac5d3c467aa1f55b94fdf7b396c2f2c425d65e49a225d4a12354d586e2d9; - 00000000000000000000000040000000 - ca61064d6edd95e3aebb9ad2ebf54d515272ecf033e146c7501a240aefb1f026 - 68c498a69f4546f60242658595a81dbb0eff031e29bffb9263411f8d346e6836; - 00000000000000000000000080000000 - f126d3c9eadd62db15cd371ba858acad93d9c0905c3e956566dbd1e5fbe4e43b - 0dc0eb6ca4d30b01f19db8d9484cbc92af194cb9cc5e698af8f9bee1a08a2f19; - 00000000000000000000000000010000 - 1f4b3e99d260d36d735f79f453108bd7ebf8746af1f39348adc65d59af6a29a1 - 8a50046878a62f10557d8e94bfeeb1a26ba39a9a5a76881ca056deb54082db16; - 00000000000000000000000000020000 - b4f573c9327db5e44aa95583f188849edd8454c6f31eb18765de7142ff91420a - 74890b23d53da33244da9f908d4812d27677a294c61e3d29d7dd495f394201a4; - 00000000000000000000000000040000 - e52d19603539f17a03ea93ca700b9eeb5a9d23de423d4631787c1572dec40780 - b97b5d286cdefb8d83cf18e6c1912adc34522bb6488e7abce2cbf743851743de; - 00000000000000000000000000080000 - 3abdcaa1600a946271ca2ba7fe9c7290b5f90adc1978e0cd5348747b118cbecb - f740e693758e1e5626bbd773a0a42a967a540498f250312d862579f7da3b534c; - 00000000000000000000000000100000 - 77411d75f740551a003ecd086d4563c881714a79d053f1d99120dd742d002fe3 - 8cb92110e3a28d7c42852b6e1e16f31c08693879ee68c8eee020ed9466904b82; - 00000000000000000000000000200000 - 09338341baf259f56644c919461974c3b7c81e3347d983545a993239bf051f62 - 1697fb4786570b99034fa0bbec3111b1d2765ad4f21492721b797ac485844630; - 00000000000000000000000000400000 - 728b0b2d9086928d19bbd761bbd18ce018114f9a357fc719416629be99d569ee - bfb243eb7dba6ceb8fcbfa948b91d438a9ac80c960adaea75af7de45fc3cd519; - 00000000000000000000000000800000 - 213be2a825b5694f131d20465a490f8805cce1b471ade0fef8ae05d473d888c3 - fe381bc82b11191ae1ba5e0e526bc64eef8a69052805c532ddfdf7a68f26c6cc; - 00000000000000000000000000000100 - 0918a9151b01813bbb43772707ed48e88464966f41581a23d1422e936b6e5dae - 65b87265aeefe0e04cdf2917a51f7c46b96b95645d4b4f8ddc40fe9de229e1e0; - 00000000000000000000000000000200 - d684c064f8ff906797e3c1046bd1dd19f1defa5a33292947081c35cb8c2dc0fe - 0e4fc41d8e7761c4e75c62da50b762820e396c794ec02386f96ab6ae4f1bdee5; - 00000000000000000000000000000400 - 568310b144f484cb6468d0140ed4d3ad6da518960f79660c7ac827f065f8f9bc - ac82171949984f7dd3d23417b98cee5ba45cf9e67bc2682c134ed58828f29ef3; - 00000000000000000000000000000800 - 3478b762b87196cf1f12e19dbbfa8b9f7ae89c5ba32ade4b9e292f40bed5daac - f455d1be4bd6c9d8f2ba12ee2506ec58774f51c61c434fd29bd307703909f9fc; - 00000000000000000000000000001000 - 61b4393bc414920b4cd28f1b62bd7d14ce09750ad2d5fa055d7264808bb49021 - 3c6b3f7410e47215bcf5649ec69aa2aea42593d18ef388f60ad8c1a74a159aae; - 00000000000000000000000000002000 - 76ce612f9d8530ea654509986ba4a0645df0d0b80e10e2b12e6a4cb702f95c2a - c0d96527fe806580b6be5d69156b82dc48bbd4b12d4990993d40cafac328f24f; - 00000000000000000000000000004000 - 72d9661f54335be3bf33f58b0691ec93c9a609c17f0fa2dfbec2447eb34e767b - e93447fc36f2f9d37e2cb768c89db3516d2101efe05d0c3b22223a1ccda827e3; - 00000000000000000000000000008000 - 8e021165e98627b217339085ae839f83eac9175aff22755ad7f74ebaa20fc5b6 - 5d2972b74ff22287c8d6e4e970bba73ef9fee1e4fef6ab2b99d89266369d5069; - 00000000000000000000000000000001 - dc73ffab02254f4b2284ffd856e2919e87fc0b9527d57b9e3bf61a31d03b81dd - 635008b2f0fa61c84f18d7a35a7a7348a962f913d1c9b2b4a5254d571da005a7; - 00000000000000000000000000000002 - 4afecb963e1c36d3136cc4f4daf50e6bff15f54267917b3351678e4600523aa6 - 7fa9d1013537692d705c5182b9091c05966dca86d0028e14189116c19f000260; - 00000000000000000000000000000004 - 9f4b44c46e94743c924e4d8cc858d6283e60143cc0874a1937306a75052fe73b - b6024707af59bbbb0615bac2ca2a33da7b06f1073959f2c40c3959bfe97393b5; - 00000000000000000000000000000008 - 63876e05b127c60c29841b6ca86ebd18fef4dda37a6a3406e043b26bef1c3e22 - a14ec552b38c9dc86fcd937f6e9693728fb6a2fb7d3d58171cc0ea566917ff0a; - 00000000000000000000000000000010 - 9edb39dd3c860b44b0b9c8c3ad0409c4d5d46ab9da835790caa0dee5fc52f638 - 500c304547307d1fe152c11064fec74c57ce41f6aab2b169c2f16f6d08fe64c7; - 00000000000000000000000000000020 - d8a17909a21e577f2e328d71016f71de512b713fea91321410a115be5acdf642 - 41f6f55e0f5f58366cf9545cd5468e2d4959ea3e68dfe86ab05bffff37e9b7c5; - 00000000000000000000000000000040 - e6b771c2479f884e6b02273538b9c801699b85cf9becab29c5fd6a0cadabe4cd - 73ab7c6f4490bdc9db345fd394569b6ecb8a645e0d3d96f6b04ed878f24c399e; - 00000000000000000000000000000080 - 0f2643a424943fb1911fd77fbda4bddec8e2c7e0fef23aeed6229717f6fe08cb - cc23471cfdb0baa7a388ad9117c1f18762ef40c169b31ea08d045cb79499f78c; - 0100000000000000000000000000000000000000 - 8070a4f0b3cb8b5c98a481a434bcd1f9fbe57a6bd2234f65d3b13837669d0123 - ff5afd2824da440e1db01ece9ffffdf0f385dde8d53e1d2bcc105cc6ef9da6e7; - 0200000000000000000000000000000000000000 - d6eb96497103e048ac9c11cb94a715d02eeadf278cbeab8fad0cb6a0ec5b0cbc - bbe61f08d13b874806e69dd218276e5063e7f1f751f5925db4589e4c3da1e297; - 0400000000000000000000000000000000000000 - 59d339d55b08d800ac4ca97c8d86a5e7c1aaee0c7e65ffa266927b3405d60e98 - 96f4751d5ef02128272f745f849b156b1ae4e9b0644a5067fce133d27c60d732; - 0800000000000000000000000000000000000000 - de5325a11316c25fe1b91e65f79d3c6a22b828c4964f23fc45e633f15a87d595 - 079c540a230618dfe713e1829b8c7e93b0e158daecbc960bebadb82320efa77b; - 1000000000000000000000000000000000000000 - 596f017382966b3627b1f25542af544e84ba96d8fd3a8aeb70144ebf31542388 - 59c9bcd67749151c8298766fb67942b6f7eae3cf18a4360fdb712cd5e75bdd7e; - 2000000000000000000000000000000000000000 - b7949a04ac3f445ce916cb9e09a05f9806ca7f0566c08f8f0dcceb97c46d1b95 - f7f160bb58a6190f3c070f2cac35b8ee30849382870b34b705e4f7dd308fa403; - 4000000000000000000000000000000000000000 - 3c881dd73e0144100351026376ce0a6a1941f10c03fa89ff2428d8826cbf1903 - 7aefa4b489a42ac86c105d410f5979fcae26792159419768cfd6aa1fc80a6f34; - 8000000000000000000000000000000000000000 - b32024da4d4bf274e91d9bc3fe46dc22e69c8b4a63d64c7b25e670f7c03c8bfa - 8e14c8584620b3d9782e828cacf93af391de629ef9c5befe7da320ad6f9f8b36; - 0001000000000000000000000000000000000000 - 0f4214c4d1bee959bc8c28d62cce6dad19939f6f860d23c635bbe5f384f12cff - 6008e0537b75cd2014da4133cd7712759fa1643be44533e1b2a03dc54e2290b2; - 0002000000000000000000000000000000000000 - 3ec7603e6690a95b44d45c6fde7fc3a78aa7b6eed2bfb895edb615a46867a7d1 - f8fa68c2908dd06a866a2c4fa3badee7c599a096346716ab31a7561db7788e25; - 0004000000000000000000000000000000000000 - 52dfd065752448ecb5ec6b0d6cf8fb9f8e8a49e2102e8ff7c37d5b3dde9c0a28 - b1f3f4bf235dff66f32faa679ebfd5b325611ba7d3f8fc51d9913e12f14de3f5; - 0008000000000000000000000000000000000000 - 3687e56d4ddb4747cc5bd9d87d788741762c70d9788726b5cf55212994138b9c - 81515cb2c8263971f764fb31fea9bf985b8407f30fe10c58ba520806832e6e73; - 0010000000000000000000000000000000000000 - d3b22949ce07d1f3d987af325246b02d4ee0e7a25ac7ba10d9fc3b92733fb076 - 448dccbba85ba4427e57bf048c2edccb826188767fa6223cce97709c3f3bf0bd; - 0020000000000000000000000000000000000000 - d6d1af9d789c6e91d1843d9ca3a45a0b7acbe96a94653bed6745d3c664d372ac - c32c33ab9df34036b5d18dff8fe15e57b3b290b0b734417035e68bb6661f2d17; - 0040000000000000000000000000000000000000 - bd8dc5a89393dfe78f81b85ba045b2d7a2035e38bb21f44b3ce1b15c617da6f2 - d0a5f64dfa590de17e3fd7b9fde24de1418221879c0465ff2e9b8528d3cd4c1c; - 0080000000000000000000000000000000000000 - 6e53761d95b891678bfa2f193b92d41b83e8c20532f35558be5038e0e85a0e8b - ca8bf1a499c9993cd56e17e5db838f99ee6e29d0f4ba6b0d684f543b71d7a489; - 0000010000000000000000000000000000000000 - 43ed0aca7101f8fb1495a03ced519942c69f4504f2be3509ab35c0be0de4cc2f - b4536eea97929db21b08fe4ea78d3069f286234e2e287a3097480538bac74b62; - 0000020000000000000000000000000000000000 - da9389cf54ee87ca918aa30b99a37f50f67e2ee8d27f15cacb4f74fbb1455844 - 28dca73c0a5b6500370aa766fd03b596ef1ad7cc27843ea83c846a258c595024; - 0000040000000000000000000000000000000000 - 61a6288bad6f3a91a68752814a0c8acefc56b94b4c45b282d3ae3ef6029e0490 - 8b8433d94c9e6b4df405d6d3214889231efb191e1d3aec05081f982f32054841; - 0000080000000000000000000000000000000000 - d7141bfb37d834afa650bb1d7839b34d1ae0ddd517864ca48b310b53dba1a47c - f68a00c3126b04a87d6a9ff061fc5c8a2d0e66ac263094fd3f081c14412c4a73; - 0000100000000000000000000000000000000000 - 8ed10898964b362405b3996a4a6ba087330190e6bca03990e3218a33411783f5 - baab2232f4ca0ed0f54fdb2b0f73f8433c9af741034117f9f5d2cd10615941c4; - 0000200000000000000000000000000000000000 - 89d7ef42eab86d3209b67353e76da8d8063c91447f916f91378a627a49a0e459 - 2a517f1fdd3019a3d026d9f3a47545ee96634ac8e13b1064a57f82218628039d; - 0000400000000000000000000000000000000000 - 009ac31bd1a5117e0368fdc254230a92cfbadd5984fedfe684b3ad18d0489f41 - a5d26e2813bc41a4e9c40af519b72ac6b2a2188c8b89c77a410b6fc732c41581; - 0000800000000000000000000000000000000000 - 1270970a59191c419b2de4003db3467cf453ad79ee93ccd5ec06da794a0174a3 - 99e4e43c3199b6f493fa633303ec08942b6991188b987900ff3b39699f7b6485; - 0000000100000000000000000000000000000000 - ef02c43eac97a89b7f0ffd491a031dead11231530abaf2ac6b2ade53e2f742be - 8a74dc87527389474c1399ac4b7f4c47522d8b93df856c96c129456e5bcfa0d8; - 0000000200000000000000000000000000000000 - 66efd72c1ad170588847c1ac5f1e957e38e4e40eb891bb75093ee03d19339141 - 8a822f512118c172bf832680ccb9e0e867e04ee2022db6a27d98ed56ea9069a0; - 0000000400000000000000000000000000000000 - cdd36ee6c5cf010b1b093b8f5e0d91d742af7a32b6e98f9ba412c1d523687e5b - 92f8d1fa8d6eda70f7c404088b519cbcd3f31a755b74a7c4474ae4eca952c7ce; - 0000000800000000000000000000000000000000 - 99576731bb509c8f2789eca8269cb7d200e7e7c487a59586e7ca065c6947c844 - c4041960f5ffca9c75a7d27f5865fab9f2c8c536ad6408d191470f2e0d6ce33d; - 0000001000000000000000000000000000000000 - a49eced3ac57b8733ac330b477469b8d0d127edbb76c8b928ef8f3f6e7a844ad - c048e5899e9eaac8ef454098a4bb1a48e0cf58a06d4f1f19f490452e43c23888; - 0000002000000000000000000000000000000000 - 6372e04bdbf3f8d4998cf16dcb310a17d4257042c2ab5f31ce7d75a7c4477ce5 - e6eb8f3eb48465f368a434ea0e66a5d1bd4a8bcb3cc665a48f9e20d6c15e2d8d; - 0000004000000000000000000000000000000000 - aa3bf81795afc567b3860441ba542fadbe778b837d89972e419d9dea5f886cbf - 2fe69f415c844ef3ead9e86620844dfdc9af44c0133e5655130fd53e59b9052a; - 0000008000000000000000000000000000000000 - 8a5c212066e91da99ccd0a8ae0fa1c7f232ff503fdf33d84a6311d421c8a6e32 - a2d43b8ed9c582f1ec1b7867b74c81c17450698fb8c2e2333e4a7fb9986180aa; - 0000000001000000000000000000000000000000 - e65a5b5f8bf7395960e4150e682c586156617280b5dfa259310491ebbe5bffa5 - 473a1e953ea38940e3d84df3ba7b6fefbb7bdf7302a9a9d959d088aa56fc439f; - 0000000002000000000000000000000000000000 - 215237bc89cf72610eb50cc2f788fb66f5dcf5a36b11148d25f87d3fda60432e - e1e465d5d23f00aac475c9021a5dabd753c292e6e0670d8db8e5e2519476c3df; - 0000000004000000000000000000000000000000 - 521741c91ad5fde0abe8ddca960ca3535041fdb1e6446194e63d1930e7c96be3 - 32611c8c38cc3a0df330bdfc4ad7366287ab2c22dedd6a852e63eea38e84192f; - 0000000008000000000000000000000000000000 - dd7eb22684ae6346df02da61fabe51ff32fe48e5c2f276976054c7fb400ca640 - 8702b65a7d1b61b5843dfe394cead041a481f9ddb368187b60291730d7132b7f; - 0000000010000000000000000000000000000000 - 5fd0b1e839354deea2b44c7811c94c81a8153e6bbfed98d4e744b02fc965bb5f - 3c6bec05f5cdb092483cecb0f7996d3aecbdb8f7d738bbfcae9d25a210d3b94e; - 0000000020000000000000000000000000000000 - 39c6626868026b6a15c5ccfa2f83dda7018b6f2f576de8cdf009d84008fc726e - b7e8ff789bee4bdab1fc6c75c73d83dc3cbc1d60c232f54c4dd946470b7f0b8b; - 0000000040000000000000000000000000000000 - c945f53f19eed324dd2035a90014bfeee3c46216f26e7b74978dbeca03765dc7 - 38b825729109c791dc588f392f448085ae8da62feae27adb5d667b7006fb1edd; - 0000000080000000000000000000000000000000 - ce0d4ce7c9a8c7ccd6ea6e5d433c4d7db4663542a7d1c90dd431e552045f5155 - c50ca8e102497116dbb78c0bfeb0e39939b5aa59bb7cac8f127ff9f693f7b124; - 0000000000010000000000000000000000000000 - dd675ec3415137b62955dc917d348109c45c85de9c60095f94539dc9cbfde9e6 - f26014ef5bebf40dab8052592070a3a2f0eb6fac1b0627a8cad7c8fd19511e41; - 0000000000020000000000000000000000000000 - cc5398fb1486ee124e32221736c765e88006f8e0f31f65e337f0703241497896 - e8527d10755dc5ed2512898102fa37a952e12d5a9cf99ca663c4f8aa556107ae; - 0000000000040000000000000000000000000000 - ba7a51cbdfcb2b3b9bf200cd0a5c7998c5753f861ca0d2591c7df18319b0780a - 6a5aa39bd5e4856eff8ce57422623aeb5c5fc7099c6d59e0b8d1f47040f833bc; - 0000000000080000000000000000000000000000 - f8b7f1b3006cfe461b183397ff4ca13eaaf8c34528f48eac5514614eef979d2b - c276a602c32cb0a9f15d45a70f606272179ff0b13e804fc3290d14cea182d555; - 0000000000100000000000000000000000000000 - 8ba47e063938c6cadd65fc3db823e83edde887175d6103417f2648a86ecfa38f - f2b45766823ad20d89b12b1eb65ea10ac1f4ca042408f775e82c3a86c7d870ca; - 0000000000200000000000000000000000000000 - 82f0a8825caedbaef6991dd7cc33d8a22757b4b65186bbb70dd274486bfdc6e9 - e98621489d27a3f8ffafa5f60c454f5b43073fa13b7b1e44cf5b42c1f410b757; - 0000000000400000000000000000000000000000 - c748b58d58bd39b77224713354f8abe888a55813cedbd581c811edb61f6ea33e - 0341ef9ecee1633e77d1d8152dbc4b536cf1d5106e279f99bdefc7f65b002dd1; - 0000000000800000000000000000000000000000 - cb1703a29bfa0d5f8e074f8c8efad1c3f99c3c9d56270a3b0b223d792414a6a5 - 153618a5aa9ce0a5640c395dbd5c65fc78ec091d9268083bf1a8ea6309572237; - 0000000000000100000000000000000000000000 - da0eb94b57b73ce632f0e096e8b9657a8df2a7602ff80f33bd23621b3a9011bc - 84946c36ac9e6ee65c9f39aeada388f91304420de373b45eb9899941e2059bd9; - 0000000000000200000000000000000000000000 - 28593a296d86d90b64ccf70ad60d0806c194a49477369151d8d1b1f534a73ccc - f4a5b4c8f1d7a01e23b7695421e91f864044ca51b3d6e946eda4dccc66bbde88; - 0000000000000400000000000000000000000000 - 5432743ae99f48de5c2c943b81b4c994e7af4a9df102302bce61e51da7b7b1f0 - cabeb087d68155a0ebfd81f81ea7a0451347e8bf2b409e4d3db752de191edaa6; - 0000000000000800000000000000000000000000 - c68b1f8b2e568b015ae4684c81d28e1dc4f2bf15ea8637043589555e59fea56c - 3c7c59a6b7446857459e8c2812f318c99d6f2eb8afdc8f7cf3fe79b9e43ebe6f; - 0000000000001000000000000000000000000000 - 1e2ce4d6fd55f7b624b05e5ceea3915ec6f061229fc5897fb5ccbd2041477968 - eb6ff717f26c66672b5c99bb95c0604d812a70360e361cfc1ed6f67226f2f738; - 0000000000002000000000000000000000000000 - 882b04a32f0ae1ee1c03856d4997bf168482eb9e3c66db15caa3a5ff61f92663 - a28f92837893ca7cdaeb5afb82ec7808d6c0aa734a81c4f9e8c207211fc00dd3; - 0000000000004000000000000000000000000000 - 0e6d2c813dbcf23cd711ecda6066bb9d03a9babe2f6471d683494b58c0788d44 - 4c601b1e752c45492e42f54e5eb528bd884a242a96bb8a638d9b92201ebb3707; - 0000000000008000000000000000000000000000 - 6e697fe8636b48bea38357c377f999c717fa7ab055a124b20868098aec8def00 - cabcf9f62a30e5a27df4064af20a3d6f0db35f915f556fc9c349f41575f97247; - 0000000000000001000000000000000000000000 - 9bb65307fb501877e3ada81442cde498d1e05d7cb5deaf88ff1f0b6db92da4a1 - c7972bfb8c66bee89a3cae24999a2671a661bb5e3591f811749725c31e95daeb; - 0000000000000002000000000000000000000000 - 4b1c3460a94891e4f8708feda342f8c13de4f500ecf890c23b54614f759c351f - 3dccf6aafd9acc0a52003729bc92cf541c72f1175408aef6754c07308f3186f9; - 0000000000000004000000000000000000000000 - 237f3b1b70bebf261fadf4fbc61f4aed6b2f7d41fd0bc3b8701ec87f0ace3b73 - 9b575ace6a7d3614985498611990b61cc6fede975d36c08b48f083a2eda498b2; - 0000000000000008000000000000000000000000 - 55819dc855dc272f8e813f473d0be9f7b0ee777581c68236fd55ba7cfd7fad54 - 01e96efb1cf82aef7bb041c59e16696a196fd263376d478d12d5c21f8b76bf38; - 0000000000000010000000000000000000000000 - 46a9e2ece5c6a61677e9fa44e91c15ce095e6c2af0e66e3daaca8be8f55bc072 - 9d1d1717693d05487a24e6c0824c07ad87c0490e6a29de6332e5aa0130311fa8; - 0000000000000020000000000000000000000000 - 9163353b13ab53a5f0cb758072b96891fb46d429da59ef58cda3ba1a9a2162e0 - 2a939e32e660b6cbd4ec22903b3eb454acabe834e59ce753bbb566bda8e5745d; - 0000000000000040000000000000000000000000 - 53653c0563d023d51c758273c7ffff07897ed19015f2b352543711805f25d2a2 - 638a9f6d0768463b2716ca71fa1c3ef0a758cc2f47e0d3c3afcb50202f251ee3; - 0000000000000080000000000000000000000000 - 7b1d6650b48a58d529d174d40c34ece0c4725893508723c9e110306f12d2769a - 09a5fc3739cd6e79e94e250eceef8a31bdb30ecb4f4f47e18f9a3645e82e2642; - 0000000000000000010000000000000000000000 - 92fcbceb6fba200a50f039637b8afda2c5d4a06efdc98e6094a986d0eeee92ef - 08250f4cc12c732a3b1a82411ec4a8604bf119f69b07072961758780c7db87e4; - 0000000000000000020000000000000000000000 - 82af5330a7aa9696a6be8129342b9b1bbace0b879ca107b5184c0902793efa49 - c286bf6ab754af7f16244b9de2566e9442e13919b2d699d62f52d384362f6331; - 0000000000000000040000000000000000000000 - 93e0bf62136720977660e0eabd4694514371b3b54a27027dccdfbff5aac51f34 - 29955264c6c52f5fc3c5475f4f6d478f1b17618585097b9fdeae091bdb9e8446; - 0000000000000000080000000000000000000000 - 69563766cc3b858a015e0655cc056ac5356ac37f3561495fab6a012ea62276b1 - 41bda0a8164a083e3caac42fb15d94247181034d2ade38a1b4399eaaac07cbd5; - 0000000000000000100000000000000000000000 - ef0523a9b2ca36ad2b3b9bd9c2209a1ab8c8dd205e48140d577de7ac0fae02f6 - 5f3f8b6b15d822ff9d852c701294d5c1bc2e5e20c4da9e56dc2ae6f1ab33c084; - 0000000000000000200000000000000000000000 - 0df666c1b2d781312887e6d30f21f12e6e2d4dfc2bdc0b5484f85d35c091a453 - 87a7fe3652e203d98ec75f3c61afbd47f8fe2f50505860a093a7aee292366d10; - 0000000000000000400000000000000000000000 - 99d1b163bd4fdd4bed820ddd6f4b5b8fa0f1590a97117956570a1a0fa075c473 - 24e6a698f9880e19447971c1de0d598472d66df54ccb88624369af5339e4627d; - 0000000000000000800000000000000000000000 - 8a76142c207334f1482a7b748f48fd583e34ecc52c33ca6938a10afe9fdabc43 - 8311c7ba99465892df7554b6c06740333d4f4e79496b6bff747d87bb3f88f780; - 0000000000000000000100000000000000000000 - 1db97ea24610af47d6b4a43c2ef0b031a81547d98723e46aaec6d8b4e29c2d8e - ead758aa4b4ce689d61f7705ebdaff4334bb882e8286fd6655398a8f5013449f; - 0000000000000000000200000000000000000000 - 38f0302fc696e3e644a4c58400b050275c75dd77880b7c81b48bc49f5eec4566 - fbf97ae99430d0582c8818945aafaa9d08516a56150d96842c67a69aeb6f79db; - 0000000000000000000400000000000000000000 - e10afdea821dcc504167b562bb1abacebf03a183a29a85593f51aa83463ccf42 - 1a60ae0e1289cb5477717f4bc7fb936b91d2018a7121f29db751b5ab9c739657; - 0000000000000000000800000000000000000000 - f8178e6e47dd9e38fa46d139e9da92320ccc56580ca6790e6739d98a16cbff2b - 4d5274c530a947a0475c0581f946897e2b4f9e01cfd5e9edd5f00109724d63ef; - 0000000000000000001000000000000000000000 - 057dad112fab7e5e2f13bfe3692d29cf7231169ba5456837384e1d3178d44399 - 493491ac15958b53294afddbcbdeeacb34f1862c38f0f8514b3190d494611dea; - 0000000000000000002000000000000000000000 - 32783556b2a205849744b683e3c1cb67a4546671d51adb868f2abc741d277ddf - 8b7ed6253816d59663a99df68a9c4437ac9ad45c2d400097e69c1492f5a26ef1; - 0000000000000000004000000000000000000000 - 192b1eceb03afbee8bce727185baf599c1e281b6819b219f7c604646362ef507 - 21c826646e076e934f521cdb6933b547e1f58a1005eb492d768a8abf545f99eb; - 0000000000000000008000000000000000000000 - 151ac1d0c9497bf7905ac32c3bee78042c1cf57d144b33563c0d524197e1684f - 532ae17f1858e56b4fc1c3442a3eb5aceb9c38dbf6c8373740d2c70ace135610; - 0000000000000000000001000000000000000000 - 43d263d71480616fc8d3ee5f26a7b4322f64c52e2eb08bf45da98a501379d42f - 10915428d4d72172524b0af0a985b857b11fb208305fc96bcb0bc5da329e5a4e; - 0000000000000000000002000000000000000000 - b93915219589225d93000fcb969ae487a545f909fc74b6eefae8ead8697f4a94 - 2071b90c399dacf0251cd331d008b40d75c5fef91e76c2319ab297226cfbb751; - 0000000000000000000004000000000000000000 - 63304c37894c70bb5d871c7cebd6a03e5e63f4e1d0ce0149c287f148d2b43bce - 5d7fcfed1eb5cc9052d66c073e9817db944323b90f2e60871781078aeb23cc33; - 0000000000000000000008000000000000000000 - 56f9602f84bb4c0c7d7cbcf427a401fa8c063edead092d93a27ecedbbc080238 - 683821a05f317992c6ed3dcc523d147872ee872552fd4d9935e72cb6880c8ffd; - 0000000000000000000010000000000000000000 - a36adff7f8c3aafad248f0c875e959212b533e09747a95c89b6443487b426be8 - 2028682f6b9482f668e55b06144ce444d4bfffdbdb119b2552bb2ceccfdbad5c; - 0000000000000000000020000000000000000000 - 76131f29b957f35e6b776ea6a737199b00f945ecfd146443de23d1c68434209d - 1f40950024d089bc682ee4b0fb5fbe079f988058993f3d3ff928cf087cb99dbc; - 0000000000000000000040000000000000000000 - 6589aac4967d58ae26372b64a7fe4741ed93ad4bf7fbe61f147c0bb21056d95b - 5bcc6be06b77e64e4f04ab552a0035c664be7c6ebb2a781e7156cce573e2856e; - 0000000000000000000080000000000000000000 - c6ad32c723a34b02cfab4f5f9d5b6f14d2a27655620fff9650c5f496271594e2 - 64dcacef6699660227dad31c50c1752711dfd4df95efd2918391371cbdb19f6b; - 0000000000000000000000010000000000000000 - 637460f7bd663081a501baf9fbd8f910d32b74f95532c73d2931cc1c70b6f61c - 6611acee8bd7dc914cb5b2310aa37c44041d2d16d2c6f66493d7d0364ea0d137; - 0000000000000000000000020000000000000000 - 2498e35499439986614f26286ced257b12145afa582093f2df311a6eb768a3ad - 552f96f75bc0d3c7995970c9785cec08d1e6a848906604d7ca1410caa09110b8; - 0000000000000000000000040000000000000000 - 08d3d5cfaacdfd78f5890e84ebffa55f6a30b332d09aa99f9a39c57b1a6e64c5 - bdb53e5e22c6dfa1a7ee078c6dde02f999d36a8d2bbb4bd6d8d63344b50d7f19; - 0000000000000000000000080000000000000000 - 6cfe9b516cf7e08a58d825e13c4602c1c878297b993fcfe48398e8d6db759940 - 38f793f71c6896b2ae6bd730a548210cbd9345ba211180de67385a6be2aad623; - 0000000000000000000000100000000000000000 - eeb6ee8db37ba7df8caa911e25dc2fa0077b3931780d2ce06d4a15e89a2c859c - f4755374b79e4a32021ef5a228d8eda5e7aafebd43f4c6bad599e957e3b1adf2; - 0000000000000000000000200000000000000000 - 6ba41750ef7da69feb66952b1ed18b75e20086c0bab3481d8211a686f317166d - 278cdb6ba1b4a9b624564a5a76a713887abdeca0ece63a6f0aeca268d8ada97c; - 0000000000000000000000400000000000000000 - 872c1762ef5842c8c9f7117ead43024f8ad0734be8d1dfb48b2be8fae98cd374 - 7cf31344e19d4886a0b36cc6b4777658216be3a32048e89dda78470379c0c653; - 0000000000000000000000800000000000000000 - 5263be92980bc943839a9024fb1140864999ff02fe7ddaaa35d3d89f9f345c13 - 9a9012f7b455a4b8c50d5917fb5969723b70ab3e0cf18cfd5a1b841aa6c0e1ff; - 0000000000000000000000000100000000000000 - 451146802e160f788555b58164ff946820a782bce9ae691a2969fcb250b66773 - 1f85560430ebcb39c18ad9bb8dc49c0b1e1d730bf8cb43121a8c94a62daf56a4; - 0000000000000000000000000200000000000000 - 83a737dc4f27d59528e688c55a52e4c44d518dbbccbf81bde212b87e9c63bd53 - 9fb8cee4a538fe0add8823986f50ee648c36504c1ef9054b748cc437ff31d25e; - 0000000000000000000000000400000000000000 - 83154c350ea26c88f23c2585c4c1ce85f7febba6ccec68b960f2bd2ae6284c15 - 9243e796bbe38ca38d0d517116510236b81b5e84d662a059c9834cd57eb2408a; - 0000000000000000000000000800000000000000 - 78f73dc4ddcd6357d1cb4fd1e61d2456cc37d84babbf5a6e70f9609ff9527602 - e0f9f54c77861caefe4ba8ea6a870a5831cdb61ff0658ae74177562676c049b4; - 0000000000000000000000001000000000000000 - 24203a6fcd8ea87e057f38fa775d88c1caaafcd57982d97ed5fa6b99a2814e10 - 7d327425d003904c745509c265bd70ace892a7ad23496f335386af2b3fd8a2c8; - 0000000000000000000000002000000000000000 - 832c6e20ac336d8d215c1b618870c33857ff4e616df40dba963cc422f9cbd3b4 - ad1f44b624941028a116896f053305978f382b85ae3b24330fbbb328fc835cd7; - 0000000000000000000000004000000000000000 - b68daadcf692eb67c1a69e854424f45a3cc07fb7c042563ce5db29811909fa5d - 4e62699870105da1c27da11a482a5c79f174881179d3448d9518547b12341eb7; - 0000000000000000000000008000000000000000 - af03141ab732bbae48789b2efd96995ef50977d07a7d9ee741cdc1440904c599 - 8b295745e425a4b798d230f62adf6cf8ed49183098666157987fccddec8f0113; - 0000000000000000000000000001000000000000 - b69d0bbfed16b59a8772777e09c866fb51391d77552a32d8a971678776e97a08 - 1cb999bb1e7e9dd64a64302e09447755ee9c1744139de4cdbd61088bc17fc24c; - 0000000000000000000000000002000000000000 - 5c982237e3d812369a5084f68792b88f33fdb8278bab9c069572c4d2d4e8b1fe - 7a4c0dbbeaae1b31858f8a8e4628b56ef552d738301b4462ffd682af0d26e871; - 0000000000000000000000000004000000000000 - b502c31e76e20b5cced9f96fcf49e786b477dae329aa612edc58c8c4b310c881 - 3dc3b0f31b61c28bf208b35ad68715ae247a8bd3ece8c6d38f4d03281e0eaae2; - 0000000000000000000000000008000000000000 - 1cf7cb0fe06fb987e82a7097abebff97b074e00d32ca59e259bb64baf610b932 - a8f685fdb0fd2a5090ccc7d7635431954e6eb4b58ca2110fe691562800725f89; - 0000000000000000000000000010000000000000 - 0fec5eeeffe04cab0fff3d6cae817db15a4151fe22a6e3ccccdb2e56b36c3ad9 - 7df075f7326a189ce1f5ed3b8428731f67d743e2bbb3037043aefc55a401b534; - 0000000000000000000000000020000000000000 - 3ea8f911b282f21db8709031e607c193b4604a8b44ec36be34cf0eac039346ae - 1ea420045663890821dd21eff43b2fbb86568519bdef2a13dc2d141c05e36830; - 0000000000000000000000000040000000000000 - 8a84fd4bc516cb8fc163352c8fd600c8f1a07861f052964727d61a91d155e7a6 - 3b8683901243ba7aa8705259365f64ff8daa64604c34bedbf4d655c20ec28b99; - 0000000000000000000000000080000000000000 - de1e1860d637140cbc270026885c391982d0855c7177106b1a38103d3cb5d956 - 21c1f9266ef014b9bb8f9b9fbb884679d1e411f96e1173ece0609fa01cb0b16a; - 0000000000000000000000000000010000000000 - 4e62340d4fe3b25f02522336c45b8f18b5944d41a72e0af43e2c1dbf4c32a504 - 185c48576c96afd58a5209a255a7324f850fc9a3be04080f9a744a5da8ab71c9; - 0000000000000000000000000000020000000000 - 9c44e17c60b2e4a25454659dc72aa415c4701d1c31170d9d403a2f16adc6521a - 092e70d956ecd2c938d1ab9b95588dcbb1fed47a6cbef019cb538c1bce1b20fb; - 0000000000000000000000000000040000000000 - c60d7ec161b0ae0e347bcba7755c40cdf150d67901070ac4698f1d7c593e6d33 - 1892f5f715f53024bf4b04aed4605e34539b21260ead7e00c4fede1b58f3f3f5; - 0000000000000000000000000000080000000000 - 7b4709c2543c6c98e858392f44244e3a4606e5459910badafbca6422762af235 - fa8b0b95b7d3897667c8798b5288bea05b8585264f1067592e70584d45e54468; - 0000000000000000000000000000100000000000 - f6a82f150ce106cd0b67c6251144cd0934623f64a7c0c02cf20f88c5b81b8f9f - d08611f1a55c0fa0022732787866879f6057bcb0d3bd8be4950de988f2703b5b; - 0000000000000000000000000000200000000000 - 036d8796288546f6c8faa0137f542b79232b1f710f00d993bdd209d608b2a983 - 0e4ee8dbde805bd218495fb6e0c012da36af3118fe3abcead1cb9b1d0d9ad7e8; - 0000000000000000000000000000400000000000 - 93bf0d046d56227e10a60b6724d8195732ac7497dafbc5f0415aec8f721feab3 - 508975892533164bd482c18d17b1190de8ac5c603e22dc78dc033dd56d70e498; - 0000000000000000000000000000800000000000 - 92242df9e82635f00fd079b03fb3e4ed2e479076a756daf823ef97e067bc0a9d - e52168fc1c39bcdaecc13f07ad602234f0d6fec3ab60edcc2703b2ebd9a428a8; - 0000000000000000000000000000000100000000 - f20f59b1d2d69ab79957d62fa9a683180b95d772f33205637f3bd211a570c182 - ba077c245b7cb7030d882130b15298bcbf15f4dcdf2df67865687956f2d68f8f; - 0000000000000000000000000000000200000000 - 0c5eb80aa685a53d856cadb59327c84b33379abcc06329cc10af1096ab8e9454 - 8d8ef3a1486b1ba3e3423ee8e188036bd06a73abc506cfdde791de57f35818e0; - 0000000000000000000000000000000400000000 - c1b93bce555e86197fbe389b926c37d918d88bbf3d704496986c0cf3bd959840 - 3a7a664d89b1acdb853c6bba7c7de3322545bf58971c93f2b8c9085d3734e31a; - 0000000000000000000000000000000800000000 - b9ad33f00c7029630ff7db4528327cdccc612b607e63faf35978fd27810f345b - 291fda0e13c6a6aa8354acd6be229759e97a52cfffb3956dc6a1dae438e26565; - 0000000000000000000000000000001000000000 - 3f7e83921a8fda45c6681ceea340a1bed22ef6ed784fa8ec0301cff998bef05a - bba9ed3d86edc3e850c58372960a340aa75046aeb845b53ac521b8b05800ae48; - 0000000000000000000000000000002000000000 - d504cbfa2d69cbf0108df37bd476fc93db12df17eac4a10f52c5d9e8560b7a93 - 81b71096f284866b1423cd41da22f003afacab0911f08c98a23bc508866a2d82; - 0000000000000000000000000000004000000000 - ca5c7b0f2e05939fb7b30358930f2db8461c4a8735971b7d0ecb429ad519e9ab - a7b781dd1aaa84c9ea0fc8977f9ebab91af4910197205e5fdf90568e51106c2c; - 0000000000000000000000000000008000000000 - 96e9e78698c3eb928ac8bf2a6572d1c153f6311d3d250115e502ded03dfc2e74 - e20aabbb2137804b4493fe7b17e3b9331592f8f44ed1903d1d1209b26fbe9a5d; - 0000000000000000000000000000000001000000 - 07334423e99b879202679cc4e3f674a82a731d02ceb5e74cab08c90b6228f0ae - 74458c222e857b9033a9f0453f366f4ad8b4cdae922b8a80e46aacbdd6f647bb; - 0000000000000000000000000000000002000000 - 68c3f9679c7a21ca77da909fe45578928bea63c882d577d08049a05103efcd56 - 3d0ef4fd9b8359f4aeb1031c31508876e8f0ef38f8613bf027823e9aeb005445; - 0000000000000000000000000000000004000000 - be2bf2722cd6eab12cf20d28cbed792662bc26f0b92295e53411267d4c72cebf - 2187e559b2130dae8142fb0757341c0a1e6df31508e6a19aba5ab2cbb0a9c872; - 0000000000000000000000000000000008000000 - cc30e166ad1cf014644af5c3b6c65b45fa594e5e371e404388e8c051e7dfa4a2 - fbd37c904a34800318acec016ed34c12de8d8d1241256d4a96a1ef02d707d53a; - 0000000000000000000000000000000010000000 - c3b8c49a86a432001397415ccc1eea4d77c5e7b1e6b8dc208d69f2865a6b8678 - de5469250f0cc42d2e202f29af0e13b31ae5acc68fd5107819880d3db6e0b8ce; - 0000000000000000000000000000000020000000 - c169eabc1437d7301865ffe544bffe0767cc733500d6a67cef204f6078d58328 - 4c09cd0d212dd836a6e4af52c5fb1ee851f5cb07465e5f592fb8024d1b0c1dc6; - 0000000000000000000000000000000040000000 - 758c11f8fe1f10f109d8df4790de952c900afc7a985c6844195a86c66bb0780c - 6985483375dab29f2c9ddf2e4acfaf9ec9ec0b90d0ff59a51f76901449125973; - 0000000000000000000000000000000080000000 - c818f59d0447e726d2839c82a4c12360f7ff8012d84bbc1a367cdb2299457199 - d1e7b740f3c2549929ba0d3210f259df6ef2322e9ee4d6f317ea4fc8ec4d2998; - 0000000000000000000000000000000000010000 - 3aec597f7d31483f810f14fcddf9be067f56080a048a9e3b4098e6e28918a800 - 7e85288628803f83717499b69f17adcd5a66ad8dac68d0851db8eafcdab3cb08; - 0000000000000000000000000000000000020000 - 0b6e2edb89d22c535a5a68e75ebcb0087ef1f236d2a2266a9d543d6adf24f479 - ac7fee6480f401eb8902005f7b8d512094017f3caacb8249082606c36d98d51e; - 0000000000000000000000000000000000040000 - da610e5a8a7a85ea2b84bbcf3b40098290a15d4ab3bdf91d7e21fa524937c783 - 477e7784dedbaab64f19ea69b8761c66d5da3c5cb51551dff47e3fa0c68fefdb; - 0000000000000000000000000000000000080000 - 0e8f5819b7a66f25281862c132d5f339cfd0fd4ac4f91c14f226ac0033dd1117 - 42352ac10368ccd3b833fec7b048741501711ab1036dc7d159e150055a11586b; - 0000000000000000000000000000000000100000 - f546da839861af04600c9417e0fe884b8c1b6f4a9a9d36c4da7b6ee24ff3c4f3 - c543450e77a3e87a7be1d6233b79b3e42597228f0e08c4f833622194f64afa71; - 0000000000000000000000000000000000200000 - f4dd95284ab89c6c53d7ae177d25aa3739dc721ac0870c2793f3723b6e093363 - 48118b3d2203906c7b319273f372bddae10266d0d8065e636cf0bfd747c7c984; - 0000000000000000000000000000000000400000 - 14094297b5bed9c5d7651a2787c232c9c9089f542b76f39b264c1b591c4f2e18 - 09a61a1aef6ad53d3e2b6e93389a279752f78c62bcf530b7cf0c1f3bd3e3b529; - 0000000000000000000000000000000000800000 - 212101a1952ec6158effde6a7d48a4929304fdeab258257266530262a8ad48f3 - f991e1ad77a2e13b92906767da523e4d057eeaa263794a087a02bb0339972b9a; - 0000000000000000000000000000000000000100 - ec652827a0f5cbec1068ec4193a152e4a80d797867646412d18367645db6df2d - 033741b62e08f79b8d6192c93775508f23100fc3a4f35c3073cb7130a5211abe; - 0000000000000000000000000000000000000200 - 646046dc56a8b7a4186e481ebf943949eccbe7147e0220de8dd05fa656e92dbc - cb5e4fef77193f8256bfc49a91e001a036582e2e3eff8173b27af708b7e8480d; - 0000000000000000000000000000000000000400 - bae05fa0ca832ff9875fb1c886d8ec8eac6b730bd2427b9cfa8696d3ab3cf5b2 - aa4ea07107c3b1cc519fbecddf7c966aab50188cdd0d46bc866b19e882deab36; - 0000000000000000000000000000000000000800 - 1f8b6b9b95efdc182d35f1ec5104489893c70bf1fe7ccaa67ae55ceca5152981 - 100e51e4e6d5a44653b9c51ba6c9f070bea9d470bf1ee0faeee1d05122cdde50; - 0000000000000000000000000000000000001000 - c1703da3b5c222872d09d493d03d07e36e6d04e8901a248ce5fc620c5dafc381 - f282d2b589be28bf64c3f8a454be2101322666b3c7b71369496d630cb5c5fdb3; - 0000000000000000000000000000000000002000 - e76669b223af08035c5deb05e10666ad09a99af191a3ff30bbb7202b65a25033 - 15240875b0e1b9427a28e2123f85f74a1b5924e3600453ee45556bb328e8e941; - 0000000000000000000000000000000000004000 - 511c0362a229d88ba90a523f862d35c0305b08dcf4b9e37bbe2efcb0dea8e6fb - e8eb57458b73a15d4eea4dbfc95dfe99ea52b7f07cb3964d1c0caa83de2fefde; - 0000000000000000000000000000000000008000 - 45d00f70b107ec873736a23b9ec02b78e68c6ffbbda1778e4a96d01d42b20eae - f5d0539741362a0c93861d3c167aebc148a5b34fb3299e600abce538bef5fc5e; - 0000000000000000000000000000000000000001 - 41ef971618e7923106427505bc765943909724f81c8bc9b0de756867d40b444b - 8bb9e4dcab530ed4e491e020b59ceaefdac18d23ed01acde992f20f44dc74004; - 0000000000000000000000000000000000000002 - 2536ff6dd06c356f864fd003738e87a81c5bfb44bb7714838c5d068300abea93 - 291f63a30d86a1aa7347a9483d8cba05eb27375c43adc7fddb0ea9bc50e5a794; - 0000000000000000000000000000000000000004 - 55dbca7e091006fe395367c4250fec2d1b994aacdf8026072d1f3d92fc7475f6 - da7cf09785d9b6792e20dea6dce0fd4e65bf87cf47ac674a83588f3642d6d50a; - 0000000000000000000000000000000000000008 - f662573e1d83a2b58697b4f1923396b7d89c56fbcb21a5a3834232c8c0451f57 - b6f749429a2d9ba1b479cfc96886c679c7431b93a95b87f9187680c1a7b7c792; - 0000000000000000000000000000000000000010 - a398f5779517a7db0f56007407f9cff857fd68803441d31bb6a4752a77dd3495 - 89ccf7cfec665a5dccbdef72ebb60388a3e2a892d6030574bfa92f4e61efe6ba; - 0000000000000000000000000000000000000020 - 58a9c4323b56584a8d5378d2004c1d6f491752ab9f1b750b9745f6b5f4c21cca - acd8d6b0c04002442e0c3c983fe656d5cc54c2782c60d867cf7445cb57feef1d; - 0000000000000000000000000000000000000040 - 98303a1f445013eb3be40cff0d6f4395501b83b825d4897520aacd6a36703962 - 1d92ad624dd448b62117c533e70c0d13ea5b3a66310a979edff479a50b99ea17; - 0000000000000000000000000000000000000080 - 11c40125db6ef51d57e603b8beec27babde3fe9ab63fc52a0cf7f76854c936b3 - b9dc8672196f58cbcc5708f68f510d6f908b8a7cc0df0ff83d3a7c8303e78777; - 010000000000000000000000000000000000000000000000 - f9e96db294715055a91833db0fb33e9c91b54bede26f9a06abdab80a60311e1a - 90b679951b11be0bea2a87a3eb8c22f42bfd07e51f33362a1ac0d7bd959b5191; - 020000000000000000000000000000000000000000000000 - 0c38a41f055332c76457a13f95ba264155c979c9124b5dde77318c49d1f4c01b - 405919405dc48814b279e93f34899237ad9ff2f2aaab9a4d7b04d5572a34c541; - 040000000000000000000000000000000000000000000000 - 1dae71958a2d1f4c332bd9f343abb658590e874b4bb4ab807773e95bb42cf82b - a87bef2e0ce41b11221e01b86192f0eca8c89fe36b119933e832d9b317abe3e4; - 080000000000000000000000000000000000000000000000 - a77d1b5d96eef9626430b7e785c2be959a590145b9a61bcb9fb5044f3b923908 - c9cb7b952ad619267f7a7ba9420f6e3933d66c3a3bd4c4ae3229bc2b462db40a; - 100000000000000000000000000000000000000000000000 - c1eada4d6ace84fc75d62263d98c696e2df8207bd62981d48abd2523dde36862 - db58cc33ea77f996d3d7688c7b6072a5e7d17ab605ecc15437b5bbd4dcdc5b99; - 200000000000000000000000000000000000000000000000 - 8b76cf095a4d226114ce825b21d0548fe181ac262ce014fea4d3a4245abeacb4 - 17584d0428af390a9d0f8c51a493870f7feafea51c183ffd9594fc1e7f41d8a0; - 400000000000000000000000000000000000000000000000 - 386b7fb85d0c186aed83e7c88ace5d6246ec46fcc3ba61b5e92da090a0754071 - 17d13a676e2a474b6ebfb05c4011cdbaeab55275c5f702b2c40c772a76b08339; - 800000000000000000000000000000000000000000000000 - 874247921bb170b486c9e211aaf4f27133550367d8d759894b9e429ebe34908e - ff52d5217ebff26f8f5be14884fc05a9771997a062892f75700ec9d0f4d1173f; - 000100000000000000000000000000000000000000000000 - 399895248799ad09b0e0a870717c7093e959e07b7ebe416cabdcfb57286a4f34 - e3702614230bc36ef9b87cb99d79aa4cdd9e9d18d18ba4ca94f250ebdf04d890; - 000200000000000000000000000000000000000000000000 - 392524e09fc57d2bfa227523fef0bad4155ea55f8a848464b7b7c005f6130579 - 9d595d7b010214a82e295f3440a682601764080288a2bef2fc208f9ed728110d; - 000400000000000000000000000000000000000000000000 - f49c44ceca01eb2d6ca71ae5b9363445261b39be75c75f0c054c1de37d95ed5a - b1de2734994d1d0d8b0ec0057ba4fbfcc1fb6ac30620c327c9161c18ea91e942; - 000800000000000000000000000000000000000000000000 - ff5b158392cdff642112789624b80d177aff782cc1a0ded6ef5a6da5230abbf2 - a844ebaf2b4f0c005d5e0345f7b3268a401181cfca767970bbec2c65e739ee1d; - 001000000000000000000000000000000000000000000000 - eee541e6da8eb4d6ea2d0bfe3eaf5c29df99da4b258190ba5da5da8e8ca97819 - 04e41aaeaa28c8e1c7e113e3cc1734121fc73804d9aa9ca4ffe8ddc896eb723f; - 002000000000000000000000000000000000000000000000 - 89f6a98d1287e78538d98345aeef5ea194a30bdd61d708010f3a3e8abe347774 - 1ccae829fff9e409ddac526fa4b4393fb9b91783d8ec6ff842321b830979e4ef; - 004000000000000000000000000000000000000000000000 - ceeebaa4ef1833984f356d6cbac91c98b032f8179a2f0ebb078b45d361059b6d - 57c5a1d7c45a9cb0cb1ca9832f23d598cb253512372406d791539b5ba788936f; - 008000000000000000000000000000000000000000000000 - 12455456daf8787770ef743ccda298d054122db7520cd1bcfb87d81da2b94aad - 4a849587efe4291325f12ab50cefdf56cfea5e2137851021cabcd8e93230b3c1; - 000001000000000000000000000000000000000000000000 - 07ebcbd8034e24f2af24d3722dc24e897756aafe2f6c7b22174b319dda5753a4 - 85d342b06d631f4975fc5ce6b7c6839cfe3a5d3837a132aa977a631719233573; - 000002000000000000000000000000000000000000000000 - e5c7b3af8f548c6684e5026f317cb0e3a27fe8c0550a5527cc9dac57ce767143 - f215844a8622bac9330dcaa70e0fd34bf732a9556a6f653d798b48f23659a643; - 000004000000000000000000000000000000000000000000 - 348bdff0e8f4b4490b2ae937b1ea6ae55a05301efd0342787184e8b8fe98f561 - 1f71659657bc15ce1c9e3d2a6e7a78fc0c8d337899b9268eb3bfe0b6326c2bc7; - 000008000000000000000000000000000000000000000000 - f72265f6266e5e3d810f5a65540206134d7e6f0b61335b646a5cea952986e5f0 - 1afa3d7fd71b74805878066b66cdbbe1151d64324ab82ffa6541a5e43622bb2b; - 000010000000000000000000000000000000000000000000 - 71fb92a42e7522fc907b549b8e21be2f5e20f926eb1db7e551196c4c6f9fd49a - ed2e6b920912cb498db549b149bd50d7dee9c2065643968fdcf6144e79e60ca5; - 000020000000000000000000000000000000000000000000 - 31d89b14ae2f205e80b1ea8bb265781350078058040cfd6cfa007e590a0d2975 - 8b57df307a928b8f04640d5602a31077f62538d711dedb4b0684a1f20d65ac57; - 000040000000000000000000000000000000000000000000 - ac0fc0e2bfff393b95228ec598d065969643d940bce158b882c4214dea7afece - 34eecde2a39bb9c4714f1f071f152c0058d1eecd56cdbdda05e747b0bc6b807f; - 000080000000000000000000000000000000000000000000 - b8379d824ecdc66d335d64670d4fd20d3d1a2f632c845d9630688ddd5c64a661 - 9332b14faf54b15574702406ec02a7500defaa0de2a53ec1ad906ad8e6158e63; - 000000010000000000000000000000000000000000000000 - 55adce8670eb35789c2b4f3c3f2a3c461b1a88131cb4bde0a54d3f4c886216fe - de33b8f153920f6f4a3fcea1b31618990d933db5a20828b143e5349e85384f0f; - 000000020000000000000000000000000000000000000000 - 0e72d86ce21c254b393a2078c148cc6158d33ebc471e74ea9e7edf7bf936218c - 7d19909092cff079bfa3854e6753967012a66277cb65771cec208e379c671f9c; - 000000040000000000000000000000000000000000000000 - 6c5d6c93ef13bde1eb5f205ab7379e9764aa5cb4bce63fd68bddebf71ac6d750 - 64bc9c9bb728abb28fd2da7f958c16d120269d103e406aa17107a4d7f8d1b4ba; - 000000080000000000000000000000000000000000000000 - 290a101970cb6dacbd175f3ca67860e10cc5ffa6e7829a40df0cc04345744de7 - f0d4fb87d679b178dd0fb39d754e35638266ddd66f61d616419c867c52398c38; - 000000100000000000000000000000000000000000000000 - 2c9c6a93c3c41f66cae82a912625b939203193e4cd0bc67dcc1ab882af0fb2a8 - 00307a8c0c9904b84973bd324a8397c4aa159176f0ba3cf4771f40a652151342; - 000000200000000000000000000000000000000000000000 - 061dd076bec69c3870f387a1d74a5a506e0ae64912b850829113b9db9988e869 - 029977f0d27d81a985781061a05477fb032c7a5b6bea7365510be2ce8e3611fc; - 000000400000000000000000000000000000000000000000 - 99e9d96e330e25d7d4d74a82232a6012c7b0332ac209985fa99a3eb4cdae4285 - 045480ead04b22fd287620db1e4b333d7d191fddca5539cd9ddb1b5ac51ba37d; - 000000800000000000000000000000000000000000000000 - 1b3b4e1eb2ceaded0eb41e2d4ae3169df36d87db3fc7c6c5df7e06c27e68c60a - 4b7087216d8396b8274fddc2fa2c300eac624313e62eb924e09eb6f608895aa4; - 000000000100000000000000000000000000000000000000 - ddbc04456d25f8af3cbd2fdf819256750c07fede724710b370b767ab6f3e777b - 80e07a753961ac4a46dbc1f3c2ac510ee59a4e6c06672e67acdb2f9d393947ea; - 000000000200000000000000000000000000000000000000 - 355e89d48b6ad74e2c253432722b3896ae7296c9e83e76f14e78b0f7e5fc8580 - 5d0307032aa30386ebf5f07b4a05175b4d3f460c95599b9de4a5098d645754bf; - 000000000400000000000000000000000000000000000000 - a692bb60016d3849f8e31b5c1956f809264aa39ee0096120e3c04466b4b72e0c - 0183ff6d49c4bf650117e1ed085ab2b3d2d4614209db86689c98d9b859b3a5a6; - 000000000800000000000000000000000000000000000000 - a1f561c977e24c5da0b75ea3706804b868223245259dcb6350eef44ceda2c248 - 2a4d332bd753a98daa3e3d4cc3fce08319b0aee1b6a710af18f6604e6cacce51; - 000000001000000000000000000000000000000000000000 - d60a120d9cd41286c8a39d0a177c75304383017cf1fcc07cdaaf8a69290e7ea1 - b1c53a187c59bb9490c50a8f10cc3ca1c6a5a3970a059d461318ba7a32b1e8da; - 000000002000000000000000000000000000000000000000 - 57bf964c24d87f4e1bc0c301d912b61ce9244022f0b566ffb0c0f2e6acde4ffa - bfc70c61151cf16bfc039483b8a00f3906a2d151c44b9e684d0195e0794c2862; - 000000004000000000000000000000000000000000000000 - 08af63069dc10fbf50e649321cd8b1ee039b7691fd6399d81e3565edf94b8193 - 54de4c85b5666702354f8ec087cbc0640faaf8e8d6c304ffbc21aa439943cd18; - 000000008000000000000000000000000000000000000000 - a77e3c5155aae9fe9baa0fb81cf9b2b60a70d9adf420844e9f8b01883706550a - 403b00473e00a57ef3822d0bb6d75a99963974ffddacb9d4e5baa9ba47deaf2f; - 000000000001000000000000000000000000000000000000 - a667891d3c97262683fa83a7b781d6f6b987888dcfe9f6b58b4ea8bbfc22eb26 - fca3b57ec70df2d5093ca93b2235be57883e1dc46f11a9eae73e047f1d2c5cfc; - 000000000002000000000000000000000000000000000000 - 1af42c0f7468eb361d4f56f3e5f45f5daeb1c2a25666804d685f1584d5ba30e9 - decc0c6bf3e04078c839acd2a62a4184aa1a1097a630a4e40012e9beaaf26a0d; - 000000000004000000000000000000000000000000000000 - c15c4ae428c067595c5fbcc12bae69ad529b7b114d30274a70a0a51e4f87a7aa - f02e1d8e8fe536918a9e62bf48195e8e45f8daad77718d78f223acbb8b8390d6; - 000000000008000000000000000000000000000000000000 - fe4a31645836d26c668ae9348047765294d707d38587c30e31493e3b9efbd239 - 021cfc4d6d24bff9ed344a57a62b9e9adc0fe0fb8b0d2a4723ef756126fe28c7; - 000000000010000000000000000000000000000000000000 - 2bb1292e04c105a871dcf6a366745441995c46e94ade34d4f7ef353e3732fb12 - 8edc70cc753d1a7499063ca76a49c49ecac4797045b9acef9bf93b363e1baef4; - 000000000020000000000000000000000000000000000000 - af7539c5952da58d8074de796697cbde1a991e0216edaf51ea363734035fc41a - f39beaecd22482bd6e1851c739a1a8de9d11c3d9c11a4cdb45f3bc0010cbe5b3; - 000000000040000000000000000000000000000000000000 - bfaa17172e854602a411f39bfe808176a30726ab4139799c2ae294bfac9066df - edaaf454146e8d399df89babdb13498cf57ec6419d6faa51a8493fe3f55e968a; - 000000000080000000000000000000000000000000000000 - 52280d21e201c397e77d527e62c85c23cc479fc81dfa10e19fb9d1ae84fe582a - c906c9878e2e36ed742c8ad5e39357e0188c0e5a59fa9d6c0cdc5831457deca9; - 000000000000010000000000000000000000000000000000 - ea223c68adf66b076da0eec9f38467139bfc51a4056650c25b1604fc7009b983 - 7ea0c34ab6f734dd80f82709f23a7ea3b3a426b2d2561d839eea4b33114d8e11; - 000000000000020000000000000000000000000000000000 - 9fa09dba1210f7cff3b54575cff0e91706f96ddee75d625dd98b55058c04641b - 707785567fd0c4d6982267bbedee319bb65be7e40cebef299b051edc5ee19674; - 000000000000040000000000000000000000000000000000 - 0462dc1e6dbac8d94b9b3f6f36909ee367cd21fe348a37f8eb149ecf77459c15 - 6f7287e3838fd23a5de96afa60eeb3e3eac80346645cb729849cf06e4574f93f; - 000000000000080000000000000000000000000000000000 - 5bb868af6de2f9814b2d53de8c4eb53597ef6bd7ad1a130b0f006b1e71b6f344 - 3e882386e07775def74428bfbeb380ddde3526cffa40ed4fcc0e98642dc9d29f; - 000000000000100000000000000000000000000000000000 - 2e5ad6aa5701ad5cfb42c92f6e1142cc2e0dd24d57a28430d3c4aba7818a11a0 - bf294d4623f8e6c683b29cbf1ebcf82338210199efdce2485f0c096b40bd3535; - 000000000000200000000000000000000000000000000000 - 6ddac861bd903abb303e8d7faa58939f6949bbcaa60341c2b9e2f32254154e61 - ce0f3955956a0e9b92d0611bb7d400bc782a61d688790a7293821accd4dd3ab8; - 000000000000400000000000000000000000000000000000 - 6c34fb5023d0cbed7e5fe09bca96c261a22706ad118e4f8e813fdf578f6a9222 - 4d53255e814b9e35f5fada8f444266a11450e21fc8cdc11841071cbaa7392b17; - 000000000000800000000000000000000000000000000000 - 1d9e348d053585d72af0d606e2a9792646fb591ec72c39e73895100c538e929f - 6cbdde875e20309dcd32d18fe4c31c98274f10cc88811a14db03b002d1651bad; - 000000000000000100000000000000000000000000000000 - 624c21fc425a9fa178eb5d8346050301d655bdf9e948fa79dd2b659122ae5864 - fd411dad007bc21eb90442ffa404e205a4c6037dfec390ca055c2d1ba0d835fa; - 000000000000000200000000000000000000000000000000 - 05a695c429b54c6ac459fec77cdf33a0e44d5d1f4dc6679fb4d1f3d07b35c984 - ec983376a5c111ea502fb4accc49d7d465f1645b747192969ffdb7ddda5769fe; - 000000000000000400000000000000000000000000000000 - eb0221e48c3562cacc4c31e2dd24cfc04aff04addc4751d747033be31d7ff0b9 - 6d7d733c19b709ff780ea3d71e47faa447fae866c5bf76089abf4c09bf6e7f15; - 000000000000000800000000000000000000000000000000 - 852be3267c18c0a005af19266019311e17ae0a266688398def4fe1a6d0f5ff8e - 6ad20d62c5ca5be801698d6f43654c4e8b895a5bdd7bc1d7d9ea04d876f8bf54; - 000000000000001000000000000000000000000000000000 - 2ad2d89c102216f17a52aee77b8e812d1d0102ab13c65fba559cab28682300fa - 9b95e0998f7112dab5de7f64457634205d654ea4ec4a32076ba30cafb218f801; - 000000000000002000000000000000000000000000000000 - f61d03a67d0209e4986cd503c3a0d6d5314563e11a473d7fbd5fe4d913eccd05 - a3c39a8321366853d78f1ffef9e2df9b09abe5a0d67fa0b0c0b02a653c23a8e1; - 000000000000004000000000000000000000000000000000 - 8053b9bb606dd5f3e6fb5ba949485fb0be1bf2f3be881ef57d8ff653a7a2ad97 - 29c8a343460b0eded72a0f80b0b266899424195a8b3f5662abae0d58286c2517; - 000000000000008000000000000000000000000000000000 - a52ab95b69c30484126546b9151f9fea89b6d479391b097c9f636abe89b123b8 - 1f76b1e1d8e7eb427115a8e7fb239e461f67bacece83e576979623f86badd31f; - 000000000000000001000000000000000000000000000000 - a7ce6c6eac537320138e72f4ed71b57497132c19f58a3a0e864ccfee8f13e243 - f31e719aa7b0aed4e324c1406fb38c7b574706555561fb57ed4fd59565b285a5; - 000000000000000002000000000000000000000000000000 - db419afa205c8ec1b824f9ab843f1bc377062337149291e559600148604b93cf - b54b0859085a9a0581286feaa0d2375f0e73ee1d306803f405021050406f6760; - 000000000000000004000000000000000000000000000000 - c97eb377cd16f86cd7efde7438d678933d5a76cb0cbf4938b00756b42d3986fa - 5535c0c0f43ef9b8b78b532ba60fcdc5dec4428ad62fd36af221378e13b59cd2; - 000000000000000008000000000000000000000000000000 - 9c379451bacebe09fe466301cbd2f15be7637a6d992b7e67ad25efa503e19da2 - e8ed8e2367fda7b029bdcc7fea10bfff2fb9ee44017f63794fa45464e60e906d; - 000000000000000010000000000000000000000000000000 - d806c06a1f28c1a7a03d11529e298069f38713d0113255cd7260fe11dccd2459 - 0a6d37fc381c2cfdea6d2dcd4ee9873da18c46d028fead0861e3c0ed6d4afae4; - 000000000000000020000000000000000000000000000000 - 3e26ea35664eb065ea94e6c8536af313c938b01a4ddb2145c907321084d1effd - 3d7efc858d2c97fc00f2f0edf39d38e5ec673c99de7238f704b809140e3698a9; - 000000000000000040000000000000000000000000000000 - c21ed702582aa1d8259b2c892c6b4a0c55aee1382fb64d4c9ef218a8bd8fc0f2 - b71a4d0e405d55d5001e92bc2cbdb822b65cf12501b8186943fd471568d82b42; - 000000000000000080000000000000000000000000000000 - 0595bf54addfb813ce8cf9a40a072e1eac4022f848bf4a9955617e1fa4a64f0d - a888376775afac427e11eaf788eee2854e2c3dbb03a2116e3f082a24459e79e3; - 000000000000000000010000000000000000000000000000 - f7c300b01efb460b636c7af17379662cd501c7e6a0c7b86315127ba7a20f238d - ad9876d442b0e84db1eb82d3c3f98f768cb4243107d05ce90952f4afb89e3206; - 000000000000000000020000000000000000000000000000 - 7922dbdb167fb4c155e062c0d5aa8b2868b893ca2cae86df02c776871b48a8ac - ae3720bf2f5b7a2fc753e87251e810e3c5d3e0960a4cf6c1985a2a0e7838ce03; - 000000000000000000040000000000000000000000000000 - 8c8a5188f9ea500e7ba44d0c5c5296292b602bea998940826972ac75a55d19fd - 75bacb58ec93ed5ce9c57a4830e0385998c3c92b6284601461e7ccfa234673b5; - 000000000000000000080000000000000000000000000000 - 855b265da2e77cec64a7c96360221ad7c08bc343ffc173ace59cf2c1f94d7248 - 6967ef1cfebbc0ad1f54833c93232d5623abe3f2a34e0a24b9688783c3a9e5a1; - 000000000000000000100000000000000000000000000000 - 81db501d3f871e765776d8d7750860c36ca39a73baea80df76168436e1dc282c - b12600493e0d643ad4c5bce38f4ff6170d582228eb9f4fab66eef8b1e6e60399; - 000000000000000000200000000000000000000000000000 - 69fa38fc792f646a679f2c69f886f1e46d0d98ae7648b7ad51bd3d92ef09e2ab - 2ca758e5230bb97262bf6ca5c4ddd5d3fc8f566561b297bc139cea05cecd517c; - 000000000000000000400000000000000000000000000000 - 07fa8e571b3b715b7adb4a0c1a42a0f5617db1ab04a3ad9d6e3f99dc392643ed - fadeeb6d2032e571c2461e588e7efea5e38b2214ec23fe7b4a7b60c512e8a66a; - 000000000000000000800000000000000000000000000000 - d86ba78cf143fc53aa651f018248c67331e69be66a33b44b3dac4f3f86b293bd - e91b1044bd8bed5ae2cfb269d6fdbd229cc6c5a0cc560acddaff1fcc7dcc939b; - 000000000000000000000100000000000000000000000000 - 4474e5926f15e979554b25ee62ca5895d69ba5f7b7264d52e936a5d7e218b7d1 - da76d56dd52888a891d31d09a2698d6605e279d90ae2f55bdc01775dd816e433; - 000000000000000000000200000000000000000000000000 - 5cf87fb984e1765a31e392dad79752549f6f9537aa800671cdbb0d89cb9ee6f7 - 309de2c3260c2a08340ce164b7cd17ff93d1939f3949fd5dbf46f75c5f13861e; - 000000000000000000000400000000000000000000000000 - fdef588c63309dab2aa804e9d897034fc81b6f1d168cb3f9976eb5a6dfdc52b8 - 83564b42d78039e88afc04e3f34b8863e7f94b4dfcc8c8c22e22f7dd17a9650b; - 000000000000000000000800000000000000000000000000 - dc29b2dc786b940f80371a1b1994e59cc5ea72348f1415dc9b9cb13af8acc81b - 0656387e108812013b668a343044ed99e7239bc1c4e8e2698e8cb7998993b1da; - 000000000000000000001000000000000000000000000000 - 309bd7d5cc9be260f1b43a255989368fa3a0fe7451c982fc7393b6bc6c784f60 - b1327d75358cefb96216f21b4432b1b603ef504186470991c12e21f4d42c609a; - 000000000000000000002000000000000000000000000000 - 2a4899c9dc7dfdccc936fb1308b9b43c8df1eb6537fdd1b5084b44c71905d71a - 50b7d28d9599ec0558f1cdb5bd28b223585b7d7f4e3a11c2f63941d99baf82a9; - 000000000000000000004000000000000000000000000000 - 8413c2819f780bb3a7d51aa0144d74dcc8f66f2db12a5e2dd739df4002355aff - 8a15145629c86c5c699ce2a012ee46dff8d81d86f08c5d9b7580d30558adb269; - 000000000000000000008000000000000000000000000000 - ab65bb89011ff73cd9aab4fc39f31853f3214768a6a0fec7454551dfc1c67648 - c92067f0ed0db296e72556344a39ee1e85f3690e568a47ec635b6a38935699f2; - 000000000000000000000001000000000000000000000000 - 6ef6fcb11ce017ae7067d34547b1e996d045b193281ea44245a348708d896bd7 - 5d85c3700c5cc45a069469a7039f84334f7f068de6b5bb9c76c2af5345eba955; - 000000000000000000000002000000000000000000000000 - a748292aa251b84a1a518074dc24d42c9a491752d2c2c12511b2e6bab39c7157 - 03bf62836deb2ebffe32fcafe5db76b8a6e1ce3f411dcaa429fd14d0c86df3a1; - 000000000000000000000004000000000000000000000000 - 44a8fdd43b3829bfa1290f00d3f796d1a4340d81221c0b1e0428bdc16960558a - 96f6822810f9d3851b97c08616ff80f5f6810486347890cc682d551e34cc6655; - 000000000000000000000008000000000000000000000000 - 44fd0991d1c3e30e50af350e41c0676b016478fd9ec4c9c66b5fbb6fd0c9eab7 - 921055ef1b383f9de45cda31c5ca372ba5ac67918305cc1817dadf8346380644; - 000000000000000000000010000000000000000000000000 - 6535a47b9ff05940f35e68f6830b1edd6c1a3cca3c69008d77cfbc90813f2c70 - 7b3b359c5ea3575d730a4d6c206ae731f59cc538d7e7ea7065c16adad980eae1; - 000000000000000000000020000000000000000000000000 - 9bf44b4910301b9f2e6ef3841a6bee5733b34459acff031c39b9ebca609a9ab7 - dc57249ff0a59f590d2d1ab020e3beba7e95598c75bd0567055285e44de4fc5c; - 000000000000000000000040000000000000000000000000 - dae9a5b164e39be36b1acbbb357d414486098d20de2634d16cb9d04d0b5c5b9e - 0a0877b39f37f8a142fda7618e6c4a06fe02921461264fb7f0a68de184d2af64; - 000000000000000000000080000000000000000000000000 - 5e90bed387aab9681116b7f1e2fdbb47fffffcd40c35856c25ea58b452339129 - 318899c5f84a5ea7de2b391b4cd069ac2f341a820a3ab3241058d21018d5de59; - 000000000000000000000000010000000000000000000000 - e89f195b0e9bb3d7487aa791f436e5757e22ad78a5c525c367476383b88923b7 - 751b55b6122f2ca9459abeb94d4a65188ecb7a02ff43cfe10ad4adf68a9ddac1; - 000000000000000000000000020000000000000000000000 - 0906b6674e6538ea82a33a89a47ffce4fbb489e6c2efdb5d1b99031fd4c5f99a - a75f0ccb1495e7cf617a8aa9ea4ede5a2665ffbda0c4e7328a86395485f0d852; - 000000000000000000000000040000000000000000000000 - 9f58ae0629353e100d7e769c61b53516bb2a0c6b843c3d54dcb8049cc98d1446 - 0298031326cbecc865a64b254af3c187f97c7fc1370c48a67fe137985eba00ad; - 000000000000000000000000080000000000000000000000 - 6e65f3a436d028afa3cf36e14fbb09484c6d60c656d405530da442fc3a95827e - 4d44aa7d331fddc2b173191d70836ac2062093823e88f42418b1b2b624be7d2f; - 000000000000000000000000100000000000000000000000 - 0d84cffdcf30d929475439e5ac19e65414b1a987c17d39ac5fdcd1f88fdbea61 - bb2c7066132af737383955b50aafc2629f62ae9a0906cf063af6950c7d93edb8; - 000000000000000000000000200000000000000000000000 - aa89078f9b49ba132929b8cdc17f0c72f03485a3f30145eae08a37b8077b1e7a - bf3d4ea78a22782aa1978b42b88fc58ab4594bce39dad5b564c9603d9f18bcc5; - 000000000000000000000000400000000000000000000000 - d54d3dfdffaeab5ece06009b61de0b631d2503251e08f5d946439dc3e23c93c5 - eb4e97cd5fb0ade077a1e463b46642785d5df66693ca3cafe4073148d4ecd8d6; - 000000000000000000000000800000000000000000000000 - 2546c7077b11fda1d13fc0a58757bf47408f4fa6801c6240a31b0821d7294bbd - 7d6f42de54cd407eed7ffd603a9cf2e2e03d5bfa3f7a2a1adff261292f5e30a0; - 000000000000000000000000000100000000000000000000 - 2f8eb8d9a3f973e0657700dd113b1fe4a124979e54206ee368c04b5507539ae2 - 65398aa3cc2250c82a47a3812637c270959613211682d1d14fe9f70524e72df1; - 000000000000000000000000000200000000000000000000 - cd7604e207e7e65de5458e56b470deb55562d2fd0f7de38468badb7d30c1107e - 04e11299732ac33fbfafd8b73ea585ad11202a865c4d633c25e690580b527654; - 000000000000000000000000000400000000000000000000 - d0f99bf98c30dcfaac9a4f14693febd6e44eed176f86d7a9b7d0ff38f7ef9b10 - eb250f8278f8602594b53456dab86a4714943910985144ad7e1044877949c9a1; - 000000000000000000000000000800000000000000000000 - 20078dcf344356d93c8874fb3ba99fa55446d9082e96981d6e4b0bf25241dfcf - 1ef8439de2abc9ee2a524e76eb98773c851de2272e9ff82872de69120dba2e3f; - 000000000000000000000000001000000000000000000000 - 6ecbc7d196fd0ec594426f8ef67f04e3fb0b187616403c3d770f07ef83e839f6 - 74f801a04bdfc3aa70c62c8111989822e36dd3954a18c03817b4958900ea6fc8; - 000000000000000000000000002000000000000000000000 - bb295bdde6c445e83709b56a027ac1491e3da32d1e27a2d40d4c604e534cf5bb - 091799a866abd7ebf18e6ac9421d394b1247deaf31e8a65ea3ea5156b78ffd67; - 000000000000000000000000004000000000000000000000 - 34d2916c9570990e5a2ce1f8fd3f4d92fd55227835ae79729494c2a56f3181ad - bd9dc29b42443bdf687aad6aeb0de8dcac403e13f40dfab97d289f5d8905d68a; - 000000000000000000000000008000000000000000000000 - 6e8e0e6a1bcab3b9c4914c1b7dbad41180fd39f4077920381e6e5d43ae29056b - d331837650a86a752e106d56056d34f6c60daee1f2ca2f5d32fa3d4c4b11f590; - 000000000000000000000000000001000000000000000000 - d15117718cda91b580c8ee37b7e92a92aafb1bacef081c8dc4efe8d9035cc3cc - dc40f2cba1490588030c77a2deba609aefda9dbb2de7caa20a27dc78b0d6a35d; - 000000000000000000000000000002000000000000000000 - 85e78f287d6dc01f23c5a7e0f3a79f7cec29705c18210ae5da37a5e787c7b900 - 4b0f88ed23950fcd28af65ed71b102b108dddf354464430823ac654c89f8146e; - 000000000000000000000000000004000000000000000000 - 674696bdfb8b749f045e4901d5327e907608abc8a441acc85298c4ec38207d7f - cc25d43dc704c71f4e18d3bc796c5d12db5771d929aac483f51b11923ad032bb; - 000000000000000000000000000008000000000000000000 - f59b32955794603eec1664d94b565126b08f689979381d4d7371a1f02d5939bc - f6a18c580d6b019f0ccf24d0585b612a9d0194292880c2bcd329b16d32d32eaf; - 000000000000000000000000000010000000000000000000 - 8331de42dd7f34562c261a24c4206206fd2f7c82077daaf793a8c13cb7736658 - 64d0688016e1fbaa84efa02d12f38becf1cc3b49af8095c645e006245d04e7a3; - 000000000000000000000000000020000000000000000000 - 33f329a6f1febd546b8dfe981052f456f1cf068257d61e4215d0270b731cf416 - 8a1bbc62bdff88601e65eacb63f3b81188df1715dc75e46e80e8d4bad7d080be; - 000000000000000000000000000040000000000000000000 - e13972f07f517f8e11951b51107feb546906c2c9c9fedded414c099e65ac612b - e0cd462d9c2676ccb8f3395ee3793469dbd0ee8bfe9b70ecc64c1a3a7cbc1afb; - 000000000000000000000000000080000000000000000000 - 30dc82438a0c01fe8916bd3d50ba378ba74c7902fe123850134bd254de36010f - b49612b958bd2f20a3662304ca13b856c325fad90020638ed5824963a8e047fc; - 000000000000000000000000000000010000000000000000 - 8bfc581db5e81ad346b934c1567c30409d0f7260895d7ff5900791730d3a780a - fe79bea87199dda2ed990add427118e574a293bcfb9a7cb74dac47ceeca73c19; - 000000000000000000000000000000020000000000000000 - 074c4229882668f1d1b2fc749d8a839f23d247e01efd86bc569422904fe86499 - 420687e93a67c0b5c4e4c4f39f596f314ac56a18f1fdf78a671b50465d200f89; - 000000000000000000000000000000040000000000000000 - c60780f4ac3b1507ce3d9e899af33930a44aea6cfa09ea11df9894f06d54286b - 9fda5c99d571f89a8b5a38f4fac48c5c21ddc91fedc481a951a8d1fa6956bdb8; - 000000000000000000000000000000080000000000000000 - fc3f7afe9eab56e59f7ac6aac5255e74dcac9a467887fb1e047531aa6b7c946d - 200436b4ccbab5f0cf2d8f6987364e88c650e5c432372a30d9aa9bb6e1c2665d; - 000000000000000000000000000000100000000000000000 - bd0f3ea9e305732b6f99f6d27d4e29cfedf59b3e6b24052ce0fac6b055ec9eec - 57ac440ffebd1a3babc1b39aa1c19bcc9086f3a841190949d3fd70387a69435d; - 000000000000000000000000000000200000000000000000 - b06265193cdafe2055c504f94068ba76858ce5e8c1723ce078821158c653051b - 7457c97d616c01e642a7608045444fa985ce002df0a8b87033a31fa4110c742d; - 000000000000000000000000000000400000000000000000 - 5478345da67f4dd32024104c5c0eb13cf4165f29ad5f0c946e35eb44a6a4e97e - 0e56f1fb7c9245ac5fcd148ec00511ed693a82a2390deabfcf2f7525a4bcc0e4; - 000000000000000000000000000000800000000000000000 - 9f583a1aaab317311422672cb6a29c036551d7653bc11274a53c50aa28958310 - e381e3727134a1ab4dbb3944447d869cfcb9cd8baf5472f1ea55d0c3911b2aab; - 000000000000000000000000000000000100000000000000 - ef31cb4447629b94a8c2bf6c2479e8d0fca2a9c3bed40506bdd009b859c1a234 - 2be2a20df00a0b9473601282902595bd30960b6eebff3eccd2772047e91bbbfa; - 000000000000000000000000000000000200000000000000 - 822f1e0b80d284ab77242e6ea6a31c7b9478fbeccd019640bd790721b94fc602 - f81e837b98de88119be6906594a26b93342990a9e432808df9bc3ff8f794fbc7; - 000000000000000000000000000000000400000000000000 - 1b048b3da8ac57c867d65c7054771b0e0f0160b7a389b9cd0c2a4c2230ecee02 - 14d4fe78bb906ab8a1174bcb83b11dc828e284f7799be720784d2c8c8c9b60e4; - 000000000000000000000000000000000800000000000000 - 6d572bb0230a9c543f278d4e44d25f07a3e337fb6bfb62443cbf9f63d54d3d23 - ec8fbf1c617dfce2e2888692f4233252500f6370f9ba9aba9976346f0b45db5d; - 000000000000000000000000000000001000000000000000 - 8f0737b4a2c72a5401388a64943d931cca5100f896ffaacab6bc6857163cb364 - 4961e5c5d4983ffcefa36d2d31f013b55d339192be61f2d7d525c9514851b9a6; - 000000000000000000000000000000002000000000000000 - 865fc49a982f200c0ce91ca8389997385cea07d2054e215624ba915da86ab56e - 9f9f408687229eebcf6d6b11a2b0e0983f8166fa538fdabbf24b5faf7a5729f0; - 000000000000000000000000000000004000000000000000 - a265014d381bf64416498ec6cd0d8280fcccff8ad00a8af1b87ffb279a5f44db - 0f96100cad1c7d79f2c7d266c2676a1aa04e507613cdfc88a9a5b032749a6849; - 000000000000000000000000000000008000000000000000 - 69c3ce6588db62df37606f44388b5d743e9589338f479a42b1994a8649b35353 - 03e557b5d65d9ce0ed50e2e77365e6dac2c5534dd29ea0ff6d6f3191ecdf3ff3; - 000000000000000000000000000000000001000000000000 - 3abdda974690d01044e1283d277823fa099234b137298cd9edf814c7df994f1d - 0624991cab7a0f9eaf650bfe2329966038ccff5599c66af5fbf77ab2a7028ee9; - 000000000000000000000000000000000002000000000000 - ae97a705ea10bf85929124addd1d620aadd98c35157e1ec67827243a013a1a55 - 1f33262e18666311dc61128867b31a015996924ea43a468fac7f06421b117a79; - 000000000000000000000000000000000004000000000000 - 1b11cc975752a04198e012614cc5a52c7570af58acd7a52cd479ff25f422a84d - 036163f34610434f92b23d88b6b9abab66dbcdcb1b3681ab63f8126ff5f3ceca; - 000000000000000000000000000000000008000000000000 - 726d34090d8de7bd8892b9e20cdd176e425b49147ff02714e13e3ba4c0176094 - cd95775f2b5274867a6485b92d8fb68c43e5b18dae52cf2a9aecdf82fa2756e5; - 000000000000000000000000000000000010000000000000 - 438b7eb9e29d625f827dbea30ee486dea4b8fba4432b35b3f1f598a49d1e3efb - f27446705c795d27c75f4e152c40979f838a577485e87154ad49e141f3906bad; - 000000000000000000000000000000000020000000000000 - b3e751e53ca877bb58140b3830ed6ca88828ee8eedc414e46f4530368559724e - 1ef875af1f5a2bb7b3705060dca18a0bbd2944e9510d1cec7d5dca01fd030abc; - 000000000000000000000000000000000040000000000000 - 0d85bc30d372bc51fec89036f8dc2a9a0c44dc732a35dc986c3308aa732dbfc6 - 41e311175cf4715f3a63de6e9d09a8f1e1ed35c7dff4ce55452dff184c67ccfb; - 000000000000000000000000000000000080000000000000 - 2911634025868ff4d90af8f03797e04facdc14c995031b8c1d399a8fb54f7945 - a23be5413808deebd664fb8bf8a44616086bd9fcd7012a6b019a288f179a61e0; - 000000000000000000000000000000000000010000000000 - dd1c1f9aa7639f84405b4ee50a0af7c1da71bc4ca4d7a84037390039073926c1 - 1cecf7f9da8b89b1793380b3ec02a069dbf91804af70248783c6eac500e72b54; - 000000000000000000000000000000000000020000000000 - 357fb20348241fab58252324b651366750f5fa3cda129beb249fd55c520ee8fa - 7943f92bda9aa429f4c67f6c60fb64f467eac75cf674f24c7e7d2b96afe230ae; - 000000000000000000000000000000000000040000000000 - 08933e7505bc9dafaa5cd4742c4321dfeed5eab0db0e8a06922f66e9b2f1d449 - 80060d8f8c9c4e78eb37a9a0ab618a212a18b809b653ba6fba4f9223a895fd55; - 000000000000000000000000000000000000080000000000 - 1a75b005be0c2e4d5ecfd57407a92c1261cb94edc3fdb86201e4122d10f178b4 - 68507c27736ef6d31e5c4abfad5e6494659724880f0e14f7cd92e4f81780216e; - 000000000000000000000000000000000000100000000000 - 4168cb291d201eff8f05e4266aa8a1f458cb66e3b01ce233ffb41f8aa6e9a12b - db84289b819e513d5116ca4aeb480616a03d7804b41e4125b03de8cb3852d6d0; - 000000000000000000000000000000000000200000000000 - 44a8f5928c2dc60ce18587c8f558258d0a5718773644b028fdc86d3aea135a4e - 0fa47daf31ccc8ec352c84e860b704b52dea2f15969bd08ed94063edaa5eb891; - 000000000000000000000000000000000000400000000000 - be7aa43951c4bee8cb3d2fd3a4869f498bf59994128cc3fa0abe0c9a317ca562 - 8c8f3694ff0333cae80183e03542e563a3bc3c25dd36c016300987445b1c0385; - 000000000000000000000000000000000000800000000000 - 279595b2e3d27000ad59360b237948d578dbfe442129ce09c963ea2467883447 - 5b0366c4833db132340334597fa4ae42c9591952639e86c7a5c5aaa67eeff61f; - 000000000000000000000000000000000000000100000000 - 3d0e6083f6dd8af24aa64f4f95c02de180ff34db8a5967bf47a38f048ba1907f - e16eb2abd16c38a5a13461b1992bf3622545c338c06bddff3c31ff4f11bfd7f0; - 000000000000000000000000000000000000000200000000 - 7184ce9462840f4f061fd8ab9053c7074a6a3fcaaf1bb7c660cf0237770f16cf - 19919262f08dab0f920541fdeb8f12b7a01e2f4350c9e42bf08819fa3d7cdbed; - 000000000000000000000000000000000000000400000000 - 7e6d7e42393e2e8cf0dd13f0f8c175796c07312be0d038162018f9f059192bb6 - 222f78b280402f19ad7ef8fff7bb9baa080925eac811f9d07a0e2625b8d0d3f9; - 000000000000000000000000000000000000000800000000 - ea6608f32a44501ad7d272ae5d4a02ba172c0da0d2ebbe99e6acc74d782b0a25 - d9b0c977617742962071dd97d359a589f323442201ed8c049ddd19986d6a7e59; - 000000000000000000000000000000000000001000000000 - ac34522fa1a172f61671921a073eebcccffea629c88c3efb024def587e85815c - 5cbaed86ba8d85fe7a1b7598344b467fc75c425bca2e057e4d29583c1339e2df; - 000000000000000000000000000000000000002000000000 - 8ef6979bc1593327ddf83f3582ca3089bd28441d603a68438b6b8963d5d5be7a - 2f35459f0fe78ed10cc345dbe5bda63ca032064173ea2222d8a44183efad70a1; - 000000000000000000000000000000000000004000000000 - e7137bbea6d5f12f35607bc208a48f9af232ba192552783ec1f1cb2ed9390abe - 400a562793f9a5340981d297af0bf0cef8ddd966b4245192676aceb0b830cd29; - 000000000000000000000000000000000000008000000000 - 0c10c073d596ebf8e92b9df89659d7e395c9755f0bde20386da97e61e28edcd4 - 1c16a91cabc951a2cad46336e8b8d63e442bde79569c953ca9040638fe7a6854; - 000000000000000000000000000000000000000001000000 - f2c778bed0cab8b49b63bbd4cd2e4b3839737629c76af97e41256fb5a51fb135 - c459e872e3d85d83bd6c02678ce707d4b55cf8baaa990a1bce85297089777032; - 000000000000000000000000000000000000000002000000 - 48ea086a4b426c28b7a789f863d6078fa557c8075f151bb376c19b0333c7617f - 3619d9a633fd99cd676764ebf0bde6392726c71c09edf1cdf6a83082043c8837; - 000000000000000000000000000000000000000004000000 - 88887c189b997032785c0211647d16f01dee57453dd8ae457904181346e3387c - a01ea4e80af98fd522c73f363fe1f67ca74b2f550cca01e1a831a371818f0a67; - 000000000000000000000000000000000000000008000000 - d1cc08438475d0a365e113a4f6cd2b3f8dd0fd16f11a7a91a24d7d57bc299a76 - 5211117b058e16a42041313422e59b867c25234913f19ce0d3e8ba2c83a1b604; - 000000000000000000000000000000000000000010000000 - a08d0c7258596d8ac11e99955d27dc5e58c1a94f3122821cb62bb7750f8c86a2 - 828f22a04c97d1608bff3c343450975b321b1f1078f4b8bb8e392bfc3d6ada6b; - 000000000000000000000000000000000000000020000000 - cfa3d2646ed862a2f5e1a0012446f25b320368f817a9f6aa34679e8256b31713 - 18ed4648e98ef43131ea244158d550f391d10aff20a786b49a7206e0cb810a17; - 000000000000000000000000000000000000000040000000 - 9f3a7d42e935c1f2e486976714115dad69a44ab16a251d2ee8d59f09f752d43e - 9d28bedbe24fdb9b7d428a5bf6f290a0d3fcd4c5d3083e8dad1deed29278352b; - 000000000000000000000000000000000000000080000000 - 5c99b3f3fe50e3d2337417eda4801ebac775bb7505ca0dc7d42bae82ae9ab9af - 8f3d15786baead2a7a7a821f651b2cdb354da45133f8f41886362285e8ae0303; - 000000000000000000000000000000000000000000010000 - 465980c12032bfaff4119e7a258e0d9c9d10ebdd694c594eceb203e3b44ce3ae - 9a2ba16d5bbaef21e0c7c28cfbab685e91840ed1c6c7e2d9afc52110f000543a; - 000000000000000000000000000000000000000000020000 - 72a31c0f8e054b278ebd35af35661bb0bb23890d62bc4ff567883e8d6df3a64b - d5a094453f00fbd672acc45fc68ca31e00260b6fb0bad3e6c1adf2a6cb873a5a; - 000000000000000000000000000000000000000000040000 - 51ee7d952e9d6ab691ae0af0cd24daa737043475b208ff66adb3fa5c09f3647f - 36a7317d1f7e27f7cbe2745adfdc49ddbff3e6406da0f0bf79b5b64877ee94fa; - 000000000000000000000000000000000000000000080000 - 03d5fefc307c92f49299cb1561e8925e4b333530d1d39e6576d999d6b18e9566 - c80301e64d2a3c192dba0fa08c12a1ce1410185174b5e97f1b7e124418566dc4; - 000000000000000000000000000000000000000000100000 - 02b1c0b7e3d4c64bedd8ca69dbca551dbb34c54007c70dfeecc64f40ec689040 - 7d9f113f627086a13dbae2a8d59a60f0d9c59693dc38db1262a6cf63ce1e161f; - 000000000000000000000000000000000000000000200000 - 31aec9854efd20aa692d58e5f35f9715aa6744763e80a2b84c52e7746024e4f0 - e298bc6d65a88ef0dda69e3cdf8f39ec836881da986c94aa8e55ebeee896f376; - 000000000000000000000000000000000000000000400000 - b6b7b784d08b13e5e9bc1de7c580a2a84bf0ce0863ace791eaaa5c448e419b12 - a7f496e466a7d3a93f52a704b165bf1798f159d1fad3e3d33cda5551e6e81b33; - 000000000000000000000000000000000000000000800000 - 7edbb0b8915926a8a2e8fee143b729415135b88414a2009f0d5d1c0683973534 - 21b1c8e53b342159b8bf091b43534ee08f4584ab504dbcdab6ef108edd7addf7; - 000000000000000000000000000000000000000000000100 - 66b011b48e7c4d63065e119be7d76dc2fe5f4832892e521b3919a567f28d78cd - 883378f113fb173d55e21afac17b6bcc13c5b825b7b39c4587e36a7bf56d33f5; - 000000000000000000000000000000000000000000000200 - 36b722f7c39d54cb3b5fd4a891b3895d6da18a6206cd9228b5f890a04a732d2b - 5ae23efac307c817a93408eaab3c71fb182b8c339c6ecd86a04dac2ea551974c; - 000000000000000000000000000000000000000000000400 - 8c62713ee186f9c9b85d3b39433a8fc48005e4b772243e2c59a0b6c9c5f8d945 - fd48ec5913d2c5a24898454ee7d127a2b3faafeaa51f1eb6bfddfdd89f29f55a; - 000000000000000000000000000000000000000000000800 - 6cb6e49700ea40fc2250f75122c7658603d210b28fd5a7d330e7eb7270571b92 - faa3c13c45e6a6058fc008d29710e17df435ca6fe03c802390e66a1f5d35f448; - 000000000000000000000000000000000000000000001000 - e209f79562f3acae829c8ac46326527581961f6a9c50efaacf05cfc299770d3d - 47fa35bd28db056ad2c960ffbf195b6726b8ba70d0e1036deb00191e1007bc73; - 000000000000000000000000000000000000000000002000 - 039ac5fc8be0833d2b344b501949b94965ee8ca968d41f799bdf4788c69dc9ff - ea9f5b28839e0ce7da245f22957bfaa6f23aa9e91797f94ba41c563ff207eb24; - 000000000000000000000000000000000000000000004000 - f8b3de78e36105f66bfb9030186225b551c54719d03a327e477a15cdae4c442a - 558f352e51df92eaf816878a8117507571e77ed0af9196f621172ab63c57e96b; - 000000000000000000000000000000000000000000008000 - a95ec4094654e78134ebfcd6d99696b59ad8922953c88d4676e690235a07bec0 - 0904f4197e14bf542f25be01e01f2902e389f872389040754b4150ce17e8a8b3; - 000000000000000000000000000000000000000000000001 - e4e55a685ce73b8e8c38484cc3a095ec77d79d4213bd7e8509e634cd22794e76 - e52aea0a67ffce6c423f49f19799b5cc144430a97a4a11cb81a15325ba58182b; - 000000000000000000000000000000000000000000000002 - e82db75f9ac6e522e32c0bb59d526efb83041531ca7f8c10b50206fa1f5c0f95 - afff3847b075d3ba60d574c58dd38734e585c6835e7080ee22dd11fbaad76187; - 000000000000000000000000000000000000000000000004 - 11c10caddec7e7df6e2b3cead72466db28943603073b181c54586cd97668913d - 4892b31c3728824d569af42be89c87986ec1d7e3ba680d77269b6d66a8674a87; - 000000000000000000000000000000000000000000000008 - 8b10fe1f2dd03e24b962a91d341424db2fb31a98e99cc36ece76fce644e7626f - 42f3a523c2108ffcc693ac50991144dee446980819ca6748337b75212f426d7f; - 000000000000000000000000000000000000000000000010 - 268ca8eee4d8bbecea331da0299a3c7722ecc81f6d9e0f360365ae115be736e4 - b39d8ee9b20baf88f8073d5c50091a4ac02e050680ec0483f13896fbd08ee022; - 000000000000000000000000000000000000000000000020 - dcb7c3ee50078883fc516b99f8ddda0cacd6df989d7408b90ba4b79ca9aeee25 - a306a8182bf7d39636b924b1398bfd4a3eb54ca10a2a92deb6394ae6ae5635d2; - 000000000000000000000000000000000000000000000040 - 3e8bbb3bdd23331becabe027092f9600030a29cf101d49a0645fb19839aba819 - 3d0ef0e093c0df6b7a6efaa547dbf7f96c77a195e7f32791c02e8d6d84bbd999; - 000000000000000000000000000000000000000000000080 - 3001310564521f5f6cc2ff5138270e2b01c98f1e0e0df104f218a7bbd4c528cb - ca56375249968d85431fda8a0f5a94a676f725730eb2387673e8e2196530d40a; - 01000000000000000000000000000000000000000000000000000000 - 2464195fdfbc0fc81a28fb4f56453d5bcc3641a478bb8e217a12e81d209a0d69 - 764217beaa547cdc74d61dddb77759fa4a46818fd71b77ef19a66ec61bad44ec; - 02000000000000000000000000000000000000000000000000000000 - e093cbcd15d9d26d2299aa256ac0ffa9479e82a7e6921c22330459282c643640 - 2d6e17704b89f170344a816657e838141938dfcb7710fbd748230abd423a8327; - 04000000000000000000000000000000000000000000000000000000 - bfc89ff49188394972ac2fcc77e4275e8b7e190ad88ec18dd46cde1e8d08fb3a - 240721b9d03626e7222eb91b29b1b56effaa86b815c8041ab46f92fd86ef6fa3; - 08000000000000000000000000000000000000000000000000000000 - 4f8fae102a0f00b1ea06377d3d331df3b492d4038a01467998878f9ca6101860 - 2b928f67b786b6977666abcc44bec615d27ac4ee3f6e3e0620a32174b0428d08; - 10000000000000000000000000000000000000000000000000000000 - 1580bccabd91d69db6608f185b39e46bb8c2822fdb63f55fcfbfda08897217d1 - db3cffd2dd7293de5ac9b47dc91e8c8c12a4890e67a5ff9399821dc7282e3125; - 20000000000000000000000000000000000000000000000000000000 - 6b99c58f03c9ade53b87383363db9b60a1cc3ef8b81b13c146b2f3356becde35 - f77668010fc0f6ab4438ba294b19a62756316746da733e22eb9432e4b8d92665; - 40000000000000000000000000000000000000000000000000000000 - e711df4d46fa41caaaa9ef1db1abe8fa9d73fcfc2c8f7bc0bcaf238d88acf2f0 - f923b9ffc408776d2e79903cf46bd57b4243142de89554a6c42c535469f4afb5; - 80000000000000000000000000000000000000000000000000000000 - 6a3a9121b368c3513dd88522b3a9d1fecc6403f30eb1dfafabdb2467db85c4b0 - ffc4cc0d9b92617db41d1d9e1f71ea3962f57624f85c06cc774e0789bad7d70e; - 00010000000000000000000000000000000000000000000000000000 - 4cb64c389bcf6ff3c15f28ccf61486e2aace7c54492d2e52f91672fc1ef68c38 - c12c3d78af5ed1c2a1b8f03127a2b183ad5876c181ddaf0b55b7d275b1270406; - 00020000000000000000000000000000000000000000000000000000 - 39e2ac45e699af272119c0f264488b382a93468433ffb73066e1b052f0b95114 - e4859a08895657b444b0a92cd027ad01b2045cafc91d5a58a70d4881df7f749d; - 00040000000000000000000000000000000000000000000000000000 - be12959b811b7990538165d11ad379332c729f72666c2d177bff7c6585c4fdcc - 2da68a259c2a68a877d5387f01faa64ab6a537e11e2e4620b4edc957dadfc1c0; - 00080000000000000000000000000000000000000000000000000000 - bd27f6928a39f0404957f340701b23f529af3a4ddcaf3176f7e5b78f31027cef - 9df676b4ad16eef5fc3d9074ef1fd0286dbb7714679449b8059a86187013cfd7; - 00100000000000000000000000000000000000000000000000000000 - 0f6c337b825811e0f4afc216133a38726cfb6d6de0da7bb8f33961a2c21be234 - 14b48beec8faeccb9500285799ef73532853b8c7cf630d64ad934884eff923d5; - 00200000000000000000000000000000000000000000000000000000 - 96b9131980599233f75d381de365ee5d71706e880840e6f97365628a1929fd32 - 651b53f4d5f76fc3eead20ef4f8bdfce994a9f4411d9ed9d9a82e2d39966295b; - 00400000000000000000000000000000000000000000000000000000 - 90131368532a05827eaf2ae0c7f7486def928c0cc3c97364fb3a33ecdce76a41 - 1070e529c583863ea11745c08ad3511e25f00fb1f6566e9a65d15c4c5b9db9f0; - 00800000000000000000000000000000000000000000000000000000 - 9e194d490e2e1a13f067736c1b4c02babbaff92656b39f2cbfbf79bcef509d32 - d68bf125bc9d18f357263378f1418d0407554c006bea0d57fce3284ebb23e996; - 00000100000000000000000000000000000000000000000000000000 - 9edaf8d2affd9975fc6edc4d7551d745f3ef5c1c2e9b6e866ecac4370718f00d - 11538a9cfde310ee1af5b1bdb89fdf7235b65f06804c1717b50a3a7bada18be9; - 00000200000000000000000000000000000000000000000000000000 - 699a6253b34d53c925a3ca885546ff6f075ec5f8f2512556f5c9939dbc66521d - 94fae63abb388be332f694d27344004f9cff783d7e0efcaccf6869622f1a7a21; - 00000400000000000000000000000000000000000000000000000000 - c8fa8a591d52dfbdd4de31dc5e7e2e34c1116f9136872d482adacf6c4ae5ea4b - d5a6965f1bb3023d6fd54c871732bec898a322a815adc5ef4ee92fbba3292ca4; - 00000800000000000000000000000000000000000000000000000000 - 755e57fa2b60ea3d49217a983e01ecd990b9f801b4bd418ed9218b0e0ab6aedc - 4dd53d0bce528d27e721a7e57dc1cc996de9fe7a1a9b68bb166e4ca3883273d8; - 00001000000000000000000000000000000000000000000000000000 - d7fcd3441c6e19f5fe50a13e8df8efeb313ea4c3d5c98a4d0218a15d2fba0501 - 03b82200d043d05cd925deb405da6fe465da86a542a99138286dd3c15180b11e; - 00002000000000000000000000000000000000000000000000000000 - 5c2aa4b1da995bdb48012fb3597f0c293ad32d35ef0b1d18818389bf293c06f4 - 5cb31ce813dabc594db8769257f0f8d6f56228968032ec3faa6089959fd312b9; - 00004000000000000000000000000000000000000000000000000000 - b492eb88b267d7e8d5b2c4f627e0134f0948dc958c3f9c3b9d53cef81d395fe9 - c17fe250e789278e9f00eb8c4031415a534797685eb90b531e6034b72bf11a45; - 00008000000000000000000000000000000000000000000000000000 - b37285ea7dbf2e60444ff339c6675efcc427f8fa6d0dbd4ec23f0936b60a1f36 - a18f8cec0b0886c08e43b9ebac17c592b95e87e8eda9dbedd9d05982f8769e0b; - 00000001000000000000000000000000000000000000000000000000 - 5cc14e4f6ef530df34196f17746dd9b10e10890beac586e16603b0a28754538d - 8397bdd286cc5961b1414830586eb2114cbbe9f626ac355da9596861320277c7; - 00000002000000000000000000000000000000000000000000000000 - 18c5f953553658bfe311783c54e1d3b988b7e13e5b1a05ff7b725a1b3fb97815 - 14f9a5aa033cfc16b02ef4d7749e136521607a74e1d874d18b257ea98078376c; - 00000004000000000000000000000000000000000000000000000000 - 986ed4e41b1925be50769c2b9f3bf9c42060e69f4825b0b27eab36628f43e727 - 0ba3f96bba6070ab9f18a6a8a3bd38db4174456c0eacc8c52ec067d8f0baf138; - 00000008000000000000000000000000000000000000000000000000 - 29dc264f8b38836ca14e4635397a48a18a489adce20717d417c004cf39c9444f - 971c02c844cc79d7464f0b7ae3ebeb6ba461d1c257ae052127d6c35dacc7931f; - 00000010000000000000000000000000000000000000000000000000 - 23c02c0924ece0eca2b9a113953f86926c7db6973ef792b7ad30ac5146bc8c1e - d5b1e384a939c12b9eea540dd46dcadf861831a2eebce73b0ae8de42bd83504a; - 00000020000000000000000000000000000000000000000000000000 - a8001a31579cd64e94ebd9e4a18818749bb0f0fc01ebeb456b8c0e065142c220 - f124e79fcf5f18fe452ee9e6593b1b2b3ecd0f68a8faecdc09c04ff179b9b01a; - 00000040000000000000000000000000000000000000000000000000 - 1f01e394b147f07da857c34896d8dee3f7888042e609ab70df48268ca31dcc5a - 04d77d393666c558f69724357158eb7bfbbb05a8a38c5f5b48e082d2ddf39ff6; - 00000080000000000000000000000000000000000000000000000000 - ba3d2f96d7bd899d2d6142369471c133bdf1ab5a9a584745538c78631b095aa4 - 1f008bc2a6ae865927fa85b29a2c45304f09b8275e5ecfb62eb44ca5244b0937; - 00000000010000000000000000000000000000000000000000000000 - 8fe14f887a1b802593b62ee61d7bd8f2733db0babcd41652ac1185d2d18f578a - 1103c814cf73455d6dd34ba8846b724fb00d6cbfeca562bc97d118f4cad784d4; - 00000000020000000000000000000000000000000000000000000000 - 8f767cb1db48efa0a1c5d642152edd3a050a1114facc07cd41409bcac7147f58 - c08e42a5019bbe1275375549b91dd15819b71b8a7592152cf8d94e964860535b; - 00000000040000000000000000000000000000000000000000000000 - 82b7a2e84536cc2d2758df01658bae073b29b11339f212e320a3d7de2b14971e - 20aec4d43c582e1cef05b6e268b61a2f9633221ca785943ea7885f690242cd00; - 00000000080000000000000000000000000000000000000000000000 - 76ac83b90aea0742f8ade2be9b160a297d8fe8b98daa5c54b4be2e44fb88cc21 - 18d1c8486e2b6f25e3f0164c2c0417af50f2438431deb4d4965f0cdf8cbb39d8; - 00000000100000000000000000000000000000000000000000000000 - 0c2e937c9717fdd4868c019ee1bdddcc7ff68d5df4bf8175a59c13fe9ffa9ec3 - 1c754234c085b09ee98fe2049b0722502e0edc5508cca7190eaafaf90df3d310; - 00000000200000000000000000000000000000000000000000000000 - acc18876ae7cc4f1a183357d04e461987b1208b2b99f8d77a5544a07bd8fe89e - 9f73b6c96743fdf8e1dc88e0022a45e19349ca3ec2bd691f2e5d5b08114c99f1; - 00000000400000000000000000000000000000000000000000000000 - 88ad33df55b990c06a2d16d9978913c23b287c7b1e220c42477c46104503a766 - f0042fdfa21c7405dbb441051b9e0f9a31e6f007a0a8fa43f97c86eae96acd38; - 00000000800000000000000000000000000000000000000000000000 - a3579b6a7d1d0efb2ff2cdfcf23612c9b2650beda7a67cc46e1844ed0dd12e69 - 1ab34729d9777a4009e98a196bce38d4431729e5ea6901824c50bcfb49b657e6; - 00000000000100000000000000000000000000000000000000000000 - 966dab579c1d3702ddbe8656f9240b4efc6704391715442a66bec541456b5710 - 06345acc4e0e9682b21f66a220fada9b4f6d82504d3b73c8f6c89311dfcb1352; - 00000000000200000000000000000000000000000000000000000000 - 12e01acdffc14a9fa3bddfb492bc348bc0c95eebbaabd17948113e63ace4c51d - 9d40be7abc07a4cdd77219952ec81d8e1ef8178df21a2cbc927587c116c5e08d; - 00000000000400000000000000000000000000000000000000000000 - 1f9f2968843c0133d070e8f0617a545b55fbd9a659e1ba9be16313d7e24a33f5 - 1eb163f3918a775d7c2cf6bad06d42359d9e4d0f0596822bb90d0db104156652; - 00000000000800000000000000000000000000000000000000000000 - 1f007682755a014c1b88d7b541b296c7cf6613e2d5644517a49e0caab2f84392 - eaa620472fc4f60a17390cdabe5a9410646b2754f26d6490bd89d8bd14d63824; - 00000000001000000000000000000000000000000000000000000000 - 8071f28971756eac7456c7e41a8157cad949b67902f67b0186cb5ff521814381 - 7b3b7fd81181c132321b9e97ccfbe4983aab6c72dcde30e9172271de5ffcde90; - 00000000002000000000000000000000000000000000000000000000 - b7c03ef5de01672dd35370e37f77309ca808868dff56bbb094f9b0ac7c37872e - 653410001ff58bd0701ec54a5302c5dd95994b6fdcb271447477dc1d35f32b28; - 00000000004000000000000000000000000000000000000000000000 - 5057644476a033599dfc0b2dfe388660dae6c40828a464c931623997a3b2b1de - dcc23d1e17bceedee546c8452cdcfc43dfe3a36f0623371066a857a592b44c87; - 00000000008000000000000000000000000000000000000000000000 - cc9d90401fa604d973e99f78ea9d9e0945344f4098d2307f7402956de7ca915c - d877bc8623e95266ed10ed810f144ea4f7889636f63b36b478819200b06b2dc0; - 00000000000001000000000000000000000000000000000000000000 - 270edd6834636fc90df711b57e4ec2a70c66189d9f149b8c6691ee901dd76c97 - 776b8906523e21663f84527687791c7f625a3eb1d456d430711212bfa0b36ff0; - 00000000000002000000000000000000000000000000000000000000 - c8d389b72ccbf5df09926294aa3a548cc07fe5693ddb4a4e69f82f736399fbf7 - 5177a1928aa122ff0281da5954ec854b2fafc3065b9d636f08bf7c6892054894; - 00000000000004000000000000000000000000000000000000000000 - 99cdf287f3a952867f4aca8fca230fdd2799829786a09a778df717200910f704 - 3369a095516c39906e537b571b36537076baf3e00e634ce403017204cdc8a2cb; - 00000000000008000000000000000000000000000000000000000000 - 23613557e1e34d83b979d4740aacf64ff2e7c353418d351932af432b4c3feac0 - 84bb895e1e113c431bcdd2f3bb02259efdc882fdca482085f64bb3490217e143; - 00000000000010000000000000000000000000000000000000000000 - 1fddf34a6c90b4d87235c5851c031e9c6c9608c22b6bcd1f1988211f8025d381 - 4687c0880f5e092eb50faef790418e0dd5ef304b7e52cd7733cbf60c29e336a1; - 00000000000020000000000000000000000000000000000000000000 - 7a448bca6c19369a549a89ce4c077fac787ff47683238cbde1bf4109d66fe10d - f5814b2ecb0954cd18dd3e633bc67890f30350c7fa2a4e2ed7fda17c4c224572; - 00000000000040000000000000000000000000000000000000000000 - 6fae8a02043b344c817ab30fdc3709eadfd9dc3e50a260ad4ceb503f0dda2ca7 - 3a167f36f5c524677eb0acb05c715e614573e2c0a685a7e30bb9b111df493c9c; - 00000000000080000000000000000000000000000000000000000000 - 8dc4aedcc4b4e7b7f96ba908e1ddcf7f07d8d26db0f599c5228404fa2e5e7fce - 244309f24c16fd9ac28cb4c01c7354833be4d339754b8439d61c88afb7082679; - 00000000000000010000000000000000000000000000000000000000 - dd772809159b566a07beb6411bfb77d8511601aa33886ff217f3d6bea6b0348a - 512926d3ded3f02d9aff5795050f2d1b8c0a7be7f7ed31b3ba085acc7d54ed8c; - 00000000000000020000000000000000000000000000000000000000 - d74853e986ef4ed4fe6e23538677a9b1800fd309e46d7cadc0be6ebce447fa58 - 6fe50d1ee521a88ae60582ec2e89acf5bb55dc13db2c5f45b01f2e95b4c3469f; - 00000000000000040000000000000000000000000000000000000000 - 3e4b0bcf8c7de8760cc7262618235b6c76807130470bd84928652849bf2c424a - 88823ee8d85199139edd4f77810ba859047ceb0cc640d10a9eb418c08280bd8c; - 00000000000000080000000000000000000000000000000000000000 - f417f0dec902322fb3754d0b5f1e841837549ac42efaa46d2c31cbd5cdb7bbbb - 4da04434a336e640bda841c17baab0c0e71f048c092782019016ca6fb89d8e72; - 00000000000000100000000000000000000000000000000000000000 - e6a2f06bbd9b5d79ea935d8d53cf2098a4a838229e4b257258d5978c850f7086 - 9087fb1b85be7c7cf4fc0c3b89da6e36c7256190477b7d6a74fd1833c19bbbad; - 00000000000000200000000000000000000000000000000000000000 - 1ccda6c45abbc6010a3267ee4e43af80f52499a819fd9bbb4c3df8a063fe0881 - fa616cfd0404f965e3fec16148c60189850611b2d28f87dd1fea7f53218a53b4; - 00000000000000400000000000000000000000000000000000000000 - 4e98a243a3167f35843ce0ead838066ed5747725daa3298eb97fadfeb2a47b8b - 13b78a61908c40108d7bdae03e85ddf8d164ad161a6de1ca1f0e51a9d04010a9; - 00000000000000800000000000000000000000000000000000000000 - 1bf5711f13594876f995324a6f688ef78fae8ba70ea49c175a27ef75ec85493d - 6e3cdb2bbcc44b41b6e307fa774296889b4b5e92ba079789f60e9006b04d13cf; - 00000000000000000100000000000000000000000000000000000000 - 442d9ba00e7313b035ab128ba863df68c0a19f1a7e572198086d7f79744cd088 - 02bdecf5b7f72546612d60fa301e01abbfbbfe27b4710d26f0c5bd50ed50dbd3; - 00000000000000000200000000000000000000000000000000000000 - 246185ae4fd65b354b04f4fa186d700c49d3d9f5018a917a31042af8e33be63d - a9264216ce3b8a5ed76ce229955191d9ff66391b9792979dfa5d7c1fbbaf9c22; - 00000000000000000400000000000000000000000000000000000000 - 1515f8b044f42fcbc8f04ac3ee3b89ce56e87f98b72134225603777fd1d66c88 - 3cedbc3b1cf63d957f2366876810213b778aaefd83f5c889dfebea8c35d2d4b3; - 00000000000000000800000000000000000000000000000000000000 - 037337c0a20e54350483349a393194c5ce8f0104f3bbf2e9cdbdb4f8c93b4eb4 - a52ee568f98bcdc658f48700b7b6062d2951a110bf0f3e48548325ab9212be1d; - 00000000000000001000000000000000000000000000000000000000 - 9afcb8f2fb0c8f7957bfe3972ab4831c47c35f1deb5f01674637bcf4d0626d6e - 7239fe3b5aab7daeca3c9016771b1ef6e67b3e3eddda777e12e8657b3f84336a; - 00000000000000002000000000000000000000000000000000000000 - abf8f708cf84184fa21b16ce492317060ba039e0815f186b162efdb47be5ca34 - 03a023c9dd6ce45f68000261b0ee2f1a8fb549c8469bf539a785feca009d289c; - 00000000000000004000000000000000000000000000000000000000 - 115090529147724bb2280029f146ca67d19feb98e1d68991e3557b7f31c65731 - e4db5a302db7910a999a6b04d5302132b3f1a21d416f4d70d2ca6c9500b4658c; - 00000000000000008000000000000000000000000000000000000000 - f8c24f3510ab36e692191e520edd4b8f7ca62e4c38976ca74f5b45fe75f0336d - 0a20e557bf3112da79d211fafce885b2d2857270912da2301466294ab9bb6bb8; - 00000000000000000001000000000000000000000000000000000000 - 006d35fbc723cf42718e015af9aa85a58785fcf5139f031de5913f4a4c9cee1f - 79d9972f8ef149e5bdb2aea1855694834e88bc28d97f7506fd016e63984a3b09; - 00000000000000000002000000000000000000000000000000000000 - b6a8633cfd175b9d20f60805043ae68cd2e4b19d7306af279a476a1467147162 - ac59474a091105832d53ca2ad5e4ef74ba1c7e227bd484d582523c8e8814062f; - 00000000000000000004000000000000000000000000000000000000 - be3e898c1f7be5fea90ea6dba94fb56d73af2540130004c2beec5244d402f219 - 2e091331eacada55955eaa588b2d7a0b60cccb37bd8ac7c1c29d5567adb7d0c7; - 00000000000000000008000000000000000000000000000000000000 - 3173147bf3d87cfdaca80b6eb38a83f935844f04cbadae7f1de427533de75e13 - fd7dc829a4cdca020ef6529b6f556393640d97049ae1c0ad75bd202f09cd3557; - 00000000000000000010000000000000000000000000000000000000 - 597eedc7cd929393f4c1293f2dc579fa4f2afe807d5a2fb5bd0a896439be3183 - e8c9cfc002d3eb8da47c8528600f0947d6049d34f6e1b1fb0c2e1fcf2691c3c4; - 00000000000000000020000000000000000000000000000000000000 - d3e7c0f4191f1a9fc7f2aa84a60daf5162b8b591cb44e7af87738378f7804c23 - 2cf8bedf4b3a75974868365f6b5baaa8c4594812130330352f3edbc791a01892; - 00000000000000000040000000000000000000000000000000000000 - 35e398c0d94aac9865c5c693f3763923f32555817648121efdc2ecfc35fc354a - 395e5543d4a31c9539f5c0a62a407abccc8fa71f52c075d5ddd927ad17e56fa2; - 00000000000000000080000000000000000000000000000000000000 - 50ddee1bdc4c0f8f0d0c3bdb456a6e0a30c71b1e08d247841eda50a85c761ebb - 6926a97fe085da68d6527a538644790ca8f8a4c68f3ecf49c3cf876a53d97479; - 00000000000000000000010000000000000000000000000000000000 - cf136f837e9c0078534bb9fcfef063fbac5dd5b7eda010502e4aed7819745a28 - 9b1a9914ba2586855e1f108998000010796c128ec5e822c3c49f1483ea7da01c; - 00000000000000000000020000000000000000000000000000000000 - dafd823ea2231a3d6590214a7bc68b9ea6159daad95778f44f3c287476b24e36 - 47906dd563422e0aee32cfb8b7cccf6c27c33e07189ab94dbfdb3fb348076c13; - 00000000000000000000040000000000000000000000000000000000 - 2ea591c02005a5a83c6a5fd17025aee427825c07ecda07b78bc540013256314b - 79af8d2a7eb63c32ce27f241dac9162dde7cb6bf0430a1ac59689807c98c3b6b; - 00000000000000000000080000000000000000000000000000000000 - 340b58195ae4140093e1224f811e8e01fefbb3a61f87aba168836442c42fa094 - 4cde591cfdc70d3c8ad8f7fa942a84f5416c3758aab6c685e1c4cb9389a9aab2; - 00000000000000000000100000000000000000000000000000000000 - 2ab8b78dff91d272586a56a661ac935a75ca0ec6c2dc6bef69b2d27889499aa2 - 3da491825757927a27b452da2e8e72e5525264af26739977392968c0351a90f9; - 00000000000000000000200000000000000000000000000000000000 - a151a348620cfe87d074baa730916f8eb8373970261759c8079b0a88eeff2741 - e7d0a61a9258933ce905ff235b0287f215cada2453030a5c5aacbfe8fd93a4cd; - 00000000000000000000400000000000000000000000000000000000 - 68185b88fd6b8ebe0ec150d966f3d48e03c51e5fbbf61d272bddc84003951168 - e74bada25673f8bb50492cbed8b197af930133b104da958ed64f47b5dd61e68b; - 00000000000000000000800000000000000000000000000000000000 - 8ca43156c06749fcce60d345cea15ecdca2cdea81b1bdf82025900fc856dd365 - fd4c9ddd669d86d2298f5ef817e4516f8848a541d0eb4375eb2ea06eb1c3d681; - 00000000000000000000000100000000000000000000000000000000 - 722563e1f5a521e0084ae6699bdbcef49147bc2db9d08eca8a155a91eff9e707 - 2053cb249b323faae9778c1bff22eec9759a6d04f67487197004fc6cf790e1e1; - 00000000000000000000000200000000000000000000000000000000 - 3abf333bef3ae7f4f7c92a57195f758f1d116ee9c40978c24f435152b511ad98 - 417aabbc6aff1f7dd197c89c16fbcb87ca9b121dd19d21501723feb8a339dfac; - 00000000000000000000000400000000000000000000000000000000 - 2a1a82d29a6c710fb7d35b1b66aa836ae340d4a9cfcefc5045a954d5988fad3b - 64d9d9567db3b4372cff3be7c789a8bc6451311fe0ad9e527edd2c6a3e97820d; - 00000000000000000000000800000000000000000000000000000000 - 92748e1df36ce322398858729265955801e70528990c15e102e1bfc6949126ec - 944ec92f07e11a517fdcff7a41c72c02a3be354a2e3fd92cc2b6c03ae35a5738; - 00000000000000000000001000000000000000000000000000000000 - 93a79e8843e5e49a7c61b9adbf5869b70a24b1786f2a476dc9b2b4b7a6d6147c - b44c96b6fc150dea743d84a3406926377ed403eb619b870ce414ad0bed5c6149; - 00000000000000000000002000000000000000000000000000000000 - 613f858f69b87d4f2ea1287d2817ff708af8ca2292388c60ff64bbf772ad0014 - 9e98afbf45a14662e33355be5aac0e67a93389037ef6e04d72cd53c9f2091b4a; - 00000000000000000000004000000000000000000000000000000000 - 26a5c693be3a5082796dea97f05cc2da9a8e1d3ef60e810d104d2105ebf81b63 - f8765cb141bb16f91a002fbf0996a7b0ff8889c4545e2625bb870103ed996f7d; - 00000000000000000000008000000000000000000000000000000000 - 6d6ae36d361da7f12442c0c5a389f6aa4967d9e1b538512ccc4f86058270d714 - 4a5be549a0f0b646e97933d3b4d645a0552e3b1b9d5474950ba154b3fb243f6e; - 00000000000000000000000001000000000000000000000000000000 - cd97ad2ab79d5e6893bc8676fc1756902033f5e502f48723e0c8f1bd636fd5ed - 702acc3d216d71a16db827a4e53b16629923fe73b2f5ad3b5147c9d40b043841; - 00000000000000000000000002000000000000000000000000000000 - 69bfe6dbf88d693e34ba867a3faae2a545c630c033a168fbad9a000b0a3d63c9 - 8c11ba612c0113627f0703c930a595f03b132c77677385b2f55eb951295b50bd; - 00000000000000000000000004000000000000000000000000000000 - 474504641ebd7e5e886cfac4e8ab717829d7afc4653051a7ec4cb6136c5725cf - 2f671c3f45b8f697207dd3edfdcbd228fbace746bc9982b107eac863a755a645; - 00000000000000000000000008000000000000000000000000000000 - 403c4c767ab1fed06a95d0a42e6fb058092996c1e7f9cd74023bd7f7f5e65cc9 - c767847b6384b478668f053277ed1e655e0e0822d6504a73c2a97adb344c0c50; - 00000000000000000000000010000000000000000000000000000000 - be00a382ce11f4b574bfff2e48e622d25d709fa043d2fc7c8ecdce33a6ca7272 - a8a42c740d6fce54fa53651fb2b0cb0d8888d8999bde23cf6f5b42c8e2d1297b; - 00000000000000000000000020000000000000000000000000000000 - 823eba2a58a9c7a43b4781255bb178a00ec401692a9f3cb64eb6b86146a89c3b - 27e4c00de764619ff0956cdc0599bb20e92d2e39e2f6a5461311b357ba5acdfc; - 00000000000000000000000040000000000000000000000000000000 - 1b9c442bfd36d7b57e185468b3fceb4b928718b24e8fe9618648119df1d75345 - 7d89665bc3883b2d57e3eb097f3f66289e08c21ecc3d641dc2ee301be9a0b7a1; - 00000000000000000000000080000000000000000000000000000000 - e52301462399a0fc87356c8d3015aef445c71699a0016598756a1a89ba3f717b - 884a598ffbbb2a2ffc52fdcc89b46ea399ac6f46e73bafc7a851a6fbab090165; - 00000000000000000000000000010000000000000000000000000000 - 02429ab56ca22bccd71cc987d3d38b99bc6144e2c70e2bbd1158a9c8020c17da - 9a2f84e0a9669cb81d36359adef338a98a82da479028e3dd8485adbd89d05bb0; - 00000000000000000000000000020000000000000000000000000000 - 124eda8fdf5c7db30c8223cecc62cc5cd66c26cd29b4d0ea304f277c77fbb6ee - 442969316b10b8bfb2a65611b09a098910deb26468ac2fa906087f4c85e634c7; - 00000000000000000000000000040000000000000000000000000000 - 52d01eb026e4dcea52de1a1f1435fc008d246693f38ef05f1957dee04b1e7a8e - 3153ae837aab345e33a38cb4d4e7277dbec1fc15fba9a5d9124dde3d4681ca8b; - 00000000000000000000000000080000000000000000000000000000 - 5e15dfa8d87cde6e726bec2aab6d7c23d059af8ea25fbdfe349f9ee20d1fa3b6 - ce57c0f4eda33d4a4f89336649d50334ee4cbba06c2e3e61ab7a9406507b5a74; - 00000000000000000000000000100000000000000000000000000000 - dc9fa20173488d514672039328f6d51b58f8e08468543cdc74840178ecfda865 - 7faa9670311e55c500d83c0dad131081666d5e3efae876d5d4aceebb108caea2; - 00000000000000000000000000200000000000000000000000000000 - 18f4ceb5efe6105f7557cfad6a335da2a84939887aa9ea69bd72aefe2c2e5d94 - 782f9a52b35d7966ab285611567cc7ab48fea542533da985dbc14945c4fcdd72; - 00000000000000000000000000400000000000000000000000000000 - 770c3b2300ffdfad2c87e1b06245d4dae9c0bf98c8a0ed071c94356e24b35cb4 - cecf717190bdd7b0e9bded5bf59751254f10563f16e4d4e8439e69bc7a269aab; - 00000000000000000000000000800000000000000000000000000000 - 54c6058fe589f2fdee3379bfba956f77f6d752501e76ebc124d65ef45bb407a1 - e269e946d75ef8fcdd9ced031c21f7d14a4640b7fbf34d45236c2cef1e6e5df9; - 00000000000000000000000000000100000000000000000000000000 - 22628fc8d9ccc487132ce5b75fc6e16d729412de93b644c9152d216587f57eff - 1b4c46083ed8c87b31820641c90a5891f82397582d827dc7e53ed4690f12f8df; - 00000000000000000000000000000200000000000000000000000000 - 4c4c2b14336eeffe279cbbf23bcdff9f77e73e7e2b01f27ecceca8adc189b3cf - 9368b0e82b3bac88ae4d521a8a834f53ef6040f120c4e40513a5cf3f7f13b930; - 00000000000000000000000000000400000000000000000000000000 - 30d18017f87290383852b0ecd0a8b284c85a590073c4aabceb860b6b59edfab1 - fe477785fb346cc1f00550f7ae473f0d6c7406ecd2b85774ec9d70057bb30ada; - 00000000000000000000000000000800000000000000000000000000 - 30897b2e3c37ad2ad3d990e71a5a5d87fb696e43430200b63840b6a90ff6f687 - 6564eadc218e0753d51b472c3b8a16f6ace1f08ca436fc43d4ab566423063056; - 00000000000000000000000000001000000000000000000000000000 - 6b86652d2308db067793d8efbabc60c248487a662844d65731c9f352a0b11082 - cbd3b17629ec688bf2404446edc156cf2dae31b7d9e251212fa6e720a16caf0d; - 00000000000000000000000000002000000000000000000000000000 - 902742d8e4b5a14e5b2f6444cd5770169d82b4a084a754b334cd25cea9c4ed81 - b80ad89010cc9ce05d6d7976205c975e1a6c5dc5134d2a67dd0c984591ad8615; - 00000000000000000000000000004000000000000000000000000000 - 7c820a4af9bc911ba3f5848386da8219e0b46d39ce42dec61cde449f348159aa - dee9870c0c8fed693fa8354d3bac82102bbd56eab88b8127e4cd706be81c70b7; - 00000000000000000000000000008000000000000000000000000000 - 6eae2da5a59fc6b3f482c8807fc30add517914fce8b45d346e19b03680f7a08c - 3d8170b8496ae73d6be7e048e61c9a21072ef2023e2b76a744f2012c3a7cc3bd; - 00000000000000000000000000000001000000000000000000000000 - dc5e94f0a7bce3155d87e4e5a274a4bdd20b6268a78265ab00d8f0aba23b9a31 - ba700f0a95807925d6e72db3eada829f80050470b8f13db0a7f9528eae284e06; - 00000000000000000000000000000002000000000000000000000000 - 409bca4c7a1cc9d627010605c790802a9e91e08d6c7febaf6ff507c441b83c3f - df58babb7a632afc991ef13c3ff7f647ed1e073c027225ed5e713235328ad697; - 00000000000000000000000000000004000000000000000000000000 - 7c0429fd417a0023263089551cc9a497c6aa70aaa7f7dd1f07d3b760524a41b7 - dc5b1bf2dc4280dc044c094d4eeab87c9c54b8d1977fabfa3376c0f07ce2042c; - 00000000000000000000000000000008000000000000000000000000 - a287c270e99030621f52acf1588bb8e0aac7dc1859c49e331aad589ea94426c1 - 0d9779c3cb59c8589c6a336c9c459ce19d3db33697815b3a459996d24e950701; - 00000000000000000000000000000010000000000000000000000000 - 06923622b8250acedbdff5cad2f88a8327d7e07ceff7a40520eef9ba4ca7c7a7 - d4738c1a3aa671759b15fe887963eee5782fb1eda3421ee372a5217315e832e9; - 00000000000000000000000000000020000000000000000000000000 - 52660b96d56a3032a48e3c1ccca1ce1fafffd43b05d96e8ecda1123898cca637 - c5d66379ce7c299d4a1958bfde3b035d7e07af1bd640511fb12637ba7a28ed8c; - 00000000000000000000000000000040000000000000000000000000 - b7bc824845abe7aded1676ebeb1b5db28f7eda76830da2348c873d1d1bda24e8 - a3c9daf34c78459933f3d113eca779b8f0e412a140c04430d8c0369697c4f762; - 00000000000000000000000000000080000000000000000000000000 - b9b434ddbd0d969547f4e575819e2012d3429bc172cccad53ffafe9fae9eff87 - 38ebcfba6197d3dabc8dcc1bc22ceefafcd9734f2b0c2f91728480e35bc43d92; - 00000000000000000000000000000000010000000000000000000000 - 2058aadc3e731b05017d412a720696d297ce2975efc4bd202011d3aa43d12ed0 - 3ca5d92cca0b200af76f87b19ca01c328e44b4ce171d8444a42ea529c4586bfd; - 00000000000000000000000000000000020000000000000000000000 - d351e7ecdd3aa6c0826526115dee7a6064988947a22728073ad5d85c77bbc934 - 62fc94852584bee32bd1977fbf330e782385bad2fff9acfd2e62183a5b07d52c; - 00000000000000000000000000000000040000000000000000000000 - 4af5b6af3be9dc3516f7d0785c3211b8c86486b6d171d8653a603903bd592cba - 1815168c3e0c51a6c52848fa4c0c2459b1149854dfe234ea15e9c67be9fb9766; - 00000000000000000000000000000000080000000000000000000000 - d19f4e25914afa257fe634f5b88909444c4670540dd0775b67eba234441a78cf - ff79f959dd28be8a30311b64a9a47f9836966f0effcf80f003144a562ede9dc7; - 00000000000000000000000000000000100000000000000000000000 - 4664cd40879d3e2cf76b67e617ad300b071758be8dcdf76b2d2c3ef3f4538c53 - c4cb7520809efae915b15fdf7d45ff8df6c506e522d72dbaf576e6c724135df5; - 00000000000000000000000000000000200000000000000000000000 - 69fc75db35df38c50e9400caa21e4255adefd3932f01830f79bbe438c5c341f3 - 4e67c1fcb607d92f3107b3f7a84e02c7c2424b59a7beed3e4ad07435fca755b1; - 00000000000000000000000000000000400000000000000000000000 - a6db7bc42c9a02150177bcdcbff996d4e63639367de8a3459d5a422c0a391a60 - 390e3998a3a6b2e5a99719ca25e065ed20162053efd9e64574a679b0b5d9d66a; - 00000000000000000000000000000000800000000000000000000000 - 409ec85f059ce5969f275f36bcec4b7d623a4e2dd6ac4f68abd8d5d7a0a422e7 - 5ad305c93905815c67ed4c67208c50350e71c48ef9c4b4d2fe846dcac41a6cf7; - 00000000000000000000000000000000000100000000000000000000 - 59a81ede728ccae99bedba5ee8d3ac4499579316ae5f7109e2656c558a7a0733 - 2307ba4eba7da1e4a566e99eeebdecff041fed0f1549c595b14230fca2a1164b; - 00000000000000000000000000000000000200000000000000000000 - 0c6b0f0151ae8ee876698da2eac5eac9ba1227e13e98336a93fe3793274a43d4 - f3baa2841495261d6b156a5886578662bcbcd13fd68ac542cd03f4331273f847; - 00000000000000000000000000000000000400000000000000000000 - f510f5e9b370b1b34a4cde599cef0b80c4f657688239f3de82a12376140fd934 - 7ee1e4a96f8b73817a2b57e3e4d0982cb92e05ebb06348681d097d7f55cf12cd; - 00000000000000000000000000000000000800000000000000000000 - d7b38ec40b465126d428dad054a190a25bde83fe1f2ae87db9dc3adcc0bb660f - 04d42fb3907165cd7c1d75da7087da71ba524cbfee56fed771f16dc3e8e176b7; - 00000000000000000000000000000000001000000000000000000000 - 414f693e93a088ab8bb5cf5049d6f3ac67e654e786fce08559dfcd96dc6a3b23 - ccc0fdf2941815dd9c050fd1c9d1e9414492912cdee277465583384a15d761d9; - 00000000000000000000000000000000002000000000000000000000 - 00a7a468282dd455b469ed76c0d67e0f507a53bbc7fd1941e8bd600bea43b982 - 4c8795a55684958d392aea1409dd01020912380b5c81bc868629ccf393594930; - 00000000000000000000000000000000004000000000000000000000 - d1bff2f245ce0690ba74588794d7306c934ec83dd8d7811493726c95822a899c - 856c5179cdae63a65f1b107e0859a1ac790b014746a7bc7bb4385bfc9fff1630; - 00000000000000000000000000000000008000000000000000000000 - d873980acedd7383fdb371beabef1cd1fbb5dadd665f2f118262ad539a118153 - 59a325d64f1e454646459c72f81b797d534a6f8f0ccccc38a8ff47298f1dcb9e; - 00000000000000000000000000000000000001000000000000000000 - d8c4dd99bfdc3bc0d25516a7980651bb545077500e01e3b543cd72ca97844486 - f0334ce2c74691e3aa5fbc12a25d5d6a14fef43bd4df05a2f3f2c9b34d4f2c44; - 00000000000000000000000000000000000002000000000000000000 - f6959bea04ef9ce9e73c363959e28ab6404e8dbca900dd2284f2b848a109f768 - 81f4bfd5b8b0df8b32299d101d339ef40f9655962916b5219145ae074338bf40; - 00000000000000000000000000000000000004000000000000000000 - 411c1c715da711eaba6972e77e408d6f5a76371d10dc7a165f2150c89154db7a - 3d1b85da27fd34e9ffacf8703b958073366ed819459b1a153db135e4a5835ed0; - 00000000000000000000000000000000000008000000000000000000 - c57d8cec898496dfa1331457c00b2d1962c1df9788d36f155ab8b94e985aff15 - 92e1ca0643703a1bfc56842a4d6f87d2acf0ae3dc58935fcba5d847aab6bf920; - 00000000000000000000000000000000000010000000000000000000 - c16ad6e1a87c475ddc84d7664f11932debeed6d987cd05e9c6fc493b0a68e261 - 3c984416b43aa267eb6e0c6a68f8a41ee2a34e14d93839ec47d2b256289b4827; - 00000000000000000000000000000000000020000000000000000000 - cc414cc5970efd4418917369edcffce4be969ef4fd721b376e85f9eb1ea7d483 - fffe4d5022ba7bf9feb0d5e8c8a87df1a49dc2353edf5a2b9cb66863cfd64661; - 00000000000000000000000000000000000040000000000000000000 - b2c9d7c5d8ff0bb054ab8f440915839840e7c9489ac78045fd1b49e0581809cf - 6b0de74a81dbc155fb23b033b45f6b3eb6256fca7fbffb4fcf0ddfadc177659d; - 00000000000000000000000000000000000080000000000000000000 - d68ceb6c0de43d2a62284fc86b872f6686ed0ee6710539cc295fa290d46f3d17 - 3f70e4f08444b9bb7d03552aa0272fcdf3f30803e2608cb299c2880e63f7e24a; - 00000000000000000000000000000000000000010000000000000000 - c6dfe5c3e64ec36a7c043ffe4b119f4cb7e40acf0d1b61fd12bde9f8253f6387 - abd8bc56bc0d4c5d136fcb6af803493efc80f0f0d00fe47ec4dd70d455ab04bf; - 00000000000000000000000000000000000000020000000000000000 - c75facc882297be6c90d4d00bc8acc443c112d7f58a20f819a987fdb01ee14df - 2aedc8d591536166b58e3bb5fca7e63b348357762912aa6a83458186ef315c34; - 00000000000000000000000000000000000000040000000000000000 - 43113d85e6094d67cd03a9111397b014557a6850a8d796e16736cfc40fe0621e - 89730f25612fa04d00a1cc4732efeebba1b80c993238786386cfce09bf10359d; - 00000000000000000000000000000000000000080000000000000000 - 60794b89b36592975d54a0448e7708e6017d4027fa3891b0335cad062ffe8db4 - 0d3401a2c417efe1859b4b165e676a7a5ac031a89094a0173bf46529e0078adb; - 00000000000000000000000000000000000000100000000000000000 - 6bdfe911c6703becfeb5c205f11d2aecc6a81dc22c365b48c1929a81dc67f32c - 61c6c80e40ab88b27bfbbf703522570fd971e8af2b460ea72ec59a92b3701558; - 00000000000000000000000000000000000000200000000000000000 - 24dbbd8de57a959b62a1668e29ebc7514c71ade4fd64c40b482bc98057d77b34 - 671e53090529d3258abd0349e9ec5ecbd0506d211d6228f4e2babcc68699e5ed; - 00000000000000000000000000000000000000400000000000000000 - cf4174ad172064185cb5c1774f08f4e47767579f5ccf71a87e622605041ee5e7 - 8617dee6d4146da406e826d90003fd4f3a77a566d21b8e45649aac687450da4e; - 00000000000000000000000000000000000000800000000000000000 - 016f5989221bbcab0a3cc90a99f6e1f21c9cce56249855bea90eb6b0e3ff925b - cf450821f51f1c80221821fd04d9676d3a81f9c003b692a33d21f21d7054e6c0; - 00000000000000000000000000000000000000000100000000000000 - 00d2fdd6d13ecbde57f8346b651c3d21fac7c08c0d5624d27b77f70583a58c21 - 89de016c263121254e78dbc2df605a71de36313d855994e9ebdc45556e721749; - 00000000000000000000000000000000000000000200000000000000 - c5d03f396dc1b171f23ed0a25571c3f3bd773bb887aac4ba4320afa817e9b460 - c223bee85f757c23c67c009f1b0912d4370315f91cdcbde866c35ed0e205a848; - 00000000000000000000000000000000000000000400000000000000 - 701df4f85e7de8ab8887806541c49911f6c0f3038751d9c109216059df06cacd - a5e35984cfce2a1000a593cfb80f79e6e8c38d5791bb7e96344bfd3dfbea88b9; - 00000000000000000000000000000000000000000800000000000000 - b58876deb62a3c880f51acb743ad9eaa2119321e096d591b06f3dbca6ef924d1 - 829c940bfc3409ec73391740d7652466113ba5a5b03118376c726351747b8b34; - 00000000000000000000000000000000000000001000000000000000 - b6bdcc6d4af946d02f2ce1f8c04df35f1c1790a663ca40bcb57697d780365439 - 99624b3c7338e8f23faf22b4a89deee5fa8bf7022903db3fa36c6f9957a819a1; - 00000000000000000000000000000000000000002000000000000000 - 79d9fcfd5ddb19aa8a8eb84496eed8fc1d815f7fbfef3162273fb108bf230da5 - 9534a0ae4ba8babe4308789f732f6197c6867d222ccbc2eaa064d598a4c24ee8; - 00000000000000000000000000000000000000004000000000000000 - c6c6b524090066e3b3cf196fba642cb3f8c5aa63e734b47d45279e7debcbcb4c - ff20409e1bd929705cfc445c37924f4b2b9151b08839c53b464eb68a807f977b; - 00000000000000000000000000000000000000008000000000000000 - 4c14e7b11e9c079bdaf893fc1e6dfbc38f205e04373760e06afb6c5fefcfdaf4 - a01f116e3bef972205aabe1494f76b70f1c6372b74f79f4a23904c58b1b51fb3; - 00000000000000000000000000000000000000000001000000000000 - 2ab3bb7f3211b75c80b01b15ded624e8046bfcac7c5f88ded7d5e5e030992b95 - 374d7ca16d59e8b6b128b7035caded032134dacc94c88b549e3891282e92cac3; - 00000000000000000000000000000000000000000002000000000000 - 06bc1a54e4a68178acc810f2f9144d01fe6724ebf72225b67a0b138df10dc6fa - 27f3b1d7e61cd1c3b73f72e367a9a4f6fa4010c94a2cfe173850d832e45e89d7; - 00000000000000000000000000000000000000000004000000000000 - f9c484b67e531856f5134b4ada1a231f6f66e6a1d383fbb1e7fe7a7399a39918 - f4c1eaaed3e8c5e62c5573b0779afcbd197aefc1cf881392e00659e0749b2256; - 00000000000000000000000000000000000000000008000000000000 - 8e00b017b4c601c6ab9e606f19e1210ca98b5cf020a2874fbed90f3e9ee0af9b - 2998fbafa21326c14cc0eccf3db5bca7daa744a086e58adbd15537576a5129a5; - 00000000000000000000000000000000000000000010000000000000 - 7fd2a56e82a8a82c0ab027ccfb68acf4b894bcaf0c03ceab68ad3f198d9336e1 - 0ea3d8f711178f80f559bc8f4402dfbe51c6dae84e3fba861050513c4b63f8d6; - 00000000000000000000000000000000000000000020000000000000 - 12eb27967c9c4c286496836bff364450b767e969aa8b53f7dcc1101cdc535eb8 - b30dc7c5d8e4bfb50f29b1be19fd953c6f6d6250ec2f1b9a1fb4b457d928e98d; - 00000000000000000000000000000000000000000040000000000000 - 1630f9a365245fb0b5f8684e3b467ac06d34651076feff3f6718a9c37a1b58c6 - 3240790bc28be631963ea289f5a3266f65bbf0f86e169751cf7512e4c12419d1; - 00000000000000000000000000000000000000000080000000000000 - 8cfd772627622c4ddd26eea011ed6160ede81e488b3c651d4526a34449921724 - 5081e4d0a86395debd81de249553a4936a510f15d07c031cad7caa563ebe0668; - 00000000000000000000000000000000000000000000010000000000 - 2bb3f8ff8c4fe0f4e66073bb662cc09311adf20fb22d6464b4d778250b542537 - 69f83515e69eecadeec5eab86e2f0bbf11ba2bad521a6f21da06ac02331db838; - 00000000000000000000000000000000000000000000020000000000 - fc635cbb01ae965a24eb7e27c1f20b45fd2f2722918ecd8eb362bb52216ba279 - 0a97f58b8cecbb100f67b8d4d46ba01a8f68d6b4c7bd06e28ffdedd28e46f076; - 00000000000000000000000000000000000000000000040000000000 - b35aea1e5f09265b3b7b6748baaaa97ff46d7118491875464590bceec70b93cc - 962374c521986b0cd478f4353c06a28a1203da79cb98a198f3523206b22606ed; - 00000000000000000000000000000000000000000000080000000000 - 89e462fe5d5c5325c5ee9252c73530692c6c29a1a3c7f389f83d533ca1b1a83e - dfd663c857be90d098b8170eaeeb7ed8a6948c8a314a74599691335a8a18c2b8; - 00000000000000000000000000000000000000000000100000000000 - 47d9c74cf8b7148a6427408e3aeb790b355bf02b447bc57c6f8c05b7c51ee8be - 28e4223e24ad191369fffebf62c84059c519f49018427b41bb8b67ee9c820222; - 00000000000000000000000000000000000000000000200000000000 - ff3ce376a28ece62a73a9c00a6ffc69767e836a8a17b49b824a4ad20c0ff0a21 - 630c092e5521f6041ede8c61e73678198e19fb339a04daf94f9f923854f3d7ef; - 00000000000000000000000000000000000000000000400000000000 - fadd0fbf5f7d4eca5fc145d4aa79f7f529950335b9d45d592f3eab084c4e883d - 0f9c8706d1385a2f0ad3a0407460f86def321d3ec5072694ee0272740a12427a; - 00000000000000000000000000000000000000000000800000000000 - cd6248d7199c68291a4d828f24d534f6fa28e4b8706974f439e28625cf8e2310 - b9cde77e2e12ea77ef2ee43e153a26bf09071198249550603c63c7709ec6d090; - 00000000000000000000000000000000000000000000000100000000 - bdc4b06d8fc5e5d3b3285ab19e1210271170c1ca306b61c888230f1d1a6b4c11 - 2e393090c2212bc3e2ae80d367d4a0821dbc121a0b4b7efb989f980918fc3412; - 00000000000000000000000000000000000000000000000200000000 - 2e0b37d02fafd0b335c0e3da36d1b67ad4ff988f2dccf9dfa5722247133f71f7 - 52e68f282e5c041eb7c8d8bef21ef3c7ac045101b3f32211507f781f0f347815; - 00000000000000000000000000000000000000000000000400000000 - 327e75a7c2c7df51c76632e55ce0f3e54ca2cce1ca5bf9bc4dab9bb4c68713de - 49bb9922ddff6cd9b917a2697b399c7f0cd803a0f9ef25bbd06cad0c8a97d2e4; - 00000000000000000000000000000000000000000000000800000000 - d95ad5b34ade4fd38e6c02bce505bef6454349dfe71aaaeeea53daf6944c76ef - 5774340daa33bf6056a6f415c82df4e48da319997b38664fc2a9dc0acbe03212; - 00000000000000000000000000000000000000000000001000000000 - a52178fc875cd004eed999610933fe8db73387b935d06ea14abdaffd7d870452 - a1a6144b8ab070d6a8cde942e6443e72bee40937eb89c3760c94f5fa74c1a6b4; - 00000000000000000000000000000000000000000000002000000000 - 588d9c2260a9ecfa95da0f3ae80ed811fdadc55a6b19ca178d705ddb4f7827fd - e21dd6f24a2344b05df56af868b16c9566c3e93562894bcd82a945ba514c5a87; - 00000000000000000000000000000000000000000000004000000000 - d15499d0351be2608940d7460b38cefdf5ee7503fce68579fe3a186bae4e5998 - 95d149362856e80e436470d08205d79591520d67694178863d929c1283d5a541; - 00000000000000000000000000000000000000000000008000000000 - 0bb9403874309bdac289a847e6be5642e67f71443097d7c1cc9e0787b6c4252e - 600cacd782749f2f91a3a26a67ebe9d31593fd520a8046f5a60cface42853a89; - 00000000000000000000000000000000000000000000000001000000 - 9b9613f244651fd3dbfebbb6dc96b52b1a771aae0b6f4bfb7d71342a0462b013 - 44d70fcdc3c9308e2e6229b2214bf6fa9ac83fa7d3dc0b7a29f2c5f3ec090b1f; - 00000000000000000000000000000000000000000000000002000000 - 259d92266dc21f7d30e7070a48a58a0a739ef71aa4e0c1bf919df19bba0c6e35 - aebd1c82b24831566492dd4b424b824fe95a52c44aa1cca0b5542e1090cc1fa9; - 00000000000000000000000000000000000000000000000004000000 - 27be0b934efa113d8c8101dd8d56c4076398c8d6e7977f347e23749b5a73f313 - ba77447b42e23157c2ee9b4c0037f4c9ea37a9a22e9abe2a23f94d3bddafba82; - 00000000000000000000000000000000000000000000000008000000 - f5430f15301470f840f91e7b75ea4cc7395b43f1edfe9bab362e8939969484a0 - ba43279cb5c71882e6c3ea7a43e456e6e5c8fd15310e38f1a8537f52993e1b5b; - 00000000000000000000000000000000000000000000000010000000 - d3fe3b4294f674572da05aa1617fecde382a03e2a429a7f5257c8aa906057091 - 7a033fd229116872c2c1a18b74fc37213c903e59ccbf0d382a946fc4204967d9; - 00000000000000000000000000000000000000000000000020000000 - 68645bb3921c1c55b0ee6e262e71b654cb8236f1844dc8b83eb012659a1db873 - c8375d6b2755a13d69f6d2027211bc5a331d0bddf05ad8a79244eafd075e07a2; - 00000000000000000000000000000000000000000000000040000000 - ea6fa9dce63e87a3aec87ca45455b89ebd39631a914824edce01560edd20f6df - 1b37c1283b94e96ce366845d3b9bdbb067a489c33c00345e310a2c9086c987c2; - 00000000000000000000000000000000000000000000000080000000 - b4398d7d35ac622252854e8e113cba5a8946ce716e3858105e4261cefdff24dd - 2d6c9392643deb1174875897917c864d9e75e9eb22dc83f754cba0605f800265; - 00000000000000000000000000000000000000000000000000010000 - 57ec1c68ee07d85bc8ed73c0ee1c0b3d7b17ee95094a1b027d00e3359bdc68cc - 76693250618daf58a86d6b7dcea6f4cde1663615cc771996f2bab17cee73c4cd; - 00000000000000000000000000000000000000000000000000020000 - 1939a6b965e7e13d46f888ceb7f41bff97a46a6ace11d3786097761e47c0d4ee - 4783bd9c5b469d4a03fde86a90fab3dd73d009004d333771155889bc19fed805; - 00000000000000000000000000000000000000000000000000040000 - 887c0455fa369ad1a63a89fe53f5c1f1f873e36673a554c19d3251ca1f401781 - 90697bd7073e82b723503b0fb86c3106d6d4d39036e9e8741b9d76f79dca96c9; - 00000000000000000000000000000000000000000000000000080000 - 09ed519fdf745461e1fb8e10471c54d52f3455fb7aa6db264b2757b02829ed41 - e36c4cfbbc607b301a28f6c0f96774722d7dfbfedde89e97674438ed31fc424c; - 00000000000000000000000000000000000000000000000000100000 - 61b58f25174e379b185ce40c08717b11460e6839c1dc0d0a7430a9f367960376 - eb6bcedc9b1a70fbb749f9535f59d60dde1a6a3de6cf21d083bb43b696d0d455; - 00000000000000000000000000000000000000000000000000200000 - 98e164ed01ec6f3a53ec5eb1d7930aa8f7689ef6d3b3f5359618d53a6f291180 - 539a4febceefe3e49cc2dd3100b1873ec5a6b03c04544bd9930e213bcf79c5f4; - 00000000000000000000000000000000000000000000000000400000 - e9956f811053405dffb566909338e93bec1c4ba2a02cc5c6bba8def3570ddf29 - 8aea5d2e8e322dbc2454e236228a6661c2e49bec36749e784398b8afde823e69; - 00000000000000000000000000000000000000000000000000800000 - 423e3d2da9cf293c881cbabc625ebc58eb58f68cbfdf74eca77d0c85def81286 - 138283360cc8db7f3cb1845cc2d7e3dd55698564c62ff10cefacbc7e754bda0d; - 00000000000000000000000000000000000000000000000000000100 - 459fb60e8f40da7efdd66d01a15959a3ceecda42ae8bae622510e92bd4374c43 - 058ffc8eb9c8c74755f80ff096b1ddd1f9ec9746fdd63f81fe94f5aaff3a4455; - 00000000000000000000000000000000000000000000000000000200 - d56a4841787cdb240d452797278e2065d92d94284b60ac78bb0d90775dbc9172 - 6414921eac73dba768b88d3753b4b61bee16ea189676d58c85f758cd4a04891f; - 00000000000000000000000000000000000000000000000000000400 - ea53b043630e6f958784f0f7dc6354418901f654c4b06ff40ab6c4909f917ff3 - 50eba9af77a57a86c497ac90e535e47645a967e5a678735e9db13175da4eaddd; - 00000000000000000000000000000000000000000000000000000800 - d7f30fa8111469c48de76fe0d1148ff48675cdfddca0ac977330d094ff796b81 - eaa3b53439f65b9d8b47a24ac6ff75a66e93aab097670ccf484197c868a0216f; - 00000000000000000000000000000000000000000000000000001000 - aef29399dee534bd8ff17b1b2057787a151255bd76bfce66f6344194009935fd - 7489520edaff91fca342b7a90edfe649756e561662f41db5b12fbecf99219897; - 00000000000000000000000000000000000000000000000000002000 - ff1026c8390f4688f025b03a0758bf56c2ae84c580ade19c22332eb5dabb2d65 - 44c179aa7070f032236520142146813b55a0a9a58209d3e869b8969e66935073; - 00000000000000000000000000000000000000000000000000004000 - 43a11b9a09783a0d7d079eecff5933c84b52f96efe0e38a21cb97b6410663128 - 2216c885bc941c655dd6d0ba0b32944c2e501823cf9b5322b51827445b74ff7d; - 00000000000000000000000000000000000000000000000000008000 - b8af4aa7c1fe35b031ee050dbd2d247091f173179686ef8d0659446d643f2e14 - 73044c40077491735fc44b1471a94c5585d0b267971270e18a54b67954e52a80; - 00000000000000000000000000000000000000000000000000000001 - 896855032d11655c16bd94f994b8f47e2f82be1c0b3a296bfcb18e0a1e9b4edc - 75ce1a2f4d77d032b86cd65dbfd97936e82d76f16f87247e1a9fd39b95307577; - 00000000000000000000000000000000000000000000000000000002 - 0082359d931ab3fc8791ea89c01e74d7a6ad0e40c7a0fc369055c28f8714c679 - 648955a8ddf7ac11dff9967156faa35f1e5bb74eb92e395099575b87799ff709; - 00000000000000000000000000000000000000000000000000000004 - 7bbd0fa76452768bdd69cd448b13b28f1ffd689df6e4f4c0c0201924078a702c - 3e9efedff4cf93e8bd34c4a1a8f06916410fa99d326a4ba831aec1c1d9c7d60f; - 00000000000000000000000000000000000000000000000000000008 - 5cf1e70d83b64b87b5b4533a0d0974a871fce3d68b085587e4434d1789c5a036 - 2cb01ab75e4ac0d2d248b1e2fe2c3a43cbb99a90ca7485357eff8f4bcf001ea6; - 00000000000000000000000000000000000000000000000000000010 - 15ad3287e48777b536309c26f3d4cd928f9f11c2d88eed60e4ee42151a78ad6b - 135d93ca9bd490f23afd619476cb934e42f7b383cde0c5db99503b3fe325b34b; - 00000000000000000000000000000000000000000000000000000020 - 7206c6beb79aafd394150835d6f2bccf7d7454b6c5b80afe0c8afc311430226f - 95373efb0b18c40fd7a2c98bf86805c0b8e6d964e12e025df90f1f63e631abb8; - 00000000000000000000000000000000000000000000000000000040 - 34adfd7c6b2ba94580eea815dc441161d91e427412f54c42df398360f43074b7 - 635bd00a91fe3410088ee2dafce819f26a2f44e194fc39732cb56ac470536592; - 00000000000000000000000000000000000000000000000000000080 - bd56867e5c02612bd20abce0a51c8c0a9a5c3ebe27af33b743d22f1862bc9b40 - 393bc6a1c9cef4829b5586e99952006b7e4af3056df28511fee2902eb5d30940; - 0100000000000000000000000000000000000000000000000000000000000000 - e15988e471d6475f8094d5704775b2ea578ada4ccd7fb6bdda530b250688c0a7 - 9b4c62614948194ec5e0d4672100f4cf032166ee1bad7d12ac3c3c292992bb01; - 0200000000000000000000000000000000000000000000000000000000000000 - 384fca7c5554145250796aba74422059a6152117b9bbf50b492d8dcc4fcd9fa9 - dc2c3521c82fa8613489e815af3bf6bff23a61a31e136870e7b88df6d2c9ef50; - 0400000000000000000000000000000000000000000000000000000000000000 - 12390d4e80fbb7ee99c80a68175dcc167177486d618d1baa5009587cd2543496 - 7ca3a28cffaf1d2d71aefcacb467f7176bf23325406236a468f9a2b75ca67eba; - 0800000000000000000000000000000000000000000000000000000000000000 - 8c43057345f8ee64b5e04daff7d9758b663e27d9249c68401e17650d38418597 - 75c3b729c8e8da036b60b63af24fc564a3a4ac1eb2e92fd59158474f744c5a12; - 1000000000000000000000000000000000000000000000000000000000000000 - 2b7e0219d0d2dfff42597690df40e53c8bae17d0d363eb001636f91658fd4d78 - ed444d40e243dce63b77c45a4eb89fc5a0af2bab390e32903c7ed80ebe3fd989; - 2000000000000000000000000000000000000000000000000000000000000000 - c0af2ffcdb963b3f836f09d07dd7529ca029baf32d683a030d8b70f64115319e - 81adeaea6574660ebf126d45700aa212d7df72cfb15ac7320544f901c87b364a; - 4000000000000000000000000000000000000000000000000000000000000000 - bdab381ffe13374b4c0fb2befb836b2a5676f551d9879230574063a7da33f55e - b73c6979db28f0090352ead9194481458c53a75716e82eec0d392f80cd7f414d; - 8000000000000000000000000000000000000000000000000000000000000000 - 059590c11ad59af788160a3dd52ba242f35e9d7c9ac2716732d45892fb7e311e - 1cf8b9d052386a37bad7006fcf1a5ed0b2ca509fa9b408d164928465b7df55ec; - 0001000000000000000000000000000000000000000000000000000000000000 - 2f59734e38211765d309b8885c0d7f12802adcfd236259e710b60f215b17e91f - b7543107d7a8d59fc58ccb5bf9cc9cd3b0aab40b936519018321e67ee4212f3b; - 0002000000000000000000000000000000000000000000000000000000000000 - b459777f2e4be5802ec40b675b180cb7362d58849b5a1002e9006d684803d1a1 - 263e0b651894b849ebcdda7de136f12c2b417864d0bab6d752676645aa44663c; - 0004000000000000000000000000000000000000000000000000000000000000 - dded78e34b5117415696866ab8277777298ba600ef8ebb0a833ada9f0fb14abb - 048cfb659677a1f6021da5cbbe7c045a6630d62c12354ba889f16dfae298f0cc; - 0008000000000000000000000000000000000000000000000000000000000000 - 23f9f9b2c9a37dbb2c46156eb1e369247bc9e3ab18b392d900933fdb2319dcb4 - b9116aea9a465f603f0d0b5f2b432bbe2eb8b5b7150cd41c88df744d1d157458; - 0010000000000000000000000000000000000000000000000000000000000000 - 00d9408d7012e74b3587b5549ee41a45150149b07a71b11b5a6787d0180405c1 - efb7ea812e9772898305defb02e62520cb5518f11bc7d1cb72aecb2a230786e8; - 0020000000000000000000000000000000000000000000000000000000000000 - 0e1acef35626a60c99bb971a72fbdb80d40adb9e1566e522f03d0d9781abb92b - 39e66a48d565bc75e2e307de3555f1bb2161fab013186e827ef720b5e67af7e6; - 0040000000000000000000000000000000000000000000000000000000000000 - 147cade7c9326104bf45afe6b8c180cd7a8a45ed9e1798846af473f241424325 - c8b47d8c7fc71f2650dc9fcd2e76656486f7f2cf79d4fc3e5b0397bf19a268f0; - 0080000000000000000000000000000000000000000000000000000000000000 - e435935752dcf49c03afe77b217af4fe8bfe3b83be1f237e80b1c5396aa60635 - ad3294a5729d4b56f5cbe417867b2895150207493091ca5b2da71661a837ea45; - 0000010000000000000000000000000000000000000000000000000000000000 - 2b0962a7233ae8f0f0c6f82d96f1fb6788b57cea3e20b18d21c01fb20c523e45 - e282636fae01bffda7e59095c3b46c85ee2df7e2f3f4eb5e9c423459dd085ae4; - 0000020000000000000000000000000000000000000000000000000000000000 - 150ec1d69180c1f65fd412fabc62eeb80146a46fd5fd7a7035c887da5d712812 - 95aefd097ac6ca69d1dc282ae7ccda8409ef4ec0a4e8d7e052a52313c3d5fea2; - 0000040000000000000000000000000000000000000000000000000000000000 - f21b883c84743f00ae25aa937c88eeff2820c8b7ec16f485d811fd58f5758710 - 5ceab4fbe84572e441c6d31bab9c213a29aeda39b5369cd5a036f0d5d3052ed4; - 0000080000000000000000000000000000000000000000000000000000000000 - e3790ad0decf178ff259a5c7340f944c253551a0e2a0efeacfafe6cb49774d8a - 93ce491989013119060c84df54e1ccf3627ce8149ff44100c08b903ec868dc29; - 0000100000000000000000000000000000000000000000000000000000000000 - 3eecc58989f78b6969f687ee0aa2c1230af4bb0efd5e26008e798b802996b458 - 55fb0121a5c2f72d1c830f431ae990c24071ddd60fe7ed997d92f433aa53e66c; - 0000200000000000000000000000000000000000000000000000000000000000 - ccef63e7caef39a6ade4da89f2fa47f4132fd354b4d594dffcd40db73171b787 - baf36d6cd4920d94301b649592ba1e990742357ea55191c40538a761fde817a2; - 0000400000000000000000000000000000000000000000000000000000000000 - d39bc7cd53aeafe63933d8bb7130a1d2fc85bf58bf76cda3683349a5257e5feb - 4e8a84d2bc89a1b2ffd5fe2e8ad3c5315bbaa5be3e9688291fdea97b19ec425d; - 0000800000000000000000000000000000000000000000000000000000000000 - a3d929cdd10fa4b13adc1df77dcaaf9348cd8993305d3ade70ccec50d2747d88 - ae241bb3dad4d6400c3d3ecf5587ff814f71708d9d85003b461ed4f714bc2830; - 0000000100000000000000000000000000000000000000000000000000000000 - 641578d6f15bb8f26e1a4e96b798f7f7e1dd592ffcd472f4af3bb90292835e38 - 8b66ed19f74864e216e4c1962326876c3d015c84f368992a51a3a7c66809c8d5; - 0000000200000000000000000000000000000000000000000000000000000000 - 81f3b791c83a0dc0da90a8e5b1460033240aafc65663b5ef8ae4b0988acc3070 - 4ba6a9d06282dd9854b5e75e3989a550a37c1a00c12199ea5c859f47408186b6; - 0000000400000000000000000000000000000000000000000000000000000000 - 59359a60897c5d84c7c3a2cfc44408a9a07f3020d2b7c5f1eaf41fd08aa482c1 - 836e0c9e8c3a7974cc99bd938a7c9c596d21d1fc7e8674321b1faebb9aafe0e6; - 0000000800000000000000000000000000000000000000000000000000000000 - fd2541c2421b5a58f8e9c89f9bd93a3f214690c86a30505050809f0e17965ec5 - 52b5f31bec989a9c167fb3bda2d145ed912e656435e4c2720b109c4161ea6499; - 0000001000000000000000000000000000000000000000000000000000000000 - a7870f4f9859f4c90747cd5a3175576969893f21f80644a85ca361c64c2760e5 - c025483295777b1b75c3f4c1311c1621d40ef55a8a74dd0f85afc16c33141731; - 0000002000000000000000000000000000000000000000000000000000000000 - e7ae0b42a64b89f72741ff01fa56ed16cb405d7de6af172da31d28b6624394e1 - a3bbf26da16b92b30f5be3f1b5a4b82ca60fa12330f546f6dbe21692397e6007; - 0000004000000000000000000000000000000000000000000000000000000000 - bea4feb7093ed08d59b1a9e367ccd59c81ac315e4fa6bff4dcda083a54ce7713 - e17743b422ba9726647323c9d863b28f672f0635965bdc5e99fd713a890fa807; - 0000008000000000000000000000000000000000000000000000000000000000 - bd7d0e194ab34c866664434679054a512ff4520c382a2c16164e3b92579986ea - 2b901d39fe9d3ad0f151be728cc8bf052a5cad3fd622da0bce99df60f5d0b900; - 0000000001000000000000000000000000000000000000000000000000000000 - 26221c4832d8daaa40a4cdf52027ad389342882b578d50690bebc93df5bfae86 - 906cbda011d3f989b85301d147e5f89c16e0d5f5236ee549f463d8e7c1230ab9; - 0000000002000000000000000000000000000000000000000000000000000000 - aaf7fd79a7ee0cf2622f61a7dde9ddd110cf585989f9fbcaba4bf8c87f97a6ca - 9221202cf78d38d22b97d3634615cdd7a1b327d0cf2edaf7ba665e2ddc98ffb9; - 0000000004000000000000000000000000000000000000000000000000000000 - ea7e4e250134fd0a6d57d45877fc13e83bd8eae4bd096371ac85d09b634888b3 - 3295b4d323d829813a3c0bc074075c3e133979d02137237ddf6abaa52c3d6633; - 0000000008000000000000000000000000000000000000000000000000000000 - 3944e76bdaec5b16c8c76c7e06452163f22ce79092bd9e3a024aa5c208eaa795 - 6f8a8a7b2dddfc1018cb4e0b7757f3e1444514c3ea056ce0cae81b8701de92f9; - 0000000010000000000000000000000000000000000000000000000000000000 - 3b4c4ac914d85958a0b5e7b8876575573681f0b313cfc0fb7f444c9e7e268615 - 312e801156e12476a12b20be7468806e9f28bd00e3c0647ba9220be6167045fa; - 0000000020000000000000000000000000000000000000000000000000000000 - 91bef844e50dfbc56fd6e2f3b7bdaa1276c316876dc81e1d6403ca7d91dd0e3c - e9dc7208167be2abed48d00beb3b9859b9e4eea2b54ae8c8bf78d59f5fdf6bd6; - 0000000040000000000000000000000000000000000000000000000000000000 - 9e024081abac727a02f619c51ce63bed18745597dce3b48ede6f61f808bf9dc4 - 2c6eebd23f08b4e8a9ba12c04ffe281c6fd241a1bfffd7850bca3e8e9b258c1c; - 0000000080000000000000000000000000000000000000000000000000000000 - 1659ebf81126d5ab0ebda35420c9be79e92a439b50660ba62dbcaa62ebbb6bce - 30972cf1c7ff5ca04ad0636279a0a6e4c9fe9a41af9d3d357f286fc68ebb0a6a; - 0000000000010000000000000000000000000000000000000000000000000000 - 114312df5056368e8facf69d0dafd7f99954ba6188579e70eca4daaf63a4bf8d - 6ed87684e24e9e8c80e7a974280a4a7210b2fb50578cff2e87f3c4f86eec23b6; - 0000000000020000000000000000000000000000000000000000000000000000 - bb6e664338c2483b6619919cff1cbd4a133e9bd461184b040fdbf08711a53c0c - 5a6a0f2f51d127d55e7659c4cfb59a4e17d329bc299ab38e18e3140c562596dc; - 0000000000040000000000000000000000000000000000000000000000000000 - a467e32c18c448d11324ef06f11efe402e7b8a9411ca83e52ae20a82eb5df7a6 - 84c2e9f00dcc6856f70ccc51f498d85679c79240f371937fd4179c5c45b0cf25; - 0000000000080000000000000000000000000000000000000000000000000000 - 0eac2d63862bf03c7d9acbb84b3ec60624a40941764d1fa716d6e08f5039f114 - dc89b1858f887d16f98b1f068e27f7d46dbb8a0df469541423d0c811298f00ef; - 0000000000100000000000000000000000000000000000000000000000000000 - 97537e552910025fade2073196f52788773bbae3ce6c7b1fcc72b55ff7ef3f0b - 49d9bb818972c65f846c31dd70412de0a193fdeacaf609dd401e929b23914e9a; - 0000000000200000000000000000000000000000000000000000000000000000 - 9408c086b3246cdd588066e449a9be69377a74c14b1f00994ff2094af3747861 - 74bc32c2914794908ac3ef670a00f9dd28e0037add9eaacfe07da756042b050c; - 0000000000400000000000000000000000000000000000000000000000000000 - 7ad5a463142244224dd5abd8342df7126e0156d92af07aa012d63b5f1b44fb6e - d82d65ada9a01bd4e9b3e79fe2d15a2075c392865b647e357099b3f1d61c92f1; - 0000000000800000000000000000000000000000000000000000000000000000 - 6d65afe3a94c84045bfe3b6aa7b159c68a64464a71f4b5a25de424d4b8cf7d3b - b80da8204dbe46d527b120b4b025c01541f6d51bf962303cc276f8610558aeed; - 0000000000000100000000000000000000000000000000000000000000000000 - afaedc6195d899fd7a085f180ffcaa940345956b194d340a2deee29c0dd2d971 - 7b88861666b09d3dd874eee025910267da0de663f3762fba0d5183ac81b59a24; - 0000000000000200000000000000000000000000000000000000000000000000 - 6ca33fb495f9b49ab2434c86bd50f1c68bf627fb423d5785d9a94557bb789a32 - dda8002e8a2c6ae938a347121e2e6a191b11a47fe0f2609d8df6504eabadcd4c; - 0000000000000400000000000000000000000000000000000000000000000000 - 048745f71e427f377631cf8b93d762ed69b23d5ce92cf88bbbd1c39d83c50962 - 9b467d9f35a61cad87273246229d0a666e7d37b4a3c3ee48e89f7316b59f9258; - 0000000000000800000000000000000000000000000000000000000000000000 - 199409ed0f69f84c55ff5816d48f78d7b9ba691a2f4c9d41f38f20e01cab00fc - 8168a685bce08ec00ab7e7fbc20dad4cf1a9af5ca3cc7fe72ab7a770bdac10da; - 0000000000001000000000000000000000000000000000000000000000000000 - 130e28c699dce84779ddfaea0a45be76cbbf3fd14a9c71b50c9ced5eb2cf6edf - 9d17f71aca5b6175d82e6a7bad34a8d21a4bc1bc404462807035c0c855033865; - 0000000000002000000000000000000000000000000000000000000000000000 - 4a376dc814c679fb3fae93836a06bad1cd77db067f76ccfe60987559ed4b7cbc - 26932158e76eaf55cfba5398b06d11ce6c88b078aaead0ddedf5e5b2505d5ed6; - 0000000000004000000000000000000000000000000000000000000000000000 - 5a04e963f90bbd5bdb3f616f3d52f23dccbc4652fa313de5d1fbf70c829f6261 - 0c65c4f4d6adbfbeb91488a00e16e978a75dcdaa4ed9302148aead46d3f8e8a0; - 0000000000008000000000000000000000000000000000000000000000000000 - f4efa7971e1b1cbd41d9ccc7c84b46ca24781c118409fdc8d86ff3825c033e85 - 0393c2f10ddc2c93911de8c22b192dc78be826d84405beb42e5cce91e0234620; - 0000000000000001000000000000000000000000000000000000000000000000 - aab379abcb48184edc2400e7942943710acaf92763cb82368779535b2fc1f3b3 - b29bde1e9b5ec2d359a8be97db7bcaa7bde9f2c3e88c6536b3a58d62bd7c1501; - 0000000000000002000000000000000000000000000000000000000000000000 - 308e739a98aef258e547d0bcd9e204da0f2c7d983383650506e66e9dbd9b0857 - 9089ef809029209d37c2895b5f098e38d68ecaaef8c2d6fcc04d72928b921c59; - 0000000000000004000000000000000000000000000000000000000000000000 - 1f7a8bef337a14785dee818be84bc9350fe1951a9a6272f797ea1f5e71a1b022 - 39148fbdfc0e0acf1f30123f11b67d72651b0d87b0e8541c9c232f07e2f93549; - 0000000000000008000000000000000000000000000000000000000000000000 - 4f0c06166efdb1bece929d31c2981e96b4a5935f1c314e4ec0b10c0c761c8f7f - 68cf4918507324eecf2cf991b5731b368a1c6bef35fd1f1c940929b1e45b1332; - 0000000000000010000000000000000000000000000000000000000000000000 - 7714ca9fa1ea7c235585ade167931ea4435a61d1d983aad7dd5452b0a291befb - 32f56751d799fe84ce7075cfe927fdb57bbe7e06eb9c88dfe4b14497a3d8d6d9; - 0000000000000020000000000000000000000000000000000000000000000000 - cb00fdf9a48bb507803079638584ba025d303d2b0cd5b81de2b644a61ac5d891 - fd821a3c9d6d04bd07a28669046eb4a7764de97e056f0aed9356d06046365ccd; - 0000000000000040000000000000000000000000000000000000000000000000 - 7af41ede49449402d065d70e9617be50ea74283c639f75a4dcd794950a2ad075 - a9126f01a04a287ba196d148de77256dd86b41a4937fea307e19c40dbdbb253b; - 0000000000000080000000000000000000000000000000000000000000000000 - b5736b632b346a2210ecdeb95a0337903449fe2154ba97da8ac5213a5cca2453 - a4a924f69ed450c80e1c090b327b75ae8c900bc0530bc580ad9096545e60dc4b; - 0000000000000000010000000000000000000000000000000000000000000000 - 305cce4b3deadb80ca17a1f06bf1a8dcce2d1d66f2c25e7b2703062460f0b7e2 - 9071f39206f73eb7e1af21cbfdcc006a017521078254de35af24593f093ebae5; - 0000000000000000020000000000000000000000000000000000000000000000 - 17fb9295d4f1e2c6717227dc01503b953dd54b327029b8577480a4e87d7ca1c0 - cae92b888cc88e686a780206dcbd4d301e03ed5258fe0d8df01c8d8b9d6c63b2; - 0000000000000000040000000000000000000000000000000000000000000000 - 27cb60b2e45fe4d7580ecab6446613dd2e9c773ba905a724458c51a2dcc1425b - a57c7f3c84048bac329e1e463f0c7226c51c9e6549d3379b78c89176ec316d08; - 0000000000000000080000000000000000000000000000000000000000000000 - 893d82ceaf9116fd2b78f36c570da29b84d7fea87ee8f0f6678652879b8d50c6 - f3f98c24d5c885055d318006e2cdff776412208b714d286cade4d3541686e281; - 0000000000000000100000000000000000000000000000000000000000000000 - f8dce549ef52a9912c8aa83f82c818dad9252b7f9711c828179329141e3de5d0 - 819acfd983335211dc97948e599fa664319a9c589ee11c181c5c0780d379d77d; - 0000000000000000200000000000000000000000000000000000000000000000 - 2915e806c01c17a353729c6c3f943b9c34e9cfaeef6becae2935d471a34f0940 - 548123fe86f653b4b0a10e361369be8f0863b4b5f15c34d7ca2e48e9e25d1b5e; - 0000000000000000400000000000000000000000000000000000000000000000 - d9a23e63ca5828b15fe38ad7e48d44659263d27f0390af84066154585087e771 - b26569bb88ab49ee647671a9cfd14764d60efa99e7aed11ee373af93ed061f22; - 0000000000000000800000000000000000000000000000000000000000000000 - 1d24835d30eb9201019d8444bb92f2598bcb1ed42346acf53810e4aa8788ff73 - 8e0c78cbee01d9ee871f2457743ef0362c15d9c93d23a12626c4e80623903181; - 0000000000000000000100000000000000000000000000000000000000000000 - a0cecac4bfd7aa747230a7c795997255068dbbba5997633ead02ffb3454619e6 - 018a38a0e5ca7db27847e3eb2854a4d6a64c0a41b3c59cc3d38ea58ec25dc93b; - 0000000000000000000200000000000000000000000000000000000000000000 - f9a9da5740a32c62bcda5efca357870d8725965abc40aaf260a18fd4ac42aa43 - 1eca828dee97965f8e8d7c1b0e87125f8f9ac3b6bee8b0b730bf3afc905cd19a; - 0000000000000000000400000000000000000000000000000000000000000000 - 4d2aa6eae1040cd338063d6cb66911fc026027db5a53b91b3612d11b2be3f710 - c749d747ca70eb7bbe5a160bf61c1e1f573366a473943ccb60129e46ff757792; - 0000000000000000000800000000000000000000000000000000000000000000 - 21b0debd7ab6d7149c058c9d69f466f9480b9ad20a59e807c9186496023f7b79 - eb1556e90beab9b3b1c5f9e520de345877a2ec446f0976f76bba0e11fe056186; - 0000000000000000001000000000000000000000000000000000000000000000 - 612a8d66984e3e664af0daeae9bd903e04f63a761123d7536639d027ced1d682 - 1577663f2b58aed2fa1b2eb87d1e86d8af977ff7439c52d4947a29f7f3ea2605; - 0000000000000000002000000000000000000000000000000000000000000000 - b502222789a36d5a9a245c0fff70ea43c2e96e5fb57fb81510aab99f80c35a32 - 0303b621ed6b340068159fdb857eb2a5479dfa6183604730b72d01233fd71586; - 0000000000000000004000000000000000000000000000000000000000000000 - 3df5c158a338ceaff80de71a2918dcf210ea5001716256b445c82ac4691f1fc0 - af811728f6e887608a5b6795b8ac6b07ab68ef95394effbf6d46b50418a77a46; - 0000000000000000008000000000000000000000000000000000000000000000 - 39b25d1e214df0a0283bce92879f056beac64269f127b0494c5e8fd4ac4b6ac4 - 5e3e7c6d0dc7ade448def91c280287733a78bba5fc3f636f9d8a6552b0142b7d; - 0000000000000000000001000000000000000000000000000000000000000000 - 00fadb701238f00fbb1d1096d3e451bed024b66aa9274760dab49ddac5c3946d - 020e78dc0f6e465fe54cc7257f547f1b48e908bf6052d7e3a5f55b58cdd507aa; - 0000000000000000000002000000000000000000000000000000000000000000 - d1c21ccbcddba34b3862b0d3c0e11e309458ad69d5ba1d42fbf33f8d8a592eb7 - 8427323b69e874b89fd3c981244e6c1a98e9baafc9cd7699028b54d5a80c4bf7; - 0000000000000000000004000000000000000000000000000000000000000000 - e783e2f80223d3bac0e249c4af0fdd6f765199defa2831e1285aa7969cd57c63 - 44935fe4ef59a0979502daba5dfc7c16ec69c1af8af85a3fd8bebd486929ea5e; - 0000000000000000000008000000000000000000000000000000000000000000 - 27bcfbd734964e7fc8a634b2ce3fa63ee453235af33b689fdcb47d6aaca6a6df - df37ee8f5ca3e21e7948163c9a189852f7df18b117e4743dbba2c770f670b8eb; - 0000000000000000000010000000000000000000000000000000000000000000 - a66846baae257774b4cdbf9ed5257c9c18c070836e35d580b95e2a7b961ff402 - d77a334ad77df938ce6042c2c06c868c507b298c59010a47eafee4203c9f47f0; - 0000000000000000000020000000000000000000000000000000000000000000 - 0dbac39c772bbe1c52105d00fa32d51a03191ed6707e175680397623e793e9bd - 0efe80fdaff4975cdcbaf28286917ad218a6bfe685fc5bdf616a40e2171297ff; - 0000000000000000000040000000000000000000000000000000000000000000 - 8db6613e226d37bb68c89e455efc591f7e2b7b7da543c3be7d9058105ccc2388 - 0d74d3b700d64545bf4a06f0625edf7d7e3a8828de3b6c95ca42e1e5b19a06fb; - 0000000000000000000080000000000000000000000000000000000000000000 - abb71c9c7f39df0dc16a00939f50759ab116eaf2024b7e690c0469fd9c6477a4 - b2432584bf1f12c9f50b9f51db6ec5082cbfbaa85202d903fd3c790a7e8c3008; - 0000000000000000000000010000000000000000000000000000000000000000 - f0a0ee6776fc98821b1695e6b253eb7eb3055f779fade81bae006e98f6dfe53a - 4e38aa14fe50a3ede3998e72a989dc77300dd5e216b4b41fd23dae7d59cbad7f; - 0000000000000000000000020000000000000000000000000000000000000000 - c24fb46f0f7d123468c9e4ec68fccc7eb4986e44c8110733d1268c124f238711 - d0aa9dc510363f80f3bd100f4fd816faf90e32b941b8e5501a171edd01ea91d3; - 0000000000000000000000040000000000000000000000000000000000000000 - cbaee780343e98edb69d95e50fe41cadf820f8e7959bb0f2580a14014df68335 - 0b13c8fd89a314d72478401f4e39d5817a9a98103ab45a458f8d23b2ebd4353d; - 0000000000000000000000080000000000000000000000000000000000000000 - 06b5fd3436cb561d100e3d1034d4c790a35e3e634fe76ccb028112818c581ddd - 2238d8f8aade266f01cd8f189bb04ce9fb8c2f30b5290a6011f2ea392cb5d716; - 0000000000000000000000100000000000000000000000000000000000000000 - b0d0316c92cf2844091b87d25ebefb5a0dfe2d60782962b7f65cf974ffc5394d - 7e6a4fdae611b25c6d62fae841a2a8b0dd5ed0f56ee0b652b2233624e9e55717; - 0000000000000000000000200000000000000000000000000000000000000000 - a0687fcebbfc5d0ffc70dfd89701eae4dcc0e0897a61f7d02f3a200e1fbc0195 - 52991b10dda46ae9a31210dd90e997745dd7a45d6782f621baec5e1b09c652ac; - 0000000000000000000000400000000000000000000000000000000000000000 - 7885103c2ddbdb34f21679c908148b48affd3030f33135ae6aeab813d76e4c7d - 32662258f351ed45638fbd08f4a9ece8cbf4259973336276ef51883445b067f5; - 0000000000000000000000800000000000000000000000000000000000000000 - 1d166eb905ee23d8608ba8df50d9ec70a29423bd25cc87cdacd5d8b3df321535 - 587b6f652ee658e4ffa3a16b95d717bf692eddb0f85fea3498ed89e2debbd053; - 0000000000000000000000000100000000000000000000000000000000000000 - 8470559686b1ce1f8297a3a2b32087cdcad147773001dd844fb4fc61bc0fe45f - 29ed1711366d01a87565165de5cdd0c817ab620aae1573be16d28cd51cd0e8cd; - 0000000000000000000000000200000000000000000000000000000000000000 - 45c7e02ac7f22af7a8fa1b6dba56ecba6be159a7a4537cc34d5970a0aab038c7 - 477d6fa3adbad6057928cbcba71d116fbadc96bec9ebcf5f1bdedd39e32d1cb0; - 0000000000000000000000000400000000000000000000000000000000000000 - 162c6b51feb10bf69bcc8fe12859b447b03af9c63d12239f1ad5ac948f3763d7 - 643e17074976de5a5ce66320e5ec38b631016e2d3caabe52f0ba8e56a9d0badf; - 0000000000000000000000000800000000000000000000000000000000000000 - f9299e0e09e8e4d408da8f4dc9e15c11b8d8e4708ca5c73bfc8714cbe42b9457 - b64579adcf37e3bdb652e15fd7221d9bb23a149b9d0cd1bb621aa60fbbea3374; - 0000000000000000000000001000000000000000000000000000000000000000 - 700ee74a28732eedefb1926e5557a613e00ffc91cc3d9b18e2f51d89055b9eb9 - d52db33d671e9c012ecc5f594b12fd563e5cf1807fd161a863080398b78bda13; - 0000000000000000000000002000000000000000000000000000000000000000 - e6e8a4eae096448cecf973ce287a7ef8e9fa41de4c3b05501654edb2c1271af2 - 1fc805e11047c0d487a61fc552569975636ab111c186231bbf05b32c95d2ff45; - 0000000000000000000000004000000000000000000000000000000000000000 - 1c1de2c45285d57eed9cd013370e3b8a57d12fcd0050ed324d641ef797fa6d57 - 1fb31c871cb66f8b0d651001bc2924b413075cb398d6a03d77b298e6b28d8bc7; - 0000000000000000000000008000000000000000000000000000000000000000 - c2e9773c4f7fa499d72af9a0487d4b02aa43ef91c5902875fd2c85c022a7be79 - 7f4575691fcbe4ac4ae9ad4f8e49d403d1d41eea43fba36c671e6a826fd16442; - 0000000000000000000000000001000000000000000000000000000000000000 - 0ee9c279b05d527706f721ac45b2b75c55cd9b1906ccdcfbd29aca32f69053b3 - 1d7ee6cedb4c2c169a5d0e511b62772e4b40c4bc8940aecafaf2e1e09b5e79a1; - 0000000000000000000000000002000000000000000000000000000000000000 - 278dbffbcb601500a725942fb302ba2ab0c6d206db5d7878979d7b2ad8d4d199 - 6f74aeda2cc6ee5704d685bec0de4363cb79679200f0ed5530a36e516ea86d68; - 0000000000000000000000000004000000000000000000000000000000000000 - e8c8c0fa175ebd8380573e7932d219a3f116d14da69693f2995471d9be202d05 - 5e1c3a0b22708722d1611b66af966d1f6d9f8faa851ddb01830b97e2d9bf383a; - 0000000000000000000000000008000000000000000000000000000000000000 - 283d859298c1e323a493a2e949ddd4c2ffa4a5da29669b348b5a72ed8c8eb1d2 - 272552fb9fe36123cbcb0e43db68b2233336f6a84c99ebd01080c0eb508fc7f3; - 0000000000000000000000000010000000000000000000000000000000000000 - 79125cca9c3c680a61d21951a4cf0b7230b578ce2e80fe838b337fb7c36a77a3 - 2ab45fadf08ebbcc5121b076806d50927df6310214f73aafb0081633cf98299d; - 0000000000000000000000000020000000000000000000000000000000000000 - 6769fa85ec1c637bde75471d0b22903895ecae1462912caf6a6bc6251a58258e - a65b3b54d75e58eb478cfd6032d291f5bd46a8c8c5765fbb2487283e46c26de7; - 0000000000000000000000000040000000000000000000000000000000000000 - 4e30e6abd785654640eca58ef491e13378f8526c2af3f51c0043e687bcb1c168 - cc48a52ff696f88d51559c46494cd51dc3291266046c085fd51e9f8baa1e1e5a; - 0000000000000000000000000080000000000000000000000000000000000000 - 96a57e2149916713b979265d60743727bb6b7aa91634dc415b408338329e82cc - ea571b458893e10883a717f3776b808cfdd26d9bec4cc64e16a72448c2211b48; - 0000000000000000000000000000010000000000000000000000000000000000 - e8883a8ef799dc1b6d2fe5ddd18acd3ae58b24e98e1e812494f8a74f4ae372be - 93fa5ae2d6d71da3fdeed466453b7ad9f4ac8ea3aeded25a15c4bbd040018fe4; - 0000000000000000000000000000020000000000000000000000000000000000 - fbafbe69b71d604c13e1cb82292190c18cfa9bf6145714aec7249a56ddee4ca9 - 6336a21084584fb303718743e6e96f479c7fe0ddd8956ecf703fad72221d64f8; - 0000000000000000000000000000040000000000000000000000000000000000 - db9b68d716130e6b173cccb08de59eafb3af28019e87c152dc3ff5d5088e3b58 - bb3fe5aef0a82c6adb2f68c9bf43548a06e7fa503ca61b48a946cdaf37e8f24e; - 0000000000000000000000000000080000000000000000000000000000000000 - 9f7bc36611372d91d4b4c0cccc840759285cd03b3e2e27afe204ae448d0f9286 - dbd6da143b4cbec22deebb4d50290a42299669dacf03fe2a2307968143d4fb7b; - 0000000000000000000000000000100000000000000000000000000000000000 - 78d8a2300ad94cfef66b3164c731377ddb2e4b275d4e701391953432347b9223 - 50f62201950be294408f88bdb661cc3296c6be60d3012075a801b5c0834ae350; - 0000000000000000000000000000200000000000000000000000000000000000 - 12e33f7ddcb2f8d174625428a62b88949f125ef8ed08fdaa354599949ca0ae66 - 06ff56ab47bc89455cf58af988b568b2ecfc06e7df27cf710a25022d87557da7; - 0000000000000000000000000000400000000000000000000000000000000000 - 56eded2b02168d3bbeacf0d9daa6af71edc952a831840440039c498f4e7f7ca4 - 704dee5d192940b0a69ab883c75151d8d6cd140362b2c1654041f43f2069f4fa; - 0000000000000000000000000000800000000000000000000000000000000000 - 755d75672e5539950e3738c9f08391595fe8666fa3630d850bc54f51db1c85e6 - 9be04b998cbd1d657d9eb034eaba6870641da53e310eade9dee5013a8c053790; - 0000000000000000000000000000000100000000000000000000000000000000 - 59a5be52f38efc387f5681e5efee14564bc0124d21a853433576752ffa429c9d - 2c8e95bc932d31e629cf4c519bfbc19b1356e82b24e4b0a0a3f0e7bff87cdb9e; - 0000000000000000000000000000000200000000000000000000000000000000 - 6a8e931278edcf28e271b3af14ef2a4c3a32187f2e99a9eed8f8bf5cc9caf92f - bec4947e08bdce74baaa30e8067010ea1a5f0a510f3ded81e1531f7c70a579b8; - 0000000000000000000000000000000400000000000000000000000000000000 - ce10996b404a63f524caa19cb2bb9ab0278718cd618687588deb24dd0acae4e5 - abee46ec2bd7acb5a6b81e03cabd1cd4c5b27255c0c53245bd1fc2b82fdd37ce; - 0000000000000000000000000000000800000000000000000000000000000000 - 322f564e6e45b4d7a556e3e0d673c24762e6aa9558221939a6e207af108ef047 - 045bdd23eddffdd2e5fe6035781a4c3f67eb5063ae2c35c4f167524c359ef09b; - 0000000000000000000000000000001000000000000000000000000000000000 - c38a5f9c6637d72c43bdf52c75f8a01a5c017202825ff09eaf27bb6a5de32c9c - a362cf96447d76f38c0ce895b2fa6bd21a02d6fcee561bba4bd20e224ce24bfb; - 0000000000000000000000000000002000000000000000000000000000000000 - 71f79d68098b9e011bb7c9400ddb9e3493dfa52fae11dd9ad77430857a136c68 - cbeba998096d1bf54c3f5202d5b06c38a8f81f7f9a729c030bc916b43544f325; - 0000000000000000000000000000004000000000000000000000000000000000 - a877f654b01488d3bbe0104bf788a18c250a453f2068bc81f2f096ef5731bfe2 - 9081748a46ae87a2524c0b27af4d4af310d5384ec8e8bfd6bdec56f7e4060ba2; - 0000000000000000000000000000008000000000000000000000000000000000 - 8ae90f0c8d8ccd1268ac98f999bda54594e219ed8cec617c13cea31a606db6b2 - 1fc23a6581656dc0a72abf427d6374ba7d3aff387493204e1036caf860ad0f86; - 0000000000000000000000000000000001000000000000000000000000000000 - b6d4e59d418667855067491c8df18244c64b1bfd728a3625161e47d4a32712d7 - 1f3752a6044179cdbc6b05ba5cb21c894be977699e1401eef6412a0397fd1287; - 0000000000000000000000000000000002000000000000000000000000000000 - bdb69d9fc2ed427ecb6848b5c2f9687c3e873271e8a3261073a05ebc4f75e244 - 023140291efee7ea2d02dc4b54d5d4cddee02c88767c33b72d0e028dd97633fc; - 0000000000000000000000000000000004000000000000000000000000000000 - 925ea1f098046aeb00899bec3d4f97ae64290279272a9dd8ce9d79b6837b3ad0 - 370a2405d17683bcd5baa70c29d57f49f9847641fbd6884173e2adc11995f203; - 0000000000000000000000000000000008000000000000000000000000000000 - 1349f44857d80fd3a0405217a8248339f70d227635af2411dc6c4214a42c2e2a - f6fe27b251602fc9c9e870f5cb4b62c43e3e875c47b775fb8d9f546b52807e02; - 0000000000000000000000000000000010000000000000000000000000000000 - 74699f36e9636c3206287bbe13384e18ced1120706175c0a65576ea86776c612 - dbe9d11b3884457e03b84deb23858d704169d7582a300c8673a7f544435dc3d3; - 0000000000000000000000000000000020000000000000000000000000000000 - b792ed127f2ea24411d063cdc2617d702230f3fb9d03387e3d0700777d97a70a - fdb09f976a749a232305946db9f7bbdb2429fecd28e584d937997446740622af; - 0000000000000000000000000000000040000000000000000000000000000000 - dcd987801779a92f86d879abdf28b9cf66f7d0318f487be0ce27c63a27fb5200 - caad8eec3c351be1e60e70dfdf98de671d2ca5d3fbc21fd440713f55df8c69fd; - 0000000000000000000000000000000080000000000000000000000000000000 - bf85c351d0e74eb5430e55479b50d0fd827578e982ebc8e338f32116ef570e46 - f81b47ebc5d2887a45aa67d0b7d0fc8a07146f30b37f1a036ce9fc236f0d7d00; - 0000000000000000000000000000000000010000000000000000000000000000 - 6c6291cc83e0314b06e19ac68fc170b93e84609fa80ae0349e86cdffefe6a193 - 67ef3467e8e0b571c5d110ea08133e0156e486310d05e07eb3a9417e4749a3d6; - 0000000000000000000000000000000000020000000000000000000000000000 - 6b71719c717d62a10a688fe8f9563571195edc246f7e8006380a1bb14dc3b8fc - b8189e40e802d55d545112e6cab102254477c52f7536d019e06512c83742975b; - 0000000000000000000000000000000000040000000000000000000000000000 - 4a2086948673804f8a97a07b16b36c31096cc0610e2d240bf1fa440fac400f33 - 395dc8ec9ead16a9cee85b07e7da6b1475f525234bc4edf65ece264e72838ebd; - 0000000000000000000000000000000000080000000000000000000000000000 - ca82c08abf42285892485b0d4e4f3a5f5877ef51e0a501e3fce14e4a8b7efd06 - 1271158ab7223bf43fe3f689e9307aefe4233b46e864cac13d234544c0af18a7; - 0000000000000000000000000000000000100000000000000000000000000000 - e7a2d99bec6b59b14475e6a1a6fc28d5394ea5a8557882ae6e9e67d34b18c949 - 0ee608417c070fd9f04a73510cfb900f3773f010e074dfe70a333df6aff09d48; - 0000000000000000000000000000000000200000000000000000000000000000 - 9ac8e222a63951e1b7c2e16012ac90436dcbbace3f0318d2aee3e0bef53d5950 - bdd3b18e99e5fcae550234719e903e0ac7f83fde47ddb396b65eb8af1373d30a; - 0000000000000000000000000000000000400000000000000000000000000000 - 7e48facca309371083f21cbc0bc25ed09d09e03f996f4dc023f54ef7217ded8d - 8dcd9aef8e729df03810d6273f1f6125a35c797606030d653eab344320297a30; - 0000000000000000000000000000000000800000000000000000000000000000 - d1c032fab24525d378aed7266f49d5f7d03de6001ea531676f845fbd8578fa80 - 16c95820117c70da72373689b04c1e6f494b3f4c165d6aad39b5ba8bc8d5cf6c; - 0000000000000000000000000000000000000100000000000000000000000000 - 904091d32d5265cea53274748694757fad2e1c22566b1908f4f9d35538e89b06 - ad3b3c6e85d8afc210b3a22d1fa0c51076bd79c6641ed3481d1533ec7fe6b7b5; - 0000000000000000000000000000000000000200000000000000000000000000 - ca0521aec053c66badec9f3c89d952e0eb69afa9ea41080397071da57161b35a - 6641463de2ee581e2748259471425e94d9fb9d79093e0cd0a19b96ec510d5de5; - 0000000000000000000000000000000000000400000000000000000000000000 - 19fd13377a56d0aa15ac4e62b99eae76dde81f2ffecdc24504051da4b9652c76 - 3f1d6001995209adb152a06b48eec5025b3f755d8e2a01e4bd3b0b536f3ba333; - 0000000000000000000000000000000000000800000000000000000000000000 - 37a40e8139fbcdba67429f72b56509f5af081173ec4bd18cb6e9e3a826bc83c0 - 35196621c8a1dacc251ebe5bed3f5763659303b6e54a10dca061c2f5517cc417; - 0000000000000000000000000000000000001000000000000000000000000000 - ab0439f8eb335ac24b73994949e1eebf0614eef32a7bdb497960791f8db18e82 - 36f36ee2dc7d53583645d308735dbd7a2c88f0a3f407e8bacc2a9737c63fd51e; - 0000000000000000000000000000000000002000000000000000000000000000 - 104c04190e24ae90c2f87caf2cc314680a748cbbaef9298320dad36f660a243a - 3cd0909e1251efd2c9b631abfb0ddffc751ad3c77ac022ac47dca42682159b14; - 0000000000000000000000000000000000004000000000000000000000000000 - 337cf2622058e3b65d83499b927011407fd627c5e77d9e657fe1bb6a224478c0 - a3f95204f3120e370abfe9115eb31f39f5db8a92aad8c525b903581069001acb; - 0000000000000000000000000000000000008000000000000000000000000000 - 2b5bd6ccf9c26f31a167e7027426aae9865c0dfb14fb3dc6daeabeae5c1c8b69 - 5eab14eec32e833ad8cce68fe95d44c7cfdc997e0f5a8386817c3b679dd9771b; - 0000000000000000000000000000000000000001000000000000000000000000 - dc2541bdba0e4d40e8cb4fafc93d0a8a60a5530b3fe27b95f6a88be92f6f36c2 - d25f0a8d66d9fed6790560b86b0d08677c65f72e090426c88cb18cd756965e7d; - 0000000000000000000000000000000000000002000000000000000000000000 - b545e6c9514c66196058a3c3a7289be91d5c5e21da87797e3373bf6e24f5d590 - 9c64e96615ada88bca95405fce376291d5ca05e23356b0ecb94983c1610d07a7; - 0000000000000000000000000000000000000004000000000000000000000000 - f34e2420486825bbe7a24b40c50a84c28c80e2f298c30f4f78bf27c0ed56afb1 - cfdeec976acd4bf09bfa70ad96558e3198c1a4203784ceb5af21657c3a54c3df; - 0000000000000000000000000000000000000008000000000000000000000000 - ab041c33802ab7dca2d6d59863404616f94bf48ac727aed1a85f3b5aa4c6250a - 1797812dff75debcdf59a7b1714d3db08f4b4830801cccd3ac74d37527d3d784; - 0000000000000000000000000000000000000010000000000000000000000000 - f943ca8fee60cc92aee5b0301fa25b129993817b9a1c75cf8528fecbb7563821 - 8c00b2753f4f23b48423836c28977481cb073f3c3693ea03d33db3b5b31f6ed1; - 0000000000000000000000000000000000000020000000000000000000000000 - b1fbd227465ccfa0e934080e315073d99faa55be4fd38e93d210db20f4cbcaf5 - c4e7c620deedc6244fbbcd829105ada603825e64a044ed864c5ee465be50141d; - 0000000000000000000000000000000000000040000000000000000000000000 - a9341c312dd5c879b6b7305557080ac059eb7d48da0d044ce4c53d46ee682a77 - efc45cb2d180e546a8e60450da7859233b04ecb5a21a11d517a6752fe5b56ba9; - 0000000000000000000000000000000000000080000000000000000000000000 - fc0d7e148270279e6a8a0bb30102642a7f1481fc2617341674319a8496b2483a - 6b32c7813bfa42592b2558adf16918b1c56686e70b2fd6cf4d9c57ef4079ef4f; - 0000000000000000000000000000000000000000010000000000000000000000 - 55702bc90512de5e92dc5106f128997ac822b95d89ea8e924bc329174da48ee8 - e009220efb6aab4487ead7b8ef0b82843d16684ef57de55b2fbc2e981aae1c6e; - 0000000000000000000000000000000000000000020000000000000000000000 - 3be68900844eed0843ad0b2ef6d0b683a3112ba3b8a35a52f40007104586ab85 - b10b32f47822dac5b5db3d240bb2d8f05a408c2c20439563bd97e96a1f4ab84b; - 0000000000000000000000000000000000000000040000000000000000000000 - 5c451eaa6c8e993e837371b4f231e93e2ae7407b930f07bd87ef5ba134d9f6fc - ff89a9dc0895b13c20a7af15ae8e860d74f9dce289c1f43bdb35025d7086490b; - 0000000000000000000000000000000000000000080000000000000000000000 - a8ce9c065e6c91129d0643c04cf73150df86bf2f5a1a947a1fbecb1aca90d26a - a1301654d68563bfb7f2110e5d9ef96635d24ba8b56320cd070b25b6be28623e; - 0000000000000000000000000000000000000000100000000000000000000000 - 2aa48f6411a0ba5040eb83e2a2b20f14e93554953c8873e8879f355678badb0d - dbb22baa33905a9740d5ff475ed0517107f413690af9b95f717e4cdbace8405d; - 0000000000000000000000000000000000000000200000000000000000000000 - 7965be05896fcc9b9dc334f9c2a43f813d5c248963e1317f798c4f9fc5f8e7fd - 34125fee23f020155f248b4cc5dd4370ed530ca871be46fd93e7a006edfea7b8; - 0000000000000000000000000000000000000000400000000000000000000000 - 1541c80be3e5c8e221540f92b631f360c5b0370223263e771b1b92d4fb73a453 - a2bff0682b9d6e3eaf8d183efaec91667808f9d026ff20c1d65f7e6e2a4676a3; - 0000000000000000000000000000000000000000800000000000000000000000 - f283204496fe825836a3aa8377f4f2db5cfb14b41c6b9f5f53e565c852db6598 - 6dc375d702992c7e30ed6cd188fb27fd7a3c4e4c7fb2856f67244fe3c7f8b760; - 0000000000000000000000000000000000000000000100000000000000000000 - e234f1c1d7ccd4ce1ace58850dc28d2abc7e2dfd171877710704282a12bab9a0 - 8d51c164dc8ae5ec5bdfcc25fb1ee9a6d9cefa47abdb748143ec18b91c72fcad; - 0000000000000000000000000000000000000000000200000000000000000000 - 4cb4412669289a6250900c8713f56cb57f5b962137b828b46a1b1dcb41bbbca0 - 2b1ea7bd9d0cd83de33ccc5415ba625c6c4d2bb211e5464c39b2bf9325aa446c; - 0000000000000000000000000000000000000000000400000000000000000000 - a6c52188edc54c3e88d4424ac378f85b690e1b6b46e552f4c855aa9e4e0b2c36 - 75e118baa53204bb91b283c80d3baf3e70c4cc204f25aa71ae6ebe0655010d9c; - 0000000000000000000000000000000000000000000800000000000000000000 - 58449e523e08c99109ca6570b8bba4011a7cfb2203257e8b93d3131bb16219aa - b1f0f1f930fbe5566ae5ab46e7a6981ae14d51dedc62a4b1786c032d16cfb829; - 0000000000000000000000000000000000000000001000000000000000000000 - edcf56d94c31b0d201066b648da08d43e0ece64dfefd3a542852fb3f945ab216 - 122c6c4b6b019b18cb0e925d191f3599d9eee57eb7a6506fe1fac494f037327d; - 0000000000000000000000000000000000000000002000000000000000000000 - b178ca20a3bb67c4f34a816d1c4636cea7642cfa004cde16efe32a6c613c9eef - 45912f3f092fd64dfaba7cd7abf0534fa7f8571d8d01949d5204223bba068166; - 0000000000000000000000000000000000000000004000000000000000000000 - d925287721da5f6117f951cddf410018ee8cd147f97305ba2f0aac26c1859312 - f3878c9586205c2f92b27656df61bd94b00a01b86202079ca1926968a1b52c08; - 0000000000000000000000000000000000000000008000000000000000000000 - 359f4ea466e0f07d6a0de61e99ff4e2007cc5dd90c59a1e4d0d5b46f03b5aa99 - 33816ce4fbfc40b806bd2bad025b9477b051dd55d2fddfe007287e66e1814afa; - 0000000000000000000000000000000000000000000001000000000000000000 - ae77a98a68d9462b74bdd4f7d124746e1c5765406cf1b9ef547d52f00b45d4d7 - 2d58c0e474a33f1957bddf17a850871ea050580f4f8d48380261189a271d4c01; - 0000000000000000000000000000000000000000000002000000000000000000 - 0bf35dc3d5fdea4d60f14bd0759906c1625c44cbb754f4087645b551355844ee - acae4ab9b17e275e54968b1ef6a2422f3bb97eefa6b0007bce18e8162a8bfa50; - 0000000000000000000000000000000000000000000004000000000000000000 - 4ed4cd19fedd9fce8b979f698f2f167909331a7ab8dffbb7fcb56a2c5afc1428 - ddb8a8c89b629b0711f72b3328b22727e1c5965dce9b3843667e1b6492962416; - 0000000000000000000000000000000000000000000008000000000000000000 - 6af47d0713e05fb4a2974110b0860baedd2597820ff5c600f9049d7d425ee100 - 2d0cf3e4db588dea89cabb0b0ad58acc1d0b83388fb6af32b367e21f7f14f41e; - 0000000000000000000000000000000000000000000010000000000000000000 - 96a82f4432529492f6a8a17fcf155ef8a6bf11bb73a77d3dd8bf3e986ca3dbbd - d8fd1163036b81998a1e5e3ed3d787fe270f05b8095f0cb853a0b934b4016dbb; - 0000000000000000000000000000000000000000000020000000000000000000 - 23e6baa1a8a67122a9855247124ec59a1dca649570c6a1a4fb089a76c81a6014 - 3583e5c1cc5e397b2b5864960caf7aa66ebe6467d4065e67008fa737c053a7a5; - 0000000000000000000000000000000000000000000040000000000000000000 - 86118f4629dad8a873b1649b9c039fcd4dd8ba032b9f6819115c3af0d1b6595b - 071740e3ca823edfdabfabc0dc10924348fbb023b6ddb344d4f42e9572de3e08; - 0000000000000000000000000000000000000000000080000000000000000000 - 982d814b00c91517c08aa4c87087069c01c6a045cbcd3d7f26a4a1c6cc97d2b6 - 3d20e5791747d98b9ea3d2026594b8ce462c5ba6e62a1c361cf5fba5ca0f1d11; - 0000000000000000000000000000000000000000000000010000000000000000 - 2dfb74f1332f7930be2ea7a1732ce3d56fb12d916d2796d1e1fba64f2e66ac20 - 4be4d901963da689112e1fc54d852a70c0f60b501b915cdc141fab94b43d0106; - 0000000000000000000000000000000000000000000000020000000000000000 - fe6cc968de80a13cb0e7a1fd4eeac2a1d1ddca48c53e2bd5f4230c4f51d1f4c0 - 8af8f0ce706f35fd089f8d8aa07d07d9a7015d4ecdc7e9548cd0f3992073aaa2; - 0000000000000000000000000000000000000000000000040000000000000000 - f8f84d21d697ff9862c223ed476722077f5865800c34d36a6560a0a975d90413 - fb9e5f6b3e8f8e78f715226d808f98c389883d65e2c53aab4ab018fa941d28eb; - 0000000000000000000000000000000000000000000000080000000000000000 - b934372f8ad78e178eebbeba49db0466073fc8e29e78a232bbfffd59b9d72d65 - 95d2ff2f7e24735bcde0d3766c83a128104bbc8ac1944f3efbc3e174517d08ff; - 0000000000000000000000000000000000000000000000100000000000000000 - ef204271d3588603c5f43eacfde91e3306723c7f074fe2088ab95fcbb45eb6be - c14741e0daa9c84264b877e8a503ae78c6c7b2329f0bff9476ba2dad653ecf12; - 0000000000000000000000000000000000000000000000200000000000000000 - 0515648007e5e5e8e37e9056a4f23232a07083fce238e2dd3853b3ab1734ea70 - 0f4f15ea46ccda314f7891ca7d0091a6215d341788a3acb732a93a14da0a0d18; - 0000000000000000000000000000000000000000000000400000000000000000 - 67b53797fd010597b38fd94cf1686270f0992e6c6666e9ca4a105a61d510d9bd - 28069c2ded2405e0ef95abeab23f36bd752b15119e4fa69b43d731624ce5178d; - 0000000000000000000000000000000000000000000000800000000000000000 - 7a47769ca3509d8811e6c23c3d5adf38da76e8d481fa13afdf60813a8b59792b - eae7e513eb59d8ba54087cb66c7c00edfda452731b93f34698b477d234dd7faf; - 0000000000000000000000000000000000000000000000000100000000000000 - 8dc1de423e5ae630989be11bcd4be30d3f62efe9d38fc26396b123810df2768f - f0c952d27a250c3f4d914d537fd04a8cdc6c057af35ba4410bab0ea89e6d7d54; - 0000000000000000000000000000000000000000000000000200000000000000 - 48571b94f3f991ca6e992e60358fa4b3255999983d5f9b9b1268e61f3db3bde8 - b889b82fb5f1e8d78eafee9275c889e23c7a2555d78487b9cc4f701d7d1f00e1; - 0000000000000000000000000000000000000000000000000400000000000000 - 1e41bd7ebac2a488c52acd8a99b336469d9fc35c98d9cfff269a6b8e9377309b - 11ec65507e8b6393c7f12023f8ce9f0985ff92b8a3ef9c78cb1f2883694878f3; - 0000000000000000000000000000000000000000000000000800000000000000 - b6eab1e877e719a42d935523dc8c904b35a30e3b02148944a6e46459e35c5f40 - 04da7f3786ccae4982a8e75aa55549a89708915b1c6f19613632cde018ff5269; - 0000000000000000000000000000000000000000000000001000000000000000 - 925e5596d9660e28a1b6c1a9e33fc7beea001f1cdbaee6c6fa7938d66e4f2e7b - 0473cfc0964e7b3f9b505789fefa176f735b564678ce0b89223c073175e685ff; - 0000000000000000000000000000000000000000000000002000000000000000 - ce02c8aab250c3d07e84fd4a8475c1cffd00a20b1f215df5feb3e93e287f6c46 - 7b9d26b50cdd0eb37a1c6cb01807017bb70760c2892b114a944b183e80392739; - 0000000000000000000000000000000000000000000000004000000000000000 - acab6f16ba40e29b015d0289c82f03f54baec63d322c1a70792094d229b2b17e - 41e4f7bad8838666d798ed77a6d4129a4a97b7740611539d9a21064ec837072c; - 0000000000000000000000000000000000000000000000008000000000000000 - beaa65cfea3e972077a48ec8d99421a5cd6e234e2ede51c080d0d99ed5fdbc5c - b83d02d1b94ace563287cac9ef6b175a7cb60c84343976f97105c2d78aa1e683; - 0000000000000000000000000000000000000000000000000001000000000000 - 9165a45f535f24531daaa5fed2621c91755e15ba9f85e57d848172c9846327b2 - f496291c25156383b867c10bcf82466c138555bfd5fecfc9c01dc2e65aa43929; - 0000000000000000000000000000000000000000000000000002000000000000 - c17d79761600447acdaae4ec9398c1743a432e58752cc8082e45d842b43f0e66 - e5ea6f466307a34d36ab278aaa884ec07a494ea17216eb405790320d8fa2fed4; - 0000000000000000000000000000000000000000000000000004000000000000 - d6868ca98e49ab85e60f5411b17d644b613f6101107c70f514b12d1b3e4133f5 - 1305d1b51ced2666839b11eed182da902e864a74e35e06e9d4137996ef50dba8; - 0000000000000000000000000000000000000000000000000008000000000000 - e35c518d1abdec18c07645ea79f07071c2967d1045ee804694dc5d43e96610ac - 1908ede77ee9510ee12f3d3f516002356731e164a9ea4f63171550ee2ee90552; - 0000000000000000000000000000000000000000000000000010000000000000 - 06eb73063502eda7c71d450742a79c9c7fa03f682efae6cb0b65f44e95fe4a74 - 31c5681726dfa952c0c2285aa56cab4eb107095337c624ea81ad277664b2a264; - 0000000000000000000000000000000000000000000000000020000000000000 - 4e7269b1930a4415947740c02e07f5a648071b525ef02c169ed6464d8b27bb8d - 6abc498904e605e1b5e28ea8628b55c7e5e029623f77cd462691d3a7fc278674; - 0000000000000000000000000000000000000000000000000040000000000000 - 826a3104a79da8022158b60aa55187dbd1fb2bced56c4690560cc83fda92e492 - d3fb967cae7452b867c88adc8a11e5b5b95989bdde92639ed95305ced7cfdc60; - 0000000000000000000000000000000000000000000000000080000000000000 - 0b92142c4fdbc92e7156469124819ba920edc66c427430c017d6bb294085ac19 - 6f327c30503e8cd50af536583f510545511e8d70da1cc285bcce2d46f92d2b2a; - 0000000000000000000000000000000000000000000000000000010000000000 - c7b17c0628edb82798962e54e097372b3860bbc02b0cad3f87dfc81b3d25d93b - 4ea78d7501f8fb379e7725fa971af497596116c475b4796ccbc7e10d1a2a21d9; - 0000000000000000000000000000000000000000000000000000020000000000 - f9286bb83357f5ba5e9fdd2c7944ca1d75d9d2375710a2894d282c85a1f94b7b - 5293a298473e7efcde744290da3a51cb3c798cfdb1fc9a4c7aaf4f7b3008297b; - 0000000000000000000000000000000000000000000000000000040000000000 - 64be8cf1fb77d638f68b6fd80b57f21adbc420b5e99d4227ac0ae6d82adb0f71 - d9de4fa7124fdab3c5473ed50c41b53fe346ced59941d71a8191a8f6ade215d8; - 0000000000000000000000000000000000000000000000000000080000000000 - 16e491e25d6f79d9a33018ae66f6a78a87e4ca6d4b225f26a70acf757eef8754 - 86fde1681d4c26c001abbc93e967065f985b607441d05683f971b05b7c5e556b; - 0000000000000000000000000000000000000000000000000000100000000000 - a499e877391ec0170d41b8e03af321fedbda237b675123018902af35d59acf9e - 78e154919e5bceb7b20a4c6f94aec7014a4e03cba4fc668ed69644f20de31abe; - 0000000000000000000000000000000000000000000000000000200000000000 - 8b058ddb6648ef4583b44e5332784c6872c52589fb2d1e7b107ff5ee64b59e6d - 4a022b951253940108f3a795bc4f39ae3baa2cf656d3e2d520138853fba56a93; - 0000000000000000000000000000000000000000000000000000400000000000 - eb530cdefc2656bdae8734131668a5833ae26f131b2c8fb50999da0106591fcb - 739475c5772aeede0aa39c19c120c20aca995eb3e7a90d4048b0a4e1efd7cd29; - 0000000000000000000000000000000000000000000000000000800000000000 - 2eb1c5426bbd82ff9526b482d3dd71bf52af1cfb1fa7f68acc457b08429d0ddd - 5ac3c96e0623ff40dc8dff86f1d4ddfb90312c1443243c89231b16efa79f0bdc; - 0000000000000000000000000000000000000000000000000000000100000000 - 3b9b9773dac3e4954d4168945e276ca5c9e1008aff8be8034d0856868bcb7dca - 65a19215b091c569c84da60a64b874091906c6c23fd975487d877e91a64e43c3; - 0000000000000000000000000000000000000000000000000000000200000000 - d09fb1b66db34ab57f57a2fc98945fd2b610ca739452954d3dc32e6d11b1cd08 - 7cc4d6e0660454281087046c740ae0cf3ade676dfbd2fa46d4d0f5ca1cf4fa5c; - 0000000000000000000000000000000000000000000000000000000400000000 - 7d02fbc809080c5e21522ce33eae610a47f7c059433bbac3ac30c5637d8aa3ae - ee4b97a5049fbac0137eb688cd389bf104afb2ef754a30dc4e72e60267efbb0c; - 0000000000000000000000000000000000000000000000000000000800000000 - 97e7a1f5b2c9d77294a3131298479c8240e33800f4e95b76462d3f0f9899abee - 669f11d848792de5621440aa51b628b667f9fa28e6c43070215ca6b52da59760; - 0000000000000000000000000000000000000000000000000000001000000000 - 92d91bc3b83ee7c8512c0dd87efad9952a41f38aaf3ff737b1bf232484b3ced6 - 6e417430040e5bdce9e6f4df84e09323e254e2c75b7ab7916dc5fc84f0dc7f2e; - 0000000000000000000000000000000000000000000000000000002000000000 - a201b9a8fe87c900acc1937c5fe32563f4f52ded3f9f7c484cad259adfd81a59 - ce267b0cf6d5e06d6a980db8fbf00a6609f8e91ac1e0dd705b53428c8a69baa9; - 0000000000000000000000000000000000000000000000000000004000000000 - d84985bd7e97e581e034d5f7b27d96bb78719cbff19e37abf66395654714ea20 - 919b92ccce355fdb77913cddd41e0fcc3d7b468dc8f6406782953388dbf82927; - 0000000000000000000000000000000000000000000000000000008000000000 - 506c7f563c6254e18d5b50e8c294a97a3634322709189dc2e6af7c1166cc846b - ec220577d30e07409eb06ab77477eb8a4d4357443fb64d739692458e82e5fd0e; - 0000000000000000000000000000000000000000000000000000000001000000 - 671217631c0840c9c9828f78a714f1bb67b864d646efe8de3c432ac20d55f133 - 39064a3dee432a3632fe78fab64d637c933bad5d44e2118a1247dd10c51adb8d; - 0000000000000000000000000000000000000000000000000000000002000000 - c5e41aa3e2d7a37c82e7a41ef0db3c81fe9b9d2948dc5c1d7b8bd862142c5603 - 0eefaadfe8682f723c8b407d90da3dce9612965c770987ed1a0f1ea66745103c; - 0000000000000000000000000000000000000000000000000000000004000000 - 762a716822e4798d1493f81f7daccbba1becbd4fbc4a478ee30e4aeaadb0b0c2 - 21e19764af6c956a9ca8c31f3344cb0fa30195bd868b524d8d8de89090944918; - 0000000000000000000000000000000000000000000000000000000008000000 - 221e93fbe263c8a6c92a87c6492e7d17fee75a585cea8f311cd79f595b42495d - 58dcbe9cc752afd2aa2008bc9f95c2e70d38fea1d5c3b87c1e6f29f9c0bc4373; - 0000000000000000000000000000000000000000000000000000000010000000 - 72b80c94d6ff97f97e9f76e139c037a3fee9a53e48f0e57266e24761592cfbfd - 1eb856387f0f0208987725a13f796cfe420ea65fd338fc594fee3667325add23; - 0000000000000000000000000000000000000000000000000000000020000000 - d147908d20daf77c962b21d4997f7b84fdbed2cb07cb06e0e59032641b9dcb3d - 5fac3709cbc5b5f3ef21ae198d9234feb1a82ea4957684891877e2ef2b3c0332; - 0000000000000000000000000000000000000000000000000000000040000000 - 7374263f1b8c9d4d21f52f1ec6f971d9dc7268a8af79ac1c1c535dc4dff5cbf8 - 241175e0afa2ed5af43ed388a818f128e6d99731dff319644fdb983951d8e765; - 0000000000000000000000000000000000000000000000000000000080000000 - 752aeaa1cdbb7d024fe734668cd9f63d61ff4b335e7f42d0f545ab81b9b234fc - 4ab2772f9d610f0d618828a10dcbf20ce04d4f78f71565a8379680ea225801ac; - 0000000000000000000000000000000000000000000000000000000000010000 - 7ec933c4574148f27c412e2a4289def909ad7cefc54387dd5f0dd2c832488790 - 99e2a4d15571d1098f1defc1d29b07c40af145ebb2edf81258d5afccb97919d6; - 0000000000000000000000000000000000000000000000000000000000020000 - 954bd7a24edf58f58ebe343632e606fe97936b2500658ff9b11ad67617d221b0 - f63398643b341b0a948cf22f5e9fdeeb8fd4fe21a3d946cee2f365e75537fe1b; - 0000000000000000000000000000000000000000000000000000000000040000 - e65323be34b117fad1cd194caaa254c7ec53fd96b65430e5703ef4697c4596e9 - dad3ec2e51bc681c018f9ebf6d137999d6234dd84958737bb438c3232d377187; - 0000000000000000000000000000000000000000000000000000000000080000 - 4b4306c5d55af9bf63dcf7c7c20268ef10b372b59ac10695d2b83277ded2b85a - da842a5af1d93e0f945101c202771981b4bb7645d9a59bf0939cf7b35cf1de41; - 0000000000000000000000000000000000000000000000000000000000100000 - 20b0a0a6c9fd63ee745798c9248c988b1aaa9dc976f783254711c57f755728e8 - 83bc5c2254747422499230ac0abdd29de42b8896a9abf47cae6811a5e7986325; - 0000000000000000000000000000000000000000000000000000000000200000 - 92c046c878b2f54671c4287237e200388bc1b03807c0e961b6e8ad336d6b0dc3 - 517c911a62e8c951bd0bebdca4940a49bd0d34eca5d7fd42f53b63a674588ad7; - 0000000000000000000000000000000000000000000000000000000000400000 - 07faa395104ee08dbe87821fe9f4bc657a0a026de98a1b7eafecdd0a0cd90950 - b8dcfe3057cff32a8346fdda5cde697a0f5daa99073a12602a14fc2c098e8d37; - 0000000000000000000000000000000000000000000000000000000000800000 - 7b66faef189ff1c27797957691d2a5393a51cc46d1fb35bbbdd9c18c5d6be3b0 - 30d0516447f18c0140c56a2d3839f19713b2777507afd01bcd3e2b5f3bf565a9; - 0000000000000000000000000000000000000000000000000000000000000100 - 4a7db25fe6b7f7195642b302df9ae60721be3bc0a0c03c0bfc02774f0770672f - 5e9e9a73d8482a46bed4f5a3d111f5128d7ce25b459cefa8dee41e8a20530cb0; - 0000000000000000000000000000000000000000000000000000000000000200 - a3666ad211b46b616702ba5460e2153563ce71527ca411720095408409c1c1eb - 9b5b488a37a2639e60077e50b3cfc23e0ca6b15303ac57d6a861d27bce87f4a6; - 0000000000000000000000000000000000000000000000000000000000000400 - 5621077387c09f1b7de44f33ee44726fb24d4f13faeb59888c94d6867c7b4989 - 0e01ed6bc6527eaff1dbce5ce7a23df23e6369f51c250ca01e757c7ea6d2b3de; - 0000000000000000000000000000000000000000000000000000000000000800 - 6ac275dfd387f63219d26d8f2bef9e73e17c026ae17707ba80ccf24899a9db69 - 63d189cbd05260d003546c599da6d7b574fa0037104cf6300f9f5f5edd6eef02; - 0000000000000000000000000000000000000000000000000000000000001000 - d9f2fe1ca70220a4471cb888f5ce568012b30c31c485977f5bb3e0310195b5a8 - e8a1128025fa4a2431858de3c7253371b487b2e49bfc477e9b5d6734e2d17d34; - 0000000000000000000000000000000000000000000000000000000000002000 - a3ab3112e4d31f85ebc84e7e43015c687276a54a96b77b462d2e1ec71b88fdae - cb586bb26463168f35f52a962e040278ea2e476ad53a6161599ebda329c46070; - 0000000000000000000000000000000000000000000000000000000000004000 - 93bd82cdc5d4b50b83eb98b2ef0735c9d95f7aa82e857a76b033b13467eefd14 - 9b3955c74930f1448504dc3e1486e9f861d25f437dd8c2db6d67ca70b4a83014; - 0000000000000000000000000000000000000000000000000000000000008000 - 9a47b3563a9a7ac67a73109c79dd36c0a4445dff6b0677ca76e30cbdbca7ba07 - 4063046b6cd73e682fce54e3ced24880627ff6ab50a9b9de367300ef07e9b9d3; - 0000000000000000000000000000000000000000000000000000000000000001 - 1e21dcd5b4cb8628bca386ab818e8b64b693a784e38c1bfa01b82c9d95846083 - 30af87491adddc2f86988318c2e7ce9f4f4d19e84eef873ce0732599a097f3f5; - 0000000000000000000000000000000000000000000000000000000000000002 - f9aab3d341f85f5fd8cdee460a5667595483f277b0f79f7b6df89fdd35a134f5 - 16f23b237ea5c03cd5ff1304890453a8311c456a2935a65c73c99e3fc12bfb3b; - 0000000000000000000000000000000000000000000000000000000000000004 - 935d4b978db6e8f84dad228410ff15093f40ed89e2a2f8d1cb8410643b74a039 - f01d8a43f5ee23843f8df421f468bd2c052677b2a993256225f34966000ab693; - 0000000000000000000000000000000000000000000000000000000000000008 - fffaf07ed7971e764123fe4e7aa181de2b0b0ab8704ffd9b82ee49495dc1f920 - 8c3bbed3d1a15e2e5d203e7d964b9b481d42e945b28fab114435df28aea6b023; - 0000000000000000000000000000000000000000000000000000000000000010 - 6e6d8318c270135985a84e3a2541053eb8b58fad367fdb2e81dbe723572421c4 - aab06f5557fb72c450d68ec0b706c97d8e7e260f70db34e3ecd28ba5473c9268; - 0000000000000000000000000000000000000000000000000000000000000020 - e8d4277d5557864cf02d3f4cfdf4a998f82777e9fc4dfe06d856091634634141 - 6f6aaf2b2ea7ee54ba5e4c28de990437e17f685194c76160875acbb35bdf4d93; - 0000000000000000000000000000000000000000000000000000000000000040 - 6e32a77e600cea713325d09408312bae15cd75d28d2c04a5f604990e65be3d89 - de71f5f1814b9a73098ea50c4d3605bb764387f317ee2f08b90b88ada605c105; - 0000000000000000000000000000000000000000000000000000000000000080 - 92128b45f2af927df41f3b200a872673a744956e2c58b0099f243b7911c50436 - ce408d59a184170a267df8713a787464af6d75f5f46b8b64ddac88daabb50ecd; -} diff --git a/tests/rmd128 b/tests/rmd128 deleted file mode 100644 index c82b25d..0000000 --- a/tests/rmd128 +++ /dev/null @@ -1,111 +0,0 @@ -# Test vectors for RIPEMD-160 -# -# $Id: rmd128,v 1.3 2004/03/21 22:44:36 mdw Exp $ - -# --- Basic hash function --- -# -# Taken from the authors' web pages. - -rmd128 { - "" cdf26213a150dc3ecb610f18f6b38b46; - "a" 86be7afa339d0fc7cfc785e72f578d33; - "abc" c14a12199c66e4ba84636b0f69144c77; - "message digest" 9e327b3d6e523062afc1132d7df9d1b8; - "abcdefghijklmnopqrstuvwxyz" - fd2aa607f71dc8f510714922b371834e; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - a1aa0689d0fafa2ddc22e88b49133a06; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - d1e959eb179c911faea4624c60c5c702; -} - -rmd128-rep { - "1234567890" 8 3f45ef194732c2dbb2c4a2c769795fa3; - "a" 1000000 4a7f5723f954eba1216c9d8f6320431f; -} - -# --- HMAC mode --- - -rmd128-hmac { - # --- Test vectors from RFC2286 --- - - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - fbf61f9492aa4bbf81c172e84e0734db; - - "what do ya want for nothing?" - 4a656665 - 875f828862b6b334b427c55f9f7ff09b; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 09f0b2846d2f543da363cbec8d62a38d; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - bdbbd7cf03e44b5aa60af815be4d2294; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - e79808f24b25fd031c155f0d551d9a3a; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - dc732928de98104a1f59d373c150acbb; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 5c6bec96793e16d40690c237635f30c5; - - # --- Test vectors from the RIPEMD160 home page --- - - "" - 00112233445566778899aabbccddeeff - ad9db2c1e22af9ab5ca9dbe5a86f67dc; - "a" - 00112233445566778899aabbccddeeff - 3bf448c762de00bcfa0310b11c0bde4c; - "abc" - 00112233445566778899aabbccddeeff - f34ec0945f02b70b8603f89e1ce4c78c; - "message digest" - 00112233445566778899aabbccddeeff - e8503a8aec2289d82aa0d8d445a06bdd; - "abcdefghijklmnopqrstuvwxyz" - 00112233445566778899aabbccddeeff - ee880b735ce3126065de1699cc136199; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 00112233445566778899aabbccddeeff - 794daf2e3bdeea2538638a5ced154434; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - 00112233445566778899aabbccddeeff - 3a06eef165b23625247800be23e232b6; - "12345678901234567890123456789012345678901234567890123456789012345678901234567890" - 00112233445566778899aabbccddeeff - 9a4f0159c0952da43a8d466d46b0af58; - - "" - 0123456789abcdeffedcba9876543210 - 8931eeee56a6b257fd1ab5418183d826; - "a" - 0123456789abcdeffedcba9876543210 - dbbcf169ea7419d5ba7bd8eb3673ff2d; - "abc" - 0123456789abcdeffedcba9876543210 - 2c4cd07d3162d6a0e338004d6b6fbc9a; - "message digest" - 0123456789abcdeffedcba9876543210 - 75bfb25888f4bb77c77ae83ad0817447; - "abcdefghijklmnopqrstuvwxyz" - 0123456789abcdeffedcba9876543210 - b1b5dc0fcb7258758855dd1840fcdce4; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 0123456789abcdeffedcba9876543210 - 670d0f7a697b18f1a8ab7d2a2a00dbc1; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - 0123456789abcdeffedcba9876543210 - 54e315fdb34a61c0475392e5c7852998; - "12345678901234567890123456789012345678901234567890123456789012345678901234567890" - 0123456789abcdeffedcba9876543210 - ad04354d8aa2a623e72e3594ee3535c0; -} diff --git a/tests/rmd160 b/tests/rmd160 deleted file mode 100644 index 1bd3a77..0000000 --- a/tests/rmd160 +++ /dev/null @@ -1,111 +0,0 @@ -# Test vectors for RIPEMD-160 -# -# $Id: rmd160,v 1.4 2004/03/21 22:44:36 mdw Exp $ - -# --- Basic hash function --- -# -# Taken from http://wwww.esat.kuleuven.ac.be/~bosselae/ripemd160.html - -rmd160 { - "" 9c1185a5c5e9fc54612808977ee8f548b2258d31; - "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe; - "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc; - "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36; - "abcdefghijklmnopqrstuvwxyz" - f71c27109c692c1b56bbdceb5b9d2865b3708dbc; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 12a053384a9c0c88e405a06c27dcf49ada62eb2b; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - b0e20b6e3116640286ed3a87a5713079b21f5189; -} - -rmd160-rep { - "1234567890" 8 9b752e45573d4b39f4dbd3323cab82bf63326bfb; - "a" 1000000 52783243c1697bdbe16d37f97f68f08325dc1528; -} - -# --- HMAC mode --- - -rmd160-hmac { - # --- Test vectors from RFC2286 --- - - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - 24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668; - - "what do ya want for nothing?" - 4a656665 - dda6c0213a485a9e24f4742064a7f033b43c4069; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - b0b105360de759960ab4f35298e116e295d8e7c1; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - 7619693978f91d90539ae786500ff3d8e0518e39; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 6466ca07ac5eac29e1bd523e5ada7605b791fd8b; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 69ea60798d71616cce5fd0871e23754cd75d5a0a; - - # --- From http://wwww.esat.kuleuven.ac.be/~bosselae/ripemd160.html --- - - "" - 00112233445566778899aabbccddeeff01234567 - cf387677bfda8483e63b57e06c3b5ecd8b7fc055; - "a" - 00112233445566778899aabbccddeeff01234567 - 0d351d71b78e36dbb7391c810a0d2b6240ddbafc; - "abc" - 00112233445566778899aabbccddeeff01234567 - f7ef288cb1bbcc6160d76507e0a3bbf712fb67d6; - "message digest" - 00112233445566778899aabbccddeeff01234567 - f83662cc8d339c227e600fcd636c57d2571b1c34; - "abcdefghijklmnopqrstuvwxyz" - 00112233445566778899aabbccddeeff01234567 - 843d1c4eb880ac8ac0c9c95696507957d0155ddb; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 00112233445566778899aabbccddeeff01234567 - 60f5ef198a2dd5745545c1f0c47aa3fb5776f881; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - 00112233445566778899aabbccddeeff01234567 - e49c136a9e5627e0681b808a3b97e6a6e661ae79; - "12345678901234567890123456789012345678901234567890123456789012345678901234567890" - 00112233445566778899aabbccddeeff01234567 - 31be3cc98cee37b79b0619e3e1c2be4f1aa56e6c; - - "" - 0123456789abcdeffedcba987654321000112233 - fe69a66c7423eea9c8fa2eff8d9dafb4f17a62f5; - "a" - 0123456789abcdeffedcba987654321000112233 - 85743e899bc82dbfa36faaa7a25b7cfd372432cd; - "abc" - 0123456789abcdeffedcba987654321000112233 - 6e4afd501fa6b4a1823ca3b10bd9aa0ba97ba182; - "message digest" - 0123456789abcdeffedcba987654321000112233 - 2e066e624badb76a184c8f90fba053330e650e92; - "abcdefghijklmnopqrstuvwxyz" - 0123456789abcdeffedcba987654321000112233 - 07e942aa4e3cd7c04dedc1d46e2e8cc4c741b3d9; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 0123456789abcdeffedcba987654321000112233 - b6582318ddcfb67a53a67d676b8ad869aded629a; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - 0123456789abcdeffedcba987654321000112233 - f1be3ee877703140d34f97ea1ab3a07c141333e2; - "12345678901234567890123456789012345678901234567890123456789012345678901234567890" - 0123456789abcdeffedcba987654321000112233 - 85f164703e61a63131be7e45958e0794123904f9; -} diff --git a/tests/rmd256 b/tests/rmd256 deleted file mode 100644 index bc4d976..0000000 --- a/tests/rmd256 +++ /dev/null @@ -1,61 +0,0 @@ -# Test vectors for RIPEMD-256 -# -# $Id: rmd256,v 1.2 2000/07/15 10:03:13 mdw Exp $ - -# --- Basic hash function --- -# -# Taken from the authors' web pages. - -rmd256 { - "" - 02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d; - "a" - f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925; - "abc" - afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65; - "message digest" - 87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e; - "abcdefghijklmnopqrstuvwxyz" - 649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - 5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8; - "12345678901234567890123456789012345678901234567890123456789012345678901234567890" - 06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd; -} - -# --- HMAC mode --- -# -# I couldn't find any official test vectors. These are therefore generated -# using the Catacomb implementation. - -rmd256-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - c1829c0d5a203bbf6e874a721d55ffec22456f3a0987e30a4861a40cad5dc9e7; - - "what do ya want for nothing?" - 4a656665 - 932d3e799272765675dd63c33f8d2815ea38181494f43271dd52fde91392619f; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - a30051679681f54ad62088438a308c3dd38cc0eb2d352fbdcfb2811abf9c1e29; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - d55d1a9b2082105103d8331581d9522d17b4cce92e95f0f4654ce8da187ffbbb; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - cc8e435de509ef9a974cecb40cdecf55c8e6a22d5458e74cb7b0a306453ad67d; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 821543a295eccf093af9b461f630d7c49206fb2158e5ac89e73a02cf089528ed; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - ca26edc0129a781f1224cc6c9f655052f120edb5842bcfcf4b8d0f8b8be551bd; -} diff --git a/tests/rmd320 b/tests/rmd320 deleted file mode 100644 index 82bbc4a..0000000 --- a/tests/rmd320 +++ /dev/null @@ -1,61 +0,0 @@ -# Test vectors for RIPEMD-320 -# -# $Id: rmd320,v 1.2 2000/07/15 10:03:13 mdw Exp $ - -# --- Basic hash function --- -# -# Taken from the authors' web pages. - -rmd320 { - "" - 22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8; - "a" - ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d; - "abc" - de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d; - "message digest" - 3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197; - "abcdefghijklmnopqrstuvwxyz" - cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4; - "12345678901234567890123456789012345678901234567890123456789012345678901234567890" - 557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42; -} - -# --- HMAC mode --- -# -# I couldn't find any official test vectors. These are therefore generated -# using the Catacomb implementation. - -rmd320-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - 03ec929cb94837c2acd709d03f4a26c3e38c7cec4fe2f5caff3b64e168321c8591b1d3ffeb87b9f4; - - "what do ya want for nothing?" - 4a656665 - e440b00b6326e4f7dad3a6591e8189e9708fc17e3cab306fc67efaf70947aad2ea89e28f79d03bd3; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 8c7ee84fb76703386f01f088cbe0ed9a694d6e0c9bfbe1c7785f56cafc5908db2e16afcb0721edae; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - 714f482ff865edbbcbfb344948ce3c8b9d2308650f2f0ed2111a6983509c967416e092e9f6b307d0; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - f0b1c83e3cec672db53c259746de4d13841e01dd6266c360fda76f3197ac47582c5e9b59d7a8a7b9; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - a61c1123c1a23ffdd9af5fb28b62b95f989876ac322452f5e4f4470c25182ef4816aaec7f0377167; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 5e5d0fe86d7f8ff85108bbf75cf25dd99e8029237b93ff0d93fb779264a103082cc62ad8914feed3; -} diff --git a/tests/rsa b/tests/rsa deleted file mode 100644 index 9534d73..0000000 --- a/tests/rsa +++ /dev/null @@ -1,393 +0,0 @@ -# $Id$ -# -# Test vectors for the completely mad RSA infrastructure tests - -p1sig-pad { - # nbits msg rc result eparam - 256 "616263" 0 - 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263 - "cc22cc"; - 129 "616263" 0 0x0001ffffffffffffffff00cc22cc616263 "cc22cc"; - 128 "616263" -1 0 "cc22cc"; -} - -p1sig-priv { - # n e d msg rc result eparam - 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 - 0x10001 - 0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9 - "616263" 0 - 0xc484642d0e4dc4a4424d22410456dbdd9275b5c157d6974a66bee9aa02501c26 - "cc22cc"; - - 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff - 0x10001 - 0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81 - "a9993e364706816aba3e25717850c26c9cd0d89d" 0 - 0x0f642606b7aaf99ff4bb5853c51e31a02c58d8c1c33f3c584d4edc58b08a16d5dc8064b6e198edcc4dc06666171a113619d7da16dfd96cebfdb5cc5050af6fab3d9f2ca8b8d6ece1d513fabc98a11fe37892fcf0827ea2e792427a69b3523504f46c55ed8af9a1c59687ca73c4baad7235a1a3faedec14f95ddfa8d0554739a8 - "3021300906052b0e03021a05000414"; -} - -p1vrf-pad { - # nbits sig msg rc result eparam - 256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263 - "" 3 "616263" "cc22cc"; - 256 0x0101ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263 - "" -1 "" "cc22cc"; - 256 0x0002ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263 - "" -1 "" "cc22cc"; - 256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff01cc22cc616263 - "" -1 "" "cc22cc"; - 256 0x0001ffffffffffffffff00cc22ccffffffffffffffffffffff00cc22cc616263 - "" 18 "ffffffffffffffffffffff00cc22cc616263" "cc22cc"; - 256 0x0001ffffffffffffff00cc22ccffffffffffffffffffffffff00cc22cc616263 - "" -1 "" "cc22cc"; - 256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc21cc616263 - "" -1 "" "cc22cc"; - 256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616262 - "" 3 "616262" "cc22cc"; - 129 0x0001ffffffffffffffff00cc22cc616263 "" 3 "616263" "cc22cc"; - 128 0x0001ffffffffffffff00cc22cc616263 "" -1 "" "cc22cc"; -} - -p1vrf-pub { - # n e sig msg rc result eparam - 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 - 0x10001 - 0xc484642d0e4dc4a4424d22410456dbdd9275b5c157d6974a66bee9aa02501c26 - "" 3 "616263" "cc22cc"; - 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 - 0x10001 - 0xc484642d0e4dc4a4424d22410456dbdd9275b5c157d6974a66bee9aa02501c26 - "616263" 0 "" "cc22cc"; - 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 - 0x10001 - 0x27654c24f4ffefffc3bef7be8ae469db3069407702391eeb551ce9544621b63a - "" 18 "ffffffffffffffffffffff00cc22cc616263" "cc22cc"; - 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 - 0x10001 - 0xd980f3047ab74bc4e7bb99eeb17fcc657f50ee26146b7f2a9f982ef2f44cba - "" -1 "" "cc22cc"; - - 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff - 0x10001 - 0x0f642606b7aaf99ff4bb5853c51e31a02c58d8c1c33f3c584d4edc58b08a16d5dc8064b6e198edcc4dc06666171a113619d7da16dfd96cebfdb5cc5050af6fab3d9f2ca8b8d6ece1d513fabc98a11fe37892fcf0827ea2e792427a69b3523504f46c55ed8af9a1c59687ca73c4baad7235a1a3faedec14f95ddfa8d0554739a8 - "" 20 "a9993e364706816aba3e25717850c26c9cd0d89d" - "3021300906052b0e03021a05000414"; -} - -p1enc-pad { - # nbits msg rc ct eparam - 256 "616263" 0 - 0x0002efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263 ""; - 105 "616263" 0 - 0x0002efbd98524ad6419b00616263 ""; - 104 "616263" -1 0 ""; -} - -p1enc-pub { - # n e msg rc ct eparam - 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 - 0x10001 "616263" 0 - 0x8f20a0fc778b7c55567f41c344d39bfcdaca04fd475f2290dc05c236585a68ca ""; - - 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff - 0x10001 - "616263" - 0 - 0xaf91f5abf4766348eaaff1e8e5561b10bc1e3b15b6dff221869389a70d371d649b6cf78c5444f5d03a9feac12d5741cbc340e09d112063b1486568fca7c59b4c90604f0b6243eccc18901afa9001fc5f669108ebc75d6713e28d4a081723184332d4fb2ca391e3247a76c85323e66352d60c0a6ce8240af6f0583058820b1e32 - ""; -} - -p1dec-pad { - # nbits msg rc pt eparam - 256 0x0002efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263 - 3 "616263" ""; - 105 0x0002efbd98524ad6419b00616263 - 3 "616263" ""; - 104 0x0002efbd98524ad64100616263 - -1 "" ""; - 256 0x0002efbdfc524ad6419b00537a59b42a4662918436d6e0e4804b6b1000616263 - 21 "537a59b42a4662918436d6e0e4804b6b1000616263" ""; - 256 0x0002efbdfc524ad6419b00537a59b42a4662918436d6e0e4804b6b1000616263 - 3 "616263" "537a59b42a4662918436d6e0e4804b6b1000"; - 256 0x0102efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263 - -1 "" ""; - 256 0x0001efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263 - -1 "" ""; - 256 0x0002efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263 - 3 "616263" ""; - 256 0x0002efbdfc524ad6410065537a59b42a4662918436d6e0e4804b6b1000616263 - -1 "" ""; -} - -p1dec-priv { - # p e d msg rc pt eparam - 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 - 0x10001 - 0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9 - 0x8f20a0fc778b7c55567f41c344d39bfcdaca04fd475f2290dc05c236585a68ca - 3 "616263" ""; - 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 - 0x10001 - 0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9 - 0x19d6408010f0c2722b44cd4d5e006b6ffaa634aa225d727fa37c7c6ec29c5155 - 21 "537a59b42a4662918436d6e0e4804b6b1000616263" ""; - 0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3 - 0x10001 - 0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9~ - 0x952aa4893cd2620e4942f449529ea2f7105b9d67e041a676259fb986bc507b7d - -1 "" ""; - - 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff - 0x10001 - 0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81 - 0xaf91f5abf4766348eaaff1e8e5561b10bc1e3b15b6dff221869389a70d371d649b6cf78c5444f5d03a9feac12d5741cbc340e09d112063b1486568fca7c59b4c90604f0b6243eccc18901afa9001fc5f669108ebc75d6713e28d4a081723184332d4fb2ca391e3247a76c85323e66352d60c0a6ce8240af6f0583058820b1e32 - 3 "616263" ""; -} - -oaepenc-pad { - # nbits msg rc ct mgf hash eparam - 1024 "616263" 0 - 0x151709bd895ba510b5b3de3293c6de93adbb20cb065dcfbe3b2ca60aa39e458b30d14406eba05f0e479ddff40f554aba11da533c6d98df0321164c986807e8019c6918896817f37700a46c7fd71741a7692fcbd443952b67c32b838a576332b3bc1bab002fe3c941e9150d08b539908ef7f1901ac1246065c8520ac1beffed - sha-mgf sha ""; -} - -oaepdec-pad { - # nbits msg rc pt mgf hash eparam - 1024 - 0x151709bd895ba510b5b3de3293c6de93adbb20cb065dcfbe3b2ca60aa39e458b30d14406eba05f0e479ddff40f554aba11da533c6d98df0321164c986807e8019c6918896817f37700a46c7fd71741a7692fcbd443952b67c32b838a576332b3bc1bab002fe3c941e9150d08b539908ef7f1901ac1246065c8520ac1beffed - 3 "616263" sha-mgf sha ""; - 1024 - 0x151709bd895ba510b5b3de3293c6de93adbb20cb065dcfbe3b2ca60aa39e458b30d14406eba05f0e479ddff40f554aba11da533c6d98df0321164c986807e8019c6918896817f37700a46c7fd71741a7692fcbd443952b67c32b838a576332b3bc1bab002fe3c941e9150d08b539908ef7f1901ac1246065c8520ac1beffec - -1 "" sha-mgf sha ""; -} - -oaepenc-pub { - # n e msg rc ct mgf hash eparam - 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff - 0x10001 - "616263" - 0 - 0xa5c94083e56aeff3490a4abd63251b332a26cca0e521815af5d2915b2422fbc7e672c8e67c3dea8c355e0b999a1f8acc905cc4437a6ddc5a7d6f54489436bd24922f83d75629d2cb92a7963d010727ef8981c3c01971962f454e42d54996e74617022d7513505fef7b1f7d5dbdeccc4673594d01f943236e4439b3175c3f801b - sha-mgf sha ""; -} - -oaepdec-priv { - # n e d msg rc pt mgf hash eparam - 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff - 0x10001 - 0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81 - 0x6ae9901c7c40104b38e10097bd42212afd437867ee4c72e7e81d7486b8721aeab493be40e3bd4335bef05c76bba1a2e30795e76fe04517d5f8fa87d16756002b061674594cb85c32b96c3a690e135d64923bd7551c45b6b89ebb89941377ce02d5c801feb33c20ebacf8dd6d6bd44d4f29bc2ff4dca35db52da545ef97733955 - 3 "616263" sha-mgf sha ""; - 0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff - 0x10001 - 0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81 - 0x6ae9901c7c40104b38e10097bd42212afd437867ee4c72e7e81d7486b8721aeab493be40e3bd4335bef05c76bba1a2e30795e76fe04517d5f8fa87d16756002b061674594cb85c32b96c3a690e135d64923bd7551c45b6b89ebb89941377ce02d5c801feb33c20ebacf8dd6d6bd44d4f29bc2ff4dca35db52da545ef97733954 - -1 "" sha-mgf sha ""; -} - -psssig-pad { - # nbits msg rc result mgf hash saltsz - 256 "a9993e364706816aba3e25717850c26c9cd0d89d" 0 - 0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc - sha-mgf sha 10; - 256 "a9993e364706816aba3e25717850c26c9cd0d89d" -1 - 0 sha-mgf sha 20; - 273 "a9993e364706816aba3e25717850c26c9cd0d89d" 0 - 0xb5c91e4c0c00aaaffba7d581011366f0477cf42d9b98fddf692f3d14f9b8a168e4bc - sha-mgf sha 10; - - 1024 "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0 - 0x2d22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc - sha-mgf sha 20; - 1025 "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0 - 0xad22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc - sha-mgf sha 20; - 1024 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 - 0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - sha256-mgf sha256 32; - 1025 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 - 0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - sha256-mgf sha256 32; - 1026 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 - 0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - sha256-mgf sha256 32; - 1027 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 - 0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - sha256-mgf sha256 32; - 1028 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 - 0x559bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - sha256-mgf sha256 32; - 1029 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 - 0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - sha256-mgf sha256 32; - 1030 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 - 0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - sha256-mgf sha256 32; - 1031 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 - 0x2d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - sha256-mgf sha256 32; - 1032 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 - 0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - sha256-mgf sha256 32; - - 2048 "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884" 0 - 0x106373ce481fe7e268a5a66f8b281e17719e23e1fa5f9d6bdfb2da5451a3fe7afab07969d8acdb904c723830280f78124717e87edf05a58626e191281b9c82edeceb02d1fc8dfab7d3e941ef3a13ea27ea51609e47dd727a784f66dc189fb8527093060ee5f982f7072e3f8a5fac4edcadd9ff107d6c8a99e9b52680a046b6f984c323afbb194e94bf2ab014804e791af59b254c164ef24af7c726b314a127febc4d026c700cbe08076d4e63be94581f6b353adbd3c754864d314f0039b3c7cae177c8be11a426358d523a1f0c97a0626aa9d565751229d488d96e168e7305cdc3d256401e6b865c246d686f0d8a673603038c464a60753dcd2b0f2a552514bc - sha256-mgf sha256 32; -} - -pssvrf-pad { - # nbits sig msg rc result mgf hash saltsz - 256 - 0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc - "a9993e364706816aba3e25717850c26c9cd0d89d" 0 "" sha-mgf sha 10; - 256 - 0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc - "a9993e364706816aba3e25717850c26c9cd0d89e" -1 "" sha-mgf sha 10; - 256 - 0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bd - "a9993e364706816aba3e25717850c26c9cd0d89d" -1 "" sha-mgf sha 10; - 256 - 0x3526a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc - "a9993e364706816aba3e25717850c26c9cd0d89d" -1 "" sha-mgf sha 10; - - 1024 - 0x2d22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc - "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0 "" - sha-mgf sha 20; - 1025 - 0xad22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc - "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0 "" - sha-mgf sha 20; - 1024 - 0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" - sha256-mgf sha256 32; - 1025 - 0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" - sha256-mgf sha256 32; - 1026 - 0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" - sha256-mgf sha256 32; - 1027 - 0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" - sha256-mgf sha256 32; - 1028 - 0x559bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" - sha256-mgf sha256 32; - 1029 - 0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" - sha256-mgf sha256 32; - 1030 - 0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" - sha256-mgf sha256 32; - 1031 - 0x2d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" - sha256-mgf sha256 32; - 1032 - 0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc - "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 "" - sha256-mgf sha256 32; - - 768 - 0x3314e642649adf696651f34108408fab0e770a617a3f7d44d981add5ca88841dc57d531bb885075f150b93e96f6e7580e18b98e1ece12826bbfe4d92dec1bc05c2e95ea362e08dd4cbf162b4abff6a9ed26b822d986ec32bdd698d162262abbc - "2923be84e16cd6ae529049f1f1bbe9ebb3a6db3c" 0 "" - sha-mgf sha 20; - 1024 - 0x29d14565cf1ad3966ad25ff10aa825c2adeb31cc431a9a388ee53afef2ea2bc3c40b54523fd6bec5d7eabbea2b969e25d1bd62086834ccc48f256d876a4065214ac4343dfba87091563921299adee851e9d0dfba8db14ae6972cc8ce569f32c01db77d291279a82c30220faa16d83b1740cb535aa7f594905d7c91122f67ffbc - "1cdbae32209a50ee407836fd124932f69e7d49dc" 0 "" - sha-mgf sha 20; - 768 - 0x1de4193d961d4c2f5737656c910d9d5262b09d463a0b8c7c426f92f91ea8db83be870d68ab125af488bef0596b15fb2416b2836c08bc6af31ee3c215c817c9c17ee84d813dc712676c86d4c41e69074eb1646fdc80c8a59e4bad819af27104bc - "b2eac9cc53bf67d6bf14d67e2ddc8e6683ef574961ff698f61cdd11e9d9c1672" 0 "" - sha256-mgf sha256 32; - 1024 - 0xb9317ad66af4a49e3d2e987c340e776ed3b7496d311813fd6374e743fd5156630453541fc82733b4c0fd44a869e8c541ede9692ea6deb7cd52dbb4fb66b0f5a9a07e84e886ee5520faadf4fc7d646f1987bf19ad3d669dd9df57eec3de510148a6d349b8626c20ffb6d95f09c0af54b276626da745502e9c2bb5496e1a29bc - "0515073b33821f187092da6454ceb1853e6915f8466a0496730ed9162f6768d4" 0 "" - sha256-mgf sha256 32; - 1025 - 0x0a9228b191158744e277bd223ada3c227429e5d64884007a748d74abca2d55358c1bb21cdf2666589ffd6cdfd458c877620009ebace86e7fc88c6d0acb99e5432f1af5705908e332e1a071e3700f0a0310b531589e79fd40922f0780b239cdd489816be7fdee9f6353f7f9f182abf873eb32e83586011fce20ae957bc66728bc - "a90b87978c2ff1151d9a95c19be1c07ee9a89aa786c2b554bf9ae7d923d15590" 0 "" - sha256-mgf sha256 32; - 1026 - 0x016ecc969a03557d5fb257119251316ec4d8630d66bd6c18e93bc5c69a3a1d68431cd298f92db41a5f017874f05054224da5d75c012855febdf801c77145c8067c714c5c218f555b1e335a73f3ca6228a9723fa074173c7941200526c3a8ad81bb25427c84bdf82052021590cb5fd6aa44d052734b9112d1063276995572300ebc - "cbc2033f4107840f1405651b2861c9c5e72c8e463608dcf3a88dfebef2eb71ff" 0 "" - sha256-mgf sha256 32; - 1027 - 0x031a071405323cf4ef20cc186ca5edc492fa2a7158565275d1d7cce302dcb10853625822b6887ab61c0713c332eb188b708690dee268ecc1e8b07f34106a1437246034347340bb65f39d8f002fe6ad5d826cce3c44d121924ba2a2fe265200523940b2f60918202839190fd4c50960be706863daf99b34cf7a152f720cbd9a2bbc - "6653330bcba1105e4cec034c73e605b4310eaaadcfd5b0ca27ffd89d144df479" 0 "" - sha256-mgf sha256 32; - 1028 - 0x032e267380b21f98eb301bfd28c95af795a29864dfd801146c6878d9755669a6a8ef0090c574d5e7b716e4bf32128787db838c1df23fa418406e124fe4c031e706e31e27982810561d0c77d391b7718a2dd12b583987fe1c3c07436d457e039c3f4a6bbc2b6e765670762138ec2f22c3b1ce84ff422c08479f90abeb39986abdbc - "d5cfd3a195ce5abe65272af607ada1be65a6b4c9c0693234092c4d018f1756c6" 0 "" - sha256-mgf sha256 32; - 1029 - 0x034a4f060407d55bea14998785fef3dc09240b2145350d7aaa8e7b0114ba531209e8a5d9cfa1f8c364f21a94d302968a0ba7905ac188da019da0b68c27e42bf513bde915eaf96a91f300a32bbd723cdf66510f1ecb964ed807679dacf7ada3903e7234167bd3dc49e8b59749a396dcdc3f06d3751d0b58216d1ea3760fface17bc - "608f6e3c7bf45b628a8a8f275cf7e5874a3b329b614084c6c3b1a7304a10ee75" 0 "" - sha256-mgf sha256 32; - 1030 - 0x0aab7297cc92ae458f1d4d3b275eab7b2c65af1a7ab4fde8f5ff78b21474751b3b245f9b32b3c7d22ca677ccc882957cfdf3583372a8038918c27e9efd9743e6673d935ade4d3a4c3029c81c56d9a900e3f403de752d816d2e224621db32baf716b7625598aae00a336df65970076a2421e82925b9496b45e889f3b91ff5c100bc - "0d2bb614ecbbb82f73e2517e7d1dd884d31f01be506b16d6432183191518982b" 0 "" - sha256-mgf sha256 32; - 1031 - 0x0a1a81c6c71b542db6ce4aac600e96d5280f31dc6d91d201a0a83f3c2fb9a1baebf0d77b5aadd2358de635eca6f802a3adfe33c4e32e321276e102bb74dbb23aafcd8ca3806abd496a55c88223478a21ce0ee9946b93d0f94dcff307f0f33e41b3ab282016b7cda40bd8a3b1a909fb9396afff909f9bb6e44a3d70240e9ec9eabc - "f25b81a07f5ccb1d36e949740255d2ac1a0bf7a92623405ba333b9358868ade1" 0 "" - sha256-mgf sha256 32; - -# This one's WRONG! -# 1024 -# 0x696c23c434d74b91841724d0cca8318938551593969a8c31468377335252f2e18cbc11902b09ea494297ac729872b459d852018bc0634e95f9a1e80f09b55b321a1cc3b5f5f8c66a6bc91f42f154c6b4406606f3e9dda02eefe343cd80436a09e013a6e6b1190d222279e6f790223c315f367f3a212ff6f1c838c728c7fafabc -# "29d7a859cc0dea26ed554e8084d92bf837b8edd57aa05c4efa9f21fc3c36858e81b07dbfeeb1e485e912078bc6ec66e2" 0 "" -# sha384-mgf sha384 48; - - 2048 - 0x7a14b3a1fbf3371d6a607e3a401b43937f77d1f0960f0caee52c3a962d097cbcf7659ee7a26d7da421bfdf650c02a275f7c839eccdb77eb8bd73e807f251a9b8dcf6c7bbde426e1cd2b05f5e0ca53d4a2e7487f56bde022384d581208489a835b0e4f23aa713497d7ad0b1ba3a0d3fdf1798e40f5add1ab96c1ca17006138941b87fa1bc7bdb93c49befa6e2e4cdf6a144e55525d14f995ebbc452f8dd31ee07ddee8935454e5d484132e3799978eeb15f66444e342e425ca456c4ed13e3504e1dfef8d29de9086e027958a0ab7975f642f8d061c94b379b2ddf8b5f5540f2c94a9f50ce509d9bc7f21c8e5cbca7c783c78b2a8235f4ec536b129e6f105d3bbc - "a744b33e02b80487b63022dde456dd617b6e3d8c5ce7c467bc2ff2ffc9cc0f1390a924111ead4b41e592283f62f5b8aefda9492b3151ca80ec2e451a3935aabe" 0 "" - sha512-mgf sha512 64; - - 2048 - 0x106373ce481fe7e268a5a66f8b281e17719e23e1fa5f9d6bdfb2da5451a3fe7afab07969d8acdb904c723830280f78124717e87edf05a58626e191281b9c82edeceb02d1fc8dfab7d3e941ef3a13ea27ea51609e47dd727a784f66dc189fb8527093060ee5f982f7072e3f8a5fac4edcadd9ff107d6c8a99e9b52680a046b6f984c323afbb194e94bf2ab014804e791af59b254c164ef24af7c726b314a127febc4d026c700cbe08076d4e63be94581f6b353adbd3c754864d314f0039b3c7cae177c8be11a426358d523a1f0c97a0626aa9d565751229d488d96e168e7305cdc3d256401e6b865c246d686f0d8a673603038c464a60753dcd2b0f2a552514bc - "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884" 0 "" - sha256-mgf sha256 32; -} - -psssig-priv { - # n e d msg rc sig mgf hash saltsz - 0x6af87c8c97ae0c7668bc361ff1c358198309c80cd8a74a6d9d9cc846ea63ede9 - 0x10001 - 0x30ec4a0a5854d733a5ddc3e3584469f0a7d4b1f0cb38b8cfb04483c68b77a01 - "a9993e364706816aba3e25717850c26c9cd0d89d" 0 - 0x2b484543397da31ca7aaf774c4b19acd69eb8bc230b6d98a2ae10798793bd53f - sha-mgf sha 10; - - 0x560e64d28a2352ab7930aeb78fede05837b4fb868f0e6920d3108bcd57c8fe019d20d5df7ccc1ba15b5b0f850282739f3c76f0f592e2120573551c0146c3cd6d165cfd3bedfdc131bed468f0b36a7f07d47caf5ec83c0790354fba9f5027394618fa1a342b752a028addc86765061ca680d748190befe34d0f4032ad5639b148d033c3b3914f0b4ef9a1a7e167bdfe22a7954a8542286f562c226c393d48a91a1b7843831f8133e7214d65a5874954ecd8b10002dfe9847f5e8061cfb77d2b5defc6ce63d553aa79d1fe75e90fab2fdb78f55d8348063717a6335367d8316070a44847a49ba53be57f44bc6d6108aecbe0efbf81a2b51cbe98407166d89e89a9 - 0x10001 - 0x27f0e74fa6a8ad5a83d59a09fd85f10dd0d131baaad40bec1dba3cc0d24129cf72efc60443e671de8ac9b162d11eddee26c0a7a6bb052d4b155407baf9eeaffe351674bc6781d2b4b576ddbbf5f1f4429c974047f4149488148e4c365c1bd063ddfcdac3a2f5eec91e4dc091689c95189c8d0edbfd23da722e25643ffa58ad94ec06f6ab21fc8805b09066ffe3849e2d5536cf8a7385e62526989605c9fefbd9092ddb51bd887ee71cababab3a150b34d7de54d01c19987438bef4672208418e51bf49cdbe1825f16e2764c58aab339afbb4f673914646d2a191fec4f7a503e512841a2cccdc8852c0f348b8aedea3123747d20c3c580c38b438ef5fde3608bf - "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884" - 0 - 0x35fcbf7c5a69bd892dbf2ee88e53e40fe58ecddb4cf7c8885b228bfa9c24730ac554e20c65d82fc98d67a7805343450b1712a5f8c5ed6970c4310e06f65a9758d33e1c9dedec7178507da977a5ab76635d9f824b136abb855210caf851700bb57eb3aef7de61b217ae79ee4d6ad7c1a94279d9f8a425e06a0e4024d4c5b709ce1af6d09a26ce346f0a7eb36675fdbe1367f3d040ab7e18235b8090f91c355ee07425e3f4adf302e741be55959ac0f31075ccf1beef20e2f90693a82a30a48969c5ef32bc779ce84961b6a8d3ae0228cc520e2c644067bae96f14d90ceda2c8d00c97de3895d434a001d3cca244777fba4e0f5b5ed01c103842652c6402d2525b - sha256-mgf sha256 32; -} - -pssvrf-pub { - # n e sig msg rc result mgf hash saltsz - 0x6af87c8c97ae0c7668bc361ff1c358198309c80cd8a74a6d9d9cc846ea63ede9 - 0x10001 - 0x2b484543397da31ca7aaf774c4b19acd69eb8bc230b6d98a2ae10798793bd53f - "a9993e364706816aba3e25717850c26c9cd0d89d" 0 "" sha-mgf sha 10; - - 0x560e64d28a2352ab7930aeb78fede05837b4fb868f0e6920d3108bcd57c8fe019d20d5df7ccc1ba15b5b0f850282739f3c76f0f592e2120573551c0146c3cd6d165cfd3bedfdc131bed468f0b36a7f07d47caf5ec83c0790354fba9f5027394618fa1a342b752a028addc86765061ca680d748190befe34d0f4032ad5639b148d033c3b3914f0b4ef9a1a7e167bdfe22a7954a8542286f562c226c393d48a91a1b7843831f8133e7214d65a5874954ecd8b10002dfe9847f5e8061cfb77d2b5defc6ce63d553aa79d1fe75e90fab2fdb78f55d8348063717a6335367d8316070a44847a49ba53be57f44bc6d6108aecbe0efbf81a2b51cbe98407166d89e89a9 - 0x10001 - 0x35fcbf7c5a69bd892dbf2ee88e53e40fe58ecddb4cf7c8885b228bfa9c24730ac554e20c65d82fc98d67a7805343450b1712a5f8c5ed6970c4310e06f65a9758d33e1c9dedec7178507da977a5ab76635d9f824b136abb855210caf851700bb57eb3aef7de61b217ae79ee4d6ad7c1a94279d9f8a425e06a0e4024d4c5b709ce1af6d09a26ce346f0a7eb36675fdbe1367f3d040ab7e18235b8090f91c355ee07425e3f4adf302e741be55959ac0f31075ccf1beef20e2f90693a82a30a48969c5ef32bc779ce84961b6a8d3ae0228cc520e2c644067bae96f14d90ceda2c8d00c97de3895d434a001d3cca244777fba4e0f5b5ed01c103842652c6402d2525b - "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884" - 0 "" - sha256-mgf sha256 32; -} diff --git a/tests/safer b/tests/safer deleted file mode 100644 index 36149a0..0000000 --- a/tests/safer +++ /dev/null @@ -1,10 +0,0 @@ -# $Id: safer,v 1.1 2001/04/29 17:37:38 mdw Exp $ -# -# Test vectors for SAFER - -# From HAC 7.114, and Richard de Moliner's implementation - -safer { - 0807060504030201 0102030405060708 c8f29cdd87783ed9; - 100f0e0d0c0b0a090807060504030201 0102030405060708 4a99b15cce9ada19; -} diff --git a/tests/safersk b/tests/safersk deleted file mode 100644 index d1ea05a..0000000 --- a/tests/safersk +++ /dev/null @@ -1,10 +0,0 @@ -# $Id: safersk,v 1.1 2001/04/29 17:37:38 mdw Exp $ -# -# Test vectors for SAFER - -# From HAC 7.114, and Richard de Moliner's implementation - -safersk { - 0102030405060708 0102030405060708 60d04ad7c49b8ded; - 100f0e0d0c0b0a090807060504030201 0102030405060708 b260740f80d2445d; -} diff --git a/tests/seal b/tests/seal deleted file mode 100644 index 7c48095..0000000 --- a/tests/seal +++ /dev/null @@ -1,8 +0,0 @@ -# Test vectors for SEAL -# -# $Id: seal,v 1.1 2000/06/17 12:11:49 mdw Exp $ - -seal { - 67452301efcdab8998badcfe10325476c3d2e1f0 0x013577af - 9505a0379cc4849b051ebea40f537306fd97b05fbd3fa1f6cdde2c6c7ceefd81e7c3bd2aff9a20648322a100855067ef534b63c1e6599028d95eaba7eb010c48; -} diff --git a/tests/sha b/tests/sha deleted file mode 100644 index 841c96c..0000000 --- a/tests/sha +++ /dev/null @@ -1,63 +0,0 @@ -# Test vectors for the SHA-1 hash function -# -# $Id: sha,v 1.6 2004/04/21 00:38:42 mdw Exp $ - -# --- Basic hash function --- -# -# Some of these are taken directly from the Secure Hash Standard -# (FIPS 180-1). Others were generated using the SSLeay implementation of -# SHA-1. - -sha { - "" da39a3ee5e6b4b0d3255bfef95601890afd80709; - "a" 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8; - "abc" a9993e364706816aba3e25717850c26c9cd0d89d; - "message digest" c12252ceda8be8994d5fa0290a47231c1d16aae3; - "abcdefghijklmnopqrstuvwxyz" - 32d10c7b8cf96570ca04ce37f2a19d84240d3a89; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 84983e441c3bd26ebaae4aa1f95129e5e54670f1; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - 761c457bf73b14d27e9e9265c46f4b4dda11f940; -} - -sha-rep { - "1234567890" 8 50abf5706a150990a08b2c5ea40fa0e585554732; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -" 23 f74d36bf17ee23c46ec166a48a24da6ab999eaea; - "a" 1000000 34aa973cd4c4daa4f61eeb2bdbad27316534016f; -} - -# --- HMAC mode --- -# -# Test vectors from RFC2202. - -sha-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - b617318655057264e28bc0b6fb378c8ef146be00; - - "what do ya want for nothing?" - 4a656665 - effcdf6ae5eb2fa2d27416d5f184df9c259a7c79; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 125d7342b9ac11cd91a39af48aa17b4f63f175d3; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - 4c9007f4026250c6bc8414f9bf50c86c2d7235da; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - 4c1a03424b55e07fe7f27be1d58bb9324a9a5a04; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aa4ae5e15272d00e95705637ce8a3b55ed402112; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - e8e99d0f45237d786d6bbaa7965c7808bbff1a91; -} diff --git a/tests/sha224 b/tests/sha224 deleted file mode 100644 index 5d9a759..0000000 --- a/tests/sha224 +++ /dev/null @@ -1,74 +0,0 @@ -# $Id: sha224,v 1.2 2004/04/21 00:38:42 mdw Exp $ -# -# Test vectors for SHA-224 - -# --- Basic hash function --- - -sha224 { - - # --- Test vectors from the definition [FALSE] --- - - "abc" - 23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525; - - # --- Other tests to trap regression --- - - "" - d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f; - "a" - abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5; - "message digest" - 2cb21c83ae2f004de7e81c3c7019cbcb65b71ab656b22d6d0c39b8eb; - "abcdefghijklmnopqrstuvwxyz" - 45a5f72c39c5cff2522eb3429799e49e5f44b356ef926bcf390dccc2; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - bff72b4fcb7d75e5632900ac5f90d219e05e97a7bde72e740db393d9; -} - -sha224-rep { - "1234567890" 8 - b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -" 23 - 5a86156c37c95ab356e003d569370580737794815f46de7f4834d634; - "a" 1000000 - 20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67; -} - -# --- HMAC mode --- -# -# Autogenerated, unofficial. - -sha224-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - 1abbc7c42cf4ca9f9d7b624564cb72d7b0945ea0a615095904a0fd34; - - "what do ya want for nothing?" - 4a656665 - a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 5121d4bc8e43ee3ddcc2b0d312c110e961fc34b19ced1cce11c7a55c; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - 6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - 0f081672137307d07aad12880537cd43f454823de00c038424741e17; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 9ed2eebc0ed23576efc815e9b5bc0d9257e36d13e4dd5d5f0c809b38; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 7358939e58683a448ac5065196d33191a1c1d33d4b8b0304dc60f5e0; -} diff --git a/tests/sha256 b/tests/sha256 deleted file mode 100644 index d00ca14..0000000 --- a/tests/sha256 +++ /dev/null @@ -1,73 +0,0 @@ -# $Id: sha256,v 1.3 2004/04/21 00:38:42 mdw Exp $ -# -# Test vectors for SHA-256 - -# --- Basic hash function --- - -sha256 { - - # --- Test vectors from the definition --- - - "abc" - ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1; - - # --- Other tests to trap regression --- - - "" - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855; - "a" - ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb; - "message digest" - f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650; - "abcdefghijklmnopqrstuvwxyz" - 71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0; -} - -sha256-rep { - "1234567890" 8 - f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -" 23 4804a2a4759acebe127b62ba651ae601a756ca0b509e4987498224acaffb0d98; - "a" 1000000 - cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0; -} - -# --- HMAC mode --- -# -# Autogenerated, unofficial. - -sha256-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - 198a607eb44bfbc69903a0f1cf2bbdc5ba0aa3f3d9ae3c1c7a3b1696a0b68cf7; - - "what do ya want for nothing?" - 4a656665 - 5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - cdcb1220d1ecccea91e53aba3092f962e549fe6ce9ed7fdc43191fbde45c30b0; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - 82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - 7546af01841fc09b1ab9c3749a5f1c17d4f589668a587b2700a9c97c1193cf42; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 6953025ed96f0c09f80a96f78e6538dbe2e7b820e3dd970e7ddd39091b32352f; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 6355ac22e890d0a3c8481a5ca4825bc884d3e7a1ff98a2fc2ac7d8e064c3b2e6; -} diff --git a/tests/sha384 b/tests/sha384 deleted file mode 100644 index 13ad630..0000000 --- a/tests/sha384 +++ /dev/null @@ -1,74 +0,0 @@ -# $Id: sha384,v 1.4 2004/04/21 00:38:42 mdw Exp $ -# -# Test vectors for SHA-384 - -# --- Basic hash function --- - -sha384 { - - # --- Test vectors from the definition --- - - "abc" - cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7; - "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" - 09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039; - - # --- Other tests to trap regression --- - - "" - 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b; - "a" - 54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31; - "message digest" - 473ed35167ec1f5d8e550368a3db39be54639f828868e9454c239fc8b52e3c61dbd0d8b4de1390c256dcbb5d5fd99cd5; - "abcdefghijklmnopqrstuvwxyz" - feb67349df3db6f5924815d6c3dc133f091809213731fe5c7b5f4999e463479ff2877f5f2936fa63bb43784b12f3ebb4; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - 1761336e3f7cbfe51deb137f026f89e01a448e3b1fafa64039c1464ee8732f11a5341a6f41e0c202294736ed64db1a84; -} - -sha384-rep { - "1234567890" 8 - b12932b0627d1c060942f5447764155655bd4da0c9afa6dd9b9ef53129af1b8fb0195996d2de9ca0df9d821ffee67026; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -" 23 - f77d169c73427bd30cceff74f822a0209657dfb78c07980509bf8452a3c5d671b7198081898d0a0034e0f7151211fa0f; - "a" 1000000 - 9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985; -} - -# --- HMAC mode --- -# -# Autogenerated, unofficial. - -sha384-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - b6a8d5636f5c6a7224f9977dcf7ee6c7fb6d0c48cbdee9737a959796489bddbc4c5df61d5b3297b4fb68dab9f1b582c2; - - "what do ya want for nothing?" - 4a656665 - af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 809f439be00274321d4a538652164b53554a508184a0c3160353e3428597003d35914a18770f9443987054944b7c4b4a; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2122232425262728292a2b2c2d2e2f30313233343536373839 - b8405cddb33af1a68a1a71a8a4e6189a724fe28209671d701f7ecd4582d4db61b3a31ddca42a0db4efa2c5caf7a0482c; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - 3b44c978360a9da6eba51d8186dd879bac52801ba2cba0afcb0f612f3305668accf4d5367a686e547426abfe7832f8ba; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 39cc73806611492e9179e2c23cebddd61c240b0b9c5a095db35f978d48642a1a49a2dde075f2b54cefbae7fe0aed4909; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data Bearing In Mind That This Hash Has An Extraordinarily Large Block Size So The Standard Test Won't Work" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - f9ac83e56d205edb71774e0d1ee102330583c474020bcbe52f02384f6fdf09e7e8b75495d74eea4788c17e48e64d6888; -} diff --git a/tests/sha512 b/tests/sha512 deleted file mode 100644 index f0cebb9..0000000 --- a/tests/sha512 +++ /dev/null @@ -1,75 +0,0 @@ -# $Id: sha512,v 1.4 2004/04/21 00:38:42 mdw Exp $ -# -# Test vectors for SHA-512 - -# --- Basic hash function --- - -sha512 { - - # --- Test vectors from the definition --- - - "abc" - ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f; - "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" - 8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909; - - # --- Other tests to trap regression --- - - "" - cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e; - "a" - 1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75; - "message digest" - 107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c; - "abcdefghijklmnopqrstuvwxyz" - 4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1; - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - 1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894; -} - -sha512-rep { - "1234567890" 8 - 72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843; - - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -" 23 - 4def32cfb1107a104eae530fe04326a57e839a0bd9675f6770ff18d0b3b3ee2d4343bf99e9d54adc272617d49d0f61eab4b4bc177f9d2bac086cd2d902b5780e; - "a" 1000000 - e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b; -} - -# --- HMAC mode --- -# -# Autogenerated, unofficial. - -sha512-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0bb0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - bb969b8e6b99529a2e09757ef582257aed4f66cb62f1b32150b969eaa7dd683d46a776726cbf0f614f784cfa0759e84ba1d0baf07a1391ed998da6ea2fd7ff53; - - "what do ya want for nothing?" - 4a656665 - 164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 2ee7acd783624ca9398710f3ee05ae41b9f9b0510c87e49e586cc9bf961733d8623c7b55cebefccf02d5581acc1c9d5fb1ff68a1de45509fbe4da9a433922655; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2122232425262728292a2b2c2d2e2f30313233343536373839 - 005a43d33fe40a285dc0947121984509698d4533519662c5eda2f8fac7a6b69f78ce84b61b1427d8dc88046aa1f35c6513b467185de195deb4dee3367b55d38d; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - 54701368cc706f527661ec9617d506ab255890b7c0cd8318f2efcf2b1bfbac560a77c369bdc01220d652e79747c0fa465da176e34b0de91cf075db0a12ac0ab5; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - ae52fbcfb432b5963d1fa0b38a584554752d41f5b4de82483ec1f32de676ae708fc20ffa3bc6525f3d4115eda6b145bf123ed5acf6cbb0ee7f7bf625402609fd; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data Bearing In Mind That This Hash Has An Extraordinarily Large Block Size So The Standard Test Won't Work" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 062d5553721e9512a061feaa8a236a5c2c5a45f25ed3ebe9c7337f3bc26b65d8ba3e1bd061b53fe45ac03800aeee4b48c6f2f3bd955c32991bd2bfaf2b1c05a3; -} diff --git a/tests/skipjack b/tests/skipjack deleted file mode 100644 index a646803..0000000 --- a/tests/skipjack +++ /dev/null @@ -1,103 +0,0 @@ -# $Id: skipjack,v 1.3 2000/08/04 23:24:01 mdw Exp $ -# -# Test vectors for Skipjack - -# --- From the Skipjack definition --- - -skipjack { - - # --- The official Skipjack test vector --- - # - # It's a bit piss-poor that they only provide one test-vector here. - - 00998877665544332211 33221100ddccbbaa 2587cae27a12d300; - - # --- From KEA test vectors --- - # - # The Skipjack algorithm is used by the KEA to derive the final key. - # Unfortunately, the test vectors given in the Skipjack/KEA spec don't - # match my (or anyone else's!) implementation. These are the values - # which seem to be generally agreed. - - e7496e99e4628b7f9ffb 99ccfe2b90fd550b 60a73d387b517fca; - e7496e99e4628b7f9ffb 60a73d387b517fca 24c90cb05d668b27; - e5caf4dcc70e55f1dd90 b71cb0d009af2765 64f4877ae68a8a62; - e5caf4dcc70e55f1dd90 64f4877ae68a8a62 fee778a838a601cd; - - # --- These are the results expected from the KEA spec --- - # - # A `?' indicates that I don't know what that digit's meant to be. I've - # derived the top 16 bits of the intermediate results from the spec. - -# e7496e99e4628b7f9ffb 99ccfe2b90fd550b 2f30????????????; -# e7496e99e4628b7f9ffb 2f30???????????? 740839dee833add4; -# e5caf4dcc70e55f1dd90 b71cb0d009af2765 8e27????????????; -# e5caf4dcc70e55f1dd90 8e27???????????? 97fd1c6bd86bc439; - - # --- Some more test vectors --- - # - # These are dreamed up by me. The above tests don't actually exhaustively - # test the F-table. There are 16 entries unaccounted for. The keys and - # plaintexts were generated using fibrand with seed 0. - - cde4bef260d7bcda1635 47d348b7551195e7 f17b3070144aebea; - 7022907dd1dff7dac5c9 941d26d0c6eb14ad a055d02c5e0eae8d; - 568f86edd1dc9268eeee 533285a6ed810c9b b4c22f4fb74c35dc; - 689daaa9060d2d4b6003 062365b0a54364c7 08698d8786f80d16; - 6c160f11896c4794846e cfa14a7130c9f137 d6db848b7cecdd39; - - # --- And some more, posted to Usenet --- - # - # Message-id <8m7slq$1i1$1@hecate.umd.edu> - - f8da02647722f7103adf 1ddf39abf5cd711e c92d22324c6b31ae; - 82760ac137948821eee4 dd6c6cce8f83e69e e32877c1d9527fff; - 843c1687d3cdca5fc5c3 beaacf177fa41a11 4745783f75b8861a; - ae870cd7ff33a995f7e5 c4c09f216c1bc60a 5c101636b8a57a72; - 5ccbd913ea8b73bd6391 d3f814b000245856 b4fc0f8e54728f91; - f65e74cd599c68a40cc7 356ec7d93832329c 93b750608f5701f8; - aa106e46d7087c4e93dc 209ecf1c537ad56c d823d45510099e61; - a93f9789a20c3cc34fea 892eea9d64e17d66 0959e231b275d95f; - 88b163cbd61616888899 991390fd760fc91b e7700209886767ae; - fb6cd1ff70487561df10 daebc947ddca9c9e e7cc49a56bd6a322; - 5edc1ac0c4e7ef5f002c 6419ddefe2cd8f2e e48a05cf26e242fd; - 8e3090c19aa32f94496a 322998ecbd068112 62c0e537b14df2c1; - b96e3fd46fa4263f9092 3aae2aee20da93cc 54d1e58a6b624d71; - 9e6635baee28c5bce2bc 14311112ca11f727 5d0f235a9d221ce0; - 04127ce16dc1b1726a66 300e4313e7ad6796 8e5b03522e68cbeb; - f0b89d75e979ccc9b172 09cd1c1accbe7797 572c9b4025a9134b; - f9bfc78798cbf1bcd4b5 31b30ca354af3cd8 8c959c904789fbda; - f43a51b4273bde27d2b0 08c59b0db99ec267 b7d7f5fa342988fb; - cd51f0a75aa73c48edd2 9784b1e3e7e60e60 763aa8ee109397b3; - b3319a3f6622aa726bb3 f65216373d4b43c7 0325600337b8ad3c; - 493254c9596e993f5f9c cba4c1215d5d36ce 68e1c551c59108c0; - 76150c2c3ced1c7ca021 82294851288e75cb 7eb6325d82a2096c; - 7140d6c5486305872df6 c3a7b7e4a52e407b 2483f385a42ee3c6; - 3c2c3901f0ee9a3b2b0e 1bfde32ab559e13a d6fa9db8685fd88a; - 606a8b4bdfaae8a0ba51 d205f7486c782838 0330489170b85293; - 7847a47a0fe79ab770ce d96ff1f7c7fc60e0 1f9b3301c9b2708c; - 73b9ab0c36c99e91a891 241d4bde19a75f8f 2b86c57ffe168895; - a37f2ad5a85e170741f5 7be1b8d58321c619 5af7ceb3eed9dca1; - f7b0c2a8170e3c4e48b3 c9214ea01ec14948 1b587736e116c04b; - a1fc67e44eacacf4a902 e2a3091feb581588 f3ecf0f1789a3923; - f14430affc5fe82a9ae9 3cb466d301b60854 e8d114c20ffa1c79; - fd26df50486a4cd96d9b b0684f8a5e63d935 222903994d64fe3a; - a6d46d46ca287e1a332a ba1f37e88edec55f 91f2baad6fa0de55; - 83c3f1cb8d06efc6196b e9fed8501b7a6579 83f9f08f89a854ee; - 0edfa44c7d4a4ef0725e eb5ca8b3fa1fcdbb 2b1b6670a6be0324; - b8edcf167d99a711ccee b8b525c6382af277 211a695da473766f; - 4f639e0d5a5d2ad7e9a4 9162e781ff683853 eb2976370d22ef22; - 37e006256a4ae6d320c4 c9f23a20a39ded11 dba4c0ef0ea098c0; - e41d0bd25f931ba1d85c 5a6f12f32f7eefdf 923daee8000709f9; - fdf65bbc5fe600f3cd68 cad5414c1c64f194 d5771e78b6f1fe1e; - 1c269af2ff166acb27ef 063a58a20b45378f 634f7a3861af97a1; - 1179f64acb6122ccf649 08fbf42b4313347b 3a803a4bd0e8c3e6; - 078c87265eb8da323e90 6d4ed0e9930532d1 f4fa372e7e1441a1; - 2fff35f8eb774c843bb0 40b699812345661d 63a9197f7b75f53f; - 09f77346a4393ce99856 22ed54626a51e505 e91a050a7481b3dd; - 5b878e0b22a705acf8fb 0c489b66e2da531b 6e9370a91b994878; - 9d72c1ab2092c1b10877 c64b10f8b191bc2c 5bdecded96d656c9; - 72865f289725e1b55502 91fdf7236f85bdd6 1a5680e51736026f; - 06e3c0e541f4aae6fe93 40009f8a465a9feb 0e7aace421bc79d8; - 2ea09f1cc89e064f09bc 543208b05bfa3858 a95d87fad12c3593; -} diff --git a/tests/square b/tests/square deleted file mode 100644 index 360d56b..0000000 --- a/tests/square +++ /dev/null @@ -1,525 +0,0 @@ -# $Id: square,v 1.1 2000/07/15 20:51:59 mdw Exp $ -# -# Test vectors for the Square block cipher - -square { - # --- From the reference implementation --- - - 000102030405060708090a0b0c0d0e0f - 000102030405060708090a0b0c0d0e0f 7c3491d94994e70f0ec2e7a5ccb5a14f; - - # --- From the validation data --- - - 80000000000000000000000000000000 - 00000000000000000000000000000000 05f8aafdefb4f5f9c751e5b36c8a37d8; - 40000000000000000000000000000000 - 00000000000000000000000000000000 60affc9b2312b1397177251cc9296391; - 20000000000000000000000000000000 - 00000000000000000000000000000000 d67b7e07c38f311446e16ddd9ea96ebe; - 10000000000000000000000000000000 - 00000000000000000000000000000000 39207579067031706fab8c3a5c6e5524; - 08000000000000000000000000000000 - 00000000000000000000000000000000 fc4f2602a3f6ac34f56906c2eeee40c5; - 04000000000000000000000000000000 - 00000000000000000000000000000000 6f2431469f4a0866632216c59c18ff11; - 02000000000000000000000000000000 - 00000000000000000000000000000000 c745f6f339d1bb9524e1b2d2b0dde843; - 01000000000000000000000000000000 - 00000000000000000000000000000000 241e113a1bb5c32cc45d95d7734165aa; - 00800000000000000000000000000000 - 00000000000000000000000000000000 5e16777211c67ae4609f6a47bf5df2c4; - 00400000000000000000000000000000 - 00000000000000000000000000000000 272330139236c300cd161f0266b62494; - 00200000000000000000000000000000 - 00000000000000000000000000000000 15115b9e29524325e7c992ead262ade8; - 00100000000000000000000000000000 - 00000000000000000000000000000000 acdcce277b801ed53dfe0fc12f4c957b; - 00080000000000000000000000000000 - 00000000000000000000000000000000 9cadb290cedd6f7ca6c10d42fe4c1a70; - 00040000000000000000000000000000 - 00000000000000000000000000000000 d70d4c24ffbf3de6e6bd54ec03b8492a; - 00020000000000000000000000000000 - 00000000000000000000000000000000 602455a418a99a942fed27123b9f73e6; - 00010000000000000000000000000000 - 00000000000000000000000000000000 f239c4efd3729d43081544104378f0ea; - 00008000000000000000000000000000 - 00000000000000000000000000000000 70259a9572990099ac563114074db3d2; - 00004000000000000000000000000000 - 00000000000000000000000000000000 932d3644863b6377100c64f243445e7e; - 00002000000000000000000000000000 - 00000000000000000000000000000000 47100bf12f2e1f718e9430f4127535be; - 00001000000000000000000000000000 - 00000000000000000000000000000000 2ed60ffa71c162a53c3a8bba2b0b042b; - 00000800000000000000000000000000 - 00000000000000000000000000000000 e2992d6bdc7c65b70b62685c0d84425c; - 00000400000000000000000000000000 - 00000000000000000000000000000000 c552ca3d805e456f5239dd7956cacd71; - 00000200000000000000000000000000 - 00000000000000000000000000000000 95b577c2ed3c2d9d96c2106e091b1f72; - 00000100000000000000000000000000 - 00000000000000000000000000000000 3d550ae470bfb0306c3099c8d5a471d8; - 00000080000000000000000000000000 - 00000000000000000000000000000000 fc13974afe73a92598aa95edcb2102e9; - 00000040000000000000000000000000 - 00000000000000000000000000000000 ab0cf3a0cfef3aa3d10738523e624a1d; - 00000020000000000000000000000000 - 00000000000000000000000000000000 72fea53144f673e283547f08da30bdda; - 00000010000000000000000000000000 - 00000000000000000000000000000000 389fef99fa1a3dbf664673aa39d848d1; - 00000008000000000000000000000000 - 00000000000000000000000000000000 041152bca8440e8de572dce9dcc88cdc; - 00000004000000000000000000000000 - 00000000000000000000000000000000 845b37c1338a0ba0f295be273841b940; - 00000002000000000000000000000000 - 00000000000000000000000000000000 e2e3a1c7998040ee6bd8714e65ebd8af; - 00000001000000000000000000000000 - 00000000000000000000000000000000 0b2b34c480648dc91f938dd368464780; - 00000000800000000000000000000000 - 00000000000000000000000000000000 96bad4a54376917044b1076727a91e2b; - 00000000400000000000000000000000 - 00000000000000000000000000000000 dd8c3dff69c3fda2802dffcdef1b1631; - 00000000200000000000000000000000 - 00000000000000000000000000000000 da45872e48af2f0ec7fc395d03ff9451; - 00000000100000000000000000000000 - 00000000000000000000000000000000 b25194c0f1953f35bc4c0871cd2d4a40; - 00000000080000000000000000000000 - 00000000000000000000000000000000 3e09af82736971f2847834082d6ec6f3; - 00000000040000000000000000000000 - 00000000000000000000000000000000 fa75a64f778b914dc4b926626bc8b4c0; - 00000000020000000000000000000000 - 00000000000000000000000000000000 d21542857f03f6a92cacd2e783e33e3e; - 00000000010000000000000000000000 - 00000000000000000000000000000000 1ec0a5b9781c5e90b1e15731e0625c36; - 00000000008000000000000000000000 - 00000000000000000000000000000000 e1c58917e586b6c46c46982fa303f14c; - 00000000004000000000000000000000 - 00000000000000000000000000000000 72ecc0d267b445482924c9969de97a15; - 00000000002000000000000000000000 - 00000000000000000000000000000000 a52af631193375dd59555e2753acde65; - 00000000001000000000000000000000 - 00000000000000000000000000000000 033b8482c4010eb20a3edd4ba35a3db7; - 00000000000800000000000000000000 - 00000000000000000000000000000000 56534a944796abdf51ad247b8c9ee9bb; - 00000000000400000000000000000000 - 00000000000000000000000000000000 9eda6fd2cd4eabf8218b98a165e82b9e; - 00000000000200000000000000000000 - 00000000000000000000000000000000 60043a7e110e1321bc41e4ac47d1f45e; - 00000000000100000000000000000000 - 00000000000000000000000000000000 90e685c8f990cedeacc8a2bfc8e46ca2; - 00000000000080000000000000000000 - 00000000000000000000000000000000 b9e77e32f721c0a7a02b50925311e834; - 00000000000040000000000000000000 - 00000000000000000000000000000000 001d2fe95bb39ef0c3548307ea7580f3; - 00000000000020000000000000000000 - 00000000000000000000000000000000 a5dd651290a063f4e7c5e714c9c398b4; - 00000000000010000000000000000000 - 00000000000000000000000000000000 aa7b3b9f459ba0367ff2a332ef725da1; - 00000000000008000000000000000000 - 00000000000000000000000000000000 a424f80b0048756879ed6343768bbe08; - 00000000000004000000000000000000 - 00000000000000000000000000000000 ea4590786de7f8a68439b4616bf7e4b9; - 00000000000002000000000000000000 - 00000000000000000000000000000000 7d15058fe884dcf0976105a816cf6366; - 00000000000001000000000000000000 - 00000000000000000000000000000000 a07d1b74ae6a3f26a8a25e1e778a0d4a; - 00000000000000800000000000000000 - 00000000000000000000000000000000 61f13db32828961c3e35d9b7ab77b57d; - 00000000000000400000000000000000 - 00000000000000000000000000000000 0e2979112efb29754605011a358093fc; - 00000000000000200000000000000000 - 00000000000000000000000000000000 a878c8a8a5230917c56f7eb74fdada25; - 00000000000000100000000000000000 - 00000000000000000000000000000000 34343f73232790e6fa44d8f606a24de9; - 00000000000000080000000000000000 - 00000000000000000000000000000000 d569b991761c26dde723cca0c262f195; - 00000000000000040000000000000000 - 00000000000000000000000000000000 f1a0f35ada018c5df56ffe0dc95636bf; - 00000000000000020000000000000000 - 00000000000000000000000000000000 b26af455039312e1206290a921459e1a; - 00000000000000010000000000000000 - 00000000000000000000000000000000 594049c7e3a34e1b9bccefaf5e75b373; - 00000000000000008000000000000000 - 00000000000000000000000000000000 4e4e037f07ff26e8e9065f26afedaf2d; - 00000000000000004000000000000000 - 00000000000000000000000000000000 ddedc3ca10ec011ea24dd4566d21409c; - 00000000000000002000000000000000 - 00000000000000000000000000000000 3660f51bb790f275a55aa435db6da193; - 00000000000000001000000000000000 - 00000000000000000000000000000000 a9a7cfe07ea640498e832ae25e2906ed; - 00000000000000000800000000000000 - 00000000000000000000000000000000 3863d1c222a36338ea6d402073341f42; - 00000000000000000400000000000000 - 00000000000000000000000000000000 ced5dfdf8b5d1d60e9ad51830a7965a9; - 00000000000000000200000000000000 - 00000000000000000000000000000000 4ffae5d7a5689a5584330cb0a5cc9cd2; - 00000000000000000100000000000000 - 00000000000000000000000000000000 1dd688d47541463915f658bb656420b4; - 00000000000000000080000000000000 - 00000000000000000000000000000000 ef3a1c1800dd3cda748fbdf17086ba4f; - 00000000000000000040000000000000 - 00000000000000000000000000000000 f9aa9b3e76543ef12f7f8b87ce393328; - 00000000000000000020000000000000 - 00000000000000000000000000000000 1813935bb67dc40dc37c68cc2999758a; - 00000000000000000010000000000000 - 00000000000000000000000000000000 8c4916d59fce8eb913b128f2d7b3d464; - 00000000000000000008000000000000 - 00000000000000000000000000000000 bb88da704c5ce031c61954efcae6ed2d; - 00000000000000000004000000000000 - 00000000000000000000000000000000 4e463bceb0f52c3f722e2926c2bd04a3; - 00000000000000000002000000000000 - 00000000000000000000000000000000 4a6181492a454604293396bbd21c4956; - 00000000000000000001000000000000 - 00000000000000000000000000000000 801f29d5462365735a6ca7a64288f48c; - 00000000000000000000800000000000 - 00000000000000000000000000000000 7933733c4daab746ef048edba2d05538; - 00000000000000000000400000000000 - 00000000000000000000000000000000 4127c1d95431fd2632f2b5e5085a3dd8; - 00000000000000000000200000000000 - 00000000000000000000000000000000 0588168ca7525333460c4030af266388; - 00000000000000000000100000000000 - 00000000000000000000000000000000 32b3f193d7237b48883de002b3cbe1c3; - 00000000000000000000080000000000 - 00000000000000000000000000000000 7ca557bc05b845a233c01412022da825; - 00000000000000000000040000000000 - 00000000000000000000000000000000 54f11361ad6dfbb069be67536cc98d81; - 00000000000000000000020000000000 - 00000000000000000000000000000000 a9df031b4e25e89f527efff89cb0beba; - 00000000000000000000010000000000 - 00000000000000000000000000000000 7da4d0d6309906d935ba27ae00cfaf33; - 00000000000000000000008000000000 - 00000000000000000000000000000000 e231ea0fec29d983d3236bb15e7cd1da; - 00000000000000000000004000000000 - 00000000000000000000000000000000 fe1b963a4f596422a6cd7787f4ab3377; - 00000000000000000000002000000000 - 00000000000000000000000000000000 848833f2f7a247d2e1d0c8614694139f; - 00000000000000000000001000000000 - 00000000000000000000000000000000 630bb1dc4e60d3272b6b673bdb918b20; - 00000000000000000000000800000000 - 00000000000000000000000000000000 500251a5c6ad5a6d2f218a3fd5765727; - 00000000000000000000000400000000 - 00000000000000000000000000000000 d019ef316e84149cfd0e85665aa2fff5; - 00000000000000000000000200000000 - 00000000000000000000000000000000 db0b5ac0e8ef011d710323fa3b8bb3a7; - 00000000000000000000000100000000 - 00000000000000000000000000000000 207e46a533617374d2c9da0c92ffd620; - 00000000000000000000000080000000 - 00000000000000000000000000000000 8273ca155249f9f1ad8cc2ca114984f3; - 00000000000000000000000040000000 - 00000000000000000000000000000000 82a73a18aae84ad671e226470f246e1a; - 00000000000000000000000020000000 - 00000000000000000000000000000000 3e0e1206e333917d4c250bd82fef6afd; - 00000000000000000000000010000000 - 00000000000000000000000000000000 2182f67239be15c796439ea3791202e1; - 00000000000000000000000008000000 - 00000000000000000000000000000000 486fb3fa7b1fe1a304cb4e8960c3c6bb; - 00000000000000000000000004000000 - 00000000000000000000000000000000 c1de50e456c4308d5d70da141cef0b4f; - 00000000000000000000000002000000 - 00000000000000000000000000000000 a623f24515a27cee3dad277429000218; - 00000000000000000000000001000000 - 00000000000000000000000000000000 02fa5762f9cd90201565bce71140c6f4; - 00000000000000000000000000800000 - 00000000000000000000000000000000 a643a0ca5154a7d10b251d562d58ea53; - 00000000000000000000000000400000 - 00000000000000000000000000000000 48660e32b1c7ee7085e5b5e9f719c790; - 00000000000000000000000000200000 - 00000000000000000000000000000000 a96366bb17b67e161fd8e33c3e1f3d2a; - 00000000000000000000000000100000 - 00000000000000000000000000000000 5659ab825fc2de031a6998cacd741ff6; - 00000000000000000000000000080000 - 00000000000000000000000000000000 1253e9e4079e9b573a73cf4ce08dc015; - 00000000000000000000000000040000 - 00000000000000000000000000000000 28205442270c735d4ba79042dce81509; - 00000000000000000000000000020000 - 00000000000000000000000000000000 98cfb10f3ed70bb82cc90597b463a1f6; - 00000000000000000000000000010000 - 00000000000000000000000000000000 cab40433631fe3a272fc401255a58064; - 00000000000000000000000000008000 - 00000000000000000000000000000000 abb041d85114da88e65e8bdcf1c67cc8; - 00000000000000000000000000004000 - 00000000000000000000000000000000 00f0926f0f9eaa0a6238dfce79c8f596; - 00000000000000000000000000002000 - 00000000000000000000000000000000 7c662d01b12d9845705b2bd4d7aef43d; - 00000000000000000000000000001000 - 00000000000000000000000000000000 8f1cc7a0fbe7d70a894d09e12fb22bb8; - 00000000000000000000000000000800 - 00000000000000000000000000000000 ebe03d0c6752d0edfebff879c33d8c07; - 00000000000000000000000000000400 - 00000000000000000000000000000000 b74ce7f67bbd969e8ff8862d1fb1715c; - 00000000000000000000000000000200 - 00000000000000000000000000000000 63ad5ea9d599ec848a40d489c0b85e8a; - 00000000000000000000000000000100 - 00000000000000000000000000000000 4e4167f091ea5776e80fb2fca38c2a04; - 00000000000000000000000000000080 - 00000000000000000000000000000000 dbf0cea3a5ed5b884ac13a2a62c32d51; - 00000000000000000000000000000040 - 00000000000000000000000000000000 7e86285068a376a3b9fe8641a38e3f90; - 00000000000000000000000000000020 - 00000000000000000000000000000000 aec1ef8d651a2cf7b5475fcc7fb7a81a; - 00000000000000000000000000000010 - 00000000000000000000000000000000 fda539d910181ce1a1e1db4c3459600b; - 00000000000000000000000000000008 - 00000000000000000000000000000000 f8072bf053d5b5163949ff0b9bb3f81a; - 00000000000000000000000000000004 - 00000000000000000000000000000000 a31eb966d34ed6a6132a6b6e9128e997; - 00000000000000000000000000000002 - 00000000000000000000000000000000 673aebbff82091a19e758ece151811d0; - 00000000000000000000000000000001 - 00000000000000000000000000000000 369bdb6f102d6bfea7645b1a6753bf37; - 80000000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 ffd90e8a92a1b025108168714f7923f7; - 40000000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 64e10ab587bc5d996cf2186c2ff2dd58; - 20000000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 eaa404b51336a16c963735588b0b2a0c; - 10000000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 51aaa1e37cb08cf5c6ec9241ac36b4c5; - 08000000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 c21b34c3c077b30add67d0e2e75e59ec; - 04000000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 f33ccd4771932f5e467552e93ae367ab; - 02000000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 b70b9f3a5814ddeb6d3549d88c5b4656; - 01000000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 5c01c66e9bf9617b155d3902722ccadc; - 00800000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 1f47def31d2e7e286172b38119fde307; - 00400000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 bd3c2f005cf0eb5ef737c29f457ed549; - 00200000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 1d409243f79ce876d13b0fdfea26ccf8; - 00100000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 b879e37c2f435b0cb941f74892c1476f; - 00080000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 58c6a8884bf8b110c9127893976a9e4e; - 00040000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 7a258ac14cb88a31432ba1b320d254f6; - 00020000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 ff382f1b4bbb54c9f42b73b256f80d25; - 00010000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 0cef334bcbe5d38e23a9780d2e3e9097; - 00008000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 3225e13778d2a3bab1eb375e034478c4; - 00004000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 4ef73320931377f64e296e49c286e5c9; - 00002000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 adbf2c07f2f42eb7d92acc07f9df7a5f; - 00001000000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 bfca14ad6925ddb4f563048db1c6b485; - 00000800000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 63f01ea46c82dc3b1d81eac5e4f1d687; - 00000400000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 b2f6eb69ce81accc720e705146cfc2a2; - 00000200000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 85b1ff06090504848fdda74dd830e960; - 00000100000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 5bcb44ab29d7c31def58c902c2491333; - 00000080000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 4d982cbc7c1455cde7c0de3f83fcbc5e; - 00000040000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 32f08276e0633e1d819fc6227e631503; - 00000020000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e6bebd4cddc205399126bfda486ed37c; - 00000010000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 afe39df4f356aea5f07069455010d9ce; - 00000008000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 a8c7b2c1e8e1ade5e28e4104ff716ba5; - 00000004000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 fbb3e4ca3e710a5bd94b50726de5fdb1; - 00000002000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 2091d65d6fbb8672d84655f33dc1473a; - 00000001000000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 9c74519acc53498333791febfd0e5e8b; - 00000000800000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 ed44022a82468ed54203b5863b63061f; - 00000000400000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 eae325499a1a9e8e1bd4d6f018e65551; - 00000000200000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 b134fe1498d7a1d926d3a623ffa5723e; - 00000000100000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 343f8d08a35c272c5cd4064a42a7b6d8; - 00000000080000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 79230ea5d7f6b5d85922ed7679aebe08; - 00000000040000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 d3f799e3579c68e10fb1c770b1cbb7c7; - 00000000020000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 90c24054dc24772ecd92a67a43335320; - 00000000010000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 bf38cfda7b75a478fa73316801883d34; - 00000000008000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 4323a85f7921a4a1fc072b72b6b46f50; - 00000000004000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 3e10218fdefd9a0b91d9032d793aecc8; - 00000000002000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 66a759ec5e5cdd9c27a4e97ff0b5aab8; - 00000000001000000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 3730876a26727d44a46404f69ba99f09; - 00000000000800000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 b277bd5a0e78eafc049bd9aa3393870f; - 00000000000400000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 af05cdd3a6dd19fb0199933bdea3c20f; - 00000000000200000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 0d962ec5f824d922924f3c39339fa934; - 00000000000100000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 de695dab525ffebc039f63c3defb200b; - 00000000000080000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 f8ce4303ff6a523a60e3526a28c1c1de; - 00000000000040000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 c00c5250a33165254408992f6aa1fb97; - 00000000000020000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 7e81d9c10bc3ac8fcac65079867183ff; - 00000000000010000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 42f91fe46e5f6485973123b586cc2517; - 00000000000008000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 0900c5c4bb963e1e421571056aeda9f0; - 00000000000004000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 933312932700ef9c82333913782fc8fb; - 00000000000002000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 d78181179ac4cc05f38a1d134b29b70a; - 00000000000001000000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 411b9bd8a8c3d3c9a2c375d28a336c4a; - 00000000000000800000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 632433f8708bd47d6a083adbdf3a8982; - 00000000000000400000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 f037e3fcd3db611bd777420b8170df1b; - 00000000000000200000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 31da207bfbdbb93157408ad2d7e559df; - 00000000000000100000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 2837b13cb713b5fde1bc07cb7b2613d9; - 00000000000000080000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 c31906513814506753848c50ab7c8d13; - 00000000000000040000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 014b54ca9f1d87c7711af20119b03afc; - 00000000000000020000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 060903be7b215ee51fbce79205b0515a; - 00000000000000010000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 f91da002995fe07969ff63b8673fa75a; - 00000000000000008000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 65a8b07ad4f77c8be4f27f975a42f2e7; - 00000000000000004000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 31a157653449da846b5dade80e2f3ae8; - 00000000000000002000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 1be98428352aeab7534e12463898bde5; - 00000000000000001000000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 a7a50bec385145e784486d6d70552fbf; - 00000000000000000800000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 eaacafae73701d566b24ab68350c4cb7; - 00000000000000000400000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 deef8a7a5de90caaa0e3412356518d9a; - 00000000000000000200000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 8d4373f4933353f589e42471ef35836c; - 00000000000000000100000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 01436b7d351b9ff0fe85dab7ef77a020; - 00000000000000000080000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 a6b2b93c4c6dafea4db5a4ecfee2c561; - 00000000000000000040000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 7b0f7781683d890db4582d4399b07fab; - 00000000000000000020000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 01c82b395331de265555d72df29c7efc; - 00000000000000000010000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 5d9ba76d5b20b4b88b70b80c20c5e350; - 00000000000000000008000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 92b2a69dd8a75d2edb01644a0b975c15; - 00000000000000000004000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e2f6e46a2a899615969f4b751d55d57f; - 00000000000000000002000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 97427298315d058eb2f7cdabd4a851c8; - 00000000000000000001000000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 8f0f710a0cc1d6049ebb01974b76caad; - 00000000000000000000800000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 2cf62d9d02afb40eed66fedb53c2db5c; - 00000000000000000000400000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 fb215ab9ec3fafc5fd91cd9ad3cee2be; - 00000000000000000000200000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 4a37472335edaf7393a304d45a233085; - 00000000000000000000100000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 d22a878d2ca3a88f34acc92a4e26c738; - 00000000000000000000080000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 f1a95970638dcbc69c4675e895370904; - 00000000000000000000040000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 1660060085c0e241f88462bffbe67602; - 00000000000000000000020000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 a097acb2eb5f779090f886beae746ae1; - 00000000000000000000010000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 9ffe05163407ba53b62a35d857f58bc6; - 00000000000000000000008000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 dfed8392eec1b389cbc261faf97c5c9e; - 00000000000000000000004000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 d2c1b3159129d86959f3aa9b70219a74; - 00000000000000000000002000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 98c043b2e86cff626abf5fbc745d98a6; - 00000000000000000000001000000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 35c5aed481c801a0ca78842273e0186d; - 00000000000000000000000800000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 ddaac5c7f13943e80d2244a4a19e9980; - 00000000000000000000000400000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 51dbf12fc81e5ffe9b1ce9963636205f; - 00000000000000000000000200000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 38ee89874d644ccdf9694280a6c48182; - 00000000000000000000000100000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 c3bc93ca8e8800622c92c56b99262ae2; - 00000000000000000000000080000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 dc2c2b7558f75b71a9db34e971892171; - 00000000000000000000000040000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 609bd72078f92ae345dcde14e6aba0e0; - 00000000000000000000000020000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 cabc8bdda6e1979199f5010c3f8b8a31; - 00000000000000000000000010000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 c993d659ba4426dc30f8dc7ea03cd2ee; - 00000000000000000000000008000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 5dd47466cbb15dca1485e04231d7491c; - 00000000000000000000000004000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e1351ce84ded187e0f5aab9bb7198387; - 00000000000000000000000002000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e5222c68fda26e5e62929c70233ad097; - 00000000000000000000000001000000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 78cc456147db73850328241bdff861c0; - 00000000000000000000000000800000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 4f10436e3ba4f38cd96744b897d5a136; - 00000000000000000000000000400000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 12b698464abcb67c3956c5d1b9c62dfd; - 00000000000000000000000000200000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 49de5db3e7d997c56dd2f82935e6617f; - 00000000000000000000000000100000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 71ea115e54775680f16b1b9d7b2ee367; - 00000000000000000000000000080000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 45b7e46c664a472af948b0c393f92af1; - 00000000000000000000000000040000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 db3678b993ef5e48931b5bf84cece6eb; - 00000000000000000000000000020000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 051c9a17d4ca77eabd8b9d9a1bce52d6; - 00000000000000000000000000010000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e805aeeac134761ff7b3260bb4308a10; - 00000000000000000000000000008000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 3301700109b460c7e41a51059f33004f; - 00000000000000000000000000004000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 d71f178093314e188bae26dde5a78927; - 00000000000000000000000000002000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 31bb9cb46fbf607fcaa5932851899420; - 00000000000000000000000000001000 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 ea77bcd0ce469ab47a828dc6324c3651; - 00000000000000000000000000000800 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e4596b0d33bdeb062a7ddb93e6efae94; - 00000000000000000000000000000400 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 24d04f34b837461cd3b8d9c13afe6fe5; - 00000000000000000000000000000200 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 ffb68c9ae4d7d2642bf5bee57d2bd914; - 00000000000000000000000000000100 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 c008d35eb9de15700c0491319e6415f0; - 00000000000000000000000000000080 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 92bfbbfcd2bbf54fff06af097893e9a3; - 00000000000000000000000000000040 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 d2475279191bc4da183ee2dba75fce6d; - 00000000000000000000000000000020 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 7b8adf2ef0e1f5fbb19cbd4b8fab1426; - 00000000000000000000000000000010 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 0b07b9c4385bdc86447f535e09a9f424; - 00000000000000000000000000000008 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 e7308875d8d6645719c076dd1660924b; - 00000000000000000000000000000004 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 bc50d54a891d6102d0c02f471f1f0567; - 00000000000000000000000000000002 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 2b14534ca7d9821a40b101035f681f0d; - 00000000000000000000000000000001 - 0f1e2d3c4b5a69788796a5b4c3d2e1f0 69bd984641e0aa887bc23738f60070db; -} diff --git a/tests/sslprf b/tests/sslprf deleted file mode 100644 index b24813d..0000000 --- a/tests/sslprf +++ /dev/null @@ -1,11 +0,0 @@ -# $Id: sslprf,v 1.1 2001/04/06 22:05:11 mdw Exp $ -# -# SSL pseudo-random function - -sslprf { - # --- Generated using SSLeay --- - - 4837879a5040b1499a9cae62747e4857b090a0334683d8492d1d87933b58fa07523d4b8d0df762b62caddf7ac1304cd9 3ace3cb1ee080975da0dc748207c2bc0eb995746d0b37ab4789932a32ec5347b3ace3cb100000000b28539b8285cbc37622b65d8efcba4ad13eb42712c47d6f5 c15e3166e8a743e6b5da7d9cbcc08c2e4107887a70f2a4e16b54243276c48894569f2916c6cb610bb84b766b7283dca0a346fcce41683ec01f06c17e91758d5d31fbd1ca0a7d75b909035f04786f41efde988d20f5d1fecad337a3a23a16fde1beae5400bc3f357c; - - 53a82e555607a83890bfc633ff7f1d9ecc7d225f450dff3a8d46dd370033968fc456ae8b6fe3639c71fa2ba9d0f798aa 3ace3ca4ac5e36c228a5ce350f22261eadacdc48873b317843061aa679ed15e63ace3ca4000000009ba10a4a1837535a372de6784f037f6cc36c3113cdcc1465 798b2f8eee4cd6b35a220f8d446672762e8dd53bae7bd773877a1dfe0aa446b4274bafd546e94b1bbe4c2d56a6e60d06871b117a7d562859f36ce2082def1c134b1c117022fe449b2da85e6d2c8e763bec6e35889a315d8686e391c277377beb037dd91accddacd1; -} diff --git a/tests/tea b/tests/tea deleted file mode 100644 index 492d21c..0000000 --- a/tests/tea +++ /dev/null @@ -1,76 +0,0 @@ -# $Id: tea,v 1.2 2000/08/16 17:57:14 mdw Exp $ -# -# Test vectors for TEA - -# --- Generated from Needham and Wheeler's original implementation --- - -tea { - 00000000000000000000000000000000 0000000000000000 41ea3a0a94baa940; - ffffffffffffffffffffffffffffffff ffffffffffffffff 319bbefb016abdb2; - 00112233445566778899aabbccddeeff 0123456789abcdef 126c6b92c0653a3e; - 00112233445566778899aabbccddeeff 67452301efcdab89 d667cc4e10bf6eb0; - 00112233445566778899aabbccddeeff b3e551c7d8378a6c db21fb2a3118e62d; - d94576cd1a5f99e4155dc7bec5d33df2 d51399607f7aa9d7 7d1eb12827ef2121; - 07ef12bc9d06d7da20131116b665e335 10b233473624ccd3 ae694e579daeff54; - c6462b48afd604b75fcc455506ffd411 3b905e951e4fafe7 d9633fcf13c30394; - be195f703d6fec2232cd0890c981b27d 15b623d1fa2df9df 916ffcb1abaf086b; - 5b8410f7a9eb92da120810c56fcaf8c9 7c1035940696d91d 460aa2db964b580c; - b85c9e26661889d0ff1054c6be27fdeb 90b245144895f3ad 87d7e95a5a4aa89a; - a8a1e956d54d238f6ceab186e7ec99ed 4ef2cfd120b8d4dc 1752f2ee188018de; - 8bc4879201a96368927ecceee67024ee f6cb5353f4a1c432 7cfa8e0718d59807; - f1372d85d8c3d1a60df57eedf317ab81 215c080cf158a09b 3b85115e0d6c5a94; - 017f01683f5e009d196feeaad385c5a9 568583061da98d0d cb0e345182f4bf0b; - 281c932ddd3c364b09f1896007ffab03 0558b306316b0823 e7adf267c7d841c2; - c1e95465c7ef8eb04254d1a5463c6a43 fdcb2764303222c7 ed48b228c11e7bc6; - 0f86dd6c96dd31164b656b0f25e4b411 eaddba89070ec46c 89fb864135a57e33; - fbacfb479ae21194c35b8184e58dd66e c6507bcf99b9c2a1 670da449ce74c658; - 2eb36c4a9598d471700a1330070fffc9 c380b0f1c21d4d37 d84fe611431c0b5e; - 0a7f48127091780617a1f534b3271bc9 e5b7c1517f24f298 4be47c656cef6ffc; - 303fb24822a1b8a84d0ece77b86380ff d14ddf77fdda17bf 1cc73315c9f72ab1; - f04ebf798c193f199c1f532af383555b b9682750bb15caad 2b5f318fb66806b9; - 200c0ce59717d5d9af6813cd207fee73 9706769a18a2d03d 8e17eeb5008dc0cb; - 2828d51f98ae0b33f4de2b7fbd18a529 edb76c54847da59e dfa6c29beb40f9af; - 61aaba6be48b0d0d14fe5d27fab852a4 178a49bafba53f23 c3bbce6715d90ce6; - 2080e2409ba01c8532fc84403ee8c06a df4cdb61a5f38536 b4e6359c9d9458aa; - 271ad15192c4d1204a4a2561e3db6ff7 7c944d08def34c0c 195c0e8f49761539; - c1e297c0c761777d8a76fff02d22b859 f4c76c1d47fe568f 551ca67c7756ff56; - 23c807a2ef0a551f858fd52d125a47d8 cab16583e15d0074 de472175d55372c9; - 9fa5d4d8cbdfcecd559e3ce88bf78ee1 97b05c60774164ad bc4bd30cb50da39b; - 24f4e91083139099d663647a7ffac321 7017a263985b735c e47fdf06a51d8c24; - 7cf8626de76d8462218ed5c9dc8acc26 15475a90df04cd29 4df54282eaafa235; - 3c6ad7df17332a3e1e3de06007387357 87ca0aaccf146cc8 f7360f57cfcc09ac; - 24237a762d8a89383a2949f5a0f5ec08 9268af048ecbae67 e98e428a9d1fee9c; - 209a2833a39472d9720380ffb2f74761 af0062cd77a84ebd 44cd624b87cbee77; - 22ebe7a30e8855b3b453a6e926d4f187 f922ca875b991a31 1e92c0c51185f7c7; - 1b5e23ebd915c1fee59f57dd91af7347 b4ecc305c3dbd8e5 063d8f75a7a77501; - 6c21d105515290da29339f142685c135 a4c2f6dc597d13ea bf8ffec7550a496b; - 01f728a7433a47b13de34fcc08958449 3af7f1ae0f58ab1d bba581d07e51d8d6; - 9a2d4c50337d3ec337673782fd385601 791d8da8cbb0bc94 7d9a4f0363b6085f; - b3b99747560e246bcd0cdc3fb33e4910 91778f2bd9233375 4b85b79a58b1321e; - 4b269e2e8dbd68b94066c95244c3a195 abfb6a33e1471e96 53d089e9313e832d; - d10b956f675dc2276b6dd90442bece3e dbedddb6a1c15a21 b81739d49c10b4fd; - 28f8fab7541766f6dafbaa5b6f3bd700 2c14d5097ab11f61 c018b6e3cca4095f; - 2b61e60478fa0c0edb9531f26791eff9 b84c80b2d245fdfc 2301e2d68d241622; - a6bfb85fa91b8ca4197c8b502a62f972 3daadd7a9633e19b 65bc93b4dbbd652f; - 94e76e54d37f932cbcc069de6bf26d52 02739eeb468450fd a477a7ec244f1e9f; - 82760ea1560e8f9d1e35f20cad1f26cc 34aa5952b5a9110f 2564284b47152721; - 3aba91211327585e0f1270b59ef9277b b584d6b34b638ba4 c829dc4da560211f; - 727074f35cd523eb6f8aafbbf76fd5b1 f0e9268a27ab70c6 f24b80555fdcb67f; - 6e0aa1c91ea6315a4a7dd297ac5936a4 47374080f27fbb30 6fdb64c32920c0a5; - 63bd2d37271a250c8593b433188cffd0 776927909196eec5 57bca56240b39c0b; - dc7beb423c2053156329d7ab79f4d1d6 24c0adb3777860ad e040f57fe32f2158; - ed219454883709efe884bbc9d30507a3 587b1683dff7f178 e2c6512996117ba9; - 40509fc5c565e9b9f3995f3bc5d5c1f4 719a39f2302a98aa b8a9f3ab1b68ac1f; - f9f10ed2bc0193605913475fd54d69ae e35b94e2940a8db0 b23358feb43a29aa; - 23003c3fbe9661b6b9386748982ac3e2 d1dfd47fac22b9ff 4165de32289acf6a; - a2caa563c2f19b10fbac1427e2177858 f7743dfe957cc82b d88dcd158b0d81c2; - 8bb42b6937d65eac506e8326356071af 690a0fa32113bf34 9095cce6d70da9d6; - 219c7f982a0c352977b978b91fcb3c45 8fb4cb86db41ce30 c688b48de8ec7e14; - 157ff76f22538eede0528c541dbe7815 ea6cd44f238be18f 35578556b38660fa; - 346194289f6d865237cc673c45415003 71690fd4ba3d75de 719f1f0a6b316a58; - 032c8c1624f7f300d8a58d151de52d78 3c0f1746798ed5b7 62c9adb10b265534; - 019471106a5cd4ee3d1f627213649b80 558a8d7a4cdc0822 014521292dcbff85; - 45aa90191c449dbf9c541fb476d1bf74 bfba3dfd06e77671 b6a6825c69d9d5eb; - c86c21d8c26dc291f662c8f2fe79b74b 0993d3b68c1d4a5d d33c2e41dd5da131; - af4f4615c7c298639b9728251991419f 1e268f9e710313b5 a9478f8cf88b7e10; -} diff --git a/tests/tiger b/tests/tiger deleted file mode 100644 index 7679aa4..0000000 --- a/tests/tiger +++ /dev/null @@ -1,64 +0,0 @@ -# $Id: tiger,v 1.1 2000/07/15 10:17:19 mdw Exp $ -# -# Test vectors for Tiger - -# --- The main hash --- -# -# These are taken from the reference implementation. - -tiger { - "" 3293ac630c13f0245f92bbb1766e16167a4e58492dde73f3; - "abc" 2aab1484e8c158f2bfb8c5ff41b57a525129131c957b5f93; - "Tiger" dd00230799f5009fec6debc838bb6a27df2b9d6f110c7937; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" - f71c8583902afb879edfe610f82c0d4786a3a534504486b5; - "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789" - 48ceeb6308b87d46e95d656112cdf18d97915f9765658957; - "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham" - 8a866829040a410c729ad23f5ada711603b3cdd357e4c15e; - "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge." - ce55a6afd591f5ebac547ff84f89227f9331dab0b611c889; - "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996." - 631abdd103eb9a3d245b6dfd4d77b257fc7439501d1568dd; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" - c54034e5b43eb8005848a7e0ae6aac76e4ff590ae715fd25; -} - -# --- HMAC mode --- -# -# No test vectors available. The HMAC implementation has not been tested -# against an external reference. The HMAC code is autogenerated anyway, and -# ought to be reliable and correct. -# -# These test vectors are here to spot changes in behaviour rather than ensure -# interoperability. - -tiger-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - 0a402190741a498d6d4a09016b0895cb6419ff849b196137; - - "what do ya want for nothing?" - 4a656665 - 3a351b1dec6075d6290e68b604e553821edc39041b82da83; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - e09ab076337fba2b5c4a83e9dbfb62993710992934f0946c; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - a452fa58bdb38b70207c472c5ee54b1e40b1893e6d604b19; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - 95981aaf2303d232824c504cc51459ea8275734336e92b1a; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - ebbb20db7af380b5dffff39f671e1224e994d840408a7941; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 308ebb428666c75b50d0442fe008777f4c208c7fa6d5ce7c; -} diff --git a/tests/tlsprf b/tests/tlsprf deleted file mode 100644 index bcbbb5c..0000000 --- a/tests/tlsprf +++ /dev/null @@ -1,11 +0,0 @@ -# $Id: tlsprf,v 1.2 2001/04/06 22:06:01 mdw Exp $ -# -# TLS pseudo-random function - -tlsprf { - # --- Generated using SSLeay --- - - 3bfcccfb9e0bf44585b7a5ffcc7ff3b27be9462d5190664b96613a089f21c06e6f4788e3a963683d5cddea86982682dc 7365727665722066696e697368656416da63a061e9dee1884336c7345060d39d8d5fb7cd42a6b15bdd4eda44890edc41137ffe 4975842aca48f758ede77403; - - 3bfcccfb9e0bf44585b7a5ffcc7ff3b27be9462d5190664b96613a089f21c06e6f4788e3a963683d5cddea86982682dc 6b657920657870616e73696f6e3acb7aca624a68136e34e262b3e813ea234662db262a2c5791986fbe101707f7201dca6e8c753a5f2d8be10a69e08577ff9d6ec92d8c3ed17be5ef40f029ad11 be41fda006e5fc3423589714c374f7de3a8bc1315610a419acdf62aee16462dcec00aa5ca4e1d615a3d0b87a4cf10bc9cfc3509f2a9a879708092ce0bd54cc12b3fa2238569a8327cbd314f779f653783f5119a81986e49750b4e300e6cbbebcc782a65cc72f302c; -} diff --git a/tests/whirlpool b/tests/whirlpool deleted file mode 100644 index 5f2383e..0000000 --- a/tests/whirlpool +++ /dev/null @@ -1,66 +0,0 @@ -# Test vectors for the Whirlpool hash function -# -# $Id: sha 2187 2004-09-04 07:50:08Z mdw $ - -# --- Basic hash function --- -# -# Some of these are taken from the ISO test vectors from the Whirlpool -# distribution. - -whirlpool { - "" - 19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3; - "a" - 8aca2602792aec6f11a67206531fb7d7f0dff59413145e6973c45001d0087b42d11bc645413aeff63a42391a39145a591a92200d560195e53b478584fdae231a; - "abc" - 4e2448a4c6f486bb16b6562c73b4020bf3043e3a731bce721ae1b303d97e6d4c7181eebdb6c57e277d0e34957114cbd6c797fc9d95d8b582d225292076d4eef5; - "message digest" - 378c84a4126e2dc6e56dcc7458377aac838d00032230f53ce1f5700c0ffb4d3b8421557659ef55c106b4b52ac5a4aaa692ed920052838f3362e86dbd37a8903e; - "abcdefghijklmnopqrstuvwxyz" - f1d754662636ffe92c82ebb9212a484a8d38631ead4238f5442ee13b8054e41b08bf2a9251c30b6a0b8aae86177ab4a6f68f673e7207865d5d9819a3dba4eb3b; - "abcdbcdecdefdefgefghfghighijhijk" - 2a987ea40f917061f5d6f0a0e4644f488a7a5a52deee656207c562f988e95c6916bdc8031bc5be1b7b947639fe050b56939baaa0adff9ae6745b7b181c3be3fd; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - dc37e008cf9ee69bf11f00ed9aba26901dd7c28cdec066cc6af42e40f82f3a1e08eba26629129d8fb7cb57211b9281a65517cc879d7b962142c65f5a7af01467; -} - -whirlpool-rep { - "1234567890" 8 - 466ef18babb0154d25b9d38a6414f5c08784372bccb204d6549c4afadb6014294d5bd8df2a6c44e538cd047b2681a51a2c60481e88c5a20b2c2a80cf3a9a083b; - "a" 1000000 - 0c99005beb57eff50a7cf005560ddf5d29057fd86b20bfd62deca0f1ccea4af51fc15490eddc47af32bb2b66c34ff9ad8c6008ad677f77126953b226e4ed8b01; -} - -# --- HMAC mode --- -# -# Home-made test vectors, for regression. - -whirlpool-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - f300802099638aa1df411accbae11c2947fbcb2a4186f1c9bc6daa75dc3ad46dd89739ae5fb39b5c4afc098435c3ba0f7f55900e8c719711cbaee6d473eef0ba; - - "what do ya want for nothing?" - 4a656665 - 3d595ccd1d4f4cfd045af53ba7d5c8283fee6ded6eaf1269071b6b4ea64800056b5077c6a942cfa1221bd4e5aed791276e5dd46a407d2b8007163d3e7cd1de66; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 4fb33849b7d0268ab9f3bc90cfc6ca90639338c32bca959b7bc47a61f4d946ca6c6a227e97205a18fe676907ce78d0f8892fcf73f44da714cb210188b92cabc9; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - 35bc33e2ed71e1cb01c140ddd3291ae3f84e9f0dce18005a1123df199983a211fe744b244449a1c093b17584069359bc6a95352271d78e2ef7a6f21dc28ab3c1; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - 502a6d22d0f8e67196dfed2a9d9ef988714db9db2e2f0ad6c30e52eed830aa348ee98744ddd3ff1974c7fe275e078b79a6ba8c967c5a41b290f6edca01183b1a; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - dd90bd637cfcd27ca914c290f33402cf68576d6e70601af0295f6b9dafa9d988d8b8fb4fde8605ac544638158dba2baa90a2bf882546cd0b876d59ab3f18962e; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - faf529af18a0f569480fd001122bb446b32a3cf758c385cec4adad9c73c77327812e260b7082011a3eb1071e71a50e1c3d37a8963f8b6a64a31cc017db1d619c; -} diff --git a/tests/whirlpool256 b/tests/whirlpool256 deleted file mode 100644 index 968777c..0000000 --- a/tests/whirlpool256 +++ /dev/null @@ -1,66 +0,0 @@ -# Test vectors for the Whirlpool hash function -# -# $Id: sha 2187 2004-09-04 07:50:08Z mdw $ - -# --- Basic hash function --- -# -# Some of these are taken from the ISO test vectors from the Whirlpool -# distribution. - -whirlpool256 { - "" - 19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a7; - "a" - 8aca2602792aec6f11a67206531fb7d7f0dff59413145e6973c45001d0087b42; - "abc" - 4e2448a4c6f486bb16b6562c73b4020bf3043e3a731bce721ae1b303d97e6d4c; - "message digest" - 378c84a4126e2dc6e56dcc7458377aac838d00032230f53ce1f5700c0ffb4d3b; - "abcdefghijklmnopqrstuvwxyz" - f1d754662636ffe92c82ebb9212a484a8d38631ead4238f5442ee13b8054e41b; - "abcdbcdecdefdefgefghfghighijhijk" - 2a987ea40f917061f5d6f0a0e4644f488a7a5a52deee656207c562f988e95c69; - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - dc37e008cf9ee69bf11f00ed9aba26901dd7c28cdec066cc6af42e40f82f3a1e; -} - -whirlpool256-rep { - "1234567890" 8 - 466ef18babb0154d25b9d38a6414f5c08784372bccb204d6549c4afadb601429; - "a" 1000000 - 0c99005beb57eff50a7cf005560ddf5d29057fd86b20bfd62deca0f1ccea4af5; -} - -# --- HMAC mode --- -# -# Home-made test vectors, for regression. - -whirlpool256-hmac { - "Hi There" - 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - 9ab3bbb27b85df2edc51f2e05c880560439547e7c2772f8cec6ae00bead0bd7e; - - "what do ya want for nothing?" - 4a656665 - 977fd7f1d53e8af854404262630bfac20269ab3fc2fccabecd8feaa05b8cdabb; - - "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 6d418c9fe3d422200ea8cf7d0d73591ca5714f49c38907c80fc96b3934ab8fc2; - - "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" - 0102030405060708090a0b0c0d0e0f10111213141516171819 - e0a3553419a54385ce04435bbb2bbf1d69d7626d8fab4f60e87a84fab731caab; - - "Test With Truncation" - 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c - 2a4f40079e618c3a8467dd1a284af43662f84b137d93d54e5623884a047f546f; - - "Test Using Larger Than Block-Size Key - Hash Key First" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 17564185de7d845576f42fbdcd027073bca1a059931ce4a901ae8662ad19caf0; - - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - 0bdc8bf26ff0a71201fbeef2d51f35bcbc3e8b0daeddedcbec2ca2b2e8f457b2; -} diff --git a/tests/xtea b/tests/xtea deleted file mode 100644 index fcc68b9..0000000 --- a/tests/xtea +++ /dev/null @@ -1,72 +0,0 @@ -# $Id: xtea,v 1.1 2000/07/15 13:44:32 mdw Exp $ -# -# Test vectors for XTEA - -# --- Generated from Needham and Wheeler's original implementation --- - -xtea { - 00112233445566778899aabbccddeeff 0123456789abcdef b8bf2821622b5b30; - d94576cd1a5f99e4155dc7bec5d33df2 d51399607f7aa9d7 782e4e131c5ba746; - 07ef12bc9d06d7da20131116b665e335 10b233473624ccd3 57733a1deece283e; - c6462b48afd604b75fcc455506ffd411 3b905e951e4fafe7 776f4965deb65775; - be195f703d6fec2232cd0890c981b27d 15b623d1fa2df9df 3bd5ad5c9ed6101e; - 5b8410f7a9eb92da120810c56fcaf8c9 7c1035940696d91d 5f93fa1d06991415; - b85c9e26661889d0ff1054c6be27fdeb 90b245144895f3ad 6105bfb0947828b7; - a8a1e956d54d238f6ceab186e7ec99ed 4ef2cfd120b8d4dc 51fae58a10f7c3dd; - 8bc4879201a96368927ecceee67024ee f6cb5353f4a1c432 550ad71ba8a34568; - f1372d85d8c3d1a60df57eedf317ab81 215c080cf158a09b 13d1e24ba9ff7b63; - 017f01683f5e009d196feeaad385c5a9 568583061da98d0d 6439b1dfe2ecb541; - 281c932ddd3c364b09f1896007ffab03 0558b306316b0823 c8f82fe4491a8917; - c1e95465c7ef8eb04254d1a5463c6a43 fdcb2764303222c7 244dbfa1d2c914e4; - 0f86dd6c96dd31164b656b0f25e4b411 eaddba89070ec46c 5a4909646763454f; - fbacfb479ae21194c35b8184e58dd66e c6507bcf99b9c2a1 6f08ec714e8a7c18; - 2eb36c4a9598d471700a1330070fffc9 c380b0f1c21d4d37 72d4d4bdf5c00585; - 0a7f48127091780617a1f534b3271bc9 e5b7c1517f24f298 64374b40bb732354; - 303fb24822a1b8a84d0ece77b86380ff d14ddf77fdda17bf 014f1e707d02c8d8; - f04ebf798c193f199c1f532af383555b b9682750bb15caad 9001d21b57ab5360; - 200c0ce59717d5d9af6813cd207fee73 9706769a18a2d03d 835fd788c089fd45; - 2828d51f98ae0b33f4de2b7fbd18a529 edb76c54847da59e b0c0125494d39ce9; - 61aaba6be48b0d0d14fe5d27fab852a4 178a49bafba53f23 ade26742f25efbe1; - 2080e2409ba01c8532fc84403ee8c06a df4cdb61a5f38536 9c895e72168b409e; - 271ad15192c4d1204a4a2561e3db6ff7 7c944d08def34c0c b784e23e00b3b498; - c1e297c0c761777d8a76fff02d22b859 f4c76c1d47fe568f 62f9e58b0364b0b6; - 23c807a2ef0a551f858fd52d125a47d8 cab16583e15d0074 4563be765e74653a; - 9fa5d4d8cbdfcecd559e3ce88bf78ee1 97b05c60774164ad 714807767366854b; - 24f4e91083139099d663647a7ffac321 7017a263985b735c cc68e1ed7f7c7832; - 7cf8626de76d8462218ed5c9dc8acc26 15475a90df04cd29 416eab1ebc155782; - 3c6ad7df17332a3e1e3de06007387357 87ca0aaccf146cc8 ded575554058ef42; - 24237a762d8a89383a2949f5a0f5ec08 9268af048ecbae67 899b9b877106c764; - 209a2833a39472d9720380ffb2f74761 af0062cd77a84ebd 26db40c151b74530; - 22ebe7a30e8855b3b453a6e926d4f187 f922ca875b991a31 2763f255636a34c1; - 1b5e23ebd915c1fee59f57dd91af7347 b4ecc305c3dbd8e5 fbbec8f5dbf4cefd; - 6c21d105515290da29339f142685c135 a4c2f6dc597d13ea 7409829de05ae6d1; - 01f728a7433a47b13de34fcc08958449 3af7f1ae0f58ab1d 950083fbd332a987; - 9a2d4c50337d3ec337673782fd385601 791d8da8cbb0bc94 13f87f8d3326553f; - b3b99747560e246bcd0cdc3fb33e4910 91778f2bd9233375 2b1f2747b356e119; - 4b269e2e8dbd68b94066c95244c3a195 abfb6a33e1471e96 8ce0dc718e757924; - d10b956f675dc2276b6dd90442bece3e dbedddb6a1c15a21 19df78dea26ea579; - 28f8fab7541766f6dafbaa5b6f3bd700 2c14d5097ab11f61 3a6fd0a5fef50079; - 2b61e60478fa0c0edb9531f26791eff9 b84c80b2d245fdfc f24ea37046b97a03; - a6bfb85fa91b8ca4197c8b502a62f972 3daadd7a9633e19b 4de5c07ea1564a64; - 94e76e54d37f932cbcc069de6bf26d52 02739eeb468450fd 0d4ef5d93f419069; - 82760ea1560e8f9d1e35f20cad1f26cc 34aa5952b5a9110f 7676f2746bfac3b7; - 3aba91211327585e0f1270b59ef9277b b584d6b34b638ba4 2cfa1f17178df25d; - 727074f35cd523eb6f8aafbbf76fd5b1 f0e9268a27ab70c6 609aee69ed6e2a8e; - 6e0aa1c91ea6315a4a7dd297ac5936a4 47374080f27fbb30 5d86f6451024e051; - 63bd2d37271a250c8593b433188cffd0 776927909196eec5 ec617cc3810e278c; - dc7beb423c2053156329d7ab79f4d1d6 24c0adb3777860ad 7f6f6083713a68ba; - ed219454883709efe884bbc9d30507a3 587b1683dff7f178 86a95a8f48fa13b0; - 40509fc5c565e9b9f3995f3bc5d5c1f4 719a39f2302a98aa 503f9481c7049890; - f9f10ed2bc0193605913475fd54d69ae e35b94e2940a8db0 59bc9b0bd5004dae; - 23003c3fbe9661b6b9386748982ac3e2 d1dfd47fac22b9ff 756ec1ac4fa8deac; - a2caa563c2f19b10fbac1427e2177858 f7743dfe957cc82b 57ae9c0144dbb9d3; - 8bb42b6937d65eac506e8326356071af 690a0fa32113bf34 5136052b310e7038; - 219c7f982a0c352977b978b91fcb3c45 8fb4cb86db41ce30 fa01561e5b9311ab; - 157ff76f22538eede0528c541dbe7815 ea6cd44f238be18f 0c3f632af5cee432; - 346194289f6d865237cc673c45415003 71690fd4ba3d75de c4448db8c1144435; - 032c8c1624f7f300d8a58d151de52d78 3c0f1746798ed5b7 e1bfbd2a7d414c8a; - 019471106a5cd4ee3d1f627213649b80 558a8d7a4cdc0822 c90e5257ea513ef8; - 45aa90191c449dbf9c541fb476d1bf74 bfba3dfd06e77671 bc715327ada1b56b; - c86c21d8c26dc291f662c8f2fe79b74b 0993d3b68c1d4a5d 2b4195c3d67e3f99; - af4f4615c7c298639b9728251991419f 1e268f9e710313b5 2536ccd8fdfe30e1; -} diff --git a/tiger-base.h b/tiger-base.h deleted file mode 100644 index 6b6a81e..0000000 --- a/tiger-base.h +++ /dev/null @@ -1,120 +0,0 @@ -/* -*-c-*- - * - * $Id: tiger-base.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Common definitions for the Tiger hash function - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_TIGER_BASE_H -#define CATACOMB_TIGER_BASE_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -/*----- Macros provided ---------------------------------------------------*/ - -/* --- The guts of a single round --- */ - -#define TIGER_ROUND(a, b, c, x, n, op) do { \ - kludge64 _t; \ - XOR64(c, c, x); \ - _t = s[0][U8(LO64(c) >> 0)]; \ - XOR64(_t, _t, s[1][U8(LO64(c) >> 16)]); \ - XOR64(_t, _t, s[2][U8(HI64(c) >> 0)]); \ - XOR64(_t, _t, s[3][U8(HI64(c) >> 16)]); \ - SUB64(a, a, _t); \ - _t = s[3][U8(LO64(c) >> 8)]; \ - XOR64(_t, _t, s[2][U8(LO64(c) >> 24)]); \ - XOR64(_t, _t, s[1][U8(HI64(c) >> 8)]); \ - XOR64(_t, _t, s[0][U8(HI64(c) >> 24)]); \ - ADD64(b, b, _t); \ - LSL64_(_t, b, n); \ - op##64(b, _t, b); \ -} while (0) - -/* --- One pass over the buffer --- */ - -#define TIGER_PASS(a, b, c, x, n, op) do { \ - TIGER_ROUND(a, b, c, x[0], n, op); \ - TIGER_ROUND(b, c, a, x[1], n, op); \ - TIGER_ROUND(c, a, b, x[2], n, op); \ - TIGER_ROUND(a, b, c, x[3], n, op); \ - TIGER_ROUND(b, c, a, x[4], n, op); \ - TIGER_ROUND(c, a, b, x[5], n, op); \ - TIGER_ROUND(a, b, c, x[6], n, op); \ - TIGER_ROUND(b, c, a, x[7], n, op); \ -} while (0) - -/* --- A step in the `key schedule' --- */ - -#define TIGER_KSTEP(a, b, c, d, op, n) do { \ - kludge64 _u; \ - XOR64(b, b, a); \ - ADD64(c, c, b); \ - CPL64(_u, b); op##64_(_u, _u, n); XOR64(_u, _u, c); SUB64(d, d, _u); \ -} while (0) - -/* --- The `key schedule' -- mangle the buffer --- */ - -#define TIGER_KSCHED(x) do { \ - kludge64 _t; \ - \ - SET64(_t, 0xa5a5a5a5, 0xa5a5a5a5); \ - XOR64(_t, _t, x[7]); SUB64(x[0], x[0], _t); \ - TIGER_KSTEP(x[0], x[1], x[2], x[3], LSL, 19); \ - TIGER_KSTEP(x[3], x[4], x[5], x[6], LSR, 23); \ - TIGER_KSTEP(x[6], x[7], x[0], x[1], LSL, 19); \ - TIGER_KSTEP(x[1], x[2], x[3], x[4], LSR, 23); \ - XOR64(x[5], x[5], x[4]); \ - ADD64(x[6], x[6], x[5]); \ - SET64(_t, 0x01234567, 0x89abcdef); \ - XOR64(_t, _t, x[6]); SUB64(x[7], x[7], _t); \ -} while (0) - -/* --- The Tiger compression function --- */ - -#define TIGER_CORE(a, b, c, x) do { \ - kludge64 _a, _b, _c; \ - _a = a, _b = b, _c = c; \ - TIGER_PASS(_a, _b, _c, x, 2, ADD); \ - TIGER_KSCHED(x); \ - TIGER_PASS(_c, _a, _b, x, 3, SUB); \ - TIGER_KSCHED(x); \ - TIGER_PASS(_b, _c, _a, x, 3, ADD); \ - XOR64(a, _a, a); SUB64(b, _b, b); ADD64(c, _c, c); \ -} while (0) - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/tiger-mktab.c b/tiger-mktab.c deleted file mode 100644 index 222c523..0000000 --- a/tiger-mktab.c +++ /dev/null @@ -1,153 +0,0 @@ -/* -*-c-*- - * - * $Id: tiger-mktab.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * Generate S-boxes for the Tiger hash function - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include -#include - -#include "tiger-base.h" - -/*----- Data structures ---------------------------------------------------*/ - -/*----- Static variables --------------------------------------------------*/ - -static kludge64 s[4][256]; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- The basic Tiger compression function --- */ - -static void tiger(kludge64 *x, kludge64 *ss) -{ - TIGER_CORE(ss[0], ss[1], ss[2], x); -} - -/* --- The S-box generator --- */ - -void gen(const char *buf, unsigned passes) -{ - kludge64 x[8], ss[3]; - unsigned i, j, k, b; - unsigned q, n; - uint32 t; - const char *p; - - for (i = 0; i < 256; i++) { - for (j = 0; j < 4; j++) { - uint32 z = 0x01010101 * i; - SET64(s[j][i], z, z); - } - } - - SET64(ss[0], 0x01234567, 0x89abcdef); - SET64(ss[1], 0xfedcba98, 0x76543210); - SET64(ss[2], 0xf096a5b4, 0xc3b2e187); - - q = 2; - for (i = 0; i < passes; i++) { - for (j = 0; j < 256; j++) { - for (k = 0; k < 4; k++) { - q++; - if (q == 3) { - q = 0; - for (p = buf, n = 0; n < 8; n++, p += 8) - LOAD64_L_(x[n], p); - tiger(x, ss); - } - for (b = 0; b < 32; b += 8) { - n = U8(LO64(ss[q]) >> b); - t = (LO64(s[k][j]) ^ LO64(s[k][n])) & (0xff << b); - SET64(s[k][j], HI64(s[k][j]), LO64(s[k][j]) ^ t); - SET64(s[k][n], HI64(s[k][n]), LO64(s[k][n]) ^ t); - } - for (b = 0; b < 32; b += 8) { - n = U8(HI64(ss[q]) >> b); - t = (HI64(s[k][j]) ^ HI64(s[k][n])) & (0xff << b); - SET64(s[k][j], HI64(s[k][j]) ^ t, LO64(s[k][j])); - SET64(s[k][n], HI64(s[k][n]) ^ t, LO64(s[k][n])); - } - } - } - } -} - -int main(void) -{ - unsigned i, j; - - gen("Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham", 5); - - fputs("\ -/* -*-c-*-\n\ - *\n\ - * S-boxes for Tiger [generated]\n\ - */\n\ -\n\ -#ifndef CATACOMB_TIGER_TAB_H\n\ -#define CATACOMB_TIGER_TAB_H\n\ -\n\ -#define TIGER_S { \\\n\ - { ", stdout); - - for (i = 0; i < 4; i++) { - for (j = 0; j < 256; j++) { -#ifdef HAVE_UINT64 - printf("{ 0x%016llxull }", s[i][j].i); -#else - printf("{ 0x%08lx, 0x%08lx }", - (unsigned long)s[i][j].hi, (unsigned long)s[i][j].lo); -#endif - if (j == 255) { - if (i == 3) - fputs(" } \\\n}\n", stdout); - else - fputs(" }, \\\n\ - \\\n\ - { ", stdout); - } else if (j % 2 == 1) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - } - - fputs("\n#endif\n", stdout); - - if (fclose(stdout)) { - fprintf(stderr, "error writing data\n"); - exit(EXIT_FAILURE); - } - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/tiger.c b/tiger.c deleted file mode 100644 index 87f3ca9..0000000 --- a/tiger.c +++ /dev/null @@ -1,175 +0,0 @@ -/* -*-c-*- - * - * $Id: tiger.c,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The Tiger hash function - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ghash-def.h" -#include "hash.h" -#include "tiger.h" -#include "tiger-tab.h" -#include "tiger-base.h" - -/*----- S-boxes -----------------------------------------------------------*/ - -static const kludge64 s[4][256] = TIGER_S; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @tiger_compress@ --- * - * - * Arguments: @tiger_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: Tiger compression function. - */ - -void tiger_compress(tiger_ctx *ctx, const void *sbuf) -{ - kludge64 x[8]; - int i; - const octet *p; - for (i = 0, p = sbuf; i < 8; i++, p += 8) - LOAD64_L_(x[i], p); - TIGER_CORE(ctx->a, ctx->b, ctx->c, x); -} - -/* --- @tiger_init@ --- * - * - * Arguments: @tiger_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void tiger_init(tiger_ctx *ctx) -{ - SET64(ctx->a, 0x01234567, 0x89abcdef); - SET64(ctx->b, 0xfedcba98, 0x76543210); - SET64(ctx->c, 0xf096a5b4, 0xc3b2e187); - ctx->off = 0; - ctx->nl = ctx->nh = 0; -} - -/* --- @tiger_set@ --- * - * - * Arguments: @tiger_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -void tiger_set(tiger_ctx *ctx, const void *buf, unsigned long count) -{ - const octet *p = buf; - LOAD64_L_(ctx->a, p + 0); - LOAD64_L_(ctx->b, p + 8); - LOAD64_L_(ctx->c, p + 16); - ctx->off = 0; - ctx->nl = U32(count); - ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); -} - -/* --- @tiger_hash@ --- * - * - * Arguments: @tiger_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void tiger_hash(tiger_ctx *ctx, const void *buf, size_t sz) -{ - HASH_BUFFER(TIGER, tiger, ctx, buf, sz); -} - -/* --- @tiger_done@ --- * - * - * Arguments: @tiger_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -void tiger_done(tiger_ctx *ctx, void *hash) -{ - octet *p = hash; - HASH_PAD(TIGER, tiger, ctx, 0x01u, 0, 8); - STORE32_L(ctx->buf + TIGER_BUFSZ - 8, ctx->nl << 3); - STORE32_L(ctx->buf + TIGER_BUFSZ - 4, (ctx->nl >> 29) | (ctx->nh << 3)); - tiger_compress(ctx, ctx->buf); - STORE64_L_(p + 0, ctx->a); - STORE64_L_(p + 8, ctx->b); - STORE64_L_(p + 16, ctx->c); -} - -/* --- @tiger_state@ --- * - * - * Arguments: @tiger_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @tiger_set@. - */ - -unsigned long tiger_state(tiger_ctx *ctx, void *state) -{ - octet *p = state; - STORE64_L_(p + 0, ctx->a); - STORE64_L_(p + 8, ctx->b); - STORE64_L_(p + 16, ctx->c); - return (ctx->nl | ((ctx->nh << 16) << 16)); -} - -/* --- Generic interface --- */ - -GHASH_DEF(TIGER, tiger) - -/* --- Test code --- */ - -HASH_TEST(TIGER, tiger) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/tiger.h b/tiger.h deleted file mode 100644 index 78e83f2..0000000 --- a/tiger.h +++ /dev/null @@ -1,160 +0,0 @@ -/* -*-c-*- - * - * $Id: tiger.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The Tiger hash function - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the Tiger hash function ----------------------------------* - * - * Tiger was designed by Eli Biham and Ross Anderson to be an efficient and - * secure hash function which worked well on 64-bit processors. This - * implementation should work everywhere, but it'll be faster if real 64-bit - * arithmetic is available. - * - * I don't know of any really good analysis of Tiger. - */ - -#ifndef CATACOMB_TIGER_H -#define CATACOMB_TIGER_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define TIGER_BUFSZ 64 -#define TIGER_HASHSZ 24 -#define TIGER_STATESZ 24 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct tiger_ctx { - kludge64 a, b, c; /* Chaining variables */ - uint32 nl, nh; /* Byte count so far */ - unsigned off; /* Offset into buffer */ - octet buf[TIGER_BUFSZ]; /* Accumulation buffer */ -} tiger_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @tiger_compress@ --- * - * - * Arguments: @tiger_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: Tiger compression function. - */ - -extern void tiger_compress(tiger_ctx */*ctx*/, const void */*sbuf*/); - -/* --- @tiger_init@ --- * - * - * Arguments: @tiger_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -extern void tiger_init(tiger_ctx */*ctx*/); - -/* --- @tiger_set@ --- * - * - * Arguments: @tiger_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -extern void tiger_set(tiger_ctx */*ctx*/, const void */*buf*/, - unsigned long /*count*/); - -/* --- @tiger_hash@ --- * - * - * Arguments: @tiger_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -extern void tiger_hash(tiger_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/); - -/* --- @tiger_done@ --- * - * - * Arguments: @tiger_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -extern void tiger_done(tiger_ctx */*ctx*/, void */*hash*/); - -/* --- @tiger_state@ --- * - * - * Arguments: @tiger_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @tiger_set@. - */ - -extern unsigned long tiger_state(tiger_ctx */*ctx*/, void */*state*/); - -/*----- Generic hash interface --------------------------------------------*/ - -extern const gchash tiger; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/tlsprf.c b/tlsprf.c deleted file mode 100644 index 04c4c25..0000000 --- a/tlsprf.c +++ /dev/null @@ -1,542 +0,0 @@ -/* -*-c-*- - * - * $Id: tlsprf.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The TLS pseudo-random function - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include "arena.h" -#include "gmac.h" -#include "grand.h" -#include "paranoia.h" -#include "tlsprf.h" - -/*----- The data expansion function ---------------------------------------*/ - -/* --- @tlsdx_init@ --- * - * - * Arguments: @tlsdx_ctx *c@ = pointer to a context - * @gmac *m@ = pointer to a generic MAC instance - * @const void *sd@ = pointer to the seed block - * @size_t sdsz@ = size of the seed block - * - * Returns: --- - * - * Use: Initializes a context for the TLS data expansion function. - * This doesn't take ownership of the MAC instance or the seed - * memory, nor does it allocate copies. - */ - -void tlsdx_init(tlsdx_ctx *c, gmac *m, const void *sd, size_t sdsz) -{ - c->k = m; - c->hashsz = GM_CLASS(c->k)->hashsz; - c->sd = sd; c->sdsz = sdsz; - - c->i = GM_INIT(c->k); - GH_HASH(c->i, sd, sdsz); - c->ai = GH_DONE(c->i, 0); - c->o = GM_INIT(c->k); - GH_HASH(c->o, c->ai, c->hashsz); - GH_HASH(c->o, sd, sdsz); - c->p = GH_DONE(c->o, 0); - c->sz = c->hashsz; -} - -/* --- @tlsdx_encrypt@ --- * - * - * Arguments: @tlsdx_ctx *c@ = pointer to a context - * @const void *src@ = pointer to source data - * @void *dest@ = pointer to destination buffer - * @size_t sz@ = size of buffer - * - * Returns: --- - * - * Use: Encrypts data using the TLS data expansion function. If the - * destination pointer is null, the generator is spun and no - * output is produced; if the source pointer is null, raw output - * from the generator is written; otherwise, the source data is - * XORed with the generator output. - */ - -void tlsdx_encrypt(tlsdx_ctx *c, const void *src, void *dest, size_t sz) -{ - const octet *s = src; - octet *d = dest; - ghash *h; - size_t i; - size_t n; - - while (sz) { - if (c->sz) - n = c->sz; - else { - h = GM_INIT(c->k); - GH_HASH(h, c->ai, c->hashsz); - c->ai = GH_DONE(h, 0); - GH_DESTROY(c->i); - c->i = h; - GH_DESTROY(c->o); - h = c->o = GM_INIT(c->k); - GH_HASH(h, c->ai, c->hashsz); - GH_HASH(h, c->sd, c->sdsz); - c->p = GH_DONE(h, 0); - c->sz = n = c->hashsz; - } - if (n > sz) - n = sz; - if (d) { - if (!s) - memcpy(d, c->p, n); - else { - for (i = 0; i < n; i++) d[i] = s[i] ^ c->p[i]; - s += n; - } - d += n; - } - c->p += n; - c->sz -= n; - sz -= n; - } -} - -/* --- @tlsdx_free@ --- * - * - * Arguments: @tlsdx_ctx *c@ = pointer to the context block - * - * Returns: --- - * - * Use: Frees a context for the TLS data expansion function - */ - -void tlsdx_free(tlsdx_ctx *c) -{ - GH_DESTROY(c->i); - GH_DESTROY(c->o); -} - -/* --- Generic random number generator --- */ - -typedef struct dx_grctx { - grand r; - grand_ops ops; - tlsdx_ctx dx; -} dx_grctx; - -static void dx_grdestroy(grand *r) -{ - dx_grctx *g = (dx_grctx *)r; - xfree((char *)g->ops.name); - xfree((octet *)g->dx.sd); - g->dx.k->ops->destroy(g->dx.k); - tlsdx_free(&g->dx); - BURN(*g); - S_DESTROY(g); -} - -static void dx_seed(dx_grctx *g, const void *p, size_t sz) -{ - octet *q; - xfree((octet *)g->dx.sd); - g->dx.sd = q = xmalloc(sz); - memcpy(q, p, sz); - g->dx.sdsz = sz; -} - -static int dx_grmisc(grand *r, unsigned op, ...) -{ - dx_grctx *g = (dx_grctx *)r; - va_list ap; - int rc = 0; - uint32 i; - octet buf[4]; - va_start(ap, op); - - switch (op) { - case GRAND_CHECK: - switch (va_arg(ap, unsigned)) { - case GRAND_CHECK: - case GRAND_SEEDINT: - case GRAND_SEEDUINT32: - case GRAND_SEEDBLOCK: - case GRAND_SEEDRAND: - rc = 1; - break; - default: - rc = 0; - break; - } - break; - case GRAND_SEEDINT: - i = va_arg(ap, unsigned); - STORE32(buf, i); - dx_seed(g, buf, sizeof(buf)); - break; - case GRAND_SEEDUINT32: - i = va_arg(ap, uint32); - STORE32(buf, i); - dx_seed(g, buf, sizeof(buf)); - break; - case GRAND_SEEDBLOCK: { - const void *p = va_arg(ap, const void *); - size_t sz = va_arg(ap, size_t); - dx_seed(g, p, sz); - } break; - case GRAND_SEEDRAND: { - grand *rr = va_arg(ap, grand *); - octet buf[16]; - rr->ops->fill(rr, buf, sizeof(buf)); - dx_seed(g, buf, sizeof(buf)); - } break; - default: - GRAND_BADOP; - break; - } - - va_end(ap); - return (rc); -} - -static octet dx_grbyte(grand *r) -{ - dx_grctx *g = (dx_grctx *)r; - octet o; - tlsdx_encrypt(&g->dx, 0, &o, 1); - return (o); -} - -static uint32 dx_grword(grand *r) -{ - dx_grctx *g = (dx_grctx *)r; - octet b[4]; - tlsdx_encrypt(&g->dx, 0, &b, sizeof(b)); - return (LOAD32(b)); -} - -static void dx_grfill(grand *r, void *p, size_t sz) -{ - dx_grctx *g = (dx_grctx *)r; - tlsdx_encrypt(&g->dx, 0, p, sz); -} - -static const grand_ops dx_grops = { - "", - GRAND_CRYPTO, 0, - dx_grmisc, dx_grdestroy, - dx_grword, dx_grbyte, dx_grword, grand_range, dx_grfill -}; - -/* ---@tlsdx_rand@ --- * - * - * Arguments: @const gcmac *mc@ = MAC function to use - * @const void *k@ = pointer to the key material - * @size_t ksz@ = size of the key material - * @const void *sd@ = pointer to the seed material - * @size_t sdsz@ = size of the seed material - * - * Returns: Pointer to generic random number generator interface. - * - * Use: Creates a generic generator which does TLS data expansion. - */ - -grand *tlsdx_rand(const gcmac *mc, const void *k, size_t ksz, - const void *sd, size_t sdsz) -{ - dx_grctx *g = S_CREATE(dx_grctx); - dstr d = DSTR_INIT; - gmac *m = GM_KEY(mc, k, ksz); - octet *q = xmalloc(sdsz); - memcpy(q, sd, sdsz); - dstr_putf(&d, "tlsdx(%s)", mc->name); - g->ops = dx_grops; - g->ops.name = xstrdup(d.buf); - g->r.ops = &g->ops; - dstr_destroy(&d); - tlsdx_init(&g->dx, m, q, sdsz); - return (&g->r); -} - -/* --- The actual very paranoid PRF ---------------------------------------*/ - -/* --- @tlsprf_init@ --- * - * - * Arguments: @tlsprf_ctx *c@ = pointer to context block - * @const gcmac *mcx, *mcy@ = left and right MAC functions - * @const void *k@ = pointer to the key material - * @size_t ksz@ = size of the key material - * @const void *sd@ = pointer to the seed material - * @size_t sdsz@ = size of the seed material - * - * Returns: --- - * - * Use: Initializes a TLS PRF context. - */ - -void tlsprf_init(tlsprf_ctx *c, const gcmac *mcx, const gcmac *mcy, - const void *k, size_t ksz, const void *sd, size_t sdsz) -{ - size_t n = (ksz + 1)/2; - const octet *kk = k; - tlsdx_init(&c->px, mcx->key(kk, n), sd, sdsz); - tlsdx_init(&c->py, mcy->key(kk + ksz - n, n), sd, sdsz); -} - -/* --- @tlsprf_encrypt@ --- * - * - * Arguments: @tlsprf_ctx *c@ = pointer to a context - * @const void *src@ = pointer to source data - * @void *dest@ = pointer to destination buffer - * @size_t sz@ = size of buffer - * - * Returns: --- - * - * Use: Encrypts data using the TLS pseudo-random function. If the - * destination pointer is null, the generator is spun and no - * output is produced; if the source pointer is null, raw output - * from the generator is written; otherwise, the source data is - * XORed with the generator output. - */ - -void tlsprf_encrypt(tlsprf_ctx *c, const void *src, void *dest, size_t sz) -{ - tlsdx_encrypt(&c->px, src, dest, sz); - tlsdx_encrypt(&c->py, dest, dest, sz); -} - -/* --- @tlsprf_free@ --- * - * - * Arguments: @tlsprf_ctx *c@ = pointer to a context - * - * Returns: --- - * - * Use: Frees a TLS PRF context. - */ - -void tlsprf_free(tlsprf_ctx *c) -{ - c->px.k->ops->destroy(c->px.k); - c->py.k->ops->destroy(c->py.k); - tlsdx_free(&c->px); - tlsdx_free(&c->py); -} - -/* --- Generic random number generator --- */ - -typedef struct prf_grctx { - grand r; - grand_ops ops; - tlsprf_ctx prf; -} prf_grctx; - -static void prf_grdestroy(grand *r) -{ - prf_grctx *g = (prf_grctx *)r; - xfree((char *)g->ops.name); - xfree((octet *)g->prf.px.sd); - tlsprf_free(&g->prf); - BURN(*g); - S_DESTROY(g); -} - -static void prf_seed(prf_grctx *g, const void *p, size_t sz) -{ - octet *q; - - xfree((octet *)g->prf.px.sz); - g->prf.px.sd = g->prf.py.sd = q = xmalloc(sz); - memcpy(q, p, sz); - g->prf.px.sdsz = g->prf.py.sdsz = sz; -} - -static int prf_grmisc(grand *r, unsigned op, ...) -{ - prf_grctx *g = (prf_grctx *)r; - va_list ap; - int rc = 0; - uint32 i; - octet buf[4]; - va_start(ap, op); - - switch (op) { - case GRAND_CHECK: - switch (va_arg(ap, unsigned)) { - case GRAND_CHECK: - case GRAND_SEEDINT: - case GRAND_SEEDUINT32: - case GRAND_SEEDBLOCK: - case GRAND_SEEDRAND: - rc = 1; - break; - default: - rc = 0; - break; - } - break; - case GRAND_SEEDINT: - i = va_arg(ap, unsigned); - STORE32(buf, i); - prf_seed(g, buf, sizeof(buf)); - break; - case GRAND_SEEDUINT32: - i = va_arg(ap, uint32); - STORE32(buf, i); - prf_seed(g, buf, sizeof(buf)); - break; - case GRAND_SEEDBLOCK: { - const void *p = va_arg(ap, const void *); - size_t sz = va_arg(ap, size_t); - prf_seed(g, p, sz); - } break; - case GRAND_SEEDRAND: { - grand *rr = va_arg(ap, grand *); - octet buf[16]; - rr->ops->fill(rr, buf, sizeof(buf)); - prf_seed(g, buf, sizeof(buf)); - } break; - default: - GRAND_BADOP; - break; - } - - va_end(ap); - return (rc); -} - -static octet prf_grbyte(grand *r) -{ - prf_grctx *g = (prf_grctx *)r; - octet o; - tlsprf_encrypt(&g->prf, 0, &o, 1); - return (o); -} - -static uint32 prf_grword(grand *r) -{ - prf_grctx *g = (prf_grctx *)r; - octet b[4]; - tlsprf_encrypt(&g->prf, 0, &b, sizeof(b)); - return (LOAD32(b)); -} - -static void prf_grfill(grand *r, void *p, size_t sz) -{ - prf_grctx *g = (prf_grctx *)r; - tlsprf_encrypt(&g->prf, 0, p, sz); -} - -static const grand_ops prf_grops = { - "", - GRAND_CRYPTO, 0, - prf_grmisc, prf_grdestroy, - prf_grword, prf_grbyte, prf_grword, grand_range, prf_grfill -}; - -/* ---@tlsprf_rand@ --- * - * - * Arguments: @const gcmac *mcx, *mcy@ = MAC function to use - * @const void *k@ = pointer to the key material - * @size_t ksz@ = size of the key material - * @const void *sd@ = pointer to the seed material - * @size_t sdsz@ = size of the seed material - * - * Returns: Pointer to generic random number generator interface. - * - * Use: Creates a generic generator which does TLS data expansion. - */ - -grand *tlsprf_rand(const gcmac *mcx, const gcmac *mcy, - const void *k, size_t ksz, const void *sd, size_t sdsz) -{ - prf_grctx *g = S_CREATE(prf_grctx); - dstr d = DSTR_INIT; - octet *q = xmalloc(sdsz); - memcpy(q, sd, sdsz); - dstr_putf(&d, "tlsprf(%s,%s)", mcx->name, mcy->name); - g->ops = prf_grops; - g->ops.name = xstrdup(d.buf); - g->r.ops = &g->ops; - dstr_destroy(&d); - tlsprf_init(&g->prf, mcx, mcy, k, ksz, q, sdsz); - return (&g->r); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include -#include - -#include -#include - -#include "sha-hmac.h" -#include "md5-hmac.h" - -static int v_generate(dstr *v) -{ - grand *g; - dstr d = DSTR_INIT; - int ok = 1; - - g = tlsprf_rand(&md5_hmac, &sha_hmac, - v[0].buf, v[0].len, v[1].buf, v[1].len); - dstr_ensure(&d, v[2].len); - d.len = v[2].len; - g->ops->fill(g, d.buf, d.len); - g->ops->destroy(g); - if (memcmp(v[2].buf, d.buf, d.len) != 0) { - ok = 0; - printf("\nfail tlsprf:" - "\n\tkey = "); - type_hex.dump(&v[0], stdout); - printf("\n\tseed = "); type_hex.dump(&v[1], stdout); - printf("\n\texpected = "); type_hex.dump(&v[2], stdout); - printf("\n\tcalculated = "); type_hex.dump(&d, stdout); - putchar('\n'); - } - return (ok); -} - -static test_chunk defs[] = { - { "tlsprf", v_generate, { &type_hex, &type_hex, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, defs, SRCDIR"/tests/tlsprf"); - return (0); -} - -#endif - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/tlsprf.h b/tlsprf.h deleted file mode 100644 index 0a702b5..0000000 --- a/tlsprf.h +++ /dev/null @@ -1,205 +0,0 @@ -/* -*-c-*- - * - * $Id: tlsprf.h,v 1.2 2004/04/08 01:36:15 mdw Exp $ - * - * The TLS pseudo-random function - * - * (c) 2001 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_TLSPRF_H -#define CATACOMB_TLSPRF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#ifndef CATACOMB_GMAC_H -# include "gmac.h" -#endif - -#ifndef CATACOMB_GRAND_H -# include "grand.h" -#endif - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct tlsdx_ctx { - gmac *k; /* The MAC key to use */ - size_t hashsz; /* Size of hash outputs */ - ghash *i, *o; /* Inner and outer hash contexts */ - const octet *sd; /* Pointer to seed buffer */ - size_t sdsz; /* Size of the seed buffer */ - octet *p; /* Pointer to buffered output */ - size_t sz; /* Bytes remaining in buffer */ - octet *ai; /* Pointer to inner result */ -} tlsdx_ctx; - -typedef struct tlsprf_ctx { - tlsdx_ctx px, py; -} tlsprf_ctx; - -/*----- The data expansion function ---------------------------------------*/ - -/* --- @tlsdx_init@ --- * - * - * Arguments: @tlsdx_ctx *c@ = pointer to a context - * @gmac *m@ = pointer to a generic MAC instance - * @const void *sd@ = pointer to the seed block - * @size_t sdsz@ = size of the seed block - * - * Returns: --- - * - * Use: Initializes a context for the TLS data expansion function. - * This doesn't take ownership of the MAC instance or the seed - * memory, nor does it allocate copies. - */ - -extern void tlsdx_init(tlsdx_ctx */*c*/, gmac */*m*/, - const void */*sd*/, size_t /*sdsz*/); - -/* --- @tlsdx_encrypt@ --- * - * - * Arguments: @tlsdx_ctx *c@ = pointer to a context - * @const void *src@ = pointer to source data - * @void *dest@ = pointer to destination buffer - * @size_t sz@ = size of buffer - * - * Returns: --- - * - * Use: Encrypts data using the TLS data expansion function. If the - * destination pointer is null, the generator is spun and no - * output is produced; if the source pointer is null, raw output - * from the generator is written; otherwise, the source data is - * XORed with the generator output. - */ - -extern void tlsdx_encrypt(tlsdx_ctx */*c*/, const void */*src*/, - void */*dest*/, size_t /*sz*/); - -/* --- @tlsdx_free@ --- * - * - * Arguments: @tlsdx_ctx *c@ = pointer to the context block - * - * Returns: --- - * - * Use: Frees a context for the TLS data expansion function - */ - -extern void tlsdx_free(tlsdx_ctx */*c*/); - -/* ---@tlsdx_rand@ --- * - * - * Arguments: @const gcmac *mc@ = MAC function to use - * @const void *k@ = pointer to the key material - * @size_t ksz@ = size of the key material - * @const void *sd@ = pointer to the seed material - * @size_t sdsz@ = size of the seed material - * - * Returns: Pointer to generic random number generator interface. - * - * Use: Creates a generic generator which does TLS data expansion. - */ - -extern grand *tlsdx_rand(const gcmac */*mc*/, - const void */*k*/, size_t /*ksz*/, - const void */*sd*/, size_t /*sdsz*/); - -/* --- The actual very paranoid PRF ---------------------------------------*/ - -/* --- @tlsprf_init@ --- * - * - * Arguments: @tlsprf_ctx *c@ = pointer to context block - * @const gcmac *mcx, *mcy@ = left and right MAC functions - * @const void *k@ = pointer to the key material - * @size_t ksz@ = size of the key material - * @const void *sd@ = pointer to the seed material - * @size_t sdsz@ = size of the seed material - * - * Returns: --- - * - * Use: Initializes a TLS PRF context. - */ - -extern void tlsprf_init(tlsprf_ctx */*c*/, - const gcmac */*mcx*/, const gcmac */*mcy*/, - const void */*k*/, size_t /*ksz*/, - const void */*sd*/, size_t /*sdsz*/); - -/* --- @tlsprf_encrypt@ --- * - * - * Arguments: @tlsprf_ctx *c@ = pointer to a context - * @const void *src@ = pointer to source data - * @void *dest@ = pointer to destination buffer - * @size_t sz@ = size of buffer - * - * Returns: --- - * - * Use: Encrypts data using the TLS pseudo-random function. If the - * destination pointer is null, the generator is spun and no - * output is produced; if the source pointer is null, raw output - * from the generator is written; otherwise, the source data is - * XORed with the generator output. - */ - -extern void tlsprf_encrypt(tlsprf_ctx */*c*/, - const void */*src*/, void */*dest*/, - size_t /*sz*/); - -/* --- @tlsprf_free@ --- * - * - * Arguments: @tlsprf_ctx *c@ = pointer to a context - * - * Returns: --- - * - * Use: Frees a TLS PRF context. - */ - -extern void tlsprf_free(tlsprf_ctx */*c*/); - -/* ---@tlsprf_rand@ --- * - * - * Arguments: @const gcmac *mcx, *mcy@ = MAC function to use - * @const void *k@ = pointer to the key material - * @size_t ksz@ = size of the key material - * @const void *sd@ = pointer to the seed material - * @size_t sdsz@ = size of the seed material - * - * Returns: Pointer to generic random number generator interface. - * - * Use: Creates a generic generator which does TLS data expansion. - */ - -extern grand *tlsprf_rand(const gcmac */*mcx*/, const gcmac */*mcy*/, - const void */*k*/, size_t /*ksz*/, - const void */*sd*/, size_t /*sdsz*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/twofish-mktab.c b/twofish-mktab.c deleted file mode 100644 index 1a31463..0000000 --- a/twofish-mktab.c +++ /dev/null @@ -1,413 +0,0 @@ -/* -*-c-*- - * - * $Id: twofish-mktab.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Build constant tables for Twofish - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include - -#include - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct { octet t[4][16]; } t_tab; -typedef struct { octet q[256]; } q_tab; - -/*----- Various Twofish tables --------------------------------------------*/ - -/* --- The t-tables --- */ - -static const t_tab qt0 = {{ - { 0x8, 0x1, 0x7, 0xd, 0x6, 0xf, 0x3, 0x2, - 0x0, 0xb, 0x5, 0x9, 0xe, 0xc, 0xa, 0x4 }, - { 0xe, 0xc, 0xb, 0x8, 0x1, 0x2, 0x3, 0x5, - 0xf, 0x4, 0xa, 0x6, 0x7, 0x0, 0x9, 0xd }, - { 0xb, 0xa, 0x5, 0xe, 0x6, 0xd, 0x9, 0x0, - 0xc, 0x8, 0xf, 0x3, 0x2, 0x4, 0x7, 0x1 }, - { 0xd, 0x7, 0xf, 0x4, 0x1, 0x2, 0x6, 0xe, - 0x9, 0xb, 0x3, 0x0, 0x8, 0x5, 0xc, 0xa } -}}; - -static const t_tab qt1 = {{ - { 0x2, 0x8, 0xb, 0xd, 0xf, 0x7, 0x6, 0xe, - 0x3, 0x1, 0x9, 0x4, 0x0, 0xa, 0xc, 0x5 }, - { 0x1, 0xe, 0x2, 0xb, 0x4, 0xc, 0x3, 0x7, - 0x6, 0xd, 0xa, 0x5, 0xf, 0x9, 0x0, 0x8 }, - { 0x4, 0xc, 0x7, 0x5, 0x1, 0x6, 0x9, 0xa, - 0x0, 0xe, 0xd, 0x8, 0x2, 0xb, 0x3, 0xf }, - { 0xb, 0x9, 0x5, 0x1, 0xc, 0x3, 0xd, 0xe, - 0x6, 0x4, 0x7, 0xf, 0x2, 0x0, 0x8, 0xa } -}}; - -static q_tab q0, q1; - -/* --- The MDS and Reed-Solomon matrices --- */ - -static const octet mds[16] = { - 0x01, 0xef, 0x5b, 0x5b, - 0x5b, 0xef, 0xef, 0x01, - 0xef, 0x5b, 0x01, 0xef, - 0xef, 0x01, 0xef, 0x5b -}; - -static const octet rs[32] = { - 0x01, 0xa4, 0x55, 0x87, 0x5a, 0x58, 0xdb, 0x9e, - 0xa4, 0x56, 0x82, 0xf3, 0x1e, 0xc6, 0x68, 0xe5, - 0x02, 0xa1, 0xfc, 0xc1, 0x47, 0xae, 0x3d, 0x19, - 0xa4, 0x55, 0x87, 0x5a, 0x58, 0xdb, 0x9e, 0x03 -}; - -/*----- Magic macros ------------------------------------------------------*/ - -#define ROR4(x) ((((x) >> 1) | ((x) << 3)) & 15) - -/*----- Building and printing @q@ tables ----------------------------------*/ - -/* --- @mkq@ --- * - * - * Arguments: @q_tab *q@ = pointer to output @q@ table - * @const t_tab *t@ = pointer to input @t@ table - * @const char *name@ = name of @q@ table - * - * Returns: --- - * - * Use: Constructs a 256-entry @q@-table. - */ - -static void mkq(q_tab *q, const t_tab *t, const char *name) -{ - int i; - int ok = 1; - - /* --- Ensure the t-table is well-formed --- */ - - for (i = 0; i < 4; i++) { - octet f[16] = { 0 }; - int j; - - for (j = 0; j < 16; j++) { - if (f[t->t[i][j]]) { - fprintf(stderr, "duplicate %i in %s[%i] (col %i and %i)\n", - t->t[i][j], name, i, j, f[t->t[i][j]]); - ok = 0; - } - f[t->t[i][j]] = j; - } - } - - if (!ok) - exit(EXIT_FAILURE); - - /* --- Construct the @q@ table --- */ - - for (i = 0; i < 256; i++) { - int a = i >> 4, b = i & 15; - int aa = t->t[0][a ^ b], bb = t->t[1][a ^ ((a << 3) & 15) ^ ROR4(b)]; - a = t->t[2][aa ^ bb], b = t->t[3][aa ^ ((aa << 3) & 15) ^ ROR4(bb)]; - q->q[i] = a | (b << 4); - } - - /* Consider testing @q@ for linear and differential properties here */ -} - -/* --- @printq@ --- * - * - * Arguments: @const q_tab *t@ = pointer to table - * @const char *name@ = pointer to table name - * - * Returns: --- - * - * Use: Prints a q table. - */ - -static void printq(const q_tab *q, const char *name) -{ - int i; - int j; - - printf("\ -#define TWOFISH_%s { \\\n\ - ", name); - j = 0; - for (i = 0; i < 256; i++) { - printf("0x%02x", q->q[i]); - j = (j + 1) & 7; - if (i == 255) - fputs(" \\\n}\n\n", stdout); - else if (j == 0) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } -} - -/*----- %$\gf{2^8}$% arithmetic -------------------------------------------*/ - -#define MDS_MOD 0x169 -#define RS_MOD 0x14d - -/* --- @mul@ --- * - * - * Arguments: @unsigned x, y@ = polynomials over %$\gf{2^8}$% - * @unsigned m@ = modulus - * - * Returns: The product of two polynomials. - * - * Use: Computes a product of polynomials, quite slowly. - */ - -static unsigned mul(unsigned x, unsigned y, unsigned m) -{ - unsigned a = 0; - unsigned i; - - for (i = 0; i < 8; i++) { - if (y & 1) - a ^= x; - y >>= 1; - x <<= 1; - if (x & 0x100) - x ^= m; - } - - return (a); -} - -/* --- @mmul@ --- * - * - * Arguments: @octet *d@ = destination vector - * @const octet *p@ = matrix of bytes - * @const octet *q@ = vector from somewhere else - * @size_t r@ = size of destination or number of rows in matrix - * @size_t n@ = length of row and vector - * @unsigned m@ = modulus polynomial - * - * Returns: --- - * - * Use: Computes an inner product of matrices over the finite field - * %$\gf{2^8}[x]/(m(x))$%. This isn't particularly rapid. - */ - -static void mmul(octet *d, const octet *p, const octet *q, - size_t r, size_t n, unsigned m) -{ - while (r) { - const octet *qq = q; - unsigned a = 0; - unsigned i; - - for (i = 0; i < n; i++) - a ^= mul(*p++, *qq++, m); - *d++ = a; - r--; - } -} - -/* --- @qrds@ --- * - * - * Arguments: --- - * - * Returns: --- - * - * Use: Prints the MDS/q table. - */ - -static void qmds(void) -{ - uint32 t[4][256]; - int i, j; - static const q_tab *q[4] = { &q1, &q0, &q1, &q0 }; - - for (i = 0; i < 4; i++) { - octet in[4] = { 0, 0, 0, 0 }; - octet out[4]; - - for (j = 0; j < 256; j++) { - in[i] = q[i]->q[j]; - mmul(out, mds, in, 4, 4, MDS_MOD); - t[i][j] = LOAD32_L(out); - } - } - - puts("\ -/* --- Expanded MDS tables --- *\n\ - *\n\ - * The table contains output vectors for computing the result of pushing\n\ - * bytes through appropriate @q@ tables and the MDS matrix.\n\ - */\n\ -\n\ -#define TWOFISH_QMDS { \\"); - for (i = 0; i < 4; i++) { - fputs(" { ", stdout); - for (j = 0; j < 256; j++) { - printf("0x%08lx", (unsigned long)t[i][j]); - if (j == 255) { - if (i == 3) - puts(" } \\\n}"); - else - puts(" }, \\\n\ - \\"); - } else if (j % 4 == 3) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - } - - putchar('\n'); -} - -/* --- @rslog@ --- * - * - * Arguments: --- - * - * Returns: --- - * - * Use: Produces the log and antilog tables for doing the RS - * arithmetic efficiently. - */ - -static void rslog(void) -{ - octet rslog[256]; - octet rsexp[256]; - - unsigned x = 1; - unsigned i; - - rslog[0] = 0; - for (i = 0; i < 255; i++) { - rslog[x] = i; - rsexp[i] = x; - x <<= 1; - if (x & 0x100) - x ^= RS_MOD; - } - - x = 0; - for (i = 0; i < 32; i++) { - if (rslog[rs[i]] > x) - x = rslog[rs[i]]; - } - - fputs("\ -/* --- Reed-Solomon log tables --- *\n\ - *\n\ - * The Reed-Solomon multiplies are accelerated by using log tables.\n\ - */\n\ -\n\ -#define TWOFISH_RSLOG { \\\n\ - ", stdout); - - for (i = 0; i < 256; i++) { - printf("0x%02x", rslog[i]); - if (i == 255) - puts(" \\\n}\n"); - else if (i % 8 == 7) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - fputs("\ -#define TWOFISH_RSEXP { \\\n\ - ", stdout); - - for (i = 0; i < 255 + x + 1; i++) { - printf("0x%02x", rsexp[i % 255]); - if (i == 255 + x) - puts(" \\\n}\n"); - else if (i % 8 == 7) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - fputs("\ -/* --- Reed-Solomon matrix with log entries --- */\n\ -\n\ -#define TWOFISH_RS { \\\n\ - ", stdout); - - for (i = 0; i < 32; i++) { - printf("0x%02x", rslog[rs[i]]); - if (i == 31) - puts(" \\\n}\n"); - else if (i % 8 == 7) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } -} - -/*----- Main program ------------------------------------------------------*/ - -/* --- @main@ --- */ - -int main(void) -{ - fputs("\ -/* -*-c-*-\n\ - *\n\ - * Twofish q tables [generated]\n\ - */\n\ -\n\ -#ifndef CATACOMB_TWOFISH_TAB_H\n\ -#define CATACOMB_TWOFISH_TAB_H\n\ -\n\ -", stdout); - - /* --- The q tables --- */ - - puts("\ -/* --- Precomputed @q@ tables --- */\n\ -"); - mkq(&q0, &qt0, "qt0"); - mkq(&q1, &qt1, "qt1"); - printq(&q0, "Q0"); - printq(&q1, "Q1"); - - /* --- The MDS/q tables --- */ - - qmds(); - rslog(); - - /* --- Done --- */ - - puts("#endif"); - - if (fclose(stdout)) { - fprintf(stderr, "error writing data\n"); - exit(EXIT_FAILURE); - } - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/twofish.c b/twofish.c deleted file mode 100644 index ad4882f..0000000 --- a/twofish.c +++ /dev/null @@ -1,429 +0,0 @@ -/* -*-c-*- - * - * $Id: twofish.c,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * Implementation of the Twofish cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "twofish.h" -#include "twofish-tab.h" -#include "paranoia.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet twofish_keysz[] = { KSZ_RANGE, TWOFISH_KEYSZ, 0, 32, 1 }; - -/*----- Important tables --------------------------------------------------*/ - -static const octet q0[256] = TWOFISH_Q0, q1[256] = TWOFISH_Q1; -static const uint32 qmds[4][256] = TWOFISH_QMDS; -static const octet rslog[] = TWOFISH_RSLOG, rsexp[] = TWOFISH_RSEXP; -static const octet rs[32] = TWOFISH_RS; - -/*----- Key initialization ------------------------------------------------*/ - -/* --- @h@ --- * - * - * Arguments: @uint32 x@ = input to the function - * @const uint32 *l@ = key values to mix in - * @unsigned k@ = number of key values there are - * - * Returns: The output of the function @h@. - * - * Use: Implements the Twofish function @h@. - */ - -static uint32 h(uint32 x, const uint32 *l, unsigned k) -{ - /* --- Apply a series of @q@ tables to an integer --- */ - -# define Q(x, qa, qb, qc, qd) \ - ((qa[((x) >> 0) & 0xff] << 0) | \ - (qb[((x) >> 8) & 0xff] << 8) | \ - (qc[((x) >> 16) & 0xff] << 16) | \ - (qd[((x) >> 24) & 0xff] << 24)) - - /* --- Grind through the tables --- */ - - switch (k) { - case 4: x = Q(x, q1, q0, q0, q1) ^ l[3]; - case 3: x = Q(x, q1, q1, q0, q0) ^ l[2]; - case 2: x = Q(x, q0, q1, q0, q1) ^ l[1]; - x = Q(x, q0, q0, q1, q1) ^ l[0]; - break; - } - -#undef Q - - /* --- Apply the MDS matrix --- */ - - return (qmds[0][U8(x >> 0)] ^ qmds[1][U8(x >> 8)] ^ - qmds[2][U8(x >> 16)] ^ qmds[3][U8(x >> 24)]); -} - -/* --- @twofish_initfk@ --- * - * - * Arguments: @twofish_ctx *k@ = pointer to key block to fill in - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * @const twofish_fk *fk@ = family-key information - * - * Returns: --- - * - * Use: Does the underlying Twofish key initialization with family - * key. Pass in a family-key structure initialized to - * all-bits-zero for a standard key schedule. - */ - -void twofish_initfk(twofish_ctx *k, const void *buf, size_t sz, - const twofish_fk *fk) -{ -# define KMAX 4 - - uint32 mo[KMAX], me[KMAX]; - octet s[4][KMAX]; - - /* --- Expand the key into the three word arrays --- */ - - { - size_t ssz; - const octet *p, *q; - octet b[32]; - int i; - - /* --- Sort out the key size --- */ - - KSZ_ASSERT(twofish, sz); - if (sz <= 16) - ssz = 16; - else if (sz <= 24) - ssz = 24; - else if (sz <= 32) - ssz = 32; - else - assert(((void)"This can't happen (bad key size in twofish_init)", 0)); - - /* --- Extend the key if necessary --- */ - - if (sz == ssz) - p = buf; - else { - memcpy(b, buf, sz); - memset(b + sz, 0, ssz - sz); - p = b; - } - - /* --- Finally get the word count --- */ - - sz = ssz / 8; - - /* --- Extract words from the key --- * - * - * The @s@ table, constructed using the Reed-Solomon matrix, is cut into - * sequences of bytes, since this is actually more useful for computing - * the S-boxes. - */ - - q = p; - for (i = 0; i < sz; i++) { - octet ss[4]; - const octet *r = rs; - int j; - - /* --- Extract the easy subkeys --- */ - - me[i] = LOAD32_L(q) ^ fk->t0[2 * i]; - mo[i] = LOAD32_L(q + 4) ^ fk->t0[2 * i + 1]; - - /* --- Now do the Reed-Solomon thing --- */ - - for (j = 0; j < 4; j++) { - const octet *qq = q; - unsigned a = 0; - int k; - - for (k = 0; k < 8; k++) { - unsigned char x = *qq ^ fk->t1[i * 8 + k]; - if (x) a ^= rsexp[rslog[x] + *r]; - qq++; - r++; - } - - s[j][sz - 1 - i] = ss[j] = a; - } - q += 8; - } - - /* --- Clear away the temporary buffer --- */ - - if (p == b) - BURN(b); - } - - /* --- Construct the expanded key --- */ - - { - uint32 p = 0x01010101; - uint32 ip = 0; - int i; - - for (i = 0; i < 40; i += 2) { - uint32 a, b; - a = h(ip, me, sz); - b = h(ip + p, mo, sz); - b = ROL32(b, 8); - a += b; b += a; - k->k[i] = U32(a); - k->k[i + 1] = ROL32(b, 9); - ip += 2 * p; - } - - for (i = 0; i < 8; i++) - k->k[i] ^= fk->t23[i]; - for (i = 8; i < 40; i += 2) { - k->k[i] ^= fk->t4[0]; - k->k[i + 1] ^= fk->t4[1]; - } - } - - /* --- Construct the S-box tables --- */ - - { - unsigned i; - static const octet *q[4][KMAX + 1] = { - { q1, q0, q0, q1, q1 }, - { q0, q0, q1, q1, q0 }, - { q1, q1, q0, q0, q0 }, - { q0, q1, q1, q0, q1 } - }; - - for (i = 0; i < 4; i++) { - unsigned j; - uint32 x; - - for (j = 0; j < 256; j++) { - x = j; - - /* --- Push the byte through the q tables --- */ - - switch (sz) { - case 4: x = q[i][4][x] ^ s[i][3]; - case 3: x = q[i][3][x] ^ s[i][2]; - case 2: x = q[i][2][x] ^ s[i][1]; - x = q[i][1][x] ^ s[i][0]; - break; - } - - /* --- Write it in the key schedule --- */ - - k->g[i][j] = qmds[i][x]; - } - } - } - - /* --- Clear everything away --- */ - - BURN(me); - BURN(mo); - BURN(s); -} - -/* --- @twofish_init@ --- * - * - * Arguments: @twofish_ctx *k@ = pointer to key block to fill in - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a Twofish key buffer. Twofish accepts key sizes - * of up to 256 bits (32 bytes). - */ - -void twofish_init(twofish_ctx *k, const void *buf, size_t sz) -{ - static const twofish_fk fk = { { 0 } }; - twofish_initfk(k, buf, sz, &fk); -} - -/* --- @twofish_fkinit@ --- * - * - * Arguments: @twofish_fk *fk@ = pointer to family key block - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a family-key buffer. This implementation allows - * family keys of any size acceptable to the Twofish algorithm. - */ - -void twofish_fkinit(twofish_fk *fk, const void *buf, size_t sz) -{ - twofish_ctx k; - uint32 pt[4], ct[4]; - const octet *kk; - unsigned i; - - twofish_init(&k, buf, sz); - - for (i = 0; i < 4; i++) pt[i] = (uint32)-1; - twofish_eblk(&k, pt, fk->t0 + 4); - - kk = buf; sz /= 4; - for (i = 0; i < sz; i++) { fk->t0[i] = LOAD32_L(kk); kk += 4; } - - for (i = 0; i < 4; i++) pt[i] = 0; twofish_eblk(&k, pt, ct); - for (i = 0; i < 4; i++) STORE32_L(fk->t1 + i * 4, ct[i]); - pt[0] = 1; twofish_eblk(&k, pt, ct); - for (i = 0; i < 4; i++) STORE32_L(fk->t1 + 4 + i * 4, ct[i]); - - pt[0] = 2; twofish_eblk(&k, pt, fk->t23 + 0); - pt[0] = 3; twofish_eblk(&k, pt, fk->t23 + 4); - pt[0] = 4; twofish_eblk(&k, pt, ct); - fk->t4[0] = ct[0]; fk->t4[1] = ct[1]; - - BURN(k); -} - -/*----- Main encryption ---------------------------------------------------*/ - -/* --- Feistel function --- */ - -#define GG(k, t0, t1, x, y, kk) do { \ - t0 = (k->g[0][U8(x >> 0)] ^ \ - k->g[1][U8(x >> 8)] ^ \ - k->g[2][U8(x >> 16)] ^ \ - k->g[3][U8(x >> 24)]); \ - t1 = (k->g[1][U8(y >> 0)] ^ \ - k->g[2][U8(y >> 8)] ^ \ - k->g[3][U8(y >> 16)] ^ \ - k->g[0][U8(y >> 24)]); \ - t0 += t1; \ - t1 += t0; \ - t0 += kk[0]; \ - t1 += kk[1]; \ -} while (0) - -/* --- Round operations --- */ - -#define EROUND(k, w, x, y, z, kk) do { \ - uint32 _t0, _t1; \ - GG(k, _t0, _t1, w, x, kk); \ - kk += 2; \ - y ^= _t0; y = ROR32(y, 1); \ - z = ROL32(z, 1); z ^= _t1; \ -} while (0) - -#define DROUND(k, w, x, y, z, kk) do { \ - uint32 _t0, _t1; \ - kk -= 2; \ - GG(k, _t0, _t1, w, x, kk); \ - y = ROL32(y, 1); y ^= _t0; \ - z ^= _t1; z = ROR32(z, 1); \ -} while (0) - -/* --- Complete encryption functions --- */ - -#define EBLK(k, a, b, c, d, w, x, y, z) do { \ - const uint32 *_kk = k->k + 8; \ - uint32 _a = a, _b = b, _c = c, _d = d; \ - _a ^= k->k[0]; _b ^= k->k[1]; _c ^= k->k[2]; _d ^= k->k[3]; \ - EROUND(k, _a, _b, _c, _d, _kk); \ - EROUND(k, _c, _d, _a, _b, _kk); \ - EROUND(k, _a, _b, _c, _d, _kk); \ - EROUND(k, _c, _d, _a, _b, _kk); \ - EROUND(k, _a, _b, _c, _d, _kk); \ - EROUND(k, _c, _d, _a, _b, _kk); \ - EROUND(k, _a, _b, _c, _d, _kk); \ - EROUND(k, _c, _d, _a, _b, _kk); \ - EROUND(k, _a, _b, _c, _d, _kk); \ - EROUND(k, _c, _d, _a, _b, _kk); \ - EROUND(k, _a, _b, _c, _d, _kk); \ - EROUND(k, _c, _d, _a, _b, _kk); \ - EROUND(k, _a, _b, _c, _d, _kk); \ - EROUND(k, _c, _d, _a, _b, _kk); \ - EROUND(k, _a, _b, _c, _d, _kk); \ - EROUND(k, _c, _d, _a, _b, _kk); \ - _c ^= k->k[4]; _d ^= k->k[5]; _a ^= k->k[6]; _b ^= k->k[7]; \ - w = U32(_c); x = U32(_d); y = U32(_a); z = U32(_b); \ -} while (0) - -#define DBLK(k, a, b, c, d, w, x, y, z) do { \ - const uint32 *_kk = k->k + 40; \ - uint32 _a = a, _b = b, _c = c, _d = d; \ - _a ^= k->k[4]; _b ^= k->k[5]; _c ^= k->k[6]; _d ^= k->k[7]; \ - DROUND(k, _a, _b, _c, _d, _kk); \ - DROUND(k, _c, _d, _a, _b, _kk); \ - DROUND(k, _a, _b, _c, _d, _kk); \ - DROUND(k, _c, _d, _a, _b, _kk); \ - DROUND(k, _a, _b, _c, _d, _kk); \ - DROUND(k, _c, _d, _a, _b, _kk); \ - DROUND(k, _a, _b, _c, _d, _kk); \ - DROUND(k, _c, _d, _a, _b, _kk); \ - DROUND(k, _a, _b, _c, _d, _kk); \ - DROUND(k, _c, _d, _a, _b, _kk); \ - DROUND(k, _a, _b, _c, _d, _kk); \ - DROUND(k, _c, _d, _a, _b, _kk); \ - DROUND(k, _a, _b, _c, _d, _kk); \ - DROUND(k, _c, _d, _a, _b, _kk); \ - DROUND(k, _a, _b, _c, _d, _kk); \ - DROUND(k, _c, _d, _a, _b, _kk); \ - _c ^= k->k[0]; _d ^= k->k[1]; _a ^= k->k[2]; _b ^= k->k[3]; \ - w = U32(_c); x = U32(_d); y = U32(_a); z = U32(_b); \ -} while (0) - -/* --- @twofish_eblk@, @twofish_dblk@ --- * - * - * Arguments: @const twofish_ctx *k@ = pointer to key block - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -void twofish_eblk(const twofish_ctx *k, const uint32 *s, uint32 *d) -{ - EBLK(k, s[0], s[1], s[2], s[3], d[0], d[1], d[2], d[3]); -} - -void twofish_dblk(const twofish_ctx *k, const uint32 *s, uint32 *d) -{ - DBLK(k, s[0], s[1], s[2], s[3], d[0], d[1], d[2], d[3]); -} - -BLKC_TEST(TWOFISH, twofish) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/twofish.h b/twofish.h deleted file mode 100644 index 65007db..0000000 --- a/twofish.h +++ /dev/null @@ -1,145 +0,0 @@ -/* -*-c-*- - * - * $Id: twofish.h,v 1.5 2004/04/08 01:36:15 mdw Exp $ - * - * The Twofish block cipher - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the Twofish block cipher ---------------------------------* - * - * Twofish was designed by Bruce Schneier, John Kelsey, Doug Whiting, David - * Wagner, Chris Hall and Niels Ferguson. The algorithm is unpatented and - * free for anyone to use. It was one of the five AES finalist algorithms. - * - * Twofish is a complex cipher offering various space and time tradeoffs. - * This implementation has a heavy key schedule and fast bulk encryption. - */ - -#ifndef CATACOMB_TWOFISH_H -#define CATACOMB_TWOFISH_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magical numbers ---------------------------------------------------*/ - -#define TWOFISH_BLKSZ 16 -#define TWOFISH_KEYSZ 32 -#define TWOFISH_CLASS (N, L, 128) - -extern const octet twofish_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct twofish_ctx { - uint32 k[40]; - uint32 g[4][256]; -} twofish_ctx; - -typedef struct twofish_fk { - uint32 t0[8], t23[8], t4[2]; - octet t1[32]; -} twofish_fk; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @twofish_initfk@ --- * - * - * Arguments: @twofish_ctx *k@ = pointer to key block to fill in - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * @const twofish_fk *fk@ = family-key information - * - * Returns: --- - * - * Use: Does the underlying Twofish key initialization with family - * key. Pass in a family-key structure initialized to - * all-bits-zero for a standard key schedule. - */ - -extern void twofish_initfk(twofish_ctx */*k*/, const void */*buf*/, - size_t /*sz*/, const twofish_fk */*fk*/); - -/* --- @twofish_init@ --- * - * - * Arguments: @twofish_ctx *k@ = pointer to key block to fill in - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a Twofish key buffer. Twofish accepts keys of up - * to 256 bits in length. - */ - -extern void twofish_init(twofish_ctx */*k*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @twofish_fkinit@ --- * - * - * Arguments: @twofish_fk *fk@ = pointer to family key block - * @const void *buf@ = pointer to buffer of key material - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes a family-key buffer. This implementation allows - * family keys of any size acceptable to the Twofish algorithm. - */ - -extern void twofish_fkinit(twofish_fk */*fk*/, - const void */*buf*/, size_t /*sz*/); - -/* --- @twofish_eblk@, @twofish_dblk@ --- * - * - * Arguments: @const twofish_ctx *k@ = pointer to key block - * @const uint32 s[4]@ = pointer to source block - * @uint32 d[4]@ = pointer to destination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void twofish_eblk(const twofish_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -extern void twofish_dblk(const twofish_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/vars.am b/vars.am new file mode 100644 index 0000000..de79545 --- /dev/null +++ b/vars.am @@ -0,0 +1,102 @@ +### -*-makefile-*- +### +### Common definitions for build scripts +### +### (c) 2013 Straylight/Edgeware +### + +###----- Licensing notice --------------------------------------------------- +### +### This file is part of Catacomb. +### +### Catacomb is free software; you can redistribute it and/or modify +### it under the terms of the GNU Library General Public License as +### published by the Free Software Foundation; either version 2 of the +### License, or (at your option) any later version. +### +### Catacomb is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU Library General Public License for more details. +### +### You should have received a copy of the GNU Library General Public +### License along with Catacomb; if not, write to the Free +### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +### MA 02111-1307, USA. + +###-------------------------------------------------------------------------- +### Miscellaneous useful definitions. + +## Some convenient abbreviations for file suffixes. +e = $(EXEEXT) +o = $(OBJEXT) +t = t$e + +## Installation directories. +archincludedir = $(pkglibdir)/include + +###-------------------------------------------------------------------------- +### Initial values of common variables. + +EXTRA_DIST = +CLEANFILES = +DISTCLEANFILES = +MAINTAINERCLEANFILES = +SUFFIXES = +TESTS = +BUILT_SOURCES = + +noinst_PROGRAMS = +pkginclude_HEADERS = +nodist_pkginclude_HEADERS = +archinclude_HEADERS = +nodist_archinclude_HEADERS = + +###-------------------------------------------------------------------------- +### Standard configuration substitutions. + +## Substitute tags in files. +confsubst = $(top_srcdir)/config/confsubst + +SUBSTITUTIONS = \ + prefix=$(prefix) exec_prefix=$(exec_prefix) \ + libdir=$(libdir) includedir=$(includedir) \ + PACKAGE=$(PACKAGE) VERSION=$(VERSION) \ + CATACOMB_LIBS="$(CATACOMB_LIBS)" + +V_SUBST = $(V_SUBST_$(V)) +V_SUBST_ = $(V_SUBST_$(AM_DEFAULT_VERBOSITY)) +V_SUBST_0 = @echo " SUBST $@"; +SUBST = $(V_SUBST)$(confsubst) + +###-------------------------------------------------------------------------- +### Include path. + +CATACOMB_INCLUDES = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/base \ + -I$(top_srcdir)/key \ + -I$(top_srcdir)/math \ + -I$(top_builddir)/math \ + -I$(top_srcdir)/misc \ + -I$(top_srcdir)/pub \ + -I$(top_srcdir)/rand \ + -I$(top_srcdir)/symm \ + -I$(top_srcdir)/symm/modes -I$(top_builddir)/symm/modes + +AM_CPPFLAGS = $(CATACOMB_INCLUDES) + +###-------------------------------------------------------------------------- +### Testing. + +SUFFIXES += .c .$t .to +.c.to: + $(AM_V_CC)$(COMPILE) -c -DTEST_RIG -DSRCDIR=\"$(srcdir)\" $< -o $@ +.to.$t: libcatacomb.la + $(AM_V_CCLD)$(LINK) $< \ + $(TEST_LIBS) $(top_builddir)/libcatacomb.la \ + $(mLib_LIBS) $(CATACOMB_LIBS) $(LIBS) +.PRECIOUS: %.to +CLEANFILES += *.to *.$t + +###----- That's all, folks -------------------------------------------------- diff --git a/whirlpool-mktab.c b/whirlpool-mktab.c deleted file mode 100644 index 75f7bb2..0000000 --- a/whirlpool-mktab.c +++ /dev/null @@ -1,233 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Generate tables for Whirlpool hash function - * - * (c) 2005 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include - -#include - -/*----- Static variables --------------------------------------------------*/ - -static const octet E[] = { - 0x1, 0xb, 0x9, 0xc, 0xd, 0x6, 0xf, 0x3, - 0xe, 0x8, 0x7, 0x4, 0xa, 0x2, 0x5, 0x0 -}, R[] = { - 0x7, 0xc, 0xb, 0xd, 0xe, 0x4, 0x9, 0xf, - 0x6, 0x3, 0x8, 0xa, 0x2, 0x5, 0x1, 0x0 -}, C[] = { - 0x1, 0x1, 0x4, 0x1, 0x8, 0x5, 0x2, 0x9 -}; - -static octet S[256], T[256][8], log[256], alog[256]; - -/*----- Main code ---------------------------------------------------------*/ - -#define S_MOD 0x11d - -static void logtable(void) -{ - unsigned i, x; - - for (i = 0, x = 1; i < 255; i++) { - log[x] = i; - alog[i] = x; - x <<= 1; - if (x & 0x100) x ^= S_MOD; - } -} - -static octet mul(octet x, octet y) - { if (!x || !y) return (0); return (alog[(log[x] + log[y]) % 255]); } - -static void sbox(void) -{ - unsigned i, j; - octet EI[16]; - octet l, r, y; - - for (i = 0; i < 16; i++) EI[E[i]] = i; - for (i = 0; i < 256; i++) { - l = (i >> 4) & 0xf; - r = (i >> 0) & 0xf; - l = E[l]; r = EI[r]; - y = R[l ^ r]; - l = E[l ^ y]; r = EI[r ^ y]; - S[i] = (l << 4) | r; - } - - for (i = 0; i < 256; i++) { - for (j = 0; j < 8; j++) - T[i][j] = mul(S[i], C[j]); - } -} - -static unsigned long w32(int i, int j, int k) -{ - kludge64 x; - LOAD64_L_(x, T[j]); - ROL64_(x, x, i * 8); - return (k ? LO64(x) : HI64(x)); -} - -int main(void) -{ - int i, j; - - puts("\ -/* -*-c-*-\n\ - *\n\ - * Whirlpool tables [generated]\n\ - */\n\ -\n\ -#ifndef CATACOMB_WHIRLPOOL_TAB_H\n\ -#define CATACOMB_WHIRLPOOL_TAB_H\n\ -"); - - /* --- Write out the S-box --- */ - - logtable(); - sbox(); - fputs("\ -/* --- The byte substitution --- */\n\ -\n\ -#define WHIRLPOOL_S { \\\n\ - ", stdout); - for (i = 0; i < 256; i++) { - printf("0x%02x", S[i]); - if (i == 255) - fputs(" \\\n}\n\n", stdout); - else if (i % 8 == 7) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - /* --- Write out the key constant tables --- */ - - fputs("\ -/* --- The key generation constants --- */\n\ -\n\ -#define WHIRLPOOL_C { \\\n\ - ", stdout); - for (i = 0; i < 10; i++) { - printf("X64(%08lx, %08lx)", - (unsigned long)LOAD32_L(&S[i * 8 + 4]), - (unsigned long)LOAD32_L(&S[i * 8 + 0])); - if (i == 9) - fputs(" \\\n}\n\n", stdout); - else if (i % 2 == 1) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - - /* --- Write out the big T tables --- */ - - fputs("\ -/* --- The 64-bit big round tables --- */\n\ -\n\ -#define WHIRLPOOL_T { \\\n\ - { ", stdout); - for (j = 0; j < 8; j++) { - for (i = 0; i < 256; i++) { - printf("X64(%08lx, %08lx)", w32(j, i, 0), w32(j, i, 1)); - if (i == 255) { - if (j == 7) - fputs(" } \\\n}\n\n", stdout); - else - fputs(" }, \\\n\ - \\\n\ - { ", stdout); - } else if (i % 2 == 1) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - } - - /* --- Write out the smaller U and V tables --- */ - - fputs("\ -/* --- The 32-bit round tables --- */\n\ -\n\ -#define WHIRLPOOL_U { \\\n\ - { ", stdout); - for (j = 0; j < 4; j++) { - for (i = 0; i < 256; i++) { - printf("0x%08lx", w32(j, i, 1)); - if (i == 255) { - if (j == 3) - fputs(" } \\\n}\n\n", stdout); - else - fputs(" }, \\\n\ - \\\n\ - { ", stdout); - } else if (i % 4 == 3) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - } - - fputs("\ -#define WHIRLPOOL_V { \\\n\ - { ", stdout); - for (j = 0; j < 4; j++) { - for (i = 0; i < 256; i++) { - printf("0x%08lx", w32(j, i, 0)); - if (i == 255) { - if (j == 3) - fputs(" } \\\n}\n\n", stdout); - else - fputs(" }, \\\n\ - \\\n\ - { ", stdout); - } else if (i % 4 == 3) - fputs(", \\\n ", stdout); - else - fputs(", ", stdout); - } - } - - /* --- Done --- */ - - puts("#endif"); - - if (fclose(stdout)) { - fprintf(stderr, "error writing data\n"); - exit(EXIT_FAILURE); - } - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/whirlpool.c b/whirlpool.c deleted file mode 100644 index 48e6e97..0000000 --- a/whirlpool.c +++ /dev/null @@ -1,306 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Whirlpool hash function - * - * (c) 2005 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "whirlpool.h" -#include "whirlpool-tab.h" - -#if defined(HAVE_UINT64) -# define USE64 -#endif - -/*----- Static variables --------------------------------------------------*/ - -static const kludge64 C[10] = WHIRLPOOL_C; - -#ifdef USE64 -static const kludge64 T[8][256] = WHIRLPOOL_T; -#else -static const uint32 U[4][256] = WHIRLPOOL_U, V[4][256] = WHIRLPOOL_V; -#endif - -/*----- Main code ---------------------------------------------------------*/ - -#define DUMP(k, v) do { \ - int i; \ - printf("\n"); \ - for (i = 0; i < 8; i++) \ - printf(" %08x %08x : %08x %08x\n", \ - HI64(k[i]), LO64(k[i]), \ - HI64(v[i]), LO64(v[i])); \ -} while (0) - -#define OFFSET(i, n) (((i) + 16 - (n)) % 8) - -#ifdef USE64 - -#define BYTE(x, j) \ - U8((j) < 4 ? \ - (LO64(x) >> ((j) * 8)) : \ - (HI64(x) >> ((j) * 8 - 32))) - -#define TT(v, i, j) T[j][BYTE(v[OFFSET(i, j)], j)] - -#define XROW(vv, v, i) do { \ - XOR64(vv[i], vv[i], TT(v, i, 1)); \ - XOR64(vv[i], vv[i], TT(v, i, 2)); \ - XOR64(vv[i], vv[i], TT(v, i, 3)); \ - XOR64(vv[i], vv[i], TT(v, i, 4)); \ - XOR64(vv[i], vv[i], TT(v, i, 5)); \ - XOR64(vv[i], vv[i], TT(v, i, 6)); \ - XOR64(vv[i], vv[i], TT(v, i, 7)); \ -} while (0) - -#define ROWZ(vv, v, i) do { \ - vv[i] = TT(v, i, 0); \ - XROW(vv, v, i); \ -} while (0) - -#define ROWK(vv, v, i, k) do { \ - vv[i] = k; \ - XOR64(vv[i], vv[i], TT(v, i, 0)); \ - XROW(vv, v, i); \ -} while (0) - -#else - -#define BYTE(x, j) U8((x) >> (((j) & 3) * 8)) - -#define UUL(v, i, j) U[j & 3][BYTE(v[OFFSET(i, j)].lo, j)] -#define VVL(v, i, j) V[j & 3][BYTE(v[OFFSET(i, j)].lo, j)] -#define UUH(v, i, j) U[j & 3][BYTE(v[OFFSET(i, j)].hi, j)] -#define VVH(v, i, j) V[j & 3][BYTE(v[OFFSET(i, j)].hi, j)] - -#define XROW(vv, v, i) do { \ - vv[i].lo ^= UUL(v, i, 1); vv[i].hi ^= VVL(v, i, 1); \ - vv[i].lo ^= UUL(v, i, 2); vv[i].hi ^= VVL(v, i, 2); \ - vv[i].lo ^= UUL(v, i, 3); vv[i].hi ^= VVL(v, i, 3); \ - vv[i].lo ^= VVH(v, i, 4); vv[i].hi ^= UUH(v, i, 4); \ - vv[i].lo ^= VVH(v, i, 5); vv[i].hi ^= UUH(v, i, 5); \ - vv[i].lo ^= VVH(v, i, 6); vv[i].hi ^= UUH(v, i, 6); \ - vv[i].lo ^= VVH(v, i, 7); vv[i].hi ^= UUH(v, i, 7); \ -} while (0) - -#define ROWZ(vv, v, i) do { \ - vv[i].lo = UUL(v, i, 0); vv[i].hi = VVL(v, i, 0); \ - XROW(vv, v, i); \ -} while (0) - -#define ROWK(vv, v, i, k) do { \ - vv[i] = k; \ - vv[i].lo ^= UUL(v, i, 0); vv[i].hi ^= VVL(v, i, 0); \ - XROW(vv, v, i); \ -} while (0) - -#endif - -#define RHO(vv, v, kk, k) do { \ - ROWK(kk, k, 0, *c++); ROWK(vv, v, 0, kk[0]); \ - ROWZ(kk, k, 1); ROWK(vv, v, 1, kk[1]); \ - ROWZ(kk, k, 2); ROWK(vv, v, 2, kk[2]); \ - ROWZ(kk, k, 3); ROWK(vv, v, 3, kk[3]); \ - ROWZ(kk, k, 4); ROWK(vv, v, 4, kk[4]); \ - ROWZ(kk, k, 5); ROWK(vv, v, 5, kk[5]); \ - ROWZ(kk, k, 6); ROWK(vv, v, 6, kk[6]); \ - ROWZ(kk, k, 7); ROWK(vv, v, 7, kk[7]); \ -} while (0) - -void whirlpool_compress(whirlpool_ctx *ctx, const void *sbuf) -{ - kludge64 m[8], k[8], kk[8], v[8], vv[8]; - const kludge64 *c = C; - const octet *s = sbuf; - int i; - - for (i = 0; i < 8; i++) { - LOAD64_L_(m[i], &s[i * 8]); - XOR64(v[i], m[i], ctx->s[i]); - } - - RHO(vv, v, kk, ctx->s); - RHO(v, vv, k, kk); - RHO(vv, v, kk, k); - RHO(v, vv, k, kk); - RHO(vv, v, kk, k); - RHO(v, vv, k, kk); - RHO(vv, v, kk, k); - RHO(v, vv, k, kk); - RHO(vv, v, kk, k); - RHO(v, vv, k, kk); - - for (i = 0; i < 8; i++) { - XOR64(ctx->s[i], ctx->s[i], m[i]); - XOR64(ctx->s[i], ctx->s[i], v[i]); - } -} - -/* --- @whirlpool_init@, @whirlpool256_init@ --- * - * - * Arguments: @whirlpool_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -void whirlpool_init(whirlpool_ctx *ctx) -{ - int i; - - for (i = 0; i < 8; i++) - SET64(ctx->s[i], 0, 0); - ctx->off = 0; - ctx->nh = ctx->nl = 0; -} - -/* --- @whirlpool_set@, @whirlpool256_set@ --- * - * - * Arguments: @whirlpool_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -void whirlpool_set(whirlpool_ctx *ctx, const void *buf, unsigned long count) -{ - const octet *p = buf; - int i; - - for (i = 0; i < 8; i++) { - LOAD64_L_(ctx->s[i], p); - p += 8; - } - ctx->off = 0; - ctx->nl = U32(count); - ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); -} - -/* --- @whirlpool_hash@, @whirlpool256_hash@ --- * - * - * Arguments: @whirlpool_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -void whirlpool_hash(whirlpool_ctx *ctx, const void *buf, size_t sz) -{ - HASH_BUFFER(WHIRLPOOL, whirlpool, ctx, buf, sz); -} - -/* --- @whirlpool_done@, @whirlpool256_done@ --- * - * - * Arguments: @whirlpool_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -static void final(whirlpool_ctx *ctx) -{ - HASH_PAD(WHIRLPOOL, whirlpool, ctx, 0x80, 0, 32); - memset(ctx->buf + WHIRLPOOL_BUFSZ - 32, 0, 24); - STORE32(ctx->buf + WHIRLPOOL_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3)); - STORE32(ctx->buf + WHIRLPOOL_BUFSZ - 4, ctx->nl << 3); - whirlpool_compress(ctx, ctx->buf); -} - -void whirlpool_done(whirlpool_ctx *ctx, void *hash) -{ - octet *p = hash; - int i; - - final(ctx); - for (i = 0; i < 8; i++) { - STORE64_L_(p, ctx->s[i]); - p += 8; - } -} - -void whirlpool256_done(whirlpool256_ctx *ctx, void *hash) -{ - octet *p = hash; - int i; - - final(ctx); - for (i = 0; i < 4; i++) { - STORE64_L_(p, ctx->s[i]); - p += 8; - } -} - -/* --- @whirlpool_state@, @whirlpool256_state@ --- * - * - * Arguments: @whirlpool_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @whirlpool_set@. - */ - -unsigned long whirlpool_state(whirlpool_ctx *ctx, void *state) -{ - octet *p = state; - int i; - - for (i = 0; i < 8; i++) { - STORE64_L_(p, ctx->s[i]); - p += 8; - } - return (ctx->nl | ((ctx->nh << 16) << 16)); -} - -/* --- Generic interface --- */ - -GHASH_DEF(WHIRLPOOL, whirlpool) - -/* --- Test code --- */ - -HASH_TEST(WHIRLPOOL, whirlpool) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/whirlpool.h b/whirlpool.h deleted file mode 100644 index eb29a16..0000000 --- a/whirlpool.h +++ /dev/null @@ -1,177 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Implementation of the Whirlpool hash function - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the Whirlpool hash function ------------------------------* - * - * Whirlpool was designed by Paulo Barreto and Vincent Rijmen. Its - * compression function is based on similar ideas to Rijndael (also - * codesigned by Rijmen). - * - * Whirlpool256 is simply Whirlpool with its final output truncated to 256 - * bits. This is, I hope, about as good as a 256-bit hash function can get. - * It isn't vulnerable to the Kelsey-Schneier generic second-preimage attack - * against MD hash functions because of its larger internal state (see also - * Lucks). - */ - -#ifndef CATACOMB_WHIRLPOOL_H -#define CATACOMB_WHIRLPOOL_H -#define CATACOMB_WHIRLPOOL256_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#ifndef CATACOMB_GHASH_H -# include "ghash.h" -#endif - -/*----- Magic numbers -----------------------------------------------------*/ - -#define WHIRLPOOL_BUFSZ 64 -#define WHIRLPOOL_HASHSZ 64 -#define WHIRLPOOL_STATESZ 64 - -#define WHIRLPOOL256_BUFSZ 64 -#define WHIRLPOOL256_HASHSZ 32 -#define WHIRLPOOL256_STATESZ 64 - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct whirlpool_ctx { - kludge64 s[8]; /* Chaining variables */ - uint32 nh, nl; /* Byte count so far */ - unsigned off; /* Offset into buffer */ - octet buf[WHIRLPOOL_BUFSZ]; /* Accumulation buffer */ -} whirlpool_ctx, whirlpool256_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @whirlpool_compress@, @whirlpool256_compress@ --- * - * - * Arguments: @whirlpool_ctx *ctx@ = pointer to context block - * @const void *sbuf@ = pointer to buffer of appropriate size - * - * Returns: --- - * - * Use: SHA-512 compression function. - */ - -extern void whirlpool_compress(whirlpool_ctx */*ctx*/, const void */*sbuf*/); -#define whirlpool256_compress whirlpool_compress - -/* --- @whirlpool_init@, @whirlpool256_init@ --- * - * - * Arguments: @whirlpool_ctx *ctx@ = pointer to context block to initialize - * - * Returns: --- - * - * Use: Initializes a context block ready for hashing. - */ - -extern void whirlpool_init(whirlpool_ctx */*ctx*/); -#define whirlpool256_init whirlpool_init - -/* --- @whirlpool_set@, @whirlpool256_set@ --- * - * - * Arguments: @whirlpool_ctx *ctx@ = pointer to context block - * @const void *buf@ = pointer to state buffer - * @unsigned long count@ = current count of bytes processed - * - * Returns: --- - * - * Use: Initializes a context block from a given state. This is - * useful in cases where the initial hash state is meant to be - * secret, e.g., for NMAC and HMAC support. - */ - -extern void whirlpool_set(whirlpool_ctx */*ctx*/, const void */*buf*/, - unsigned long /*count*/); -#define whirlpool256_set whirlpool_set - -/* --- @whirlpool_hash@, @whirlpool256_hash@ --- * - * - * Arguments: @whirlpool_ctx *ctx@ = pointer to context block - * @const void *buf@ = buffer of data to hash - * @size_t sz@ = size of buffer to hash - * - * Returns: --- - * - * Use: Hashes a buffer of data. The buffer may be of any size and - * alignment. - */ - -extern void whirlpool_hash(whirlpool_ctx */*ctx*/, - const void */*buf*/, size_t /*sz*/); -#define whirlpool256_hash whirlpool_hash - -/* --- @whirlpool_done@, @whirlpool256_done@ --- * - * - * Arguments: @whirlpool_ctx *ctx@ = pointer to context block - * @void *hash@ = pointer to output buffer - * - * Returns: --- - * - * Use: Returns the hash of the data read so far. - */ - -extern void whirlpool_done(whirlpool_ctx */*ctx*/, void */*hash*/); -extern void whirlpool256_done(whirlpool_ctx */*ctx*/, void */*hash*/); - -/* --- @whirlpool_state@, @whirlpool256_state@ --- * - * - * Arguments: @whirlpool_ctx *ctx@ = pointer to context - * @void *state@ = pointer to buffer for current state - * - * Returns: Number of bytes written to the hash function so far. - * - * Use: Returns the current state of the hash function such that - * it can be passed to @whirlpool_set@. - */ - -extern unsigned long whirlpool_state(whirlpool_ctx */*ctx*/, - void */*state*/); -#define whirlpool256_state whirlpool_state - -/*----- Generic hash interface --------------------------------------------*/ - -extern const gchash whirlpool; -extern const gchash whirlpool256; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/whirlpool256.c b/whirlpool256.c deleted file mode 100644 index 38fe665..0000000 --- a/whirlpool256.c +++ /dev/null @@ -1,14 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Stub code for Whirlpool-256 - */ - -#include "ghash.h" -#include "ghash-def.h" -#include "hash.h" -#include "whirlpool256.h" - -GHASH_DEF(WHIRLPOOL256, whirlpool256) -HASH_TEST(WHIRLPOOL256, whirlpool256) diff --git a/whirlpool256.h b/whirlpool256.h deleted file mode 100644 index 171d886..0000000 --- a/whirlpool256.h +++ /dev/null @@ -1,13 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Stub header for Whirlpool-256 - */ - -#ifndef CATACOMB_WHIRLPOOL256_H -#define CATACOMB_WHIRLPOOL256_H - -#include "whirlpool.h" - -#endif diff --git a/xtea.c b/xtea.c deleted file mode 100644 index 13cb7fd..0000000 --- a/xtea.c +++ /dev/null @@ -1,122 +0,0 @@ -/* -*-c-*- - * - * $Id: xtea.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ - * - * The Extended Tiny Encryption Algorithm - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include "blkc.h" -#include "gcipher.h" -#include "paranoia.h" -#include "xtea.h" - -/*----- Global variables --------------------------------------------------*/ - -const octet xtea_keysz[] = { KSZ_RANGE, XTEA_KEYSZ, 0, 16, 1 }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @xtea_init@ --- * - * - * Arguments: @xtea_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes an XTEA key buffer. The key buffer must be 16 - * bytes long. - */ - -void xtea_init(xtea_ctx *k, const void *buf, size_t sz) -{ - octet kb[16]; - const octet *p; - - KSZ_ASSERT(xtea, sz); - if (sz >= sizeof(kb)) - p = buf; - else { - memcpy(kb, buf, sz); - memset(kb + sz, 0, sizeof(kb) - sz); - p = kb; - } - - k->k[0] = LOAD32(p + 0); k->k[1] = LOAD32(p + 4); - k->k[2] = LOAD32(p + 8); k->k[3] = LOAD32(p + 12); - k->r = 32; - - if (p == kb) - BURN(kb); -} - -/* --- @xtea_eblk@, @xtea_dblk@ --- * - * - * Arguments: @const xtea_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to xteatination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -#define DELTA 0x9e3779b9 - -void xtea_eblk(const xtea_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 y = s[0], z = s[1]; - uint32 n = 0; - unsigned i; - - for (i = 0; i < k->r; i++) { - y = U32(y + ((((z << 4) ^ (z >> 5)) + z) ^ (n + k->k[n & 3]))); - n += DELTA; - z = U32(z + ((((y << 4) ^ (y >> 5)) + y) ^ (n + k->k[(n >> 11) & 3]))); - } - d[0] = y; d[1] = z; -} - -void xtea_dblk(const xtea_ctx *k, const uint32 *s, uint32 *d) -{ - uint32 y = s[0], z = s[1]; - uint32 n = DELTA * k->r; - unsigned i; - - for (i = 0; i < k->r; i++) { - z = U32(z - ((((y << 4) ^ (y >> 5)) + y) ^ (n + k->k[(n >> 11) & 3]))); - n -= DELTA; - y = U32(y - ((((z << 4) ^ (z >> 5)) + z) ^ (n + k->k[n & 3]))); - } - d[0] = y; d[1] = z; -} - -BLKC_TEST(XTEA, xtea) - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/xtea.h b/xtea.h deleted file mode 100644 index 9e40b1e..0000000 --- a/xtea.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -*-c-*- - * - * $Id: xtea.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ - * - * The Extended Tiny Encryption Algorithm - * - * (c) 2000 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Notes on the Tiny Encryption Algorithm ----------------------------* - * - * XTEA is an amazingly simple 64-round Feistel network. It's tiny, fairly - * quick and surprisingly strong. It was invented by David Wheeler and Roger - * Needham. It's unpatented. XTEA is a new version of TEA, by the same - * designers, which fixes some weaknesses in TEA's key schedule. - * - * This implementation uses big-endian byte order, following SCAN. - */ - -#ifndef CATACOMB_XTEA_H -#define CATACOMB_XTEA_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Header files ------------------------------------------------------*/ - -#include - -#include - -/*----- Magical numbers ---------------------------------------------------*/ - -#define XTEA_BLKSZ 8 -#define XTEA_KEYSZ 16 -#define XTEA_CLASS (N, B, 64) - -extern const octet xtea_keysz[]; - -/*----- Data structures ---------------------------------------------------*/ - -typedef struct xtea_ctx { - unsigned r; - uint32 k[4]; -} xtea_ctx; - -/*----- Functions provided ------------------------------------------------*/ - -/* --- @xtea_init@ --- * - * - * Arguments: @xtea_ctx *k@ = pointer to key block - * @const void *buf@ = pointer to key buffer - * @size_t sz@ = size of key material - * - * Returns: --- - * - * Use: Initializes an XTEA key buffer. The key buffer may be up to - * 16 bytes long. - */ - -extern void xtea_init(xtea_ctx */*k*/, const void */*buf*/, size_t /*sz*/); - -/* --- @xtea_eblk@, @xtea_dblk@ --- * - * - * Arguments: @const xtea_ctx *k@ = pointer to key block - * @const uint32 s[2]@ = pointer to source block - * @uint32 d[2]@ = pointer to xteatination block - * - * Returns: --- - * - * Use: Low-level block encryption and decryption. - */ - -extern void xtea_eblk(const xtea_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); -extern void xtea_dblk(const xtea_ctx */*k*/, - const uint32 */*s*/, uint32 */*d*/); - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif -- 2.11.0